Refactor dalvik_reg.

Also, fix ComputeMethodInfo, ARRAY_LENGTH may throw exception.

Don't store arguments to shadow frame, it already existed in the
caller's shadow frame.

Change-Id: I184a93ed7f3caea924514d425e6a00dc60464f90
diff --git a/src/compiler_llvm/dalvik_reg.cc b/src/compiler_llvm/dalvik_reg.cc
index e19067f..c3263ae 100644
--- a/src/compiler_llvm/dalvik_reg.cc
+++ b/src/compiler_llvm/dalvik_reg.cc
@@ -23,62 +23,13 @@
 using namespace art::compiler_llvm;
 
 
-namespace {
-
-  class DalvikLocalVarReg : public DalvikReg {
-   public:
-    DalvikLocalVarReg(MethodCompiler& method_compiler, uint32_t reg_idx);
-
-    virtual void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
-
-    virtual ~DalvikLocalVarReg();
-
-   private:
-    virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);
-
-   private:
-    uint32_t reg_idx_;
-    llvm::Value* reg_32_;
-    llvm::Value* reg_64_;
-    llvm::Value* reg_obj_;
-    llvm::Value* reg_shadow_frame_;
-  };
-
-  class DalvikRetValReg : public DalvikReg {
-   public:
-    DalvikRetValReg(MethodCompiler& method_compiler);
-
-    virtual ~DalvikRetValReg();
-
-   private:
-    virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);
-
-   private:
-    llvm::Value* reg_32_;
-    llvm::Value* reg_64_;
-    llvm::Value* reg_obj_;
-  };
-
-} // anonymous namespace
-
-
 //----------------------------------------------------------------------------
 // Dalvik Register
 //----------------------------------------------------------------------------
 
-DalvikReg* DalvikReg::CreateLocalVarReg(MethodCompiler& method_compiler,
-                                        uint32_t reg_idx) {
-  return new DalvikLocalVarReg(method_compiler, reg_idx);
-}
-
-
-DalvikReg* DalvikReg::CreateRetValReg(MethodCompiler& method_compiler) {
-  return new DalvikRetValReg(method_compiler);
-}
-
-
-DalvikReg::DalvikReg(MethodCompiler& method_compiler)
-: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()) {
+DalvikReg::DalvikReg(MethodCompiler& method_compiler, const std::string& name)
+: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()),
+  reg_name_(name), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
 }
 
 
@@ -133,7 +84,7 @@
   switch (space) {
   case kReg:
   case kField:
-    value = irb_.CreateLoad(GetAddr(jty, space), kTBAARegister);
+    value = irb_.CreateLoad(GetAddr(jty), kTBAARegister);
     break;
 
   case kAccurate:
@@ -150,7 +101,7 @@
       // NOTE: In array type space, boolean is truncated from i32 to i8, while
       // in accurate type space, boolean is truncated from i32 to i1.
       // For the other cases, array type space is equal to accurate type space.
-      value = RegCat1Trunc(irb_.CreateLoad(GetAddr(jty, space), kTBAARegister),
+      value = RegCat1Trunc(irb_.CreateLoad(GetAddr(jty), kTBAARegister),
                            irb_.getJType(jty, space));
       break;
 
@@ -159,7 +110,7 @@
     case kFloat:
     case kDouble:
     case kObject:
-      value = irb_.CreateLoad(GetAddr(jty, space), kTBAARegister);
+      value = irb_.CreateLoad(GetAddr(jty), kTBAARegister);
       break;
 
     default:
@@ -190,7 +141,7 @@
   switch (space) {
   case kReg:
   case kField:
-    irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
+    irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
     return;
 
   case kAccurate:
@@ -204,7 +155,7 @@
       // NOTE: In accurate type space, we have to zero extend boolean from
       // i1 to i32, and char from i16 to i32.  In array type space, we have
       // to zero extend boolean from i8 to i32, and char from i16 to i32.
-      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space), kTBAARegister);
+      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty), kTBAARegister);
       break;
 
     case kByte:
@@ -212,7 +163,7 @@
       // NOTE: In accurate type space, we have to signed extend byte from
       // i8 to i32, and short from i16 to i32.  In array type space, we have
       // to sign extend byte from i8 to i32, and short from i16 to i32.
-      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space), kTBAARegister);
+      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty), kTBAARegister);
       break;
 
     case kInt:
