Using gcmap instead of shadow frame.

Fix misuse of TBAAJRuntime & TBAARuntimeInfo. Now, the TBAAJRuntime is
only for runtime support function.

Update DexPC before lock object and suspend.

Change-Id: I40fa37f4863fe6e127328a8413285ee3c62e8505
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 901ec64..b7a2f9c 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -99,6 +99,15 @@
 
   // Constructs a CompiledMethod for the LLVM compiler.
   CompiledMethod(InstructionSet instruction_set,
+                 const std::vector<uint8_t>& code,
+                 const std::vector<uint8_t>& gc_map)
+      : CompiledCode(instruction_set, code),
+        frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
+        fp_spill_mask_(0), native_gc_map_(gc_map) {
+  }
+
+  // Constructs a CompiledMethod for the LLVM JniCompiler.
+  CompiledMethod(InstructionSet instruction_set,
                  const std::vector<uint8_t>& code)
       : CompiledCode(instruction_set, code),
         frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc
index c1d61d4..2c27bb0 100644
--- a/src/compiler/codegen/mir_to_gbc.cc
+++ b/src/compiler/codegen/mir_to_gbc.cc
@@ -544,34 +544,6 @@
   DefineValue(cu, res, rl_dest.orig_sreg);
 }
 
-static void SetShadowFrameEntry(CompilationUnit* cu, llvm::Value* new_val)
-{
-  int index = -1;
-  DCHECK(new_val != NULL);
-  int v_reg = SRegToVReg(cu, GetLoc(cu, new_val).orig_sreg);
-  for (int i = 0; i < cu->num_shadow_frame_entries; i++) {
-    if (cu->shadow_map[i] == v_reg) {
-      index = i;
-      break;
-    }
-  }
-  if (index == -1) {
-    return;
-  }
-  llvm::Type* ty = new_val->getType();
-  greenland::IntrinsicHelper::IntrinsicId id =
-      greenland::IntrinsicHelper::SetShadowFrameEntry;
-  llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id);
-  llvm::Value* table_slot = cu->irb->getInt32(index);
-  // If new_val is a Null pointer, we'll see it here as a const int.  Replace
-  if (!ty->isPointerTy()) {
-    // TODO: assert new_val created w/ dex_lang_const_int(0) or dex_lang_const_float(0)
-    new_val = cu->irb->GetJNull();
-  }
-  llvm::Value* args[] = { new_val, table_slot };
-  cu->irb->CreateCall(func, args);
-}
-
 static void ConvertArithOpLit(CompilationUnit* cu, OpKind op, RegLocation rl_dest,
                               RegLocation rl_src1, int32_t imm)
 {
@@ -633,10 +605,6 @@
   llvm::Value* res = cu->irb->CreateCall(intr, args);
   if (info->result.location != kLocInvalid) {
     DefineValue(cu, res, info->result.orig_sreg);
-    if (info->result.ref) {
-      SetShadowFrameEntry(cu, reinterpret_cast<llvm::Value*>
-                          (cu->llvm_values.elem_list[info->result.orig_sreg]));
-    }
   }
 }
 
@@ -855,8 +823,6 @@
   uint32_t vC = mir->dalvikInsn.vC;
   int opt_flags = mir->optimization_flags;
 
-  bool object_definition = false;
-
   if (cu->verbose) {
     if (op_val < kMirOpFirst) {
       LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" << std::hex << op_val;
@@ -900,9 +866,6 @@
       rl_dest = GetDestWide(cu, mir);
     } else {
       rl_dest = GetDest(cu, mir);
-      if (rl_dest.ref) {
-        object_definition = true;
-      }
     }
   }
 
@@ -935,9 +898,6 @@
     case Instruction::CONST:
     case Instruction::CONST_4:
     case Instruction::CONST_16: {
-        if (vB == 0) {
-          object_definition = true;
-        }
         llvm::Constant* imm_value = cu->irb->GetJInt(vB);
         llvm::Value* res = EmitConst(cu, imm_value, rl_dest);
         DefineValue(cu, res, rl_dest.orig_sreg);
@@ -1662,10 +1622,6 @@
       UNIMPLEMENTED(FATAL) << "Unsupported Dex opcode 0x" << std::hex << opcode;
       res = true;
   }
-  if (object_definition) {
-    SetShadowFrameEntry(cu, reinterpret_cast<llvm::Value*>
-                        (cu->llvm_values.elem_list[rl_dest.orig_sreg]));
-  }
   return res;
 }
 
@@ -3022,7 +2978,6 @@
                 cu->intrinsic_helper->GetIntrinsicId(callee);
             switch (id) {
               case greenland::IntrinsicHelper::AllocaShadowFrame:
-              case greenland::IntrinsicHelper::SetShadowFrameEntry:
               case greenland::IntrinsicHelper::PopShadowFrame:
               case greenland::IntrinsicHelper::SetVReg:
                 // Ignore shadow frame stuff for quick compiler
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 1c04dc8..32f9b51 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -21,11 +21,10 @@
 
 %JavaObject = type opaque
 
-%ShadowFrame = type { %ShadowFrame*        ; Previous frame
+%ShadowFrame = type { i32                  ; Number of VRegs
+                    , %ShadowFrame*        ; Previous frame
                     , %JavaObject*         ; Method object pointer
                     , i32                  ; Line number for stack backtrace
-                    , i32                  ; Number of references
-                    ; [0 x %JavaObject*]   ; References
                     ; [0 x i32]            ; VRegs
                     }
 
@@ -45,7 +44,7 @@
 declare void @art_test_suspend_from_code(%JavaObject*)
 
 declare %ShadowFrame* @art_push_shadow_frame_from_code(%JavaObject*, %ShadowFrame*,
-                                                       %JavaObject*, i16, i16)
+                                                       %JavaObject*, i32)
 declare void @art_pop_shadow_frame_from_code(%ShadowFrame*)
 
 
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index a27ea6e..3524cdd 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -78,75 +78,6 @@
 
 #include <string>
 
-namespace {
-
-// TODO: We may need something to manage these passes.
-// TODO: We need high-level IR to analysis and do this at the IRBuilder level.
-class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
- public:
-  static char ID;
-
-  AddSuspendCheckToLoopLatchPass() : llvm::LoopPass(ID), irb_(NULL) {
-    LOG(FATAL) << "Unexpected instantiation of AddSuspendCheckToLoopLatchPass";
-    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
-    // this constructor won't work because we have no information on
-    // IRBuilder.  Thus, we should place a LOG(FATAL) here.
-  }
-
-  AddSuspendCheckToLoopLatchPass(art::compiler_llvm::IRBuilder* irb)
-    : llvm::LoopPass(ID), irb_(irb) {
-  }
-
-  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
-    AU.addRequired<llvm::LoopInfo>();
-    AU.addRequiredID(llvm::LoopSimplifyID);
-
-    AU.addPreserved<llvm::DominatorTree>();
-    AU.addPreserved<llvm::LoopInfo>();
-    AU.addPreservedID(llvm::LoopSimplifyID);
-    AU.addPreserved<llvm::ScalarEvolution>();
-    AU.addPreservedID(llvm::BreakCriticalEdgesID);
-  }
-
-  virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) {
-    llvm::LoopInfo* loop_info = &getAnalysis<llvm::LoopInfo>();
-
-    CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!";
-    llvm::BasicBlock* bb = loop->getLoopLatch();
-    CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist.";
-
-    llvm::BasicBlock* tb = bb->splitBasicBlock(bb->getTerminator(), "suspend_exit");
-    // Remove unconditional branch which is added by splitBasicBlock.
-    bb->getTerminator()->eraseFromParent();
-
-    irb_->SetInsertPoint(bb);
-    irb_->Runtime().EmitTestSuspend();
-    irb_->CreateBr(tb);
-
-    loop->addBasicBlockToLoop(tb, loop_info->getBase());
-    // EmitTestSuspend() creates some basic blocks. We should add them to using
-    // addBasicBlockToLoop(...) as above.
-    for (llvm::succ_iterator succ_iter = llvm::succ_begin(bb), succ_end = llvm::succ_end(bb);
-         succ_iter != succ_end;
-         succ_iter++) {
-      loop->addBasicBlockToLoop(*succ_iter, loop_info->getBase());
-    }
-
-    return true;
-  }
-
- private:
-  art::compiler_llvm::IRBuilder* irb_;
-};
-
-char AddSuspendCheckToLoopLatchPass::ID = 0;
-
-llvm::RegisterPass<AddSuspendCheckToLoopLatchPass> reg_add_suspend_check_to_loop_latch_pass_(
-  "add-suspend-check-to-loop-latch", "Add suspend check to loop latch pass", false, false);
-
-
-} // end anonymous namespace
-
 namespace art {
 namespace compiler_llvm {
 
@@ -328,30 +259,22 @@
   if (bitcode_filename_.empty()) {
     // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
     // regular FunctionPass.
-#if defined(ART_USE_DEXLANG_FRONTEND)
-    fpm.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
-#elif defined(ART_USE_PORTABLE_COMPILER)
+#if defined(ART_USE_PORTABLE_COMPILER)
     fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
                                   compiler_, oat_compilation_unit_));
 #endif
-    fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
   } else {
-    // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file.
+#if defined(ART_USE_PORTABLE_COMPILER)
     llvm::FunctionPassManager fpm2(module_);
-#if defined(ART_USE_DEXLANG_FRONTEND)
-    fpm2.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
-#elif defined(ART_USE_PORTABLE_COMPILER)
     fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
                                    compiler_, oat_compilation_unit_));
