am f8bbb844: Add code size to oat files

* commit 'f8bbb8448c733e9e3ad43aad69774c37888329b1':
  Add code size to oat files
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index 1b584d6..bb7b458 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -83,11 +83,11 @@
     libLLVMARMCodeGen \
     libLLVMARMDesc
 
-#  libart_compiler_llvm_mips_STATIC_LIBRARIES := \
-#    libLLVMMipsInfo \
-#    libLLVMMipsCodeGen \
-#    libLLVMMipsDesc \
-#    libLLVMMipsAsmPrinter \
+  libart_compiler_llvm_mips_STATIC_LIBRARIES := \
+    libLLVMMipsInfo \
+    libLLVMMipsCodeGen \
+    libLLVMMipsDesc \
+    libLLVMMipsAsmPrinter \
 
   libart_compiler_llvm_x86_STATIC_LIBRARIES := \
     libLLVMX86Info \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index aa00a31..5bc8f46 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -88,11 +88,11 @@
       libLLVMARMCodeGen \
       libLLVMARMDesc
 
-#    libart_mips_STATIC_LIBRARIES := \
-#      libLLVMMipsInfo \
-#      libLLVMMipsCodeGen \
-#      libLLVMMipsDesc \
-#      libLLVMMipsAsmPrinter \
+    libart_mips_STATIC_LIBRARIES := \
+      libLLVMMipsInfo \
+      libLLVMMipsCodeGen \
+      libLLVMMipsDesc \
+      libLLVMMipsAsmPrinter \
 
     libart_x86_STATIC_LIBRARIES := \
       libLLVMX86Info \
diff --git a/src/asm_support.h b/src/asm_support.h
index 6ba23bc..bcad9ad 100644
--- a/src/asm_support.h
+++ b/src/asm_support.h
@@ -30,7 +30,7 @@
 
 #elif defined(__i386__)
 // Offset of field Thread::self_ verified in InitCpu
-#define THREAD_SELF_OFFSET 108
+#define THREAD_SELF_OFFSET 112
 #endif
 
 #endif  // ART_SRC_ASM_SUPPORT_H_
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 39fbec7..78d388b 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -21,14 +21,14 @@
 
 %JavaObject = type opaque
 
-%ArtFrame = type { %ArtFrame*           ; Previous frame (sirt)
-                 , %JavaObject*         ; Method object pointer
-                 , i32                  ; Line number for stack backtrace
-                 , i32                  ; Size of SIRT
-                 ; [0 x %JavaObject*]   ; Stack indirect reference table
-                 }
+%ShadowFrame = type { %ShadowFrame*        ; Previous frame
+                    , %JavaObject*         ; Method object pointer
+                    , i32                  ; Line number for stack backtrace
+                    , i32                  ; Number of references
+                    ; [0 x %JavaObject*]   ; References
+                    }
 
-declare void @__art_type_list(%JavaObject*, %ArtFrame*)
+declare void @__art_type_list(%JavaObject*, %ShadowFrame*)
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -43,7 +43,7 @@
 
 declare void @art_test_suspend_from_code()
 
-declare void @art_push_shadow_frame_from_code(%ArtFrame*)
+declare void @art_push_shadow_frame_from_code(%ShadowFrame*)
 declare void @art_pop_shadow_frame_from_code()
 
 
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index dedc392..fe708ae 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -39,19 +39,19 @@
 PointerType* PointerTy_1 = PointerType::get(StructTy_JavaObject, 0);
 
 FuncTy_0_args.push_back(PointerTy_1);
-StructType *StructTy_ArtFrame = mod->getTypeByName("ArtFrame");
-if (!StructTy_ArtFrame) {
-StructTy_ArtFrame = StructType::create(mod->getContext(), "ArtFrame");
+StructType *StructTy_ShadowFrame = mod->getTypeByName("ShadowFrame");
+if (!StructTy_ShadowFrame) {
+StructTy_ShadowFrame = StructType::create(mod->getContext(), "ShadowFrame");
 }
-std::vector<Type*>StructTy_ArtFrame_fields;
-PointerType* PointerTy_2 = PointerType::get(StructTy_ArtFrame, 0);
+std::vector<Type*>StructTy_ShadowFrame_fields;
+PointerType* PointerTy_2 = PointerType::get(StructTy_ShadowFrame, 0);
 
-StructTy_ArtFrame_fields.push_back(PointerTy_2);
-StructTy_ArtFrame_fields.push_back(PointerTy_1);
-StructTy_ArtFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
-StructTy_ArtFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
-if (StructTy_ArtFrame->isOpaque()) {
-StructTy_ArtFrame->setBody(StructTy_ArtFrame_fields, /*isPacked=*/false);
+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);
 }
 
 