@@ -220,7 +171,7 @@
     case kFloat:
     case kDouble:
     case kObject:
-      irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
+      irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
       break;
 
     default:
@@ -230,94 +181,23 @@
 }
 
 
-llvm::Value* DalvikReg::GetAddr(JType jty, JTypeSpace space) {
-  return GetRawAddr(jty, space);
-}
-
-
-//----------------------------------------------------------------------------
-// Dalvik Local Variable Register
-//----------------------------------------------------------------------------
-
-DalvikLocalVarReg::DalvikLocalVarReg(MethodCompiler& method_compiler,
-                                     uint32_t reg_idx)
-: DalvikReg(method_compiler), reg_idx_(reg_idx),
-  reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL), reg_shadow_frame_(NULL) {
-}
-
-
-DalvikLocalVarReg::~DalvikLocalVarReg() {
-}
-
-
-void DalvikLocalVarReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
-  DalvikReg::SetValue(jty, space, value);
-
-  if (jty == kObject && reg_shadow_frame_ != NULL) {
-    irb_.CreateStore(value, reg_shadow_frame_, kTBAAShadowFrame);
-  }
-}
-
-
-llvm::Value* DalvikLocalVarReg::GetRawAddr(JType jty, JTypeSpace space) {
+llvm::Value* DalvikReg::GetAddr(JType jty) {
   switch (GetRegCategoryFromJType(jty)) {
   case kRegCat1nr:
     if (reg_32_ == NULL) {
-      reg_32_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat1nr, reg_idx_);
+      reg_32_ = method_compiler_->AllocDalvikReg(kRegCat1nr, reg_name_);
     }
     return reg_32_;
 
   case kRegCat2:
     if (reg_64_ == NULL) {
-      reg_64_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat2, reg_idx_);
+      reg_64_ = method_compiler_->AllocDalvikReg(kRegCat2, reg_name_);
     }
     return reg_64_;
 
   case kRegObject:
     if (reg_obj_ == NULL) {
-      reg_obj_ = method_compiler_->AllocDalvikLocalVarReg(kRegObject, reg_idx_);
-      reg_shadow_frame_ = method_compiler_->AllocShadowFrameEntry(reg_idx_);
-    }
-    return reg_obj_;
-
-  default:
-    LOG(FATAL) << "Unexpected register category: "
-               << GetRegCategoryFromJType(jty);
-    return NULL;
-  }
-}
-
-
-//----------------------------------------------------------------------------
-// Dalvik Returned Value Temporary Register
-//----------------------------------------------------------------------------
-
-DalvikRetValReg::DalvikRetValReg(MethodCompiler& method_compiler)
-: DalvikReg(method_compiler), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
-}
-
-
-DalvikRetValReg::~DalvikRetValReg() {
-}
-
-
-llvm::Value* DalvikRetValReg::GetRawAddr(JType jty, JTypeSpace space) {
-  switch (GetRegCategoryFromJType(jty)) {
-  case kRegCat1nr:
-    if (reg_32_ == NULL) {
-      reg_32_ = method_compiler_->AllocDalvikRetValReg(kRegCat1nr);
-    }
-    return reg_32_;
-
-  case kRegCat2:
-    if (reg_64_ == NULL) {
-      reg_64_ = method_compiler_->AllocDalvikRetValReg(kRegCat2);
-    }
-    return reg_64_;
-
-  case kRegObject:
-    if (reg_obj_ == NULL) {
-      reg_obj_ = method_compiler_->AllocDalvikRetValReg(kRegObject);
+      reg_obj_ = method_compiler_->AllocDalvikReg(kRegObject, reg_name_);
     }
     return reg_obj_;
 
diff --git a/src/compiler_llvm/dalvik_reg.h b/src/compiler_llvm/dalvik_reg.h
index 7356c87..f950771 100644
--- a/src/compiler_llvm/dalvik_reg.h
+++ b/src/compiler_llvm/dalvik_reg.h
@@ -20,6 +20,7 @@
 #include "backend_types.h"
 
 #include <stdint.h>
+#include <string>
 
 namespace llvm {
   class Type;
@@ -34,16 +35,13 @@
 
 class DalvikReg {
  public:
-  static DalvikReg* CreateLocalVarReg(MethodCompiler& method_compiler,
-                                      uint32_t reg_idx);
-
-  static DalvikReg* CreateRetValReg(MethodCompiler& method_compiler);
-
   static llvm::Type* GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat);
 
   static char GetRegCategoryNamePrefix(RegCategory reg_cat);
 
-  virtual ~DalvikReg();
+  DalvikReg(MethodCompiler& method_compiler, const std::string& name);
+
+  ~DalvikReg();
 
   llvm::Value* GetValue(JType jty, JTypeSpace space);
 
@@ -51,28 +49,27 @@
     return GetValue(GetJTypeFromShorty(shorty), space);
   }
 
-  virtual void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
+  void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
 
   void SetValue(char shorty, JTypeSpace space, llvm::Value* value) {
     return SetValue(GetJTypeFromShorty(shorty), space, value);
   }
 
- protected:
-  DalvikReg(MethodCompiler& method_compiler);
-
  private:
-  llvm::Value* GetAddr(JType jty, JTypeSpace space);
+  llvm::Value* GetAddr(JType jty);
 
   llvm::Value* RegCat1SExt(llvm::Value* value);
   llvm::Value* RegCat1ZExt(llvm::Value* value);
 
   llvm::Value* RegCat1Trunc(llvm::Value* value, llvm::Type* ty);
 
-  virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space) = 0;
-
- protected:
   MethodCompiler* method_compiler_;
   IRBuilder& irb_;
+
+  std::string reg_name_;
+  llvm::Value* reg_32_;
+  llvm::Value* reg_64_;
+  llvm::Value* reg_obj_;
 };
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 2781598..f76f57b 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 "dalvik_reg.h"
 #include "inferred_reg_category_map.h"
 #include "ir_builder.h"
 #include "logging.h"