-#endif
-    fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
     fpm2.doInitialization();
     for (llvm::Module::iterator F = module_->begin(), E = module_->end();
          F != E; ++F) {
       fpm2.run(*F);
     }
     fpm2.doFinalization();
-
+#endif
 
     // Write bitcode to file
     std::string errmsg;
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 3ec5e68..7843407 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -31,6 +31,7 @@
 #include "stl_util.h"
 #include "stub_compiler.h"
 #include "utils_llvm.h"
+#include "verifier/method_verifier.h"
 
 #include <llvm/LinkAllPasses.h>
 #include <llvm/LinkAllVMCore.h>
@@ -180,8 +181,10 @@
 
     cunit->Materialize();
 
-    return new CompiledMethod(cunit->GetInstructionSet(),
-                              cunit->GetCompiledCode());
+    Compiler::MethodReference mref(dex_file_, method_idx_);
+    return new CompiledMethod(cunit_->GetInstructionSet(),
+                              cunit_->GetCompiledCode(),
+                              *verifier::MethodVerifier::GetDexGcMap(mref));
   }
 #else
   UniquePtr<MethodCompiler> method_compiler(
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 57a13d5..93d7d48 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -217,9 +217,7 @@
 
   llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
 
-  void Expand_AllocaShadowFrame(llvm::Value* num_entry_value, llvm::Value* num_vregs_value);
-
-  void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
+  void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
 
   void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
 
@@ -710,7 +708,7 @@
   llvm::Value* callee_method_object_field_addr =
     EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
 
-  return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
+  return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
 }
 
 llvm::Value* GBCExpanderPass::
@@ -765,7 +763,27 @@
 }
 
 void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+
+  llvm::Value* suspend_count =
+      irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
+                                              irb_.getInt16Ty(),
+                                              kTBAARuntimeInfo);
+  llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
+
+  llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
+  llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
+
+  irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_suspend);
+  if (dex_pc != art::DexFile::kDexNoIndex) {
+    EmitUpdateDexPC(dex_pc);
+  }
   irb_.Runtime().EmitTestSuspend();
+  irb_.CreateBr(basic_block_cont);
+
+  irb_.SetInsertPoint(basic_block_cont);
   return;
 }
 
@@ -781,7 +799,7 @@
 
   llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
 
-  return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+  return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
 }
 
 llvm::Value*
@@ -792,7 +810,7 @@
   llvm::Value* type_field_addr =
     EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
 
-  return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+  return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
 }
 
 void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
@@ -980,7 +998,7 @@
   llvm::Value* storage_field_addr =
     EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
 
-  return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+  return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
 }
 
 llvm::Value*
@@ -1021,7 +1039,7 @@
     irb_.LoadFromObjectOffset(callee_method_object_addr,
                               art::AbstractMethod::GetCodeOffset().Int32Value(),
                               callee_method_type->getPointerTo(),
-                              kTBAAJRuntime);
+                              kTBAARuntimeInfo);
 
   // Invoke callee
   llvm::Value* retval = irb_.CreateCall(code_addr, args);
@@ -1093,17 +1111,14 @@
   return result;
 }
 
-void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value,
-                                               llvm::Value* num_vregs_value) {
+void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
   // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
   // MethodCompiler::EmitPushShadowFrame
-  uint16_t num_shadow_frame_refs =
-    llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
   uint16_t num_vregs =
     llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
 
   llvm::StructType* shadow_frame_type =
-    irb_.getShadowFrameTy(num_shadow_frame_refs, num_vregs);
+    irb_.getShadowFrameTy(num_vregs);
 
   shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
@@ -1111,26 +1126,14 @@
   old_shadow_frame_ =
     irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
 
-  // Zero-initialization of the shadow frame table
-  llvm::Value* shadow_frame_table =
-    irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
-  llvm::Type* table_type = shadow_frame_type->getElementType(1);
-
-  llvm::ConstantAggregateZero* zero_initializer =
-    llvm::ConstantAggregateZero::get(table_type);
-
-  irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
-
   // Push the shadow frame
   llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
 
-  // Push the shadow frame
   llvm::Value* shadow_frame_upcast =
     irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
 
   llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
                                                  method_object_addr,
-                                                 num_shadow_frame_refs,
                                                  num_vregs);
 
   irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
@@ -1138,34 +1141,13 @@
   return;
 }
 
-// TODO: We will remove ShadowFrameEntry later, so I just copy/paste from ShadowFrameEntry.
-void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
-                                                 llvm::Value* entry_idx) {
-  DCHECK(shadow_frame_ != NULL);
-
-  llvm::Value* gep_index[] = {
-    irb_.getInt32(0), // No pointer displacement
-    irb_.getInt32(1), // SIRT
-    entry_idx // Pointer field
-  };
-
-  llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
-#if defined(ART_USE_PORTABLE_COMPILER)
-  if (obj->getType() != irb_.getJObjectTy()) {
-    obj = irb_.getJNull();
-  }
-#endif
-  irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
-  return;
-}
-
 void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
                                      llvm::Value* value) {
   DCHECK(shadow_frame_ != NULL);
 
   llvm::Value* gep_index[] = {
     irb_.getInt32(0), // No pointer displacement
-    irb_.getInt32(2), // VRegs
+    irb_.getInt32(1), // VRegs
     entry_idx // Pointer field
   };
 
@@ -1560,7 +1542,7 @@
     llvm::Value* type_field_addr =
       EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
 
-    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
 
     if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
       return type_object_addr;
@@ -1625,7 +1607,7 @@
   llvm::Value* storage_field_addr =
     EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
 
-  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
 
   llvm::BasicBlock* block_original = irb_.GetInsertBlock();
 
@@ -1832,7 +1814,7 @@
 
   llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
 
-  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
 
   if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
     llvm::BasicBlock* block_str_exist =
@@ -1905,6 +1887,8 @@
     EmitGuard_NullPointerException(dex_pc, object_addr);
   }
 
+  EmitUpdateDexPC(dex_pc);
+
   irb_.Runtime().EmitLockObject(object_addr);
 
   return;
@@ -2177,7 +2161,7 @@
       irb_.LoadFromObjectOffset(callee_method_object_addr,
                                 art::AbstractMethod::GetCodeOffset().Int32Value(),
                                 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
-                                kTBAAJRuntime);
+                                kTBAARuntimeInfo);
   }
 
   // Invoke callee
@@ -2700,7 +2684,7 @@
       return irb_.Runtime().EmitGetCurrentThread();
     }
     case IntrinsicHelper::CheckSuspend: {
-      // We will add suspend by ourselves.
+      Expand_TestSuspend(call_inst);
       return NULL;
     }
     case IntrinsicHelper::TestSuspend: {
@@ -3478,13 +3462,7 @@
 
     //==- Shadow Frame -----------------------------------------------------==//
     case IntrinsicHelper::AllocaShadowFrame: {
-      Expand_AllocaShadowFrame(call_inst.getArgOperand(0),
-                               call_inst.getArgOperand(1));
-      return NULL;
-    }
-    case IntrinsicHelper::SetShadowFrameEntry: {
-      Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
-                                 call_inst.getArgOperand(1));
+      Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
       return NULL;
     }
     case IntrinsicHelper::SetVReg: {
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index e118646..ef8d6da 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -44,12 +44,12 @@
 StructTy_ShadowFrame = StructType::create(mod->getContext(), "ShadowFrame");
 }
 std::vector<Type*>StructTy_ShadowFrame_fields;
+StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
 PointerType* PointerTy_2 = PointerType::get(StructTy_ShadowFrame, 0);
 
 StructTy_ShadowFrame_fields.push_back(PointerTy_2);
 StructTy_ShadowFrame_fields.push_back(PointerTy_1);
 StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
-StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
 if (StructTy_ShadowFrame->isOpaque()) {
 StructTy_ShadowFrame->setBody(StructTy_ShadowFrame_fields, /*isPacked=*/false);
 }
