Reduce shadow frame size.

Change-Id: Ifbd5cb38d0666a1f5db1abe7da36ff86a93f87b5
diff --git a/src/compiler_llvm/dalvik_reg.cc b/src/compiler_llvm/dalvik_reg.cc
index ab5cc40..84da907 100644
--- a/src/compiler_llvm/dalvik_reg.cc
+++ b/src/compiler_llvm/dalvik_reg.cc
@@ -246,9 +246,7 @@
 void DalvikLocalVarReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
   DalvikReg::SetValue(jty, space, value);
 
-  if (jty == kObject) {
-    DCHECK_NE(reg_shadow_frame_, static_cast<llvm::Value*>(NULL))
-      << "Didn't allocate shadow frame entry.";
+  if (jty == kObject && reg_shadow_frame_ != NULL) {
     irb_.CreateStore(value, reg_shadow_frame_, kTBAAShadowFrame);
   }
 }
diff --git a/src/compiler_llvm/inferred_reg_category_map.cc b/src/compiler_llvm/inferred_reg_category_map.cc
index 04acd6f..2403750 100644
--- a/src/compiler_llvm/inferred_reg_category_map.cc
+++ b/src/compiler_llvm/inferred_reg_category_map.cc
@@ -28,7 +28,7 @@
 
 InferredRegCategoryMap::InferredRegCategoryMap(uint32_t insns_size,
                                                uint8_t regs_size)
-: registers_size_(regs_size), lines_(insns_size, NULL) {
+: registers_size_(regs_size), lines_(insns_size, NULL), can_be_object_(regs_size) {
 }
 
 InferredRegCategoryMap::~InferredRegCategoryMap() {
@@ -55,6 +55,14 @@
   }
 }
 
+bool InferredRegCategoryMap::IsRegCanBeObject(uint16_t reg_idx) const {
+  return can_be_object_[reg_idx];
+}
+
+void InferredRegCategoryMap::SetRegCanBeObject(uint16_t reg_idx) {
+  can_be_object_[reg_idx] = true;
+}
+
 bool InferredRegCategoryMap::
 operator==(InferredRegCategoryMap const& rhs) const {
 
diff --git a/src/compiler_llvm/inferred_reg_category_map.h b/src/compiler_llvm/inferred_reg_category_map.h
index 7b3501b..7f4082d 100644
--- a/src/compiler_llvm/inferred_reg_category_map.h
+++ b/src/compiler_llvm/inferred_reg_category_map.h
@@ -67,6 +67,9 @@
   RegCategory GetRegCategory(uint32_t dex_pc, uint16_t reg_idx) const;
   void SetRegCategory(uint32_t dex_pc, uint16_t reg_idx, RegCategory cat);
 
+  bool IsRegCanBeObject(uint16_t reg_idx) const;
+  void SetRegCanBeObject(uint16_t reg_idx);
+
   bool operator==(InferredRegCategoryMap const& rhs) const;
   bool operator!=(InferredRegCategoryMap const& rhs) const;
 
@@ -75,6 +78,8 @@
 
   std::vector<RegCategoryLine*> lines_;
 
+  std::vector<bool> can_be_object_;
+
   DISALLOW_COPY_AND_ASSIGN(InferredRegCategoryMap);
 };
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index c5606c7..3f3e0ad 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -60,7 +60,11 @@
     access_flags_(oat_compilation_unit->access_flags_),
     module_(cunit->GetModule()),
     context_(cunit->GetLLVMContext()),
-    irb_(*cunit->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
+    irb_(*cunit->GetIRBuilder()),
+    func_(NULL),
+    regs_(code_item_->registers_size_),
+    reg_to_shadow_frame_index_(code_item_->registers_size_, -1),
+    retval_reg_(NULL),
     basic_block_stack_overflow_(NULL),
     basic_block_reg_alloca_(NULL), basic_block_shadow_frame_alloca_(NULL),
     basic_block_reg_arg_init_(NULL),
@@ -165,7 +169,7 @@
 
   // Create register array
   for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
-    regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
+    regs_[r] = DalvikReg::CreateLocalVarReg(*this, r);
   }
 
   retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
@@ -250,10 +254,12 @@
   irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
 
   // Allocate the shadow frame now!
-  uint32_t sirt_size = code_item_->registers_size_;
-  // TODO: registers_size_ is a bad approximation.  Compute a
-  // tighter approximation at Dex verifier while performing data-flow
-  // analysis.
+  uint32_t sirt_size = 0;
+  for (uint32_t i = 0, num_of_regs = code_item_->registers_size_; i < num_of_regs; ++i) {
+    if (IsRegCanBeObject(i)) {
+      reg_to_shadow_frame_index_[i] = sirt_size++;
+    }
+  }
 
   llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
   shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
@@ -2141,10 +2147,7 @@
                     GetNextBasicBlock(dex_pc));
 }
 
-
-RegCategory MethodCompiler::GetInferredRegCategory(uint32_t dex_pc,
-                                                   uint16_t reg_idx) {
-
+InferredRegCategoryMap const* MethodCompiler::GetInferredRegCategoryMap() {
   Compiler::MethodReference mref(dex_file_, method_idx_);
 
   InferredRegCategoryMap const* map =
@@ -2152,9 +2155,22 @@
 
   CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
 
+  return map;
+}
+
+RegCategory MethodCompiler::GetInferredRegCategory(uint32_t dex_pc,
+                                                   uint16_t reg_idx) {
+  InferredRegCategoryMap const* map = GetInferredRegCategoryMap();
+
   return map->GetRegCategory(dex_pc, reg_idx);
 }
 
+bool MethodCompiler::IsRegCanBeObject(uint16_t reg_idx) {
+  InferredRegCategoryMap const* map = GetInferredRegCategoryMap();
+
+  return map->IsRegCanBeObject(reg_idx);
+}
+
 
 llvm::Value* MethodCompiler::EmitConditionResult(llvm::Value* lhs,
                                                  llvm::Value* rhs,
@@ -3839,6 +3855,11 @@
 
 
 llvm::Value* MethodCompiler::AllocShadowFrameEntry(uint32_t reg_idx) {
+  if (reg_to_shadow_frame_index_[reg_idx] == -1) {
+    // This register dosen't need ShadowFrame entry
+    return NULL;
+  }
+
   std::string reg_name;
 
 #if !defined(NDEBUG)
@@ -3853,7 +3874,7 @@
   llvm::Value* gep_index[] = {
     irb_.getInt32(0), // No pointer displacement
     irb_.getInt32(1), // SIRT
-    irb_.getInt32(reg_idx) // Pointer field
+    irb_.getInt32(reg_to_shadow_frame_index_[reg_idx]) // Pointer field
   };
 
   llvm::Value* reg_addr = irb_.CreateGEP(shadow_frame_, gep_index, reg_name);
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index e1465dc..e815e3b 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -374,6 +374,10 @@
 
   RegCategory GetInferredRegCategory(uint32_t dex_pc, uint16_t reg);
 
+  InferredRegCategoryMap const* GetInferredRegCategoryMap();
+
+  bool IsRegCanBeObject(uint16_t reg_idx);
+
 
   // Basic block helper functions
   llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
@@ -453,6 +457,7 @@
   llvm::Function* func_;
 
   std::vector<DalvikReg*> regs_;
+  std::vector<int32_t> reg_to_shadow_frame_index_;
   UniquePtr<DalvikReg> retval_reg_;
 
   llvm::BasicBlock* basic_block_stack_overflow_;