@@ -63,6 +64,7 @@
     irb_(*cunit->GetIRBuilder()),
     func_(NULL),
     regs_(code_item_->registers_size_),
+    shadow_frame_entries_(code_item_->registers_size_),
     reg_to_shadow_frame_index_(code_item_->registers_size_, -1),
     retval_reg_(NULL),
     basic_block_stack_overflow_(NULL),
@@ -170,18 +172,29 @@
   irb_.SetInsertPoint(basic_block_alloca_);
   jvalue_temp_ = irb_.CreateAlloca(irb_.getJValueTy());
 
-  // Create register array
-  for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
-    regs_[r] = DalvikReg::CreateLocalVarReg(*this, r);
-  }
-
-  retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
-
   // Create Shadow Frame
   if (method_info_.need_shadow_frame) {
     EmitPrologueAllocShadowFrame();
   }
 
+  // Create register array
+  for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
+    std::string name;
+#if !defined(NDEBUG)
+    name = StringPrintf("%u", r);
+#endif
+    regs_[r] = new DalvikReg(*this, name);
+
+    // Cache shadow frame entry address
+    shadow_frame_entries_[r] = GetShadowFrameEntry(r);
+  }
+
+  std::string name;
+#if !defined(NDEBUG)
+  name = "_res";
+#endif
+  retval_reg_.reset(new DalvikReg(*this, name));
+
   // Store argument to dalvik register
   irb_.SetInsertPoint(basic_block_reg_arg_init_);
   EmitPrologueAssignArgRegister();
@@ -324,13 +337,13 @@
   ++arg_iter; // skip method object
 
   if (!oat_compilation_unit_->IsStatic()) {
-    EmitStoreDalvikReg(arg_reg, kObject, kAccurate, arg_iter);
+    regs_[arg_reg]->SetValue(kObject, kAccurate, arg_iter);
     ++arg_iter;
     ++arg_reg;
   }
 
   for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
-    EmitStoreDalvikReg(arg_reg, shorty[i], kAccurate, arg_iter);
+    regs_[arg_reg]->SetValue(shorty[i], kAccurate, arg_iter);
 
     ++arg_reg;
     if (shorty[i] == 'J' || shorty[i] == 'D') {
@@ -3876,14 +3889,13 @@
 }
 
 
-llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
-                                                    uint32_t reg_idx) {
+llvm::Value* MethodCompiler::AllocDalvikReg(RegCategory cat, const std::string& name) {
   // Get reg_type and reg_name from DalvikReg
   llvm::Type* reg_type = DalvikReg::GetRegCategoryEquivSizeTy(irb_, cat);
   std::string reg_name;
 
 #if !defined(NDEBUG)
-  StringAppendF(&reg_name, "%c%u", DalvikReg::GetRegCategoryNamePrefix(cat), reg_idx);
+  StringAppendF(&reg_name, "%c%s", DalvikReg::GetRegCategoryNamePrefix(cat), name.c_str());
 #endif
 
   // Save current IR builder insert point
@@ -3901,7 +3913,7 @@
 }
 
 
-llvm::Value* MethodCompiler::AllocShadowFrameEntry(uint32_t reg_idx) {
+llvm::Value* MethodCompiler::GetShadowFrameEntry(uint32_t reg_idx) {
   if (reg_to_shadow_frame_index_[reg_idx] == -1) {
     // This register dosen't need ShadowFrame entry
     return NULL;
@@ -3914,7 +3926,7 @@
   std::string reg_name;
 
 #if !defined(NDEBUG)
-  StringAppendF(&reg_name, "o%u", reg_idx);
+  StringAppendF(&reg_name, "s%u", reg_idx);
 #endif
 
   // Save current IR builder insert point
@@ -3938,30 +3950,6 @@
 }
 
 
-llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
-  // Get reg_type and reg_name from DalvikReg
-  llvm::Type* reg_type = DalvikReg::GetRegCategoryEquivSizeTy(irb_, cat);
-  std::string reg_name;
-
-#if !defined(NDEBUG)
-  StringAppendF(&reg_name, "%c_res", DalvikReg::GetRegCategoryNamePrefix(cat));
-#endif
-
-  // Save current IR builder insert point
-  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
-  irb_.SetInsertPoint(basic_block_alloca_);
-
-  // Alloca
-  llvm::Value* reg_addr = irb_.CreateAlloca(reg_type, 0, reg_name);
-
-  // Restore IRBuilder insert point
-  irb_.restoreIP(irb_ip_original);
-
-  DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
-  return reg_addr;
-}
-
-
 void MethodCompiler::EmitPopShadowFrame() {
   if (!method_info_.need_shadow_frame) {
     return;
@@ -3981,6 +3969,48 @@
 }
 
 
+llvm::Value* MethodCompiler::EmitLoadDalvikReg(uint32_t reg_idx, JType jty,
+                                               JTypeSpace space) {
+  return regs_[reg_idx]->GetValue(jty, space);
+}
+
+llvm::Value* MethodCompiler::EmitLoadDalvikReg(uint32_t reg_idx, char shorty,
+                                               JTypeSpace space) {
+  return EmitLoadDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space);
+}
+
+void MethodCompiler::EmitStoreDalvikReg(uint32_t reg_idx, JType jty,
+                                        JTypeSpace space, llvm::Value* new_value) {
+  regs_[reg_idx]->SetValue(jty, space, new_value);
+  if (jty == kObject && shadow_frame_entries_[reg_idx] != NULL) {
+    irb_.CreateStore(new_value, shadow_frame_entries_[reg_idx], kTBAAShadowFrame);
+  }
+}
+
+void MethodCompiler::EmitStoreDalvikReg(uint32_t reg_idx, char shorty,
+                                        JTypeSpace space, llvm::Value* new_value) {
+  EmitStoreDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space, new_value);
+}
+
+llvm::Value* MethodCompiler::EmitLoadDalvikRetValReg(JType jty, JTypeSpace space) {
+  return retval_reg_->GetValue(jty, space);
+}
+
+llvm::Value* MethodCompiler::EmitLoadDalvikRetValReg(char shorty, JTypeSpace space) {
+  return EmitLoadDalvikRetValReg(GetJTypeFromShorty(shorty), space);
+}
+
+void MethodCompiler::EmitStoreDalvikRetValReg(JType jty, JTypeSpace space,
+                                              llvm::Value* new_value) {
+  retval_reg_->SetValue(jty, space, new_value);
+}
+
+void MethodCompiler::EmitStoreDalvikRetValReg(char shorty, JTypeSpace space,
+                                              llvm::Value* new_value) {
+  EmitStoreDalvikRetValReg(GetJTypeFromShorty(shorty), space, new_value);
+}
+
+
 // TODO: Use high-level IR to do this
 bool MethodCompiler::EmitInlineJavaIntrinsic(const std::string& callee_method_name,
                                              const std::vector<llvm::Value*>& args,
@@ -4139,18 +4169,7 @@
       break;
 
     case Instruction::INSTANCE_OF:
-      may_throw_exception = true;
-      if (dec_insn.vA == this_reg_idx) {
-        modify_this = true;
-      }
-      break;
-
     case Instruction::ARRAY_LENGTH:
-      if (dec_insn.vA == this_reg_idx) {
-        modify_this = true;
-      }
-      break;
-
     case Instruction::NEW_INSTANCE:
     case Instruction::NEW_ARRAY:
       may_throw_exception = true;
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 50411a1..6de50ed 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -18,7 +18,6 @@
 #define ART_SRC_COMPILER_LLVM_METHOD_COMPILER_H_
 
 #include "backend_types.h"
-#include "dalvik_reg.h"
 #include "dex_file.h"
 #include "dex_instruction.h"
 #include "invoke_type.h"
@@ -59,6 +58,7 @@
 
 class CompilationUnit;
 class CompilerLLVM;
+class DalvikReg;
 class IRBuilder;
 
 class MethodCompiler {
@@ -81,11 +81,9 @@
 
   // Register helper function
 
-  llvm::Value* AllocDalvikLocalVarReg(RegCategory cat, uint32_t reg_idx);
+  llvm::Value* AllocDalvikReg(RegCategory cat, const std::string& name);
 
-  llvm::Value* AllocShadowFrameEntry(uint32_t reg_idx);
-
-  llvm::Value* AllocDalvikRetValReg(RegCategory cat);
+  llvm::Value* GetShadowFrameEntry(uint32_t reg_idx);
 
 
  private:
@@ -395,43 +393,23 @@
 
   // Register helper function
 
-  llvm::Value* EmitLoadDalvikReg(uint32_t reg_idx, JType jty,
-                                 JTypeSpace space) {
-    return regs_[reg_idx]->GetValue(jty, space);
-  }
+  llvm::Value* EmitLoadDalvikReg(uint32_t reg_idx, JType jty, JTypeSpace space);
 
-  llvm::Value* EmitLoadDalvikReg(uint32_t reg_idx, char shorty,
-                                 JTypeSpace space) {
-    return EmitLoadDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space);
-  }
+  llvm::Value* EmitLoadDalvikReg(uint32_t reg_idx, char shorty, JTypeSpace space);
 
   void EmitStoreDalvikReg(uint32_t reg_idx, JType jty,
-                          JTypeSpace space, llvm::Value* new_value) {
-    regs_[reg_idx]->SetValue(jty, space, new_value);
-  }
+                          JTypeSpace space, llvm::Value* new_value);
 
   void EmitStoreDalvikReg(uint32_t reg_idx, char shorty,
-                          JTypeSpace space, llvm::Value* new_value) {
-    EmitStoreDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space, new_value);
-  }
+                          JTypeSpace space, llvm::Value* new_value);
 