@@ -93,8 +93,7 @@
 FuncTy_7_args.push_back(PointerTy_1);
 FuncTy_7_args.push_back(PointerTy_2);
 FuncTy_7_args.push_back(PointerTy_1);
-FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
-FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_7 = FunctionType::get(
  /*Result=*/PointerTy_2,
  /*Params=*/FuncTy_7_args,
diff --git a/src/compiler_llvm/ir_builder.cc b/src/compiler_llvm/ir_builder.cc
index b271002..e8e73e3 100644
--- a/src/compiler_llvm/ir_builder.cc
+++ b/src/compiler_llvm/ir_builder.cc
@@ -151,8 +151,8 @@
 }
 
 
-llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_size) {
-  std::string name(StringPrintf("ShadowFrame%u_vreg%u", sirt_size, vreg_size));
+llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t vreg_size) {
+  std::string name(StringPrintf("ShadowFrame%u", vreg_size));
 
   // Try to find the existing struct type definition
   if (llvm::Type* type = module_->getTypeByName(name)) {
@@ -163,7 +163,6 @@
   // Create new struct type definition
   llvm::Type* elem_types[] = {
     art_frame_type_,
-    llvm::ArrayType::get(jobject_type_, sirt_size),
     llvm::ArrayType::get(getInt32Ty(), vreg_size),
   };
 
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index cc0bc8e..4a58515 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -315,7 +315,7 @@
     return getJLongTy();
   }
 
-  llvm::StructType* getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_size);
+  llvm::StructType* getShadowFrameTy(uint32_t vreg_size);
 
 
   //--------------------------------------------------------------------------
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index d5a7869..2a17320 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -101,7 +101,7 @@
   }
 
   // Shadow stack
-  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size, 0);
+  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
   llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
   // Store the dex pc
@@ -113,20 +113,20 @@
   // Push the shadow frame
   llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
   llvm::Value* old_shadow_frame =
-      irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr, sirt_size, 0);
+      irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr, sirt_size);
 
   // Get JNIEnv
   llvm::Value* jni_env_object_addr =
       irb_.Runtime().EmitLoadFromThreadOffset(Thread::JniEnvOffset().Int32Value(),
                                               irb_.getJObjectTy(),
-                                              kTBAAJRuntime);
+                                              kTBAARuntimeInfo);
 
   // Get callee code_addr
   llvm::Value* code_addr =
       irb_.LoadFromObjectOffset(method_object_addr,
                                 AbstractMethod::NativeMethodOffset().Int32Value(),
                                 GetFunctionType(method_idx_, is_static, true)->getPointerTo(),
-                                kTBAAJRuntime);
+                                kTBAARuntimeInfo);
 
   // Load actual parameters
   std::vector<llvm::Value*> args;
@@ -145,7 +145,8 @@
 
   // Store the "this object or class object" to SIRT
   gep_index[2] = irb_.getInt32(sirt_member_index++);
-  llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+  llvm::Value* sirt_field_addr = irb_.CreateBitCast(irb_.CreateGEP(shadow_frame_, gep_index),
+                                                    irb_.getJObjectTy()->getPointerTo());
   irb_.CreateStore(this_object_or_class_object, sirt_field_addr, kTBAAShadowFrame);
   // Push the "this object or class object" to out args
   this_object_or_class_object = irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy());
@@ -155,7 +156,8 @@
     if (arg_iter->getType() == irb_.getJObjectTy()) {
       // Store the reference type arguments to SIRT
       gep_index[2] = irb_.getInt32(sirt_member_index++);
-      llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+      llvm::Value* sirt_field_addr = irb_.CreateBitCast(irb_.CreateGEP(shadow_frame_, gep_index),
+                                                        irb_.getJObjectTy()->getPointerTo());
       irb_.CreateStore(arg_iter, sirt_field_addr, kTBAAShadowFrame);
       // Note null is placed in the SIRT but the jobject passed to the native code must be null
       // (not a pointer into the SIRT as with regular references).
diff --git a/src/compiler_llvm/md_builder.cc b/src/compiler_llvm/md_builder.cc
index f5232aa..038e133 100644
--- a/src/compiler_llvm/md_builder.cc
+++ b/src/compiler_llvm/md_builder.cc
@@ -39,8 +39,10 @@
     case kTBAAHeapInstance: spec_ty = createTBAANode("HeapInstance", tbaa_root_); break;
     case kTBAAHeapStatic:   spec_ty = createTBAANode("HeapStatic", tbaa_root_); break;
     case kTBAAJRuntime:     spec_ty = createTBAANode("JRuntime", tbaa_root_); break;
-    case kTBAARuntimeInfo:  spec_ty = createTBAANode("RuntimeInfo", tbaa_root_); break;
-    case kTBAAShadowFrame:  spec_ty = createTBAANode("ShadowFrame", tbaa_root_); break;
+    case kTBAARuntimeInfo:  spec_ty = createTBAANode("RuntimeInfo",
+                                                     GetTBAASpecialType(kTBAAJRuntime)); break;
+    case kTBAAShadowFrame:  spec_ty = createTBAANode("ShadowFrame",
+                                                     GetTBAASpecialType(kTBAAJRuntime)); break;
     case kTBAAConstJObject: spec_ty = createTBAANode("ConstJObject", tbaa_root_, true); break;
     default:
       LOG(FATAL) << "Unknown TBAA special type: " << sty_id;
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index f09553c..68121de 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -60,8 +60,6 @@
     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_alloca_(NULL), basic_block_shadow_frame_(NULL),
     basic_block_reg_arg_init_(NULL),
@@ -69,7 +67,7 @@
     basic_block_landing_pads_(code_item_->tries_size_, NULL),
     basic_block_unwind_(NULL),
     shadow_frame_(NULL), old_shadow_frame_(NULL),
-    already_pushed_shadow_frame_(NULL), num_shadow_frame_refs_(0) {
+    already_pushed_shadow_frame_(NULL) {
 }
 
 
@@ -176,9 +174,6 @@
     name = StringPrintf("%u", r);
 #endif
     regs_[r] = new DalvikReg(*this, name, GetVRegEntry(r));
-
-    // Cache shadow frame entry address
-    shadow_frame_entries_[r] = GetShadowFrameEntry(r);
   }
 
   std::string name;
@@ -256,7 +251,9 @@
     EmitStackOverflowCheck();
   }
   // Garbage collection safe-point
-  EmitGuard_GarbageCollectionSuspend();
+  if (method_info_.has_invoke) {
+    EmitGuard_GarbageCollectionSuspend(DexFile::kDexNoIndex);
+  }
   irb_.CreateBr(basic_block_shadow_frame_);
 
   irb_.SetInsertPoint(basic_block_shadow_frame_);
@@ -268,24 +265,7 @@
   irb_.SetInsertPoint(basic_block_alloca_);
 
   // Allocate the shadow frame now!
-  num_shadow_frame_refs_ = 0;
-  uint16_t arg_reg_start = code_item_->registers_size_ - code_item_->ins_size_;
-  if (method_info_.need_shadow_frame_entry) {
-    for (uint32_t i = 0, num_of_regs = code_item_->registers_size_; i < num_of_regs; ++i) {
-      if (i >= arg_reg_start && !method_info_.set_to_another_object[i]) {
-        // If we don't set argument registers to another object, we don't need the shadow frame
-        // entry for it. Because the arguments must have been in the caller's shadow frame.
-        continue;
-      }
-
-      if (IsRegCanBeObject(i)) {
-        reg_to_shadow_frame_index_[i] = num_shadow_frame_refs_++;
-      }
-    }
-  }
-
-  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(num_shadow_frame_refs_,
-                                                              code_item_->registers_size_);
+  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(code_item_->registers_size_);
   shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
   // Alloca a pointer to old shadow frame
@@ -293,15 +273,6 @@
 
   irb_.SetInsertPoint(basic_block_shadow_frame_);
 
-  // Zero-initialization of the shadow frame table
-  llvm::Value* shadow_frame_table = irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
-  llvm::Type* table_type = shadow_frame_type->getElementType(1);
-
-  llvm::ConstantAggregateZero* zero_initializer =
-    llvm::ConstantAggregateZero::get(table_type);
-
-  irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
-
   // Lazy pushing shadow frame
   if (method_info_.lazy_push_shadow_frame) {
     irb_.SetInsertPoint(basic_block_alloca_);
@@ -1375,7 +1346,7 @@
 
   llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
 
-  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
 
   if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
     llvm::BasicBlock* block_str_exist =
@@ -1444,7 +1415,7 @@
     llvm::Value* type_field_addr =
       EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
 
-    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
 
     if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
       return type_object_addr;
@@ -1523,6 +1494,8 @@
     EmitGuard_NullPointerException(dex_pc, object_addr);
   }
 
