Fix 065 and 066 tests (NULL Method bug). Don't use Method in LLVM method compiler.

Change-Id: I98e4e9b329448b1b72c3b5c9d712ea68dab624bd
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 8932b47..49717fc 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -19,6 +19,7 @@
 #include "backend_types.h"
 #include "compilation_unit.h"
 #include "compiler.h"
+#include "dex_verifier.h"
 #include "inferred_reg_category_map.h"
 #include "ir_builder.h"
 #include "logging.h"
@@ -55,8 +56,6 @@
     dex_cache_(oat_compilation_unit->dex_cache_),
     code_item_(oat_compilation_unit->code_item_),
     oat_compilation_unit_(oat_compilation_unit),
-    method_(dex_cache_->GetResolvedMethod(oat_compilation_unit->method_idx_)),
-    method_helper_(method_),
     method_idx_(oat_compilation_unit->method_idx_),
     access_flags_(oat_compilation_unit->access_flags_),
     module_(cunit->GetModule()),
@@ -82,7 +81,7 @@
 
   // Get function type
   llvm::FunctionType* func_type =
-    GetFunctionType(method_idx_, method_->IsStatic());
+    GetFunctionType(method_idx_, oat_compilation_unit_->IsStatic());
 
   // Create function
   func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
@@ -96,7 +95,7 @@
   arg_iter->setName("method");
   ++arg_iter;
 