@@ -142,26 +142,26 @@
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_14_args;
-FuncTy_14_args.push_back(PointerTy_1);
 FuncTy_14_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_14_args.push_back(PointerTy_1);
+FuncTy_14_args.push_back(PointerTy_1);
 FunctionType* FuncTy_14 = FunctionType::get(
  /*Result=*/PointerTy_1,
  /*Params=*/FuncTy_14_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_15_args;
-FuncTy_15_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_15_args.push_back(PointerTy_1);
 FuncTy_15_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_15 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Result=*/PointerTy_1,
  /*Params=*/FuncTy_15_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_16_args;
 FuncTy_16_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_16_args.push_back(PointerTy_1);
-FuncTy_16_args.push_back(IntegerType::get(mod->getContext(), 64));
+FuncTy_16_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_16 = FunctionType::get(
  /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_16_args,
@@ -170,7 +170,7 @@
 std::vector<Type*>FuncTy_17_args;
 FuncTy_17_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_17_args.push_back(PointerTy_1);
-FuncTy_17_args.push_back(PointerTy_1);
+FuncTy_17_args.push_back(IntegerType::get(mod->getContext(), 64));
 FunctionType* FuncTy_17 = FunctionType::get(
  /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_17_args,
@@ -179,6 +179,7 @@
 std::vector<Type*>FuncTy_18_args;
 FuncTy_18_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_18_args.push_back(PointerTy_1);
+FuncTy_18_args.push_back(PointerTy_1);
 FunctionType* FuncTy_18 = FunctionType::get(
  /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_18_args,
@@ -188,17 +189,15 @@
 FuncTy_19_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_19_args.push_back(PointerTy_1);
 FunctionType* FuncTy_19 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_19_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_20_args;
 FuncTy_20_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_20_args.push_back(PointerTy_1);
-FuncTy_20_args.push_back(PointerTy_1);
-FuncTy_20_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_20 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
  /*Params=*/FuncTy_20_args,
  /*isVarArg=*/false);
 
@@ -206,7 +205,7 @@
 FuncTy_21_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_21_args.push_back(PointerTy_1);
 FuncTy_21_args.push_back(PointerTy_1);
-FuncTy_21_args.push_back(IntegerType::get(mod->getContext(), 64));
+FuncTy_21_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_21 = FunctionType::get(
  /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_21_args,
@@ -216,7 +215,7 @@
 FuncTy_22_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_22_args.push_back(PointerTy_1);
 FuncTy_22_args.push_back(PointerTy_1);
-FuncTy_22_args.push_back(PointerTy_1);
+FuncTy_22_args.push_back(IntegerType::get(mod->getContext(), 64));
 FunctionType* FuncTy_22 = FunctionType::get(
  /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_22_args,
@@ -226,8 +225,9 @@
 FuncTy_23_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_23_args.push_back(PointerTy_1);
 FuncTy_23_args.push_back(PointerTy_1);
+FuncTy_23_args.push_back(PointerTy_1);
 FunctionType* FuncTy_23 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_23_args,
  /*isVarArg=*/false);
 
@@ -236,7 +236,7 @@
 FuncTy_24_args.push_back(PointerTy_1);
 FuncTy_24_args.push_back(PointerTy_1);
 FunctionType* FuncTy_24 = FunctionType::get(
- /*Result=*/PointerTy_1,
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
  /*Params=*/FuncTy_24_args,
  /*isVarArg=*/false);
 
@@ -526,7 +526,7 @@
 Function* func_art_find_interface_method_from_code = mod->getFunction("art_find_interface_method_from_code");
 if (!func_art_find_interface_method_from_code) {
 func_art_find_interface_method_from_code = Function::Create(
- /*Type=*/FuncTy_24,
+ /*Type=*/FuncTy_14,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_find_interface_method_from_code", mod); // (external, no body)
 func_art_find_interface_method_from_code->setCallingConv(CallingConv::C);
@@ -537,7 +537,7 @@
 Function* func_art_find_virtual_method_from_code = mod->getFunction("art_find_virtual_method_from_code");
 if (!func_art_find_virtual_method_from_code) {
 func_art_find_virtual_method_from_code = Function::Create(
- /*Type=*/FuncTy_24,
+ /*Type=*/FuncTy_14,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_find_virtual_method_from_code", mod); // (external, no body)
 func_art_find_virtual_method_from_code->setCallingConv(CallingConv::C);
@@ -548,7 +548,7 @@
 Function* func_art_find_super_method_from_code = mod->getFunction("art_find_super_method_from_code");
 if (!func_art_find_super_method_from_code) {
 func_art_find_super_method_from_code = Function::Create(
- /*Type=*/FuncTy_24,
+ /*Type=*/FuncTy_14,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_find_super_method_from_code", mod); // (external, no body)
 func_art_find_super_method_from_code->setCallingConv(CallingConv::C);
@@ -592,7 +592,7 @@
 Function* func_art_resolve_string_from_code = mod->getFunction("art_resolve_string_from_code");
 if (!func_art_resolve_string_from_code) {
 func_art_resolve_string_from_code = Function::Create(
- /*Type=*/FuncTy_14,
+ /*Type=*/FuncTy_15,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_resolve_string_from_code", mod); // (external, no body)
 func_art_resolve_string_from_code->setCallingConv(CallingConv::C);
@@ -603,7 +603,7 @@
 Function* func_art_set32_static_from_code = mod->getFunction("art_set32_static_from_code");
 if (!func_art_set32_static_from_code) {
 func_art_set32_static_from_code = Function::Create(
- /*Type=*/FuncTy_15,
+ /*Type=*/FuncTy_16,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_set32_static_from_code", mod); // (external, no body)
 func_art_set32_static_from_code->setCallingConv(CallingConv::C);
@@ -614,7 +614,7 @@
 Function* func_art_set64_static_from_code = mod->getFunction("art_set64_static_from_code");
 if (!func_art_set64_static_from_code) {
 func_art_set64_static_from_code = Function::Create(
- /*Type=*/FuncTy_16,
+ /*Type=*/FuncTy_17,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_set64_static_from_code", mod); // (external, no body)
 func_art_set64_static_from_code->setCallingConv(CallingConv::C);
@@ -625,7 +625,7 @@
 Function* func_art_set_obj_static_from_code = mod->getFunction("art_set_obj_static_from_code");
 if (!func_art_set_obj_static_from_code) {
 func_art_set_obj_static_from_code = Function::Create(
- /*Type=*/FuncTy_17,
+ /*Type=*/FuncTy_18,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_set_obj_static_from_code", mod); // (external, no body)
 func_art_set_obj_static_from_code->setCallingConv(CallingConv::C);
@@ -636,7 +636,7 @@
 Function* func_art_get32_static_from_code = mod->getFunction("art_get32_static_from_code");
 if (!func_art_get32_static_from_code) {
 func_art_get32_static_from_code = Function::Create(
- /*Type=*/FuncTy_18,
+ /*Type=*/FuncTy_19,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_get32_static_from_code", mod); // (external, no body)
 func_art_get32_static_from_code->setCallingConv(CallingConv::C);
@@ -647,7 +647,7 @@
 Function* func_art_get64_static_from_code = mod->getFunction("art_get64_static_from_code");
 if (!func_art_get64_static_from_code) {
 func_art_get64_static_from_code = Function::Create(
- /*Type=*/FuncTy_19,
+ /*Type=*/FuncTy_20,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_get64_static_from_code", mod); // (external, no body)
 func_art_get64_static_from_code->setCallingConv(CallingConv::C);
@@ -669,7 +669,7 @@
 Function* func_art_set32_instance_from_code = mod->getFunction("art_set32_instance_from_code");
 if (!func_art_set32_instance_from_code) {
 func_art_set32_instance_from_code = Function::Create(
- /*Type=*/FuncTy_20,
+ /*Type=*/FuncTy_21,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_set32_instance_from_code", mod); // (external, no body)
 func_art_set32_instance_from_code->setCallingConv(CallingConv::C);
@@ -680,7 +680,7 @@
 Function* func_art_set64_instance_from_code = mod->getFunction("art_set64_instance_from_code");
 if (!func_art_set64_instance_from_code) {
 func_art_set64_instance_from_code = Function::Create(
- /*Type=*/FuncTy_21,
+ /*Type=*/FuncTy_22,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_set64_instance_from_code", mod); // (external, no body)
 func_art_set64_instance_from_code->setCallingConv(CallingConv::C);
@@ -691,7 +691,7 @@
 Function* func_art_set_obj_instance_from_code = mod->getFunction("art_set_obj_instance_from_code");
 if (!func_art_set_obj_instance_from_code) {
 func_art_set_obj_instance_from_code = Function::Create(
- /*Type=*/FuncTy_22,
+ /*Type=*/FuncTy_23,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_set_obj_instance_from_code", mod); // (external, no body)
 func_art_set_obj_instance_from_code->setCallingConv(CallingConv::C);
@@ -702,7 +702,7 @@
 Function* func_art_get32_instance_from_code = mod->getFunction("art_get32_instance_from_code");
 if (!func_art_get32_instance_from_code) {
 func_art_get32_instance_from_code = Function::Create(
- /*Type=*/FuncTy_17,
+ /*Type=*/FuncTy_18,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_get32_instance_from_code", mod); // (external, no body)
 func_art_get32_instance_from_code->setCallingConv(CallingConv::C);
@@ -713,7 +713,7 @@
 Function* func_art_get64_instance_from_code = mod->getFunction("art_get64_instance_from_code");
 if (!func_art_get64_instance_from_code) {
 func_art_get64_instance_from_code = Function::Create(
- /*Type=*/FuncTy_23,
+ /*Type=*/FuncTy_24,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_get64_instance_from_code", mod); // (external, no body)
 func_art_get64_instance_from_code->setCallingConv(CallingConv::C);
@@ -724,7 +724,7 @@
 Function* func_art_get_obj_instance_from_code = mod->getFunction("art_get_obj_instance_from_code");
 if (!func_art_get_obj_instance_from_code) {
 func_art_get_obj_instance_from_code = Function::Create(
- /*Type=*/FuncTy_24,
+ /*Type=*/FuncTy_14,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_get_obj_instance_from_code", mod); // (external, no body)
 func_art_get_obj_instance_from_code->setCallingConv(CallingConv::C);
diff --git a/src/compiler_llvm/ir_builder.cc b/src/compiler_llvm/ir_builder.cc
index 60f31f2..d38960a 100644
--- a/src/compiler_llvm/ir_builder.cc
+++ b/src/compiler_llvm/ir_builder.cc
@@ -33,7 +33,7 @@
 
   // Get java object type from module
   llvm::Type* jobject_struct_type = module.getTypeByName("JavaObject");
-  CHECK_NE(jobject_struct_type, static_cast<llvm::Type*>(NULL));
+  CHECK(jobject_struct_type != NULL);
   jobject_type_ = jobject_struct_type->getPointerTo();
 
   // Create JEnv* type
@@ -41,8 +41,8 @@
   jenv_type_ = jenv_struct_type->getPointerTo();
 
   // Get Art shadow frame struct type from module
-  art_frame_type_ = module.getTypeByName("ArtFrame");
-  CHECK_NE(art_frame_type_, static_cast<llvm::StructType*>(NULL));
+  art_frame_type_ = module.getTypeByName("ShadowFrame");
+  CHECK(art_frame_type_ != NULL);
 
   // Load the runtime support function declaration from module
   InitRuntimeSupportFuncDecl();
@@ -185,7 +185,7 @@
 
 
 llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t sirt_size) {
-  std::string name(StringPrintf("ArtFrame%u", sirt_size));
+  std::string name(StringPrintf("ShadowFrame%u", sirt_size));
 
   // Try to find the existing struct type definition
   if (llvm::Type* type = module_->getTypeByName(name)) {
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 18e157e..03f4458 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -26,6 +26,7 @@
 #include "object.h"
 #include "object_utils.h"
 #include "runtime_support_func.h"
+#include "shadow_frame.h"
 #include "stl_util.h"
 #include "stringprintf.h"
 #include "utils_llvm.h"
@@ -199,26 +200,25 @@
 
   irb_.CreateStore(zero_initializer, shadow_frame_);
 
-  // Variables for GetElementPtr
-  llvm::Constant* zero = irb_.getInt32(0);
-
-  llvm::Value* gep_index[] = {
-    zero, // No displacement for shadow frame pointer
-    zero, // Get the %ArtFrame data structure
-    NULL,
-  };
-
   // Store the method pointer
-  gep_index[2] = irb_.getInt32(1);
-  llvm::Value* method_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+  llvm::Value* method_field_addr =
+    irb_.CreatePtrDisp(shadow_frame_,
+                       irb_.getPtrEquivInt(ShadowFrame::MethodOffset()),
+                       irb_.getJObjectTy()->getPointerTo());
+
   llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
   irb_.CreateStore(method_object_addr, method_field_addr);
 
   // Store the number of the pointer slots
-  gep_index[2] = irb_.getInt32(3);
-  llvm::Value* size_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
-  llvm::ConstantInt* sirt_size_value = irb_.getInt32(sirt_size);
-  irb_.CreateStore(sirt_size_value, size_field_addr);
+  llvm::ConstantInt* num_of_refs_offset =
+    irb_.getPtrEquivInt(ShadowFrame::NumberOfReferencesOffset());
+
+  llvm::Value* num_of_refs_field_addr =
+    irb_.CreatePtrDisp(shadow_frame_, num_of_refs_offset,
+                       irb_.getJIntTy()->getPointerTo());
+
+  llvm::ConstantInt* num_of_refs_value = irb_.getJInt(sirt_size);
+  irb_.CreateStore(num_of_refs_value, num_of_refs_field_addr);
 
   // Push the shadow frame
   llvm::Value* shadow_frame_upcast =
@@ -3881,15 +3881,11 @@
 
 
 void MethodCompiler::EmitUpdateLineNum(int32_t line_num) {
-  llvm::Constant* zero = irb_.getInt32(0);
+  llvm::Value* line_num_field_addr =
+    irb_.CreatePtrDisp(shadow_frame_,
+                       irb_.getPtrEquivInt(ShadowFrame::LineNumOffset()),
+                       irb_.getJIntTy()->getPointerTo());
 
-  llvm::Value* gep_index[] = {
-    zero, // No displacement for shadow frame pointer
-    zero, // Get the %ArtFrame data structure
-    irb_.getInt32(2),
-  };
-
-  llvm::Value* line_num_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
   llvm::ConstantInt* line_num_value = irb_.getInt32(line_num);
   irb_.CreateStore(line_num_value, line_num_field_addr);
 }
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 013a530..f09d6c1 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -6,6 +6,7 @@
 #include "object_utils.h"
 #include "runtime_support_common.h"
 #include "runtime_support_llvm.h"
+#include "shadow_frame.h"
 #include "thread.h"
 #include "thread_list.h"
 
@@ -49,14 +50,12 @@
 
 void art_push_shadow_frame_from_code(void* new_shadow_frame) {
   Thread* thread = Thread::Current();
-  thread->PushSirt(
-      static_cast<StackIndirectReferenceTable*>(new_shadow_frame)
-                   );
+  thread->PushShadowFrame(static_cast<ShadowFrame*>(new_shadow_frame));
 }
 
 void art_pop_shadow_frame_from_code() {
   Thread* thread = Thread::Current();
-  thread->PopSirt();
+  thread->PopShadowFrame();
 }
 
 
diff --git a/src/dex_instruction_list.h b/src/dex_instruction_list.h
index 8a5b5ad..ed26795 100644
--- a/src/dex_instruction_list.h
+++ b/src/dex_instruction_list.h
@@ -53,7 +53,7 @@
   V(0x23, NEW_ARRAY, "new-array", k22c, true, kTypeRef, kContinue | kThrow, kVerifyRegA | kVerifyRegB | kVerifyRegCNewArray) \
   V(0x24, FILLED_NEW_ARRAY, "filled-new-array", k35c, false, kTypeRef, kContinue | kThrow, kVerifyRegBType | kVerifyVarArg) \
   V(0x25, FILLED_NEW_ARRAY_RANGE, "filled-new-array/range", k3rc, false, kTypeRef, kContinue | kThrow, kVerifyRegBType | kVerifyVarArgRange) \
-  V(0x26, FILL_ARRAY_DATA, "fill-array-data", k31t, false, kNone, kContinue, kVerifyRegA | kVerifyArrayData) \
+  V(0x26, FILL_ARRAY_DATA, "fill-array-data", k31t, false, kNone, kContinue | kThrow, kVerifyRegA | kVerifyArrayData) \
   V(0x27, THROW, "throw", k11x, false, kNone, kThrow, kVerifyRegA) \
   V(0x28, GOTO, "goto", k10t, false, kNone, kBranch, kVerifyBranchTarget) \
   V(0x29, GOTO_16, "goto/16", k20t, false, kNone, kBranch, kVerifyBranchTarget) \
diff --git a/src/mem_map.cc b/src/mem_map.cc
index 92c6a59..885389d 100644
--- a/src/mem_map.cc
+++ b/src/mem_map.cc
@@ -29,7 +29,9 @@
 
 namespace art {
 
-size_t ParseHex(const std::string& string) {
+#if !defined(NDEBUG)
+
+static size_t ParseHex(const std::string& string) {
   CHECK_EQ(8U, string.size());
   const char* str = string.c_str();
   char* end;
@@ -39,17 +41,65 @@
   return value;
 }
 
+static void CheckMapRegion(uint32_t base, uint32_t limit, uint32_t start, uint32_t end, const std::string& maps) {
+  CHECK(!(base >= start && base < end)      // start of new within old
+        && !(limit > start && limit < end)  // end of new within old
+        && !(base <= start && limit > end)) // start/end of new includes all of old
+      << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
+                      base, limit, start, end)
+      << maps;
+}
+
 void CheckMapRequest(byte* addr, size_t length) {
-#if !defined(NDEBUG)
-#if defined(__APPLE__)
-  UNIMPLEMENTED(WARNING);
-#else
   if (addr == NULL) {
     return;
   }
-  size_t base = reinterpret_cast<size_t>(addr);
-  size_t limit = base + length;
+  uint32_t base = reinterpret_cast<size_t>(addr);
+  uint32_t limit = base + length;
 
+#if defined(__APPLE__)
+  // Mac OS vmmap(1) output currently looks something like this:
+
+  // Virtual Memory Map of process 51036 (dex2oatd)
+  // Output report format:  2.2  -- 32-bit process
+  //
+  // ==== regions for process 51036  (non-writable and writable regions are interleaved)
+  // __PAGEZERO             00000000-00001000 [    4K     0K     0K] ---/--- SM=NUL          out/host/darwin-x86/bin/dex2oatd
+  // __TEXT                 00001000-00015000 [   80K    80K     0K] r-x/rwx SM=COW          out/host/darwin-x86/bin/dex2oatd
+  // __DATA                 00015000-00016000 [    4K     4K     4K] rw-/rwx SM=PRV          out/host/darwin-x86/bin/dex2oatd
+  // __LINKEDIT             00016000-00044000 [  184K   184K     0K] r--/rwx SM=COW          out/host/darwin-x86/bin/dex2oatd
+  // __TEXT                 00044000-00046000 [    8K     8K     4K] r-x/rwx SM=COW          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // __DATA                 00046000-00047000 [    4K     4K     4K] rw-/rwx SM=ZER          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // __LINKEDIT             00047000-0004a000 [   12K    12K     0K] r--/rwx SM=COW          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // ...
+
+  std::string command(StringPrintf("vmmap -v -interleaved %d", getpid()));
+  FILE* fp = popen(command.c_str(), "r");
+  if (fp == NULL) {
+    PLOG(FATAL) << "popen failed";
+  }
+  std::vector<char> chars(512);
+  std::string maps;
+  while (fgets(&chars[0], chars.size(), fp) != NULL) {
+    std::string line(&chars[0]);
+    maps += line;
+    if (line.size() < 40 || line[31] != '-') {
+      continue;
+    }
+
+    std::string start_str(line.substr(22, 8));
+    std::string end_str(line.substr(31, 8));
+    uint32_t start = ParseHex(start_str);
+    uint32_t end = ParseHex(end_str);
+    CheckMapRegion(base, limit, start, end, maps);
+  }
+  if (ferror(fp)) {
+    PLOG(FATAL) << "fgets failed";
+  }
+  if (pclose(fp) == -1) {
+    PLOG(FATAL) << "pclose failed";
+  }
+#else // Linux
   std::string maps;
   bool read = ReadFileToString("/proc/self/maps", &maps);
   if (!read) {
@@ -93,20 +143,18 @@
     std::string end_str(maps.substr(i+1+8, 8));
     uint32_t start = ParseHex(start_str);
     uint32_t end = ParseHex(end_str);
-    CHECK(!(base >= start && base < end)       // start of new within old
-          && !(limit > start && limit < end)  // end of new within old
-          && !(base <= start && limit > end))  // start/end of new includes all of old
-        << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
-                        base, limit, start, end)
-        << maps;
+    CheckMapRegion(base, limit, start, end, maps);
     i += 8+1+8;
     i = maps.find('\n', i);
     CHECK(i != std::string::npos) << "Failed to find newline from pos " << i << "\n" << maps;
   }
 #endif
-#endif
 }
 
+#else
+static void CheckMapRequest(byte* addr, size_t length) { }
+#endif
+
 MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t length, int prot) {
   CHECK_NE(0U, length);
   CHECK_NE(0, prot);
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 0ca581a..dff360c 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -21,7 +21,38 @@
 
 namespace art {
 
-class OatTest : public CommonTest {};
+class OatTest : public CommonTest {
+ protected:
+  void CheckMethod(Method* method,
+                   const OatFile::OatMethod& oat_method,
+                   const DexFile* dex_file) {
+    const CompiledMethod* compiled_method =
+        compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
+                                                               method->GetDexMethodIndex()));
+
+    if (compiled_method == NULL) {
+      EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " "
+                                                << oat_method.GetCode();
+      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
+      EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
+      EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
+    } else {
+      const void* oat_code = oat_method.GetCode();
+      EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
+      uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
+      oat_code = reinterpret_cast<const void*>(oat_code_aligned);
+
+      const std::vector<uint8_t>& code = compiled_method->GetCode();
+      size_t code_size = code.size() * sizeof(code[0]);
+      EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
+          << PrettyMethod(method) << " " << code_size;
+      CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
+      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
+      EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
+      EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
+    }
+  }
+};
 
 TEST_F(OatTest, WriteRead) {
   const bool compile = false;  // DISABLED_ due to the time to compile libcore
@@ -64,59 +95,12 @@
 
     size_t method_index = 0;
     for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
-      Method* method = klass->GetDirectMethod(i);
-      const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-      const CompiledMethod* compiled_method =
-          compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
-                                                                 method->GetDexMethodIndex()));
-
-      if (compiled_method == NULL) {
-        EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " " << oat_method.GetCode();
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
-        EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
-      } else {
-        const void* oat_code = oat_method.GetCode();
-        uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
-        oat_code = reinterpret_cast<const void*>(oat_code_aligned);
-
-        const std::vector<uint8_t>& code = compiled_method->GetCode();
-        size_t code_size = code.size() * sizeof(code[0]);
-        EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
-            << PrettyMethod(method) << " " << code_size;
-        CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
-        EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
-      }
+      CheckMethod(klass->GetDirectMethod(i),
+                  oat_class->GetOatMethod(method_index), dex_file);
     }
     for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
-      Method* method = klass->GetVirtualMethod(i);
-      const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-      const CompiledMethod* compiled_method =
-          compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file,
-                                                                 method->GetDexMethodIndex()));
-
-      if (compiled_method == NULL) {
-        EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " " << oat_method.GetCode();
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
-        EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
-      } else {
-        const void* oat_code = oat_method.GetCode();
-        EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
-        uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
-        oat_code = reinterpret_cast<const void*>(oat_code_aligned);
-
-        const std::vector<uint8_t>& code = compiled_method->GetCode();
-        size_t code_size = code.size() * sizeof(code[0]);
-        EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
-            << PrettyMethod(method) << " " << code_size;
-        CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
-        EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
-        EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
-        EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
-      }
+      CheckMethod(klass->GetVirtualMethod(i),
+                  oat_class->GetOatMethod(method_index), dex_file);
     }
   }
 }
diff --git a/src/shadow_frame.h b/src/shadow_frame.h
new file mode 100644
index 0000000..3bdee8e
--- /dev/null
+++ b/src/shadow_frame.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_SHADOW_FRAME_H_
+#define ART_SRC_SHADOW_FRAME_H_
+
+#include "logging.h"
+#include "macros.h"
+
+namespace art {
+
+class Object;
+
+class ShadowFrame {
+ public:
+  // Number of references contained within this shadow frame
+  uint32_t NumberOfReferences() const {
+    return number_of_references_;
+  }
+
+  // Link to previous shadow frame or NULL
+  ShadowFrame* GetLink() const {
+    return link_;
+  }
+
+  void SetLink(ShadowFrame* frame) {
+    DCHECK_NE(this, frame);
+    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;
+  }
+
+  // Offset of link within shadow frame
+  static size_t LinkOffset() {
+    return OFFSETOF_MEMBER(ShadowFrame, link_);
+  }
+
+  // Offset of method within shadow frame
+  static size_t MethodOffset() {
+    return OFFSETOF_MEMBER(ShadowFrame, method_);
+  }
+
+  // Offset of line number within shadow frame
+  static size_t LineNumOffset() {
+    return OFFSETOF_MEMBER(ShadowFrame, line_num_);
+  }
+
+  // Offset of length within shadow frame
+  static size_t NumberOfReferencesOffset() {
+    return OFFSETOF_MEMBER(ShadowFrame, number_of_references_);
+  }
+
+  // Offset of references within shadow frame
+  static size_t ReferencesOffset() {
+    return OFFSETOF_MEMBER(ShadowFrame, references_);
+  }
+
+ private:
+  // ShadowFrame should be allocated by the generated code directly.
+  // We should not create new shadow stack in the runtime support function.
+  ~ShadowFrame() {}
+
+  uint32_t number_of_references_;
+  ShadowFrame* link_;
+  Object* method_;
+  uint32_t line_num_;
+  Object* references_[];
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame);
+};
+
+}  // namespace art
+
+#endif  // ART_SRC_SHADOW_FRAME_H_
diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h
index 5c6bc0a..5f37294 100644
--- a/src/stack_indirect_reference_table.h
+++ b/src/stack_indirect_reference_table.h
@@ -90,10 +90,6 @@
 
   size_t number_of_references_;
   StackIndirectReferenceTable* link_;
-#if defined(ART_USE_LLVM_COMPILER)
-  Object* method_;
-  uint32_t line_num_;
-#endif
 
   // number_of_references_ are available if this is allocated and filled in by jni_compiler.
   Object* references_[1];
diff --git a/src/thread.cc b/src/thread.cc
index 629cb0f..4417b7f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -43,6 +43,7 @@
 #include "runtime_support.h"
 #include "ScopedLocalRef.h"
 #include "scoped_jni_thread_state.h"
+#include "shadow_frame.h"
 #include "space.h"
 #include "stack.h"
 #include "stack_indirect_reference_table.h"
@@ -868,6 +869,7 @@
       stack_end_(NULL),
       native_to_managed_record_(NULL),
       top_sirt_(NULL),
+      top_shadow_frame_(NULL),
       jni_env_(NULL),
       state_(Thread::kNative),
       self_(NULL),
@@ -1003,6 +1005,18 @@
   }
 }
 
+void Thread::ShadowFrameVisitRoots(Heap::RootVisitor* visitor, void* arg) {
+  for (ShadowFrame* cur = top_shadow_frame_; cur; cur = cur->GetLink()) {
+    size_t num_refs = cur->NumberOfReferences();
+    for (size_t j = 0; j < num_refs; j++) {
+      Object* object = cur->GetReference(j);
+      if (object != NULL) {
+        visitor(object, arg);
+      }
+    }
+  }
+}
+
 Object* Thread::DecodeJObject(jobject obj) {
   DCHECK(CanAccessDirectReferences());
   if (obj == NULL) {
@@ -1181,6 +1195,18 @@
   return pc;
 }
 
+void Thread::PushShadowFrame(ShadowFrame* frame) {
+  frame->SetLink(top_shadow_frame_);
+  top_shadow_frame_ = frame;
+}
+
+ShadowFrame* Thread::PopShadowFrame() {
+  CHECK(top_shadow_frame_ != NULL);
+  ShadowFrame* frame = top_shadow_frame_;
+  top_shadow_frame_ = frame->GetLink();
+  return frame;
+}
+
 void Thread::PushSirt(StackIndirectReferenceTable* sirt) {
   sirt->SetLink(top_sirt_);
   top_sirt_ = sirt;
@@ -1665,6 +1691,7 @@
   jni_env_->monitors.VisitRoots(visitor, arg);
 
   SirtVisitRoots(visitor, arg);
+  ShadowFrameVisitRoots(visitor, arg);
 
   // Cheat and steal the long jump context. Assume that we are not doing a GC during exception
   // delivery.
diff --git a/src/thread.h b/src/thread.h
index 51385f9..bbf7730 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -50,6 +50,7 @@
 class Monitor;
 class Object;
 class Runtime;
+class ShadowFrame;
 class StackIndirectReferenceTable;
 class StackTraceElement;
 class StaticStorageBase;
@@ -266,6 +267,8 @@
 
   void SirtVisitRoots(Heap::RootVisitor* visitor, void* arg);
 
+  void ShadowFrameVisitRoots(Heap::RootVisitor* visitor, void* arg);
+
   // Convert a jobject into a Object*
   Object* DecodeJObject(jobject obj);
 
@@ -393,6 +396,9 @@
     return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_pc_));
   }
 
+  void PushShadowFrame(ShadowFrame* frame);
+  ShadowFrame* PopShadowFrame();
+
   void PushSirt(StackIndirectReferenceTable* sirt);
   StackIndirectReferenceTable* PopSirt();
 
@@ -524,6 +530,10 @@
   // Top of linked list of stack indirect reference tables or NULL for none
   StackIndirectReferenceTable* top_sirt_;
 
+  // Top of linked list of shadow stack or NULL for none
+  // Some backend may require shadow frame to ease the GC work.
+  ShadowFrame* top_shadow_frame_;
+
   // Every thread may have an associated JNI environment
   JNIEnvExt* jni_env_;