+  EmitUpdateDexPC(dex_pc);
+
   irb_.Runtime().EmitLockObject(object_addr);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
@@ -1914,6 +1887,11 @@
 
   int32_t branch_offset = dec_insn.vA;
 
+  if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
+    // Garbage collection safe-point on backward branch
+    EmitGuard_GarbageCollectionSuspend(dex_pc);
+  }
+
   irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
 }
 
@@ -2044,6 +2022,11 @@
 
   int32_t branch_offset = dec_insn.vC;
 
+  if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
+    // Garbage collection safe-point on backward branch
+    EmitGuard_GarbageCollectionSuspend(dex_pc);
+  }
+
   llvm::Value* src1_value;
   llvm::Value* src2_value;
 
@@ -2105,6 +2088,11 @@
 
   int32_t branch_offset = dec_insn.vB;
 
+  if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
+    // Garbage collection safe-point on backward branch
+    EmitGuard_GarbageCollectionSuspend(dex_pc);
+  }
+
   llvm::Value* src1_value;
   llvm::Value* src2_value;
 
@@ -2145,12 +2133,6 @@
   return map->GetRegCategory(dex_pc, reg_idx);
 }
 
-bool MethodCompiler::IsRegCanBeObject(uint16_t reg_idx) {
-  const greenland::InferredRegCategoryMap* map = GetInferredRegCategoryMap();
-
-  return map->IsRegCanBeObject(reg_idx);
-}
-
 
 llvm::Value* MethodCompiler::EmitConditionResult(llvm::Value* lhs,
                                                  llvm::Value* rhs,
@@ -2442,7 +2424,7 @@
   llvm::Value* storage_field_addr =
     EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
 
-  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
 
   llvm::BasicBlock* block_original = irb_.GetInsertBlock();
 
@@ -2809,7 +2791,7 @@
       irb_.LoadFromObjectOffset(callee_method_object_addr,
                                 AbstractMethod::GetCodeOffset().Int32Value(),
                                 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
-                                kTBAAJRuntime);
+                                kTBAARuntimeInfo);
   }
 
   // Invoke callee
@@ -2835,7 +2817,7 @@
   llvm::Value* callee_method_object_field_addr =
     EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
 
-  return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
+  return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
 }
 
 
@@ -3529,8 +3511,10 @@
 
   cunit_->Materialize();
 
+  Compiler::MethodReference mref(dex_file_, method_idx_);
   return new CompiledMethod(cunit_->GetInstructionSet(),
-                            cunit_->GetCompiledCode());
+                            cunit_->GetCompiledCode(),
+                            *verifier::MethodVerifier::GetDexGcMap(mref));
 }
 
 
@@ -3570,13 +3554,26 @@
 }
 
 
-void MethodCompiler::EmitGuard_GarbageCollectionSuspend() {
-  // Loop suspend will be added by our llvm pass.
-  if (!method_info_.has_invoke) {
-    return;
-  }
+void MethodCompiler::EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc) {
+  llvm::Value* suspend_count =
+      irb_.Runtime().EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
+                                              irb_.getInt16Ty(),
+                                              kTBAARuntimeInfo);
+  llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
 
+  llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
+  llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
+
+  irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_suspend);
+  if (dex_pc != DexFile::kDexNoIndex) {
+    EmitUpdateDexPC(dex_pc);
+  }
   irb_.Runtime().EmitTestSuspend();
+  irb_.CreateBr(basic_block_cont);
+
+  irb_.SetInsertPoint(basic_block_cont);
 }
 
 
@@ -3766,49 +3763,7 @@
 }
 
 
-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;
-  }
-
-  if (!method_info_.need_shadow_frame_entry) {
-    return NULL;
-  }
-
-  std::string reg_name;
-
-#if !defined(NDEBUG)
-  StringAppendF(&reg_name, "s%u", reg_idx);
-#endif
-
-  // Save current IR builder insert point
-  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
-
-  irb_.SetInsertPoint(basic_block_shadow_frame_);
-
-  llvm::Value* gep_index[] = {
-    irb_.getInt32(0), // No pointer displacement
-    irb_.getInt32(1), // SIRT
-    irb_.getInt32(reg_to_shadow_frame_index_[reg_idx]) // Pointer field
-  };
-
-  llvm::Value* reg_addr = irb_.CreateGEP(shadow_frame_, gep_index, reg_name);
-
-  // Restore IRBuilder insert point
-  irb_.restoreIP(irb_ip_original);
-
-  DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
-  return reg_addr;
-}
-
-
-// TODO: We will remove ShadowFrameEntry later, so I just copy/paste from ShadowFrameEntry.
 llvm::Value* MethodCompiler::GetVRegEntry(uint32_t reg_idx) {
-  if (!compiler_->IsDebuggingSupported()) {
-    return NULL;
-  }
-
   if (!method_info_.need_shadow_frame_entry) {
     return NULL;
   }
@@ -3826,7 +3781,7 @@
 
   llvm::Value* gep_index[] = {
     irb_.getInt32(0), // No pointer displacement
-    irb_.getInt32(2), // VRegs
+    irb_.getInt32(1), // VRegs
     irb_.getInt32(reg_idx) // Pointer field
   };
 
@@ -3857,12 +3812,9 @@
   llvm::Value* result;
   if (is_inline) {
     result = irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr,
-                                                num_shadow_frame_refs_,
                                                 code_item_->registers_size_);
   } else {
-    DCHECK(num_shadow_frame_refs_ == 0);
     result = irb_.Runtime().EmitPushShadowFrameNoInline(shadow_frame_upcast, method_object_addr,
-                                                        num_shadow_frame_refs_,
                                                         code_item_->registers_size_);
   }
   irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
@@ -3932,9 +3884,6 @@
 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,
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 02c3d6a..f67866a 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -289,7 +289,7 @@
 
   void EmitBranchExceptionLandingPad(uint32_t dex_pc);
 
-  void EmitGuard_GarbageCollectionSuspend();
+  void EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc);
 
   llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
                                           llvm::Value* cmp_lt);
@@ -461,9 +461,7 @@
   llvm::Function* func_;
 
   std::vector<DalvikReg*> regs_;
-  std::vector<llvm::Value*> shadow_frame_entries_;
   std::vector<llvm::Value*> vregs_;
-  std::vector<int32_t> reg_to_shadow_frame_index_;
   UniquePtr<DalvikReg> retval_reg_;
 
   llvm::BasicBlock* basic_block_alloca_;
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index dbcbe89..169f8e8 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -86,8 +86,8 @@
 /* ShadowFrame */
 
 llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
-                                                        llvm::Value* method, uint16_t num_refs,
-                                                        uint16_t num_vregs) {
+                                                        llvm::Value* method,
+                                                        uint32_t num_vregs) {
   Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                                                      irb_.getArtFrameTy()->getPointerTo(),
                                                      kTBAARuntimeInfo);
@@ -101,16 +101,10 @@
                            method,
                            kTBAAShadowFrame);
 
-  // Store the number of the reference slots
-  irb_.StoreToObjectOffset(new_shadow_frame,
-                           ShadowFrame::NumberOfReferencesOffset(),
-                           irb_.getInt16(num_refs),
-                           kTBAAShadowFrame);
-
   // Store the number of vregs
   irb_.StoreToObjectOffset(new_shadow_frame,
                            ShadowFrame::NumberOfVRegsOffset(),
-                           irb_.getInt16(num_vregs),
+                           irb_.getInt32(num_vregs),
                            kTBAAShadowFrame);
 
   // Store the link to previous shadow frame
@@ -124,16 +118,15 @@
 
 llvm::Value*
 RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
-                                                   llvm::Value* method, uint16_t num_refs,
-                                                   uint16_t num_vregs) {
+                                                   llvm::Value* method,
+                                                   uint32_t num_vregs) {
   Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
   llvm::CallInst* call_inst =
-      irb_.CreateCall5(func,
+      irb_.CreateCall4(func,
                        EmitGetCurrentThread(),
                        new_shadow_frame,
                        method,
-                       irb_.getInt16(num_refs),
-                       irb_.getInt16(num_vregs));
+                       irb_.getInt32(num_vregs));
   irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
   return call_inst;
 }
@@ -156,7 +149,7 @@
 llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
   Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
                                               irb_.getJObjectTy(),
-                                              kTBAAJRuntime);
+                                              kTBAARuntimeInfo);
   // If exception not null
   return irb_.CreateIsNotNull(exception);
 }