-  if (!method_->IsStatic()) {
+  if (!oat_compilation_unit_->IsStatic()) {
     DCHECK_NE(arg_iter, arg_end);
     arg_iter->setName("this");
     ++arg_iter;
@@ -216,7 +215,7 @@
   irb_.CreateCall(irb_.GetRuntime(ThrowStackOverflowException));
 
   // Unwind.
-  char ret_shorty = method_helper_.GetShorty()[0];
+  char ret_shorty = oat_compilation_unit_->GetShorty()[0];
   if (ret_shorty == 'V') {
     irb_.CreateRetVoid();
   } else {
@@ -294,19 +293,19 @@
   llvm::Function::arg_iterator arg_iter(func_->arg_begin());
   llvm::Function::arg_iterator arg_end(func_->arg_end());
 
-  char const* shorty = method_helper_.GetShorty();
-  int32_t shorty_size = method_helper_.GetShortyLength();
-  CHECK_LE(1, shorty_size);
+  uint32_t shorty_size = 0;
+  char const* shorty = oat_compilation_unit_->GetShorty(&shorty_size);
+  CHECK_GE(shorty_size, 1u);
 
   ++arg_iter; // skip method object
 
-  if (!method_->IsStatic()) {
+  if (!oat_compilation_unit_->IsStatic()) {
     EmitStoreDalvikReg(arg_reg, kObject, kAccurate, arg_iter);
     ++arg_iter;
     ++arg_reg;
   }
 
-  for (int32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
+  for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
     EmitStoreDalvikReg(arg_reg, shorty[i], kAccurate, arg_iter);
 
     ++arg_reg;
@@ -1319,7 +1318,7 @@
   // the return value might be collected since the shadow stack is popped.
 
   // Return!
-  char ret_shorty = method_helper_.GetShorty()[0];
+  char ret_shorty = oat_compilation_unit_->GetShorty()[0];
   llvm::Value* retval = EmitLoadDalvikReg(dec_insn.vA, ret_shorty, kAccurate);
 
   irb_.CreateRet(retval);
@@ -1812,40 +1811,41 @@
     EmitAllocNewArray(dex_pc, dec_insn.vA, dec_insn.vB, true);
 
   if (dec_insn.vA > 0) {
-    llvm::Value* object_addr_int =
-      irb_.CreatePtrToInt(object_addr, irb_.getPtrEquivIntTy());
-
-    // TODO: currently FilledNewArray doesn't support I, J, D and L, [ so computing the component
-    // size using int alignment is safe. This code should determine the width of the FilledNewArray
-    // component.
-    llvm::Value* data_field_offset =
-      irb_.getPtrEquivInt(Array::DataOffset(sizeof(int32_t)).Int32Value());
-
-    llvm::Value* data_field_addr_int =
-      irb_.CreateAdd(object_addr_int, data_field_offset);
-
-    Class* klass = method_->GetDexCacheResolvedTypes()->Get(dec_insn.vB);
+    // Resolve the element type
+    Class* klass = dex_cache_->GetResolvedType(dec_insn.vB);
+    // TODO: Avoid the usage of the dex_cache_.  Try to figure out a better
+    // way to distinguish [I and [L.
     CHECK_NE(klass, static_cast<Class*>(NULL));
-    // Moved this below already: CHECK(!klass->IsPrimitive() || klass->IsPrimitiveInt());
 
-    llvm::Constant* word_size = irb_.getSizeOfPtrEquivIntValue();
+    uint32_t alignment;
+    llvm::Constant* elem_size;
+    llvm::PointerType* field_type;
 
-    llvm::Type* field_type;
+    // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
+    // as the element, thus we are only checking 2 cases: primitive int and
+    // non-primitive type.
     if (klass->IsPrimitiveInt()) {
+      alignment = sizeof(int32_t);
+      elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
       field_type = irb_.getJIntTy()->getPointerTo();
     } else {
       CHECK(!klass->IsPrimitive());
+      alignment = irb_.getSizeOfPtrEquivInt();
+      elem_size = irb_.getSizeOfPtrEquivIntValue();
       field_type = irb_.getJObjectTy()->getPointerTo();
     }
 
+    llvm::Value* data_field_offset =
+      irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
+
+    llvm::Value* data_field_addr =
+      irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
+
     // TODO: Tune this code.  Currently we are generating one instruction for
     // one element which may be very space consuming.  Maybe changing to use
     // memcpy may help; however, since we can't guarantee that the alloca of
     // dalvik register are continuous, we can't perform such optimization yet.
     for (uint32_t i = 0; i < dec_insn.vA; ++i) {
-      llvm::Value* data_field_addr =
-        irb_.CreateIntToPtr(data_field_addr_int, field_type);
-
       int reg_index;
       if (is_range) {
         reg_index = dec_insn.vC + i;
@@ -1862,7 +1862,8 @@
 
       irb_.CreateStore(reg_value, data_field_addr);
 
-      data_field_addr_int = irb_.CreateAdd(data_field_addr_int, word_size);
+      data_field_addr =
+        irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
     }
   }
 
@@ -2209,7 +2210,12 @@
 
 RegCategory MethodCompiler::GetInferredRegCategory(uint32_t dex_pc,
                                                    uint16_t reg_idx) {
-  InferredRegCategoryMap const* map = method_->GetInferredRegCategoryMap();
+
+  Compiler::MethodReference mref(dex_file_, method_idx_);
+
+  InferredRegCategoryMap const* map =
+    verifier::DexVerifier::GetInferredRegCategoryMap(mref);
+
   CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
 
   return map->GetRegCategory(dex_pc, reg_idx);
@@ -2361,12 +2367,11 @@
 
 
 void MethodCompiler::PrintUnresolvedFieldWarning(int32_t field_idx) {
-  DexFile const& dex_file = method_helper_.GetDexFile();
-  DexFile::FieldId const& field_id = dex_file.GetFieldId(field_idx);
+  DexFile::FieldId const& field_id = dex_file_->GetFieldId(field_idx);
 
   LOG(WARNING) << "unable to resolve static field " << field_idx << " ("
-               << dex_file.GetFieldName(field_id) << ") in "
-               << dex_file.GetFieldDeclaringClassDescriptor(field_id);
+               << dex_file_->GetFieldName(field_id) << ") in "
+               << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
 }
 
 
@@ -3622,9 +3627,6 @@
   // Verify the generated bitcode
   llvm::verifyFunction(*func_, llvm::PrintMessageAction);
 
-  // Delete the inferred register category map (won't be used anymore)
-  method_->ResetInferredRegCategoryMap();
-
   // Add the memory usage approximation of the compilation unit
   cunit_->AddMemUsageApproximation(code_item_->insns_size_in_code_units_ * 900);
   // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
@@ -3823,7 +3825,7 @@
   EmitPopShadowFrame();
 
   // Emit the code to return default value (zero) for the given return type.
-  char ret_shorty = method_helper_.GetShorty()[0];
+  char ret_shorty = oat_compilation_unit_->GetShorty()[0];
   if (ret_shorty == 'V') {
     irb_.CreateRetVoid();
   } else {
@@ -3947,7 +3949,9 @@
 
 
 void MethodCompiler::EmitUpdateLineNumFromDexPC(uint32_t dex_pc) {
-  EmitUpdateLineNum(dex_file_->GetLineNumFromPC(method_, dex_pc));
+  EmitUpdateLineNum(
+    dex_file_->GetLineNumFromPC(oat_compilation_unit_->IsStatic(),
+                                method_idx_, code_item_, dex_pc));
 }
 
 
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 74c55f0..7b374af 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -447,8 +447,6 @@
   DexFile::CodeItem const* code_item_;
 
   OatCompilationUnit* oat_compilation_unit_;
-  Method* method_;
-  MethodHelper method_helper_;
 
   uint32_t method_idx_;
   uint32_t access_flags_;
diff --git a/src/dex_file.cc b/src/dex_file.cc
index c3e7c84..6168f9e 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -580,7 +580,6 @@
   return descriptor;
 }
 
-
 int32_t DexFile::GetLineNumFromPC(const Method* method, uint32_t rel_pc) const {
   // For native method, lineno should be -2 to indicate it is native. Note that
   // "line number == -2" is how libcore tells from StackTraceElement.
@@ -588,12 +587,18 @@
     return -2;
   }
 
-  const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
+  return GetLineNumFromPC(method->IsStatic(), method->GetDexMethodIndex(),
+                          GetCodeItem(method->GetCodeItemOffset()), rel_pc);
+}
+
+int32_t DexFile::GetLineNumFromPC(bool is_static, uint32_t method_idx,
+                                  const CodeItem* code_item,
+                                  uint32_t rel_pc) const {
   DCHECK(code_item != NULL) << GetLocation();
 
   // A method with no line number info should return -1
   LineNumFromPcContext context(rel_pc, -1);
-  DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
+  DecodeDebugInfo(code_item, is_static, method_idx, LineNumForPcCb,
                   NULL, &context);
   return context.line_num_;
 }
diff --git a/src/dex_file.h b/src/dex_file.h
index e6c8a94..02d0b27 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -755,6 +755,9 @@
   // This is used by runtime; therefore use art::Method not art::DexFile::Method.
   int32_t GetLineNumFromPC(const Method* method, uint32_t rel_pc) const;
 
+  int32_t GetLineNumFromPC(bool is_static, uint32_t method_idx,
+                           const CodeItem* code_item, uint32_t rel_pc) const;
+
   void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
                        DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
                        void* context) const;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index f02379c..91d6ccd 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -1691,12 +1691,12 @@
   Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
   verifier::DexVerifier::SetGcMap(ref, *gc_map);
 
-#if !defined(ART_USE_LLVM_COMPILER)
   method_->SetGcMap(&gc_map->at(0));
-#else
+
+#if defined(ART_USE_LLVM_COMPILER)
   /* Generate Inferred Register Category for LLVM-based Code Generator */
   const InferredRegCategoryMap* table = GenerateInferredRegCategoryMap();
-  method_->SetInferredRegCategoryMap(table);
+  verifier::DexVerifier::SetInferredRegCategoryMap(ref, *table);
 #endif
 
   return true;
@@ -4077,7 +4077,7 @@
 }
 
 #if defined(ART_USE_LLVM_COMPILER)
-InferredRegCategoryMap const* DexVerifier::GenerateInferredRegCategoryMap() {
+const InferredRegCategoryMap* DexVerifier::GenerateInferredRegCategoryMap() {
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
   uint16_t regs_size = code_item_->registers_size_;
 
@@ -4087,7 +4087,7 @@
   for (size_t i = 0; i < insns_size; ++i) {
     if (RegisterLine* line = reg_table_.GetLine(i)) {
       for (size_t r = 0; r < regs_size; ++r) {
-        RegType const &rt = line->GetRegisterType(r);
+        const RegType &rt = line->GetRegisterType(r);
 
         if (rt.IsZero()) {
           table->SetRegCategory(i, r, kRegZero);
@@ -4106,6 +4106,56 @@
 
   return table.release();
 }
+
+Mutex* DexVerifier::inferred_reg_category_maps_lock_ = NULL;
+DexVerifier::InferredRegCategoryMapTable* DexVerifier::inferred_reg_category_maps_ = NULL;
+
+void DexVerifier::InitInferredRegCategoryMaps() {
+  inferred_reg_category_maps_lock_ = new Mutex("verifier GC maps lock");
+  MutexLock mu(*inferred_reg_category_maps_lock_);
+  inferred_reg_category_maps_ = new DexVerifier::InferredRegCategoryMapTable;
+}
+
+void DexVerifier::DeleteInferredRegCategoryMaps() {
+  {
+    MutexLock mu(*inferred_reg_category_maps_lock_);
+    STLDeleteValues(inferred_reg_category_maps_);
+    delete inferred_reg_category_maps_;
+    inferred_reg_category_maps_ = NULL;
+  }
+  delete inferred_reg_category_maps_lock_;
+  inferred_reg_category_maps_lock_ = NULL;
+}
+
+
+void DexVerifier::SetInferredRegCategoryMap(Compiler::MethodReference ref,
+                                            const InferredRegCategoryMap& inferred_reg_category_map) {
+  MutexLock mu(*inferred_reg_category_maps_lock_);
+  const InferredRegCategoryMap* existing_inferred_reg_category_map =
+    GetInferredRegCategoryMap(ref);
+
+  if (existing_inferred_reg_category_map != NULL) {
+    CHECK(*existing_inferred_reg_category_map == inferred_reg_category_map);
+    delete existing_inferred_reg_category_map;
+  }
+
+  (*inferred_reg_category_maps_)[ref] = &inferred_reg_category_map;
+  CHECK(GetInferredRegCategoryMap(ref) != NULL);
+}
+
+const InferredRegCategoryMap*
+DexVerifier::GetInferredRegCategoryMap(Compiler::MethodReference ref) {
+  MutexLock mu(*inferred_reg_category_maps_lock_);
+
+  InferredRegCategoryMapTable::const_iterator it =
+      inferred_reg_category_maps_->find(ref);
+
+  if (it == inferred_reg_category_maps_->end()) {
+    return NULL;
+  }
+  CHECK(it->second != NULL);
+  return it->second;
+}
 #endif
 
 }  // namespace verifier
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 46f9ef2..043e4f9 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -922,6 +922,12 @@
   static void InitGcMaps();
   static void DeleteGcMaps();
 
+#if defined(ART_USE_LLVM_COMPILER)
+  static const compiler_llvm::InferredRegCategoryMap* GetInferredRegCategoryMap(Compiler::MethodReference ref);
+  static void InitInferredRegCategoryMaps();
+  static void DeleteInferredRegCategoryMaps();
+#endif
+
   static bool IsClassRejected(Compiler::ClassReference ref);
 
  private:
@@ -1305,6 +1311,16 @@
   static GcMapTable* gc_maps_;
   static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map);
 
+#if defined(ART_USE_LLVM_COMPILER)
+  // All the inferred register category maps that the verifier has created
+  typedef std::map<const Compiler::MethodReference,
+                   const compiler_llvm::InferredRegCategoryMap*> InferredRegCategoryMapTable;
+  static Mutex* inferred_reg_category_maps_lock_;
+  static InferredRegCategoryMapTable* inferred_reg_category_maps_;
+  static void SetInferredRegCategoryMap(Compiler::MethodReference ref,
+                                        const compiler_llvm::InferredRegCategoryMap& m);
+#endif
+
   static void AddRejectedClass(Compiler::ClassReference ref);
 
   RegTypeCache reg_types_;
diff --git a/src/oat_compilation_unit.h b/src/oat_compilation_unit.h
index b21a5b0..0000f21 100644
--- a/src/oat_compilation_unit.h
+++ b/src/oat_compilation_unit.h
@@ -46,6 +46,30 @@
                                   callee_access_flags);
   }
 
+  const ClassLoader* GetClassLoader() const {
+    return class_loader_;
+  }
+
+  ClassLinker* GetClassLinker() const {
+    return class_linker_;
+  }
+
+  const DexFile* GetDexFile() const {
+    return dex_file_;
+  }
+
+  DexCache* GetDexCache() const {
+    return dex_cache_;
+  }
+
+  uint32_t GetDexMethodIndex() const {
+    return method_idx_;
+  }
+
+  const DexFile::CodeItem* GetCodeItem() const {
+    return code_item_;
+  }
+
   const char* GetShorty() const {
     const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx_);
     return dex_file_->GetMethodShorty(method_id);
@@ -56,6 +80,10 @@
     return dex_file_->GetMethodShorty(method_id, shorty_len);
   }
 
+  bool IsStatic() const {
+    return ((access_flags_ & kAccStatic) != 0);
+  }
+
  public:
   const ClassLoader* class_loader_;
   ClassLinker* class_linker_;
diff --git a/src/object.cc b/src/object.cc
index 0bcf5c7..cd6b51f 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -384,35 +384,6 @@
       new_value, false);
 }
 
-#if defined(ART_USE_LLVM_COMPILER)
-
-const InferredRegCategoryMap* Method::GetInferredRegCategoryMap() const {
-  const InferredRegCategoryMap* map = GetFieldPtr<const InferredRegCategoryMap*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, gc_map_), false);
-  DCHECK(map != NULL) << PrettyMethod(this);
-  return map;
-}
-
-void Method::SetInferredRegCategoryMap(const InferredRegCategoryMap* map) {
-  const InferredRegCategoryMap* existing_map = GetFieldPtr<const InferredRegCategoryMap*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, gc_map_), false);
-
-  DCHECK(existing_map == NULL) << PrettyMethod(this);
-  DCHECK(map != NULL) << PrettyMethod(this);
-
-  // TODO: Remove if we won't find any use of InferredRegCategoryMap at runtime.
-  SetFieldPtr<const InferredRegCategoryMap*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, gc_map_), map, false);
-}
-
-void Method::ResetInferredRegCategoryMap() {
-  delete GetInferredRegCategoryMap();
-  SetFieldPtr<const InferredRegCategoryMap*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, gc_map_), NULL, false);
-}
-
-#endif
-
 size_t Method::NumArgRegisters(const StringPiece& shorty) {
   CHECK_LE(1, shorty.length());
   uint32_t num_registers = 0;
diff --git a/src/object.h b/src/object.h
index 4d054b9..3ece535 100644
--- a/src/object.h
+++ b/src/object.h
@@ -760,16 +760,6 @@
     SetGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
   }
 