-  llvm::Value* EmitLoadDalvikRetValReg(JType jty, JTypeSpace space) {
-    return retval_reg_->GetValue(jty, space);
-  }
+  llvm::Value* EmitLoadDalvikRetValReg(JType jty, JTypeSpace space);
 
-  llvm::Value* EmitLoadDalvikRetValReg(char shorty, JTypeSpace space) {
-    return EmitLoadDalvikRetValReg(GetJTypeFromShorty(shorty), space);
-  }
+  llvm::Value* EmitLoadDalvikRetValReg(char shorty, JTypeSpace space);
 
-  void EmitStoreDalvikRetValReg(JType jty, JTypeSpace space,
-                                llvm::Value* new_value) {
-    retval_reg_->SetValue(jty, space, new_value);
-  }
+  void EmitStoreDalvikRetValReg(JType jty, JTypeSpace space, llvm::Value* new_value);
 
-  void EmitStoreDalvikRetValReg(char shorty, JTypeSpace space,
-                                llvm::Value* new_value) {
-    EmitStoreDalvikRetValReg(GetJTypeFromShorty(shorty), space, new_value);
-  }
+  void EmitStoreDalvikRetValReg(char shorty, JTypeSpace space, llvm::Value* new_value);
 
   // TODO: Use high-level IR to do this
   bool EmitInlineJavaIntrinsic(const std::string& callee_method_name,
@@ -477,6 +455,7 @@
   llvm::Function* func_;
 
   std::vector<DalvikReg*> regs_;
+  std::vector<llvm::Value*> shadow_frame_entries_;
   std::vector<int32_t> reg_to_shadow_frame_index_;
   UniquePtr<DalvikReg> retval_reg_;