@@ -166,22 +159,8 @@
 
 void RuntimeSupportBuilder::EmitTestSuspend() {
   Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
-  Value* suspend_count = EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
-                                                  irb_.getInt16Ty(),
-                                                  kTBAARuntimeInfo);
-  Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
-
-  Function* parent_func = irb_.GetInsertBlock()->getParent();
-  BasicBlock* basic_block_suspend = BasicBlock::Create(context_, "suspend", parent_func);
-  BasicBlock* basic_block_cont = BasicBlock::Create(context_, "suspend_cont", parent_func);
-  irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
-
-  irb_.SetInsertPoint(basic_block_suspend);
   CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
-  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
-  irb_.CreateBr(basic_block_cont);
-
-  irb_.SetInsertPoint(basic_block_cont);
+  irb_.SetTBAA(call_inst, kTBAAJRuntime);
 }
 
 
diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h
index ba512af..58f01f6 100644
--- a/src/compiler_llvm/runtime_support_builder.h
+++ b/src/compiler_llvm/runtime_support_builder.h
@@ -51,9 +51,9 @@
 
   /* ShadowFrame */
   virtual llvm::Value* EmitPushShadowFrame(llvm::Value* new_shadow_frame,
-                                       llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
+                                           llvm::Value* method, uint32_t num_vregs);
   virtual llvm::Value* EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
-                                       llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
+                                                   llvm::Value* method, uint32_t num_vregs);
   virtual void EmitPopShadowFrame(llvm::Value* old_shadow_frame);
 
   /* Exception */
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 3cdd532..7d73249 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -90,11 +90,9 @@
 }
 
 ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
-                                             AbstractMethod* method, uint16_t num_refs,
-                                             uint16_t num_vregs) {
+                                             AbstractMethod* method, uint32_t num_vregs) {
   ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
   new_shadow_frame->SetMethod(method);
-  new_shadow_frame->SetNumberOfReferences(num_refs);
   new_shadow_frame->SetNumberOfVRegs(num_vregs);
   return old_frame;
 }
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index c52b7f9..6c133c9 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -26,8 +26,7 @@
 //----------------------------------------------------------------------------
 
 ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
-                                             AbstractMethod* method, uint16_t num_refs,
-                                             uint16_t num_vregs);
+                                             AbstractMethod* method, uint32_t num_vregs);
 
 void art_pop_shadow_frame_from_code(void*);
 
diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc
index 4854c9f..4571f58 100644
--- a/src/compiler_llvm/stub_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -148,7 +148,7 @@
     irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
                        accurate_func_type->getPointerTo()->getPointerTo());
 
-  llvm::Value* code_addr = irb_.CreateLoad(code_field_addr, kTBAAJRuntime);
+  llvm::Value* code_addr = irb_.CreateLoad(code_field_addr, kTBAARuntimeInfo);
 
   llvm::CallInst* retval = irb_.CreateCall(code_addr, args);
 #if defined(ART_USE_PORTABLE_COMPILER)
diff --git a/src/greenland/inferred_reg_category_map.cc b/src/greenland/inferred_reg_category_map.cc
index 86c855c..0c31634 100644
--- a/src/greenland/inferred_reg_category_map.cc
+++ b/src/greenland/inferred_reg_category_map.cc
@@ -27,7 +27,7 @@
 
 InferredRegCategoryMap::InferredRegCategoryMap(uint32_t insns_size,
                                                uint16_t regs_size)
-: registers_size_(regs_size), can_be_object_(regs_size) {
+: registers_size_(regs_size) {
 }
 
 InferredRegCategoryMap::~InferredRegCategoryMap() {
@@ -54,14 +54,6 @@
   }
 }
 
-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/greenland/inferred_reg_category_map.h b/src/greenland/inferred_reg_category_map.h
index b48dcee..b354097 100644
--- a/src/greenland/inferred_reg_category_map.h
+++ b/src/greenland/inferred_reg_category_map.h
@@ -63,9 +63,6 @@
   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;
 
@@ -74,8 +71,6 @@
 
   SafeMap<uint32_t, RegCategoryLine*> lines_;
 
-  std::vector<bool> can_be_object_;
-
   DISALLOW_COPY_AND_ASSIGN(InferredRegCategoryMap);
 };
 
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index 57faf4c..e6e3ec2 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -1546,14 +1546,7 @@
                           dex_lang_alloca_shadow_frame,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG2(kInt32ConstantTy, kInt32ConstantTy))