-#if defined(ART_USE_LLVM_COMPILER)
-  // NOTE: In order not to change the Oat file format, we are reusing the
-  // gc_map_ field, so be careful while altering the GC map related code.
-
-  const compiler_llvm::InferredRegCategoryMap* GetInferredRegCategoryMap() const;
-
-  void SetInferredRegCategoryMap(const compiler_llvm::InferredRegCategoryMap* map);
-  void ResetInferredRegCategoryMap();
-#endif
-
   size_t GetFrameSizeInBytes() const {
     DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
     size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_), false);
diff --git a/src/runtime.cc b/src/runtime.cc
index 014ce6b..d16ee78 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -99,6 +99,9 @@
 
   delete class_linker_;
   delete heap_;
+#if defined(ART_USE_LLVM_COMPILER)
+  verifier::DexVerifier::DeleteInferredRegCategoryMaps();
+#endif
   verifier::DexVerifier::DeleteGcMaps();
   delete intern_table_;
   delete java_vm_;
@@ -643,6 +646,10 @@
 
   verifier::DexVerifier::InitGcMaps();
 
+#if defined(ART_USE_LLVM_COMPILER)
+  verifier::DexVerifier::InitInferredRegCategoryMaps();
+#endif
+
   heap_ = new Heap(options->heap_initial_size_,
                    options->heap_growth_limit_,
                    options->heap_maximum_size_,