-
-// void dex_lang_set_shadow_frame_entry(JavaObject* obj, int entry_idx)
-_EVAL_DEF_INTRINSICS_FUNC(SetShadowFrameEntry,
-                          dex_lang_set_shadow_frame_entry,
-                          kAttrNoThrow,
-                          kVoidTy,
-                          _EXPAND_ARG2(kJavaObjectTy, kInt32ConstantTy))
+                          _EXPAND_ARG1(kInt32ConstantTy))
 
 // void dex_lang_set_vreg(int entry_idx, ...)
 _EVAL_DEF_INTRINSICS_FUNC(SetVReg,
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 8c217c7..5aa4c2d 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -377,7 +377,7 @@
   if (type == kStatic) {
     receiver = NULL;
   } else {
-    receiver = shadow_frame.GetReference(dec_insn.vC);
+    receiver = shadow_frame.GetVRegReference(dec_insn.vC);
     if (UNLIKELY(receiver == NULL)) {
       ThrowNullPointerExceptionForMethodAccess(shadow_frame.GetMethod(), dec_insn.vB, type);
       result->SetJ(0);
@@ -426,7 +426,7 @@
     if (is_static) {
       obj = f->GetDeclaringClass();
     } else {
-      obj = shadow_frame.GetReference(dec_insn.vB);
+      obj = shadow_frame.GetVRegReference(dec_insn.vB);
       if (UNLIKELY(obj == NULL)) {
         ThrowNullPointerExceptionForFieldAccess(f, true);
         return;
@@ -452,7 +452,7 @@
         shadow_frame.SetVRegLong(dec_insn.vA, f->GetLong(obj));
         break;
       case Primitive::kPrimNot:
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, f->GetObject(obj));
+        shadow_frame.SetVRegReference(dec_insn.vA, f->GetObject(obj));
         break;
       default:
         LOG(FATAL) << "Unreachable: " << field_type;
@@ -473,7 +473,7 @@
     if (is_static) {
       obj = f->GetDeclaringClass();
     } else {
-      obj = shadow_frame.GetReference(dec_insn.vB);
+      obj = shadow_frame.GetVRegReference(dec_insn.vB);
       if (UNLIKELY(obj == NULL)) {
         ThrowNullPointerExceptionForFieldAccess(f, false);
         return;
@@ -499,7 +499,7 @@
         f->SetLong(obj, shadow_frame.GetVRegLong(dec_insn.vA));
         break;
       case Primitive::kPrimNot:
-        f->SetObj(obj, shadow_frame.GetReference(dec_insn.vA));
+        f->SetObj(obj, shadow_frame.GetVRegReference(dec_insn.vA));
         break;
       default:
         LOG(FATAL) << "Unreachable: " << field_type;
@@ -567,8 +567,8 @@
       LOG(INFO) << PrettyMethod(shadow_frame.GetMethod())
                 << StringPrintf("\n0x%x: %s\nReferences:",
                                 inst->GetDexPc(insns), inst->DumpString(&mh.GetDexFile()).c_str());
-      for (size_t i = 0; i < shadow_frame.NumberOfReferences(); ++i) {
-        Object* o = shadow_frame.GetReference(i);
+      for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
+        Object* o = shadow_frame.GetVRegReference(i);
         if (o != NULL) {
           if (o->GetClass()->IsStringClass() && o->AsString()->GetCharArray() != NULL) {
             LOG(INFO) << i << ": java.lang.String " << static_cast<void*>(o)
@@ -581,7 +581,7 @@
         }
       }
       LOG(INFO) << "vregs:";
-      for (size_t i = 0; i < shadow_frame.NumberOfReferences(); ++i) {
+      for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
         LOG(INFO) << StringPrintf("%d: %08x", i, shadow_frame.GetVReg(i));
       }
     }
@@ -602,8 +602,7 @@
       case Instruction::MOVE_OBJECT:
       case Instruction::MOVE_OBJECT_FROM16:
       case Instruction::MOVE_OBJECT_16:
-        shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
-        shadow_frame.SetReference(dec_insn.vA, shadow_frame.GetReference(dec_insn.vB));
+        shadow_frame.SetVRegReference(dec_insn.vA, shadow_frame.GetVRegReference(dec_insn.vB));
         break;
       case Instruction::MOVE_RESULT:
         shadow_frame.SetVReg(dec_insn.vA, result_register.GetI());
@@ -612,12 +611,12 @@
         shadow_frame.SetVRegLong(dec_insn.vA, result_register.GetJ());
         break;
       case Instruction::MOVE_RESULT_OBJECT:
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, result_register.GetL());
+        shadow_frame.SetVRegReference(dec_insn.vA, result_register.GetL());
         break;
       case Instruction::MOVE_EXCEPTION: {
         Throwable* exception = self->GetException();
         self->ClearException();
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, exception);
+        shadow_frame.SetVRegReference(dec_insn.vA, exception);
         break;
       }
       case Instruction::RETURN_VOID: {
@@ -639,14 +638,14 @@
       case Instruction::RETURN_OBJECT: {
         JValue result;
         result.SetJ(0);
-        result.SetL(shadow_frame.GetReference(dec_insn.vA));
+        result.SetL(shadow_frame.GetVRegReference(dec_insn.vA));
         return result;
       }
       case Instruction::CONST_4: {
         int32_t val = static_cast<int32_t>(dec_insn.vB << 28) >> 28;
         shadow_frame.SetVReg(dec_insn.vA, val);
         if (val == 0) {
-          shadow_frame.SetReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
         }
         break;
       }
@@ -654,7 +653,7 @@
         int32_t val = static_cast<int16_t>(dec_insn.vB);
         shadow_frame.SetVReg(dec_insn.vA, val);
         if (val == 0) {
-          shadow_frame.SetReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
         }
         break;
       }
@@ -662,7 +661,7 @@
         int32_t val = dec_insn.vB;
         shadow_frame.SetVReg(dec_insn.vA, val);
         if (val == 0) {
-          shadow_frame.SetReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
         }
         break;
       }
@@ -670,7 +669,7 @@
         int32_t val = dec_insn.vB << 16;
         shadow_frame.SetVReg(dec_insn.vA, val);
         if (val == 0) {
-          shadow_frame.SetReference(dec_insn.vA, NULL);
+          shadow_frame.SetVRegReference(dec_insn.vA, NULL);
         }
         break;
       }
@@ -693,16 +692,16 @@
                                                                   true, true);
         }
         String* s = mh.ResolveString(dec_insn.vB);
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, s);
+        shadow_frame.SetVRegReference(dec_insn.vA, s);
         break;
       }
       case Instruction::CONST_CLASS: {
         Class* c = ResolveVerifyAndClinit(dec_insn.vB, shadow_frame.GetMethod(), self, false, true);
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, c);
+        shadow_frame.SetVRegReference(dec_insn.vA, c);
         break;
       }
       case Instruction::MONITOR_ENTER: {
-        Object* obj = shadow_frame.GetReference(dec_insn.vA);
+        Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
         if (UNLIKELY(obj == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
         } else {
@@ -711,7 +710,7 @@
         break;
       }
       case Instruction::MONITOR_EXIT: {
-        Object* obj = shadow_frame.GetReference(dec_insn.vA);
+        Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
         if (UNLIKELY(obj == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
         } else {
@@ -724,7 +723,7 @@
         if (UNLIKELY(c == NULL)) {
           CHECK(self->IsExceptionPending());
         } else {
-          Object* obj = shadow_frame.GetReference(dec_insn.vA);
+          Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
           if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
             self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
                 "%s cannot be cast to %s",
@@ -739,13 +738,13 @@
         if (UNLIKELY(c == NULL)) {
           CHECK(self->IsExceptionPending());
         } else {
-          Object* obj = shadow_frame.GetReference(dec_insn.vB);
+          Object* obj = shadow_frame.GetVRegReference(dec_insn.vB);
           shadow_frame.SetVReg(dec_insn.vA, (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
         }
         break;
       }
       case Instruction::ARRAY_LENGTH:  {
-        Object* array = shadow_frame.GetReference(dec_insn.vB);
+        Object* array = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(array == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -755,13 +754,13 @@
       }
       case Instruction::NEW_INSTANCE: {
         Object* obj = AllocObjectFromCode(dec_insn.vB, shadow_frame.GetMethod(), self, true);
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, obj);
+        shadow_frame.SetVRegReference(dec_insn.vA, obj);
         break;
       }
       case Instruction::NEW_ARRAY: {
         int32_t length = shadow_frame.GetVReg(dec_insn.vB);
         Object* obj = AllocArrayFromCode(dec_insn.vC, shadow_frame.GetMethod(), length, self, true);
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, obj);
+        shadow_frame.SetVRegReference(dec_insn.vA, obj);
         break;
       }
       case Instruction::FILLED_NEW_ARRAY:
@@ -861,7 +860,7 @@
         break;
       }
       case Instruction::THROW: {
-        Throwable* t = shadow_frame.GetReference(dec_insn.vA)->AsThrowable();
+        Throwable* t = shadow_frame.GetVRegReference(dec_insn.vA)->AsThrowable();
         self->DeliverException(t);
         break;
       }
@@ -918,7 +917,7 @@
         break;
       }
       case Instruction::FILL_ARRAY_DATA: {
-        Object* obj = shadow_frame.GetReference(dec_insn.vA);
+        Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
         if (UNLIKELY(obj == NULL)) {
           Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
               "null array in FILL_ARRAY_DATA");
@@ -1024,7 +1023,7 @@
         break;
       }
       case Instruction::AGET_BOOLEAN: {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1034,7 +1033,7 @@
         break;
       }
       case Instruction::AGET_BYTE: {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1044,7 +1043,7 @@
         break;
       }
       case Instruction::AGET_CHAR: {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1054,7 +1053,7 @@
         break;
       }
       case Instruction::AGET_SHORT: {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1064,7 +1063,7 @@
         break;
       }
       case Instruction::AGET: {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1074,7 +1073,7 @@
         break;
       }
       case Instruction::AGET_WIDE:  {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1084,18 +1083,18 @@
         break;
       }
       case Instruction::AGET_OBJECT: {
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, a->AsObjectArray<Object>()->Get(index));
+        shadow_frame.SetVRegReference(dec_insn.vA, a->AsObjectArray<Object>()->Get(index));
         break;
       }
       case Instruction::APUT_BOOLEAN: {
         uint8_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1106,7 +1105,7 @@
       }
       case Instruction::APUT_BYTE: {
         int8_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1117,7 +1116,7 @@
       }
       case Instruction::APUT_CHAR: {
         uint16_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1128,7 +1127,7 @@
       }
       case Instruction::APUT_SHORT: {
         int16_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1139,7 +1138,7 @@
       }
       case Instruction::APUT: {
         int32_t val = shadow_frame.GetVReg(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1150,7 +1149,7 @@
       }
       case Instruction::APUT_WIDE: {
         int64_t val = shadow_frame.GetVRegLong(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1160,8 +1159,8 @@
         break;
       }
       case Instruction::APUT_OBJECT: {
-        Object* val = shadow_frame.GetReference(dec_insn.vA);
-        Object* a = shadow_frame.GetReference(dec_insn.vB);
+        Object* val = shadow_frame.GetVRegReference(dec_insn.vA);
+        Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
@@ -1777,14 +1776,14 @@
   }
   // Set up shadow frame with matching number of reference slots to vregs.
   ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
-  UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs, num_regs,
+  UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs,
                                                           (last_shadow_frame == NULL) ? NULL : last_shadow_frame->GetLink(),
                                                           method, 0));
   self->PushShadowFrame(shadow_frame.get());
   size_t cur_reg = num_regs - num_ins;
   if (!method->IsStatic()) {
     CHECK(receiver != NULL);
-    shadow_frame->SetReferenceAndVReg(cur_reg, receiver);
+    shadow_frame->SetVRegReference(cur_reg, receiver);
     ++cur_reg;
   } else if (!method->GetDeclaringClass()->IsInitializing()) {
     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
@@ -1801,7 +1800,7 @@
     switch (shorty[arg_pos + 1]) {
       case 'L': {
         Object* o = args[arg_pos].GetL();
-        shadow_frame->SetReferenceAndVReg(cur_reg, o);
+        shadow_frame->SetVRegReference(cur_reg, o);
         break;
       }
       case 'J': case 'D':
diff --git a/src/invoke_arg_array_builder.h b/src/invoke_arg_array_builder.h
index 5d4fa5a..16eedfe 100644
--- a/src/invoke_arg_array_builder.h
+++ b/src/invoke_arg_array_builder.h
@@ -148,7 +148,7 @@
           arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(range_start + offset));
           break;
         case 'L':
-          arg_array_[i - 1].SetL(shadow_frame.GetReference(range_start + offset));
+          arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(range_start + offset));
           break;
         case 'D':
           arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(range_start + offset));
@@ -185,7 +185,7 @@
           arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(arg_regs[offset]));
           break;
         case 'L':
-          arg_array_[i - 1].SetL(shadow_frame.GetReference(arg_regs[offset]));
+          arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(arg_regs[offset]));
           break;
         case 'D':
           arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(arg_regs[offset]));
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 382139e..a15c5cf 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -302,7 +302,7 @@
     size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
     gc_map_offset = (gc_map_size == 0) ? 0 : offset;
 
-#if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER)
+#if !defined(NDEBUG)
     // We expect GC maps except when the class hasn't been verified or the method is native
     Compiler::ClassReference class_ref = Compiler::ClassReference(dex_file, class_def_index);
     CompiledClass* compiled_class = compiler_->GetCompiledClass(class_ref);
diff --git a/src/stack.cc b/src/stack.cc
index be737ac..be6fe45 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -24,13 +24,16 @@
 
 namespace art {
 
-size_t ManagedStack::NumShadowFrameReferences() const {
+size_t ManagedStack::NumJniShadowFrameReferences() const {
   size_t count = 0;
   for (const ManagedStack* current_fragment = this; current_fragment != NULL;
        current_fragment = current_fragment->GetLink()) {
     for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL;
          current_frame = current_frame->GetLink()) {
-      count += current_frame->NumberOfReferences();
+      if (current_frame->GetMethod()->IsNative()) {
+        // The JNI ShadowFrame only contains references. (For indirect reference.)
+        count += current_frame->NumberOfVRegs();
+      }
     }
   }
   return count;
diff --git a/src/stack.h b/src/stack.h
index 1134b25..ce84807 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -51,26 +51,34 @@
   kUndefined,
 };
 
+// ShadowFrame has 3 possible layouts: portable (VRegs & references overlap),
+// interpreter (VRegs and separate references array), JNI (just VRegs, but where
+// VRegs really => references).
 class ShadowFrame {
  public:
-  static ShadowFrame* Create(uint16_t num_refs, uint16_t num_vregs, ShadowFrame* link,
+  // Create ShadowFrame for interpreter.
+  static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
                              AbstractMethod* method, uint32_t dex_pc) {
-    size_t sz = sizeof(ShadowFrame) + (sizeof(Object*) * num_refs) + (sizeof(uint32_t) * num_vregs);
+    size_t sz = sizeof(ShadowFrame) +
+                (sizeof(uint32_t) * num_vregs) +
+                (sizeof(Object*) * num_vregs);
     uint8_t* memory = new uint8_t[sz];
-    return new (memory) ShadowFrame(num_refs, num_vregs, link, method, dex_pc);
+    ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
+    return sf;
   }
   ~ShadowFrame() {}
 
-  uint32_t NumberOfReferences() const {
-    return number_of_references_;
+  bool HasReferenceArray() const {
+    return (number_of_vregs_ & kHasReferenceArray) != 0;
   }
 
-  void SetNumberOfReferences(uint16_t number_of_references) {
-    number_of_references_ = number_of_references;
+  uint32_t NumberOfVRegs() const {
+    return number_of_vregs_ & ~kHasReferenceArray;
   }
 
-  void SetNumberOfVRegs(uint16_t number_of_vregs) {
-    number_of_vregs_ = number_of_vregs;
+  void SetNumberOfVRegs(uint32_t number_of_vregs) {
+    DCHECK(number_of_vregs < kHasReferenceArray);
+    number_of_vregs_ = number_of_vregs | (number_of_vregs_ & kHasReferenceArray);
   }
 
   uint32_t GetDexPC() const {
@@ -90,67 +98,68 @@
     link_ = frame;
   }
 
-  Object* GetReference(size_t i) const {
-    DCHECK_LT(i, number_of_references_);
-    return references_[i];
-  }
-
-  void SetReference(size_t i, Object* object) {
-    DCHECK_LT(i, number_of_references_);
-    references_[i] = object;
-  }
-
   int32_t GetVReg(size_t i) const {
-    DCHECK_LT(i, number_of_vregs_);
-    const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
-    return reinterpret_cast<const int32_t*>(vregs)[i];
+    DCHECK_LT(i, NumberOfVRegs());
+    const uint32_t* vreg = &vregs_[i];
+    return *reinterpret_cast<const int32_t*>(vreg);
   }
 
   float GetVRegFloat(size_t i) const {
-    DCHECK_LT(i, number_of_vregs_);
-    const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
-    return reinterpret_cast<const float*>(vregs)[i];
+    DCHECK_LT(i, NumberOfVRegs());
+    // NOTE: Strict-aliasing?
+    const uint32_t* vreg = &vregs_[i];
+    return *reinterpret_cast<const float*>(vreg);
   }
 
   int64_t GetVRegLong(size_t i) const {
-    const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
-    const int32_t* low_half = &reinterpret_cast<const int32_t*>(vregs)[i];
-    return *reinterpret_cast<const int64_t*>(low_half);
+    const uint32_t* vreg = &vregs_[i];
+    return *reinterpret_cast<const int64_t*>(vreg);
   }
 
   double GetVRegDouble(size_t i) const {
-    const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
-    const int32_t* low_half = &reinterpret_cast<const int32_t*>(vregs)[i];
-    return *reinterpret_cast<const double*>(low_half);
+    const uint32_t* vreg = &vregs_[i];
+    return *reinterpret_cast<const double*>(vreg);
+  }
+
+  Object* GetVRegReference(size_t i) const {
+    DCHECK_LT(i, NumberOfVRegs());
+    if (HasReferenceArray()) {
+      return References()[i];
+    } else {
+      const uint32_t* vreg = &vregs_[i];
+      return *reinterpret_cast<Object* const*>(vreg);
+    }
   }
 
   void SetVReg(size_t i, int32_t val) {
-    DCHECK_LT(i, number_of_vregs_);
-    int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
-    reinterpret_cast<int32_t*>(vregs)[i] = val;
+    DCHECK_LT(i, NumberOfVRegs());
+    uint32_t* vreg = &vregs_[i];
+    *reinterpret_cast<int32_t*>(vreg) = val;
   }
 
   void SetVRegFloat(size_t i, float val) {
-    DCHECK_LT(i, number_of_vregs_);
-    int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
-    reinterpret_cast<float*>(vregs)[i] = val;
+    DCHECK_LT(i, NumberOfVRegs());
+    uint32_t* vreg = &vregs_[i];
+    *reinterpret_cast<float*>(vreg) = val;
   }
 
   void SetVRegLong(size_t i, int64_t val) {
-    int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
-    int32_t* low_half = &reinterpret_cast<int32_t*>(vregs)[i];
-    *reinterpret_cast<int64_t*>(low_half) = val;
+    uint32_t* vreg = &vregs_[i];
+    *reinterpret_cast<int64_t*>(vreg) = val;
   }
 
   void SetVRegDouble(size_t i, double val) {
-    int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
-    int32_t* low_half = &reinterpret_cast<int32_t*>(vregs)[i];
-    *reinterpret_cast<double*>(low_half) = val;
+    uint32_t* vreg = &vregs_[i];
+    *reinterpret_cast<double*>(vreg) = val;
   }
 
-  void SetReferenceAndVReg(size_t i, Object* val) {
-    SetReference(i, val);
-    SetVReg(i, reinterpret_cast<int32_t>(val));
+  void SetVRegReference(size_t i, Object* val) {
+    DCHECK_LT(i, NumberOfVRegs());
+    uint32_t* vreg = &vregs_[i];
+    *reinterpret_cast<Object**>(vreg) = val;
+    if (HasReferenceArray()) {
+      References()[i] = val;
+    }
   }
 
   AbstractMethod* GetMethod() const {
@@ -163,19 +172,14 @@
     method_ = method;
   }
 
-  bool Contains(Object** shadow_frame_entry) const {
-    return ((&references_[0] <= shadow_frame_entry) &&
-            (shadow_frame_entry <= (&references_[number_of_references_ - 1])));
-  }
-
-  template <typename Visitor>
-  void VisitRoots(const Visitor& visitor) {
-    size_t num_refs = NumberOfReferences();
-    for (size_t j = 0; j < num_refs; j++) {
-      Object* object = GetReference(j);
-      if (object != NULL) {
-        visitor(object, j);
-      }
+  bool Contains(Object** shadow_frame_entry_obj) const {
+    if (HasReferenceArray()) {
+      return ((&References()[0] <= shadow_frame_entry_obj) &&
+              (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1])));
+    } else {
+      uint32_t* shadow_frame_entry = reinterpret_cast<uint32_t*>(shadow_frame_entry_obj);
+      return ((&vregs_[0] <= shadow_frame_entry) &&
+              (shadow_frame_entry <= (&vregs_[NumberOfVRegs() - 1])));
     }
   }
 
@@ -191,43 +195,48 @@
     return OFFSETOF_MEMBER(ShadowFrame, dex_pc_);
   }
 
-  static size_t NumberOfReferencesOffset() {
-    return OFFSETOF_MEMBER(ShadowFrame, number_of_references_);
-  }
-
   static size_t NumberOfVRegsOffset() {
     return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_);
   }
 
-  static size_t ReferencesOffset() {
-    return OFFSETOF_MEMBER(ShadowFrame, references_);
-  }
-
-  size_t VRegsOffset() const {
-    return ReferencesOffset() + (sizeof(Object*) * NumberOfReferences());
+  static size_t VRegsOffset() {
+    return OFFSETOF_MEMBER(ShadowFrame, vregs_);
   }
 
  private:
-  ShadowFrame(uint16_t num_refs, uint16_t num_vregs, ShadowFrame* link, AbstractMethod* method,
-              uint32_t dex_pc)
-      : number_of_references_ (num_refs), number_of_vregs_(num_vregs), link_(link),
-        method_(method), dex_pc_(dex_pc) {
-    for (size_t i = 0; i < num_refs; ++i) {
-      SetReference(i, NULL);
+  ShadowFrame(uint32_t num_vregs, ShadowFrame* link, AbstractMethod* method, uint32_t dex_pc,
+              bool has_reference_array)
+      : number_of_vregs_(num_vregs), link_(link), method_(method), dex_pc_(dex_pc) {
+    if (has_reference_array) {
+      number_of_vregs_ |= kHasReferenceArray;
+      for (size_t i = 0; i < num_vregs; ++i) {
+        SetVRegReference(i, NULL);
+      }
     }
     for (size_t i = 0; i < num_vregs; ++i) {
       SetVReg(i, 0);
     }
   }
 
+  Object* const* References() const {
+    const uint32_t* vreg_end = &vregs_[NumberOfVRegs()];
+    return reinterpret_cast<Object* const*>(vreg_end);
+  }
+
+  Object** References() {
+    return const_cast<Object**>(const_cast<const ShadowFrame*>(this)->References());
+  }
+
+  enum ShadowFrameFlag {
+    kHasReferenceArray = 1ul << 31
+  };
   // TODO: make the majority of these fields const.
-  uint16_t number_of_references_;
-  uint16_t number_of_vregs_;
+  uint32_t number_of_vregs_;
   // Link to previous shadow frame or NULL.
   ShadowFrame* link_;
   AbstractMethod* method_;
   uint32_t dex_pc_;
-  Object* references_[0];
+  uint32_t vregs_[0];
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame);
 };
@@ -306,7 +315,7 @@
     return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
   }
 
-  size_t NumShadowFrameReferences() const;
+  size_t NumJniShadowFrameReferences() const;
 
   bool ShadowFramesContain(Object** shadow_frame_entry) const;
 
diff --git a/src/thread.cc b/src/thread.cc
index 75d0468..7490d2a 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -52,6 +52,7 @@
 #include "stack_indirect_reference_table.h"
 #include "thread_list.h"
 #include "utils.h"
+#include "verifier/dex_gc_map.h"
 #include "well_known_classes.h"
 
 namespace art {
@@ -1853,8 +1854,39 @@
     }
     ShadowFrame* shadow_frame = GetCurrentShadowFrame();
     if (shadow_frame != NULL) {
-      WrapperVisitor wrapperVisitor(visitor_, this);
-      shadow_frame->VisitRoots(wrapperVisitor);
+      AbstractMethod* m = shadow_frame->GetMethod();
+      size_t num_regs = shadow_frame->NumberOfVRegs();
+      if (m->IsNative() || shadow_frame->HasReferenceArray()) {
+        // SIRT for JNI or References for interpreter.
+        for (size_t reg = 0; reg < num_regs; ++reg) {
+          Object* ref = shadow_frame->GetVRegReference(reg);
+          if (ref != NULL) {
+            visitor_(ref, reg, this);
+          }
+        }
+      } else {
+        // Java method.
+        // Portable path use DexGcMap and store in Method.native_gc_map_.
+        const uint8_t* gc_map = m->GetNativeGcMap();
+        CHECK(gc_map != NULL) << PrettyMethod(m);
+        uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
+                                                       (gc_map[1] << 16) |
+                                                       (gc_map[2] << 8) |
+                                                       (gc_map[3] << 0));
+        verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
+        uint32_t dex_pc = GetDexPc();
+        const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
+        DCHECK(reg_bitmap != NULL);
+        num_regs = std::min(dex_gc_map.RegWidth() * 8, num_regs);
+        for (size_t reg = 0; reg < num_regs; ++reg) {
+          if (TestBitmap(reg, reg_bitmap)) {
+            Object* ref = shadow_frame->GetVRegReference(reg);
+            if (ref != NULL) {
+              visitor_(ref, reg, this);
+            }
+          }
+        }
+      }
     } else {
       AbstractMethod* m = GetMethod();
       // Process register map (which native and runtime methods don't have)
@@ -1903,21 +1935,6 @@
   }
 
  private:
-
-  class WrapperVisitor {
-   public:
-    WrapperVisitor(const RootVisitor& root_visitor, const StackVisitor* stack_visitor)
-      : root_visitor_(root_visitor), stack_visitor_(stack_visitor) {}
-
-    void operator()(const Object* obj, size_t offset) const {
-      root_visitor_(obj, offset, stack_visitor_);
-    }
-
-   private:
-    const RootVisitor& root_visitor_;
-    const StackVisitor* const stack_visitor_;
-  };
-
   static bool TestBitmap(int reg, const uint8_t* reg_vector) {
     return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
   }
diff --git a/src/thread.h b/src/thread.h
index 8b9c81d..7bd64c8 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -524,17 +524,17 @@
                         ManagedStack::TopShadowFrameOffset());
   }
 
-  // Number of references allocated in ShadowFrames on this thread
-  size_t NumShadowFrameReferences() const {
-    return managed_stack_.NumShadowFrameReferences();
+  // Number of references allocated in JNI ShadowFrames on this thread
+  size_t NumJniShadowFrameReferences() const {
+    return managed_stack_.NumJniShadowFrameReferences();
   }
 
   // Number of references in SIRTs on this thread
   size_t NumSirtReferences();
 
-  // Number of references allocated in SIRTs & shadow frames on this thread
+  // Number of references allocated in SIRTs & JNI shadow frames on this thread
   size_t NumStackReferences() {
-    return NumSirtReferences() + NumShadowFrameReferences();
+    return NumSirtReferences() + NumJniShadowFrameReferences();
   };
 
   // Is the given obj in this thread's stack indirect reference table?
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index d6cd665..b96989d 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -979,7 +979,6 @@
   return true;
 }
 
-#if !defined(ART_USE_LLVM_COMPILER)
 static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(const std::vector<uint8_t>& gc_map) {
   std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
   length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
@@ -997,7 +996,6 @@
                                 (length_prefixed_gc_map->at(3) << 0)));
   return length_prefixed_gc_map;
 }
-#endif
 
 bool MethodVerifier::VerifyCodeFlow() {
   uint16_t registers_size = code_item_->registers_size_;
@@ -1029,7 +1027,6 @@
 
   Compiler::MethodReference ref(dex_file_, dex_method_idx_);
 
-#if !defined(ART_USE_LLVM_COMPILER)
 
   /* Generate a register map and add it to the method. */
   UniquePtr<const std::vector<uint8_t> > map(GenerateGcMap());
@@ -1043,13 +1040,13 @@
   const std::vector<uint8_t>* dex_gc_map = CreateLengthPrefixedDexGcMap(*(map.get()));
   verifier::MethodVerifier::SetDexGcMap(ref, *dex_gc_map);
 
-#else  // defined(ART_USE_LLVM_COMPILER)
+#if defined(ART_USE_LLVM_COMPILER)
   /* Generate Inferred Register Category for LLVM-based Code Generator */
   const InferredRegCategoryMap* table = GenerateInferredRegCategoryMap();
   verifier::MethodVerifier::SetInferredRegCategoryMap(ref, *table);
-
 #endif
 
+
   return true;
 }
 
@@ -3498,17 +3495,6 @@
   for (size_t i = 0; i < insns_size; ++i) {
     if (RegisterLine* line = reg_table_.GetLine(i)) {
       const Instruction* inst = Instruction::At(code_item_->insns_ + i);
-
-      // GC points
-      if (inst->IsBranch() || inst->IsInvoke()) {
-        for (size_t r = 0; r < regs_size; ++r) {
-          const RegType &rt = line->GetRegisterType(r);
-          if (rt.IsNonZeroReferenceTypes()) {
-            table->SetRegCanBeObject(r);
-          }
-        }
-      }
-
       /* We only use InferredRegCategoryMap in one case */
       if (inst->IsBranch()) {
         for (size_t r = 0; r < regs_size; ++r) {