GBC Expander. Removed lir.

Change-Id: If8d13e36f1e6d82c2a7f7bfec62b8fb41fd8cdaa
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 7a6495a..4cfbdd3 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -26,6 +26,18 @@
 ART_USE_LLVM_COMPILER := true
 endif
 
+ART_USE_DEXLANG_FRONTEND := false
+ifeq ($(ART_USE_LLVM_COMPILER),true)
+  ifneq ($(wildcard art/USE_DEXLANG_FRONTEND),)
+  $(info Enabling ART_USE_DEXLANG_FRONTEND because of existence of art/USE_DEXLANG_FRONTEND)
+  ART_USE_DEXLANG_FRONTEND := true
+  endif
+  ifeq ($(WITH_ART_USE_DEXLANG_FRONTEND),true)
+  $(info Enabling ART_USE_DEXLANG_FRONTEND because WITH_ART_USE_DEXLANG_FRONTEND=true)
+  ART_USE_DEXLANG_FRONTEND := true
+  endif
+endif
+
 ART_USE_GREENLAND_COMPILER := false
 ifneq ($(wildcard art/USE_GREENLAND_COMPILER),)
 $(info Enabling ART_USE_GREENLAND_COMPILER because of existence of art/USE_GREENLAND_COMPILER)
@@ -254,7 +266,14 @@
 
 ifeq ($(ART_USE_GREENLAND_COMPILER),true)
 LIBART_COMMON_SRC_FILES += \
-	src/greenland/inferred_reg_category_map.cc
+	src/compiler_llvm/inferred_reg_category_map.cc \
+	src/greenland/runtime_entry_points.cc \
+	src/greenland/runtime/support_alloc.cc \
+	src/greenland/runtime/support_cast.cc \
+	src/greenland/runtime/support_dexcache.cc \
+	src/greenland/runtime/support_exception.cc \
+	src/greenland/runtime/support_field.cc \
+	src/greenland/runtime/support_thread.cc
 endif
 
 LIBART_COMMON_SRC_FILES += \
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index 3f0280b..ac1d64e 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -20,6 +20,9 @@
 ART_EXECUTABLES_CFLAGS :=
 ifeq ($(ART_USE_LLVM_COMPILER),true)
   ART_EXECUTABLES_CFLAGS += -DART_USE_LLVM_COMPILER=1
+  ifeq ($(ART_USE_DEXLANG_FRONTEND),true)
+    ART_EXECUTABLES_CFLAGS += -DART_USE_DEXLANG_FRONTEND=1
+  endif
 endif
 
 ifeq ($(ART_USE_GREENLAND_COMPILER),true)
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index cf98476..de8c502 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -22,6 +22,9 @@
 ART_TEST_CFLAGS :=
 ifeq ($(ART_USE_LLVM_COMPILER),true)
   ART_TEST_CFLAGS += -DART_USE_LLVM_COMPILER=1
+  ifeq ($(ART_USE_DEXLANG_FRONTEND),true)
+    ART_TEST_CFLAGS += -DART_USE_DEXLANG_FRONTEND=1
+  endif
 endif
 
 ifeq ($(ART_USE_GREENLAND_COMPILER),true)
diff --git a/build/Android.libart-compiler-greenland.mk b/build/Android.libart-compiler-greenland.mk
index c25ebd9..b999eff 100644
--- a/build/Android.libart-compiler-greenland.mk
+++ b/build/Android.libart-compiler-greenland.mk
@@ -18,16 +18,14 @@
 LIBART_COMPILER_GREENLAND_CFLAGS := -DART_USE_GREENLAND_COMPILER=1
 
 LIBART_COMPILER_GREENLAND_SRC_FILES += \
+	src/compiler_llvm/inferred_reg_category_map.cc \
 	src/greenland/dalvik_reg.cc \
 	src/greenland/dex_lang.cc \
+	src/greenland/gbc_context.cc \
 	src/greenland/greenland.cc \
-	src/greenland/lir.cc \
-	src/greenland/lir_function.cc \
-	src/greenland/inferred_reg_category_map.cc \
 	src/greenland/intrinsic_helper.cc \
-	src/greenland/ir_builder.cc \
+	src/greenland/register_allocator.cc \
 	src/greenland/target_codegen_machine.cc \
-	src/greenland/target_lir_emitter.cc \
 	src/greenland/target_registry.cc \
 	src/oat/jni/calling_convention.cc \
 	src/oat/jni/jni_compiler.cc \
@@ -49,6 +47,21 @@
   src/greenland/x86/x86_lir_info.cc \
   src/greenland/x86/x86_invoke_stub_compiler.cc
 
+########################################################################
+
+include $(CLEAR_VARS)
+LOCAL_CPP_EXTENSION := $(ART_CPP_EXTENSION)
+LOCAL_MODULE := target_lir_builder_generator
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+LOCAL_SRC_FILES := src/greenland/tools/target_lir_builder_generator.cc
+LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+LOCAL_C_INCLUDES := $(ART_C_INCLUDES)
+include $(BUILD_HOST_EXECUTABLE)
+TARGET_LIR_BUILDER_GENERATOR := $(LOCAL_BUILT_MODULE)
+
+########################################################################
+
 # $(1): target or host
 # $(2): ndebug or debug
 define build-libart-compiler-greenland
@@ -85,21 +98,35 @@
   ifeq ($$(art_target_or_host),target)
     LOCAL_CFLAGS += $(ART_TARGET_CFLAGS)
   else # host
+    LOCAL_IS_HOST_MODULE := true
     LOCAL_CFLAGS += $(ART_HOST_CFLAGS)
   endif
 
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
 
   ifeq ($$(art_target_or_host),target)
+    ENUM_INCLUDE_LIR_TARGETS := arm
     LOCAL_SRC_FILES += \
       $(LIBART_COMPILER_GREENLAND_$(TARGET_ARCH)_SRC_FILES)
   else
+    ENUM_INCLUDE_LIR_TARGETS := arm mips x86
     LOCAL_SRC_FILES += \
       $(LIBART_COMPILER_GREENLAND_arm_SRC_FILES) \
       $(LIBART_COMPILER_GREENLAND_mips_SRC_FILES) \
       $(LIBART_COMPILER_GREENLAND_x86_SRC_FILES)
   endif
 
+  GENERATED_SRC_DIR := $$(call intermediates-dir-for,$$(LOCAL_MODULE_CLASS),$$(LOCAL_MODULE),$$(LOCAL_IS_HOST_MODULE),)
+  ENUM_TARGEET_LIR_BUILDER_INC_FILES := $$(foreach lir_target, $$(ENUM_INCLUDE_LIR_TARGETS), $$(lir_target)_lir_builder_base.inc)
+  ENUM_TARGET_LIR_BUILDER_OUT_GEN := $$(addprefix $$(GENERATED_SRC_DIR)/, $$(ENUM_TARGEET_LIR_BUILDER_INC_FILES))
+
+$$(ENUM_TARGET_LIR_BUILDER_OUT_GEN): PRIVATE_LIR_TARGET = $$(subst _lir_builder_base.inc,,$$(notdir $$@))
+$$(ENUM_TARGET_LIR_BUILDER_OUT_GEN): %.inc : $$(TARGET_LIR_BUILDER_GENERATOR)
+	@echo "target Generated: $$@"
+	$$(hide) $$(TARGET_LIR_BUILDER_GENERATOR) $$(PRIVATE_LIR_TARGET) > $$@
+
+LOCAL_GENERATED_SOURCES += $$(ENUM_TARGET_LIR_BUILDER_OUT_GEN)
+
   LOCAL_STATIC_LIBRARIES += \
     libLLVMBitWriter \
     libLLVMBitReader \
@@ -114,7 +141,7 @@
   ifeq ($$(art_target_or_host),target)
     LOCAL_SHARED_LIBRARIES += libcutils libstlport libz libdl
     LOCAL_SHARED_LIBRARIES += libdynamic_annotations # tsan support
-#    LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
+    LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
   else # host
     LOCAL_STATIC_LIBRARIES += libcutils
     LOCAL_SHARED_LIBRARIES += libz-host
@@ -144,7 +171,6 @@
     include $(LLVM_DEVICE_BUILD_MK)
     include $(BUILD_SHARED_LIBRARY)
   else # host
-    LOCAL_IS_HOST_MODULE := true
     include $(LLVM_GEN_INTRINSICS_MK)
     include $(LLVM_HOST_BUILD_MK)
     include $(BUILD_HOST_SHARED_LIBRARY)
@@ -163,9 +189,9 @@
       $(HOST_OUT_EXECUTABLES)/dex2oat: $$(LOCAL_INSTALLED_MODULE)
     endif
   endif
-
 endef
 
+
 ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
   $(eval $(call build-libart-compiler-greenland,target,ndebug))
 endif
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index 6e178d6..894fb54 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -16,16 +16,17 @@
 
 
 LIBART_COMPILER_LLVM_CFLAGS := -DART_USE_LLVM_COMPILER=1
+ifeq ($(ART_USE_DEXLANG_FRONTEND),true)
+  LIBART_COMPILER_LLVM_CFLAGS += -DART_USE_DEXLANG_FRONTEND=1
+endif
 
 LIBART_COMPILER_LLVM_SRC_FILES += \
 	src/compiler_llvm/compilation_unit.cc \
 	src/compiler_llvm/compiler_llvm.cc \
-	src/compiler_llvm/dalvik_reg.cc \
 	src/compiler_llvm/generated/art_module.cc \
 	src/compiler_llvm/inferred_reg_category_map.cc \
 	src/compiler_llvm/ir_builder.cc \
 	src/compiler_llvm/jni_compiler.cc \
-	src/compiler_llvm/method_compiler.cc \
 	src/compiler_llvm/runtime_support_builder.cc \
 	src/compiler_llvm/runtime_support_builder_arm.cc \
 	src/compiler_llvm/runtime_support_builder_thumb2.cc \
@@ -34,6 +35,19 @@
 	src/compiler_llvm/stub_compiler.cc \
 	src/compiler_llvm/tbaa_info.cc
 
+ifeq ($(ART_USE_DEXLANG_FRONTEND),true)
+  LIBART_COMPILER_LLVM_SRC_FILES += \
+    src/compiler_llvm/gbc_expander.cc \
+    src/greenland/dalvik_reg.cc \
+    src/greenland/dex_lang.cc \
+    src/greenland/intrinsic_helper.cc \
+    src/greenland/ir_builder.cc
+else
+  LIBART_COMPILER_LLVM_SRC_FILES += \
+	  src/compiler_llvm/dalvik_reg.cc \
+	  src/compiler_llvm/method_compiler.cc
+endif
+
 # $(1): target or host
 # $(2): ndebug or debug
 define build-libart-compiler-llvm
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 9ccbe3f..6eaa778 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -17,6 +17,9 @@
 LIBART_CFLAGS :=
 ifeq ($(ART_USE_LLVM_COMPILER),true)
   LIBART_CFLAGS += -DART_USE_LLVM_COMPILER=1
+  ifeq ($(ART_USE_DEXLANG_FRONTEND),true)
+    LIBART_CFLAGS += -DART_USE_DEXLANG_FRONTEND=1
+  endif
 endif
 
 ifeq ($(ART_USE_GREENLAND_COMPILER),true)
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index 25aae11..dae9b16 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -267,7 +267,7 @@
                           RegLocation rlArray)
 {
   greenland::IntrinsicHelper::IntrinsicId id;
-  id = greenland::IntrinsicHelper::FillArrayData;
+  id = greenland::IntrinsicHelper::HLFillArrayData;
   llvm::SmallVector<llvm::Value*, 2> args;
   args.push_back(cUnit->irb->getInt32(offset));
   args.push_back(getLLVMValue(cUnit, rlArray.origSReg));
@@ -340,7 +340,7 @@
 {
   llvm::Value* src = getLLVMValue(cUnit, rlSrc.origSReg);
   llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(
-      greenland::IntrinsicHelper::Throw);
+      greenland::IntrinsicHelper::ThrowException);
   cUnit->irb->CreateCall(func, src);
 }
 
@@ -362,7 +362,7 @@
   args.push_back(cUnit->irb->getInt32(optFlags));
   args.push_back(getLLVMValue(cUnit, rlSrc.origSReg));
   llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(
-      greenland::IntrinsicHelper::ArrayLength);
+      greenland::IntrinsicHelper::OptArrayLength);
   llvm::Value* res = cUnit->irb->CreateCall(func, args);
   defineValue(cUnit, res, rlDest.origSReg);
 }
@@ -584,7 +584,7 @@
    */
   greenland::IntrinsicHelper::IntrinsicId id;
   if (isFilledNewArray) {
-    id = greenland::IntrinsicHelper::FilledNewArray;
+    id = greenland::IntrinsicHelper::HLFilledNewArray;
   } else if (info->result.location == kLocInvalid) {
     id = greenland::IntrinsicHelper::HLInvokeVoid;
   } else {
@@ -623,7 +623,7 @@
                       RegLocation rlSrc)
 {
   greenland::IntrinsicHelper::IntrinsicId id;
-  id = greenland::IntrinsicHelper::CheckCast;
+  id = greenland::IntrinsicHelper::HLCheckCast;
   llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id);
   llvm::SmallVector<llvm::Value*, 2> args;
   args.push_back(cUnit->irb->getInt32(type_idx));
@@ -1759,8 +1759,10 @@
 {
   if (bb->blockType == kDead) return false;
   llvm::BasicBlock* llvmBB = getLLVMBlock(cUnit, bb->id);
-  cUnit->irb->SetInsertPoint(llvmBB);
-  setDexOffset(cUnit, bb->startOffset);
+  if (llvmBB != NULL) {
+    cUnit->irb->SetInsertPoint(llvmBB);
+    setDexOffset(cUnit, bb->startOffset);
+  }
 
   if (cUnit->printMe) {
     LOG(INFO) << "................................";
@@ -3012,10 +3014,10 @@
               case greenland::IntrinsicHelper::HLInvokeVoid:
                 cvtInvoke(cUnit, callInst, true /* isVoid */, false /* newArray */);
                 break;
-              case greenland::IntrinsicHelper::FilledNewArray:
+              case greenland::IntrinsicHelper::HLFilledNewArray:
                 cvtInvoke(cUnit, callInst, false /* isVoid */, true /* newArray */);
                 break;
-              case greenland::IntrinsicHelper::FillArrayData:
+              case greenland::IntrinsicHelper::HLFillArrayData:
                 cvtFillArrayData(cUnit, callInst);
                 break;
               case greenland::IntrinsicHelper::ConstString:
@@ -3024,7 +3026,7 @@
               case greenland::IntrinsicHelper::ConstClass:
                 cvtConstObject(cUnit, callInst, false /* isString */);
                 break;
-              case greenland::IntrinsicHelper::CheckCast:
+              case greenland::IntrinsicHelper::HLCheckCast:
                 cvtCheckCast(cUnit, callInst);
                 break;
               case greenland::IntrinsicHelper::NewInstance:
@@ -3063,7 +3065,7 @@
               case greenland::IntrinsicHelper::GetException:
                 cvtMoveException(cUnit, callInst);
                 break;
-              case greenland::IntrinsicHelper::Throw:
+              case greenland::IntrinsicHelper::ThrowException:
                 cvtThrow(cUnit, callInst);
                 break;
               case greenland::IntrinsicHelper::MonitorEnter:
@@ -3072,7 +3074,7 @@
               case greenland::IntrinsicHelper::MonitorExit:
                 cvtMonitorEnterExit(cUnit, false /* isEnter */, callInst);
                 break;
-              case greenland::IntrinsicHelper::ArrayLength:
+              case greenland::IntrinsicHelper::OptArrayLength:
                 cvtArrayLength(cUnit, callInst);
                 break;
               case greenland::IntrinsicHelper::NewArray:
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index f84ebf4..87fd724 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -136,6 +136,12 @@
 namespace art {
 namespace compiler_llvm {
 
+#ifdef ART_USE_DEXLANG_FRONTEND
+llvm::FunctionPass*
+CreateGBCExpanderPass(const greenland::IntrinsicHelper& intrinsic_helper,
+                      IRBuilder& irb);
+#endif
+
 llvm::Module* makeLLVMModuleContents(llvm::Module* module);
 
 
@@ -148,6 +154,10 @@
   module_ = new llvm::Module("art", *context_);
   makeLLVMModuleContents(module_);
 
+#ifdef ART_USE_DEXLANG_FRONTEND
+  dex_lang_ctx_ = new greenland::DexLang::Context(*module_);
+#endif
+
   // Create IRBuilder
   irb_.reset(new IRBuilder(*context_, *module_));
 
@@ -174,6 +184,9 @@
 
 
 CompilationUnit::~CompilationUnit() {
+#ifdef ART_USE_DEXLANG_FRONTEND
+  delete dex_lang_ctx_;
+#endif
 }
 
 
@@ -291,10 +304,16 @@
   if (bitcode_filename_.empty()) {
     // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
     // regular FunctionPass.
+#ifdef ART_USE_DEXLANG_FRONTEND
+    fpm.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
+#endif
     fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
   } else {
     // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file.
     llvm::FunctionPassManager fpm2(module_);
+#ifdef ART_USE_DEXLANG_FRONTEND
+    fpm2.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
+#endif
     fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
     fpm2.doInitialization();
     for (llvm::Module::iterator F = module_->begin(), E = module_->end();
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index 576b65f..d1dfa0c 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -19,6 +19,9 @@
 
 #include "../mutex.h"
 #include "globals.h"
+#ifdef ART_USE_DEXLANG_FRONTEND
+# include "greenland/dex_lang.h"
+#endif
 #include "instruction_set.h"
 #include "logging.h"
 #include "runtime_support_builder.h"
@@ -71,6 +74,12 @@
     return irb_.get();
   }
 
+#ifdef ART_USE_DEXLANG_FRONTEND
+  greenland::DexLang::Context* GetDexLangContext() const {
+    return dex_lang_ctx_;
+  }
+#endif
+
   void SetBitcodeFileName(const std::string& bitcode_filename) {
     bitcode_filename_ = bitcode_filename;
   }
@@ -94,6 +103,9 @@
   UniquePtr<IRBuilder> irb_;
   UniquePtr<RuntimeSupportBuilder> runtime_support_;
   llvm::Module* module_;
+#ifdef ART_USE_DEXLANG_FRONTEND
+  greenland::DexLang::Context* dex_lang_ctx_;
+#endif
 
   std::string bitcode_filename_;
 
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index b30486c..dc79643 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -23,11 +23,14 @@
 #include "compiler.h"
 #include "ir_builder.h"
 #include "jni_compiler.h"
-#include "method_compiler.h"
+#ifndef ART_USE_DEXLANG_FRONTEND
+# include "method_compiler.h"
+#endif
 #include "oat_compilation_unit.h"
 #include "oat_file.h"
 #include "stl_util.h"
 #include "stub_compiler.h"
+#include "utils_llvm.h"
 
 #include <llvm/LinkAllPasses.h>
 #include <llvm/LinkAllVMCore.h>
@@ -121,10 +124,25 @@
 CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
   UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
+#ifdef ART_USE_DEXLANG_FRONTEND
+  // Run DexLang for Dex to Greenland Bitcode
+  UniquePtr<greenland::DexLang> dex_lang(
+      new greenland::DexLang(*cunit->GetDexLangContext(), *compiler_,
+                             *oat_compilation_unit));
+
+  llvm::Function* func = dex_lang->Build();
+  CHECK(func != NULL);
+
+  cunit->Materialize();
+
+  return new CompiledMethod(cunit->GetInstructionSet(),
+                            cunit->GetCompiledCode());
+#else
   UniquePtr<MethodCompiler> method_compiler(
       new MethodCompiler(cunit.get(), compiler_, oat_compilation_unit));
 
   return method_compiler->Compile();
+#endif
 }
 
 
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
new file mode 100644
index 0000000..e2b9834
--- /dev/null
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -0,0 +1,1518 @@
+/*
+ * 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.
+ */
+
+#include "ir_builder.h"
+#include "utils_llvm.h"
+
+#include "greenland/intrinsic_helper.h"
+#include "object.h"
+#include "thread.h"
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/Intrinsics.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/CFG.h>
+#include <llvm/Support/InstIterator.h>
+
+#include <vector>
+
+using namespace art;
+using namespace compiler_llvm;
+
+using art::greenland::IntrinsicHelper;
+
+namespace {
+
+class GBCExpanderPass : public llvm::FunctionPass {
+ private:
+  const IntrinsicHelper& intrinsic_helper_;
+  IRBuilder& irb_;
+
+  llvm::LLVMContext& context_;
+  RuntimeSupportBuilder& rtb_;
+
+ private:
+  llvm::AllocaInst* shadow_frame_;
+  llvm::Value* old_shadow_frame_;
+  uint32_t shadow_frame_size_;
+
+ private:
+  //----------------------------------------------------------------------------
+  // Helper function for GBC expansion
+  //----------------------------------------------------------------------------
+
+  // Split the basic block containing INST at INST and insert a sequence of
+  // basic blocks with a single entry at BEGIN_BB and a single exit at END_BB
+  // before INST.
+  llvm::BasicBlock*
+  SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
+                                 llvm::BasicBlock* begin_bb,
+                                 llvm::BasicBlock* end_bb);
+
+  llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
+                               llvm::CallInst& inst);
+
+ private:
+  // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
+  // Refactor these utility functions from MethodCompiler to avoid forking.
+
+  bool EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
+
+  //----------------------------------------------------------------------------
+  // Dex cache code generation helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
+
+  llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
+
+  llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
+
+  llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
+
+  llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
+
+  //----------------------------------------------------------------------------
+  // Code generation helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitLoadMethodObjectAddr();
+
+  llvm::Value* EmitLoadArrayLength(llvm::Value* array);
+
+  llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
+
+  llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
+                                                     llvm::Value* this_addr);
+
+  llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
+                            llvm::Value* index_value,
+                            JType elem_jty);
+
+ private:
+  //----------------------------------------------------------------------------
+  // Expand Greenland intrinsics
+  //----------------------------------------------------------------------------
+  void Expand_TestSuspend(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_GetException();
+
+  llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
+
+  llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
+
+  void Expand_LockObject(llvm::Value* obj);
+
+  void Expand_UnlockObject(llvm::Value* obj);
+
+  llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
+                               llvm::Value* index_value,
+                               JType elem_jty);
+
+  void Expand_ArrayPut(llvm::Value* new_value,
+                       llvm::Value* array_addr,
+                       llvm::Value* index_value,
+                       JType elem_jty);
+
+  void Expand_FilledNewArray(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
+                               llvm::Value* is_volatile_value,
+                               llvm::Value* object_addr,
+                               JType field_jty);
+
+  void Expand_IPutFast(llvm::Value* field_offset_value,
+                       llvm::Value* is_volatile_value,
+                       llvm::Value* object_addr,
+                       llvm::Value* new_value,
+                       JType field_jty);
+
+  llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
+                               llvm::Value* field_offset_value,
+                               llvm::Value* is_volatile_value,
+                               JType field_jty);
+
+  void Expand_SPutFast(llvm::Value* static_storage_addr,
+                       llvm::Value* field_offset_value,
+                       llvm::Value* is_volatile_value,
+                       llvm::Value* new_value,
+                       JType field_jty);
+
+  llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
+
+  llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
+
+  llvm::Value*
+  Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
+
+  llvm::Value*
+  Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
+                                           llvm::Value* this_addr);
+
+  llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_DivRem(llvm::Value* dividend, llvm::Value* divisor,
+                             bool is_div, JType op_jty);
+
+  void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
+
+  void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
+
+  void Expand_PopShadowFrame();
+
+  void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
+
+ public:
+  static char ID;
+
+  GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
+      : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
+        context_(irb.getContext()), rtb_(irb.Runtime())
+  { }
+
+  bool runOnFunction(llvm::Function& func);
+
+ private:
+  bool InsertStackOverflowCheck(llvm::Function& func);
+
+  llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
+                               llvm::CallInst& call_inst);
+
+};
+
+char GBCExpanderPass::ID = 0;
+
+bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
+  bool changed;
+
+  changed = InsertStackOverflowCheck(func);
+
+  std::list<std::pair<llvm::CallInst*,
+                      IntrinsicHelper::IntrinsicId> > work_list;
+
+  for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
+          inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
+    // Only CallInst with its called function is dexlang intrinsic need to
+    // process
+    llvm::Instruction* inst = &*inst_iter;
+    if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
+      const llvm::Function* callee = call_inst->getCalledFunction();
+
+      if (callee != NULL) {
+        IntrinsicHelper::IntrinsicId intr_id =
+            intrinsic_helper_.GetIntrinsicId(callee);
+
+        if (intr_id != IntrinsicHelper::UnknownId) {
+          work_list.push_back(std::make_pair(call_inst, intr_id));
+        }
+      }
+    }
+  }
+
+  changed |= !work_list.empty();
+
+  shadow_frame_ = NULL;
+  old_shadow_frame_ = NULL;
+  shadow_frame_size_ = 0;
+
+  // Remove the instruction containing in the work_list
+  while (!work_list.empty()) {
+    llvm::CallInst* intr_inst = work_list.front().first;
+    IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
+
+    // Remove the instruction from work list
+    work_list.pop_front();
+
+    // Move the IRBuilder insert pointer
+    irb_.SetInsertPoint(intr_inst);
+
+    // Process the expansion
+    llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
+
+    // Use the new value from the expansion
+    if (new_value != NULL) {
+      intr_inst->replaceAllUsesWith(new_value);
+    }
+
+    // Remove the intrinsic instruction
+    intr_inst->eraseFromParent();
+  }
+
+  VERIFY_LLVM_FUNCTION(func);
+
+  return changed;
+}
+
+llvm::BasicBlock*
+GBCExpanderPass::SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
+                                                llvm::BasicBlock* begin_bb,
+                                                llvm::BasicBlock* end_bb) {
+  llvm::BasicBlock* original = inst->getParent();
+  llvm::Function* parent = original->getParent();
+
+  // 1. Create a new basic block A after ORIGINAL
+  llvm::BasicBlock *insert_before =
+    llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
+  llvm::BasicBlock* a =
+    llvm::BasicBlock::Create(context_, "", parent, insert_before);
+
+  // 2. Move all instructions in ORIGINAL after INST (included) to A
+  a->getInstList().splice(a->end(), original->getInstList(),
+                          inst, original->end());
+
+  // 3. Add an unconditional branch in ORIGINAL to begin_bb
+  llvm::BranchInst::Create(begin_bb, original);
+
+  // 4. Add an unconditional branch in END_BB to A
+  llvm::BranchInst::Create(a, end_bb);
+
+  // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
+  // with incoming basic block from ORIGINAL to A
+  for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
+          succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
+    llvm::BasicBlock* succ = *succ_iter;
+    llvm::PHINode* phi;
+    for (llvm::BasicBlock::iterator inst_iter = succ->begin();
+         (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
+      int idx;
+      while ((idx  = phi->getBasicBlockIndex(original)) != -1) {
+        phi->setIncomingBlock(static_cast<unsigned>(idx), a);
+      }
+    }
+  }
+
+  return a;
+}
+
+llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
+                                              llvm::CallInst& inst) {
+  // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
+  // the arguments passed to the GBC intrinsic are as the same as IBC runtime
+  // function, therefore only called function is needed to change.
+  unsigned num_args = inst.getNumArgOperands();
+
+  if (num_args <= 0) {
+    return irb_.CreateCall(irb_.GetRuntime(rt));
+  } else {
+    std::vector<llvm::Value*> args;
+    for (unsigned i = 0; i < num_args; i++) {
+      args.push_back(inst.getArgOperand(i));
+    }
+
+    return irb_.CreateCall(irb_.GetRuntime(rt), args);
+  }
+}
+
+bool
+GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
+  llvm::Function* func = first_non_alloca->getParent()->getParent();
+  llvm::Module* module = func->getParent();
+
+  llvm::BasicBlock* block_entry =
+      llvm::BasicBlock::Create(context_, "stack_overflow_entry", func);
+
+  irb_.SetInsertPoint(block_entry);
+
+  // Call llvm intrinsic function to get frame address.
+  llvm::Function* frameaddress =
+      llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
+
+  // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
+  llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
+
+  // Cast i8* to int
+  frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
+
+  // Get thread.stack_end_
+  llvm::Value* stack_end =
+    irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
+                                            irb_.getPtrEquivIntTy(),
+                                            kTBAARuntimeInfo);
+
+  // Check the frame address < thread.stack_end_ ?
+  llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
+
+  llvm::BasicBlock* block_exception =
+      llvm::BasicBlock::Create(context_, "stack_overflow", func);
+
+  llvm::BasicBlock* block_continue =
+      llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
+
+  irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
+
+  // If stack overflow, throw exception.
+  irb_.SetInsertPoint(block_exception);
+  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
+
+  // Unwind.
+  llvm::Type* ret_type = func->getReturnType();
+  if (ret_type->isVoidTy()) {
+    irb_.CreateRetVoid();
+  } else {
+    // The return value is ignored when there's an exception. MethodCompiler
+    // returns zero value under the the corresponding return type  in this case.
+    // GBCExpander returns LLVM undef value here for brevity
+    irb_.CreateRet(llvm::UndefValue::get(ret_type));
+  }
+
+  irb_.SetInsertPoint(block_continue);
+
+  SplitAndInsertBasicBlocksAfter(*first_non_alloca, block_entry, block_continue);
+
+  return true;
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  return irb_.LoadFromObjectOffset(method_object_addr,
+                                   offset.Int32Value(),
+                                   irb_.getJObjectTy(),
+                                   kTBAAConstJObject);
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
+  llvm::Value* static_storage_dex_cache_addr =
+    EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
+
+  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
+
+  return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
+  llvm::Value* resolved_type_dex_cache_addr =
+    EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
+
+  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
+
+  return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
+  llvm::Value* resolved_method_dex_cache_addr =
+    EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
+
+  llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
+
+  return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
+  llvm::Value* string_dex_cache_addr =
+    EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
+
+  llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
+
+  return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
+  llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+  return parent_func->arg_begin();
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
+  // Load array length
+  return irb_.LoadFromObjectOffset(array,
+                                   Array::LengthOffset().Int32Value(),
+                                   irb_.getJIntTy(),
+                                   kTBAAConstJObject);
+
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
+  llvm::Value* callee_method_object_field_addr =
+    EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
+
+  return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
+  // Load class object of *this* pointer
+  llvm::Value* class_object_addr =
+    irb_.LoadFromObjectOffset(this_addr,
+                              Object::ClassOffset().Int32Value(),
+                              irb_.getJObjectTy(),
+                              kTBAAConstJObject);
+
+  // Load vtable address
+  llvm::Value* vtable_addr =
+    irb_.LoadFromObjectOffset(class_object_addr,
+                              Class::VTableOffset().Int32Value(),
+                              irb_.getJObjectTy(),
+                              kTBAAConstJObject);
+
+  // Load callee method object
+  llvm::Value* vtable_idx_value =
+    irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
+
+  llvm::Value* method_field_addr =
+    EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
+
+  return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
+}
+
+// Emit Array GetElementPtr
+llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
+                                           llvm::Value* index_value,
+                                           JType elem_jty) {
+
+  int data_offset;
+  if (elem_jty == kLong || elem_jty == kDouble ||
+      (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
+    data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
+  } else {
+    data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
+  }
+
+  llvm::Constant* data_offset_value =
+    irb_.getPtrEquivInt(data_offset);
+
+  llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
+
+  llvm::Value* array_data_addr =
+    irb_.CreatePtrDisp(array_addr, data_offset_value,
+                       elem_type->getPointerTo());
+
+  return irb_.CreateGEP(array_data_addr, index_value);
+}
+
+void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
+  llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+  llvm::BasicBlock* suspend_test_begin_bb =
+    llvm::BasicBlock::Create(context_, "suspend_test", parent_func);
+
+  irb_.SetInsertPoint(suspend_test_begin_bb);
+  irb_.Runtime().EmitTestSuspend();
+
+  llvm::BasicBlock* suspend_test_end_bb = irb_.GetInsertBlock();
+
+  SplitAndInsertBasicBlocksAfter(call_inst, suspend_test_begin_bb,
+                                            suspend_test_end_bb);
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_GetException() {
+  // Get thread-local exception field address
+  llvm::Value* exception_object_addr =
+    irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
+                                            irb_.getJObjectTy(),
+                                            kTBAAJRuntime);
+
+  // Set thread-local exception field address to NULL
+  irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
+                                         irb_.getJNull(),
+                                         kTBAAJRuntime);
+
+  return exception_object_addr;
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
+  uint32_t string_idx =
+    llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
+
+  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
+
+  return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
+  uint32_t type_idx =
+    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
+
+  llvm::Value* type_field_addr =
+    EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
+
+  return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+}
+
+void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
+  llvm::BasicBlock::iterator lock_obj_inst = irb_.GetInsertPoint();
+  llvm::Function* parent = irb_.GetInsertBlock()->getParent();
+
+  llvm::BasicBlock* lock_obj_begin_bb =
+    llvm::BasicBlock::Create(context_, "", parent);
+
+  irb_.SetInsertPoint(lock_obj_begin_bb);
+  rtb_.EmitLockObject(obj);
+
+  llvm::BasicBlock* lock_obj_end_bb = irb_.GetInsertBlock();
+
+  SplitAndInsertBasicBlocksAfter(lock_obj_inst, lock_obj_begin_bb,
+                                 lock_obj_end_bb);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
+  llvm::BasicBlock::iterator unlock_obj_inst = irb_.GetInsertPoint();
+  llvm::Function* parent = irb_.GetInsertBlock()->getParent();
+
+  llvm::BasicBlock* unlock_obj_begin_bb =
+    llvm::BasicBlock::Create(context_, "", parent);
+
+  irb_.SetInsertPoint(unlock_obj_begin_bb);
+  rtb_.EmitUnlockObject(obj);
+
+  llvm::BasicBlock* unlock_obj_end_bb = irb_.GetInsertBlock();
+
+  SplitAndInsertBasicBlocksAfter(unlock_obj_inst, unlock_obj_begin_bb,
+                                 unlock_obj_end_bb);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
+                                              llvm::Value* index_value,
+                                              JType elem_jty) {
+  llvm::Value* array_elem_addr =
+    EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
+}
+
+void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
+                                      llvm::Value* array_addr,
+                                      llvm::Value* index_value,
+                                      JType elem_jty) {
+  llvm::Value* array_elem_addr =
+    EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
+  // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
+  llvm::Value* array = call_inst.getArgOperand(0);
+
+  uint32_t element_jty =
+    llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
+
+  DCHECK(call_inst.getNumArgOperands() > 2);
+  unsigned num_elements = (call_inst.getNumArgOperands() - 2);
+
+  bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
+
+  uint32_t alignment;
+  llvm::Constant* elem_size;
+  llvm::PointerType* field_type;
+
+  // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
+  // as the element, thus we are only checking 2 cases: primitive int and
+  // non-primitive type.
+  if (is_elem_int_ty) {
+    alignment = sizeof(int32_t);
+    elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
+    field_type = irb_.getJIntTy()->getPointerTo();
+  } else {
+    alignment = irb_.getSizeOfPtrEquivInt();
+    elem_size = irb_.getSizeOfPtrEquivIntValue();
+    field_type = irb_.getJObjectTy()->getPointerTo();
+  }
+
+  llvm::Value* data_field_offset =
+    irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
+
+  llvm::Value* data_field_addr =
+    irb_.CreatePtrDisp(array, data_field_offset, field_type);
+
+  for (unsigned i = 0; i < num_elements; ++i) {
+    // Values to fill the array begin at the 3rd argument
+    llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
+
+    irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
+
+    data_field_addr =
+      irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
+                                              llvm::Value* /*is_volatile_value*/,
+                                              llvm::Value* object_addr,
+                                              JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::PointerType* field_type =
+    irb_.getJType(field_jty, kField)->getPointerTo();
+
+  field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* field_addr =
+    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+  // TODO: Check is_volatile.  We need to generate atomic load instruction
+  // when is_volatile is true.
+  return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
+}
+
+void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
+                                      llvm::Value* /* is_volatile_value */,
+                                      llvm::Value* object_addr,
+                                      llvm::Value* new_value,
+                                      JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::PointerType* field_type =
+    irb_.getJType(field_jty, kField)->getPointerTo();
+
+  field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* field_addr =
+    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
+                                              llvm::Value* field_offset_value,
+                                              llvm::Value* /*is_volatile_value*/,
+                                              JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* static_field_addr =
+    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                       irb_.getJType(field_jty, kField)->getPointerTo());
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
+}
+
+void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
+                                      llvm::Value* field_offset_value,
+                                      llvm::Value* /* is_volatile_value */,
+                                      llvm::Value* new_value,
+                                      JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* static_field_addr =
+    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                       irb_.getJType(field_jty, kField)->getPointerTo());
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
+
+  return;
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
+  return irb_.LoadFromObjectOffset(method_object_addr,
+                                   Method::DeclaringClassOffset().Int32Value(),
+                                   irb_.getJObjectTy(),
+                                   kTBAAConstJObject);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
+  uint32_t type_idx =
+    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
+
+  llvm::Value* storage_field_addr =
+    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+
+  return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
+  uint32_t callee_method_idx =
+    llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
+
+  return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
+}
+
+llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
+    llvm::Value* vtable_idx_value,
+    llvm::Value* this_addr) {
+  int vtable_idx =
+    llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
+
+  return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
+}
+
+llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
+  // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
+  llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
+  unsigned num_args = call_inst.getNumArgOperands();
+  llvm::Type* ret_type = call_inst.getType();
+
+  // Determine the function type of the callee method
+  std::vector<llvm::Type*> args_type;
+  std::vector<llvm::Value*> args;
+  for (unsigned i = 0; i < num_args; i++) {
+    args.push_back(call_inst.getArgOperand(i));
+    args_type.push_back(args[i]->getType());
+  }
+
+  llvm::FunctionType* callee_method_type =
+    llvm::FunctionType::get(ret_type, args_type, false);
+
+  llvm::Value* code_addr =
+    irb_.LoadFromObjectOffset(callee_method_object_addr,
+                              Method::GetCodeOffset().Int32Value(),
+                              callee_method_type->getPointerTo(),
+                              kTBAAJRuntime);
+
+  // Invoke callee
+  llvm::Value* retval = irb_.CreateCall(code_addr, args);
+
+  return retval;
+}
+
+llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::Value* dividend,
+                                            llvm::Value* divisor,
+                                            bool is_div, JType op_jty) {
+  // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
+
+  // Check the special case: MININT / -1 = MININT
+  // That case will cause overflow, which is undefined behavior in llvm.
+  // So we check the divisor is -1 or not, if the divisor is -1, we do
+  // the special path to avoid undefined behavior.
+  llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
+  llvm::Value* zero = irb_.getJZero(op_jty);
+  llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
+
+  llvm::BasicBlock::iterator div_rem_inst = irb_.GetInsertPoint();
+  llvm::Function* parent = irb_.GetInsertBlock()->getParent();
+
+  llvm::BasicBlock* begin_div_rem =
+    llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* neg_one_cont =
+    llvm::BasicBlock::Create(context_, "", parent);
+
+  irb_.SetInsertPoint(begin_div_rem);
+  llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
+  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
+
+  // If divisor == -1
+  irb_.SetInsertPoint(eq_neg_one);
+  llvm::Value* eq_result;
+  if (is_div) {
+    // We can just change from "dividend div -1" to "neg dividend". The sub
+    // don't care the sign/unsigned because of two's complement representation.
+    // And the behavior is what we want:
+    //  -(2^n)        (2^n)-1
+    //  MININT  < k <= MAXINT    ->     mul k -1  =  -k
+    //  MININT == k              ->     mul k -1  =   k
+    //
+    // LLVM use sub to represent 'neg'
+    eq_result = irb_.CreateSub(zero, dividend);
+  } else {
+    // Everything modulo -1 will be 0.
+    eq_result = zero;
+  }
+  irb_.CreateBr(neg_one_cont);
+
+  // If divisor != -1, just do the division.
+  irb_.SetInsertPoint(ne_neg_one);
+  llvm::Value* ne_result;
+  if (is_div) {
+    ne_result = irb_.CreateSDiv(dividend, divisor);
+  } else {
+    ne_result = irb_.CreateSRem(dividend, divisor);
+  }
+  irb_.CreateBr(neg_one_cont);
+
+  irb_.SetInsertPoint(neg_one_cont);
+  llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
+  result->addIncoming(eq_result, eq_neg_one);
+  result->addIncoming(ne_result, ne_neg_one);
+
+  SplitAndInsertBasicBlocksAfter(div_rem_inst, begin_div_rem, neg_one_cont);
+
+  return result;
+}
+
+void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
+  // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
+  // MethodCompiler::EmitPushShadowFrame
+  shadow_frame_size_ =
+    llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
+
+  llvm::StructType* shadow_frame_type =
+    irb_.getShadowFrameTy(shadow_frame_size_);
+
+  shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
+
+  // Alloca a pointer to old shadow frame
+  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,
+                                                 shadow_frame_size_);
+
+  irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
+
+  return;
+}
+
+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);
+  irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
+  return;
+}
+
+void GBCExpanderPass::Expand_PopShadowFrame() {
+  rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
+  return;
+}
+
+void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
+  irb_.StoreToObjectOffset(shadow_frame_,
+                           ShadowFrame::DexPCOffset(),
+                           dex_pc_value,
+                           kTBAAShadowFrame);
+  return;
+}
+
+bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
+  // DexLang generates all alloca instruction in the first basic block of the
+  // FUNC and also there's no any alloca instructions after the first non-alloca
+  // instruction
+
+  llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
+  while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
+    ++first_non_alloca;
+  }
+
+  // Insert stack overflow check codes before first_non_alloca (i.e., after all
+  // alloca instructions)
+  return EmitStackOverflowCheck(&*first_non_alloca);
+}
+
+llvm::Value*
+GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
+                                 llvm::CallInst& call_inst) {
+  switch (intr_id) {
+    //==- Thread -----------------------------------------------------------==//
+    case IntrinsicHelper::GetCurrentThread: {
+      return ExpandToRuntime(runtime_support::GetCurrentThread, call_inst);
+    }
+    case IntrinsicHelper::TestSuspend: {
+      Expand_TestSuspend(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::MarkGCCard: {
+      return ExpandToRuntime(runtime_support::MarkGCCard, call_inst);
+    }
+    //==- Exception --------------------------------------------------------==//
+    case IntrinsicHelper::ThrowException: {
+      return ExpandToRuntime(runtime_support::ThrowException, call_inst);
+    }
+    case IntrinsicHelper::GetException: {
+      return Expand_GetException();
+    }
+    case IntrinsicHelper::IsExceptionPending: {
+      return irb_.Runtime().EmitIsExceptionPending();
+    }
+    case IntrinsicHelper::FindCatchBlock: {
+      return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
+    }
+    case IntrinsicHelper::ThrowDivZeroException: {
+      return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
+    }
+    case IntrinsicHelper::ThrowNullPointerException: {
+      return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
+    }
+    case IntrinsicHelper::ThrowIndexOutOfBounds: {
+      return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
+    }
+    //==- ConstString ------------------------------------------------------==//
+    case IntrinsicHelper::LoadStringFromDexCache: {
+      return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::ResolveString: {
+      return ExpandToRuntime(runtime_support::ResolveString, call_inst);
+    }
+    //==- ConstClass -------------------------------------------------------==//
+    case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
+      return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
+    }
+    case IntrinsicHelper::LoadTypeFromDexCache: {
+      return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::InitializeType: {
+      return ExpandToRuntime(runtime_support::InitializeType, call_inst);
+    }
+    //==- Lock -------------------------------------------------------------==//
+    case IntrinsicHelper::LockObject: {
+      Expand_LockObject(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    case IntrinsicHelper::UnlockObject: {
+      Expand_UnlockObject(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    //==- Cast -------------------------------------------------------------==//
+    case IntrinsicHelper::CheckCast: {
+      return ExpandToRuntime(runtime_support::CheckCast, call_inst);
+    }
+    case IntrinsicHelper::IsAssignable: {
+      return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
+    }
+    //==- Alloc ------------------------------------------------------------==//
+    case IntrinsicHelper::AllocObject: {
+      return ExpandToRuntime(runtime_support::AllocObject, call_inst);
+    }
+    case IntrinsicHelper::AllocObjectWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
+    }
+    //==- Array ------------------------------------------------------------==//
+    case IntrinsicHelper::ArrayLength: {
+      return EmitLoadArrayLength(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::AllocArray: {
+      return ExpandToRuntime(runtime_support::AllocArray, call_inst);
+    }
+    case IntrinsicHelper::AllocArrayWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
+                             call_inst);
+    }
+    case IntrinsicHelper::CheckAndAllocArray: {
+      return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
+    }
+    case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
+                             call_inst);
+    }
+    case IntrinsicHelper::ArrayGet: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kInt);
+    }
+    case IntrinsicHelper::ArrayGetWide: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kLong);
+    }
+    case IntrinsicHelper::ArrayGetObject: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kObject);
+    }
+    case IntrinsicHelper::ArrayGetBoolean: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kBoolean);
+    }
+    case IntrinsicHelper::ArrayGetByte: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kByte);
+    }
+    case IntrinsicHelper::ArrayGetChar: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kChar);
+    }
+    case IntrinsicHelper::ArrayGetShort: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kShort);
+    }
+    case IntrinsicHelper::ArrayPut: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutWide: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutObject: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutBoolean: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutByte: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutChar: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutShort: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::CheckPutArrayElement: {
+      return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
+    }
+    case IntrinsicHelper::FilledNewArray: {
+      Expand_FilledNewArray(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::FillArrayData: {
+      return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
+    }
+    //==- Instance Field ---------------------------------------------------==//
+    case IntrinsicHelper::InstanceFieldGet:
+    case IntrinsicHelper::InstanceFieldGetBoolean:
+    case IntrinsicHelper::InstanceFieldGetByte:
+    case IntrinsicHelper::InstanceFieldGetChar:
+    case IntrinsicHelper::InstanceFieldGetShort: {
+      return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetWide: {
+      return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetObject: {
+      return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kInt);
+    }
+    case IntrinsicHelper::InstanceFieldGetWideFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kLong);
+    }
+    case IntrinsicHelper::InstanceFieldGetObjectFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kObject);
+    }
+    case IntrinsicHelper::InstanceFieldGetBooleanFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kBoolean);
+    }
+    case IntrinsicHelper::InstanceFieldGetByteFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kByte);
+    }
+    case IntrinsicHelper::InstanceFieldGetCharFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kChar);
+    }
+    case IntrinsicHelper::InstanceFieldGetShortFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kShort);
+    }
+    case IntrinsicHelper::InstanceFieldPut:
+    case IntrinsicHelper::InstanceFieldPutBoolean:
+    case IntrinsicHelper::InstanceFieldPutByte:
+    case IntrinsicHelper::InstanceFieldPutChar:
+    case IntrinsicHelper::InstanceFieldPutShort: {
+      return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutWide: {
+      return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutObject: {
+      return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutWideFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutObjectFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutBooleanFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutByteFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutCharFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutShortFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kShort);
+      return NULL;
+    }
+    //==- Static Field -----------------------------------------------------==//
+    case IntrinsicHelper::StaticFieldGet:
+    case IntrinsicHelper::StaticFieldGetBoolean:
+    case IntrinsicHelper::StaticFieldGetByte:
+    case IntrinsicHelper::StaticFieldGetChar:
+    case IntrinsicHelper::StaticFieldGetShort: {
+      return ExpandToRuntime(runtime_support::Get32Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetWide: {
+      return ExpandToRuntime(runtime_support::Get64Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetObject: {
+      return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kInt);
+    }
+    case IntrinsicHelper::StaticFieldGetWideFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kLong);
+    }
+    case IntrinsicHelper::StaticFieldGetObjectFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kObject);
+    }
+    case IntrinsicHelper::StaticFieldGetBooleanFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kBoolean);
+    }
+    case IntrinsicHelper::StaticFieldGetByteFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kByte);
+    }
+    case IntrinsicHelper::StaticFieldGetCharFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kChar);
+    }
+    case IntrinsicHelper::StaticFieldGetShortFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kShort);
+    }
+    case IntrinsicHelper::StaticFieldPut:
+    case IntrinsicHelper::StaticFieldPutBoolean:
+    case IntrinsicHelper::StaticFieldPutByte:
+    case IntrinsicHelper::StaticFieldPutChar:
+    case IntrinsicHelper::StaticFieldPutShort: {
+      return ExpandToRuntime(runtime_support::Set32Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutWide: {
+      return ExpandToRuntime(runtime_support::Set64Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutObject: {
+      return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutWideFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutObjectFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutBooleanFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutByteFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutCharFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutShortFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::LoadDeclaringClassSSB: {
+      return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::LoadClassSSBFromDexCache: {
+      return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::InitializeAndLoadClassSSB: {
+      return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
+    }
+    //==- Invoke -----------------------------------------------------------==//
+    case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
+      return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
+      return Expand_GetVirtualCalleeMethodObjAddrFast(
+                call_inst.getArgOperand(0), call_inst.getArgOperand(1));
+    }
+    case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
+      return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
+    }
+    case IntrinsicHelper::InvokeRetVoid:
+    case IntrinsicHelper::InvokeRetBoolean:
+    case IntrinsicHelper::InvokeRetByte:
+    case IntrinsicHelper::InvokeRetChar:
+    case IntrinsicHelper::InvokeRetShort:
+    case IntrinsicHelper::InvokeRetInt:
+    case IntrinsicHelper::InvokeRetLong:
+    case IntrinsicHelper::InvokeRetFloat:
+    case IntrinsicHelper::InvokeRetDouble:
+    case IntrinsicHelper::InvokeRetObject: {
+      return Expand_Invoke(call_inst);
+    }
+    //==- Math -------------------------------------------------------------==//
+    case IntrinsicHelper::DivInt: {
+      return Expand_DivRem(call_inst.getArgOperand(0),
+                           call_inst.getArgOperand(1),
+                           /* is_div */true, kInt);
+    }
+    case IntrinsicHelper::RemInt: {
+      return Expand_DivRem(call_inst.getArgOperand(0),
+                           call_inst.getArgOperand(1),
+                           /* is_div */false, kInt);
+    }
+    case IntrinsicHelper::DivLong: {
+      return Expand_DivRem(call_inst.getArgOperand(0),
+                           call_inst.getArgOperand(1),
+                           /* is_div */true, kLong);
+    }
+    case IntrinsicHelper::RemLong: {
+      return Expand_DivRem(call_inst.getArgOperand(0),
+                           call_inst.getArgOperand(1),
+                           /* is_div */false, kLong);
+    }
+    case IntrinsicHelper::D2L: {
+      return ExpandToRuntime(runtime_support::art_d2l, call_inst);
+    }
+    case IntrinsicHelper::D2I: {
+      return ExpandToRuntime(runtime_support::art_d2i, call_inst);
+    }
+    case IntrinsicHelper::F2L: {
+      return ExpandToRuntime(runtime_support::art_f2l, call_inst);
+    }
+    case IntrinsicHelper::F2I: {
+      return ExpandToRuntime(runtime_support::art_f2i, call_inst);
+    }
+    //==- Shadow Frame -----------------------------------------------------==//
+    case IntrinsicHelper::AllocaShadowFrame: {
+      Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    case IntrinsicHelper::SetShadowFrameEntry: {
+      Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1));
+      return NULL;
+    }
+    case IntrinsicHelper::PopShadowFrame: {
+      Expand_PopShadowFrame();
+      return NULL;
+    }
+    case IntrinsicHelper::UpdateDexPC: {
+      Expand_UpdateDexPC(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    default: {
+      const IntrinsicHelper::IntrinsicInfo& intr_info =
+          IntrinsicHelper::GetInfo(intr_id);
+
+      UNIMPLEMENTED(FATAL) << "expand DexLang intrinsic: " << intr_info.name_;
+      break;
+    }
+  }
+  return NULL;
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace compiler_llvm {
+
+llvm::FunctionPass*
+CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
+  return new GBCExpanderPass(intrinsic_helper, irb);
+}
+
+} // namespace compiler_llvm
+} // namespace art
diff --git a/src/greenland/arm/arm_codegen_machine.h b/src/greenland/arm/arm_codegen_machine.h
index c78ddf8..8639417 100644
--- a/src/greenland/arm/arm_codegen_machine.h
+++ b/src/greenland/arm/arm_codegen_machine.h
@@ -29,9 +29,27 @@
   ARMCodeGenMachine();
   virtual ~ARMCodeGenMachine();
 
-  virtual TargetLIREmitter* CreateLIREmitter(const llvm::Function& func,
-                                             const OatCompilationUnit& cunit,
-                                             DexLang::Context& dex_lang_ctx) {
+  virtual TargetLIREmitter* CreateLIREmitter() {
+    return NULL;
+  }
+
+  virtual const TargetDataLayout* GetDataLayout() const {
+    return NULL;
+  }
+
+  virtual const TargetLIRInfo* GetLIRInfo() const {
+    return NULL;
+  }
+
+  virtual const TargetRegisterInfo* GetRegisterInfo() const {
+    return NULL;
+  }
+
+  virtual const char* GetConditionCodeName(unsigned cond) const {
+    return NULL;
+  }
+
+  virtual TargetLIRBuilder* CreateLIRBuilder() {
     return NULL;
   }
 
@@ -42,6 +60,10 @@
   virtual TargetAssembler* GetAssembler() {
     return NULL;
   }
+
+  virtual std::string PrettyTargeteLIR(const LIR& lir) const {
+    return "";
+  }
 };
 
 } // namespace greenland
diff --git a/src/greenland/dalvik_reg.cc b/src/greenland/dalvik_reg.cc
index eb4a89c..3155a8c 100644
--- a/src/greenland/dalvik_reg.cc
+++ b/src/greenland/dalvik_reg.cc
@@ -16,350 +16,201 @@
 
 #include "dalvik_reg.h"
 
-#include "dex_lang.h"
 #include "ir_builder.h"
-#include "intrinsic_helper.h"
+#include "dex_lang.h"
 
-#include <llvm/Function.h>
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-  class DalvikArgReg : public DalvikReg {
-   public:
-    DalvikArgReg(DexLang& dex_lang, unsigned reg_idx, JType jty);
-
-    virtual llvm::Value* GetValue(JType jty, JTypeSpace space);
-    virtual void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
-
-   private:
-    llvm::Value* reg_addr_;
-    JType jty_;
-
-    inline void CheckJType(JType jty) const {
-      CHECK_EQ(jty, jty_) << "Get value of type " << jty << " from Dalvik "
-                             "argument register v" << reg_idx_ << "(type: "
-                          << jty_ << ") without type coercion!";
-      return;
-    }
-  };
-
-  class DalvikLocalVarReg : public DalvikReg {
-   public:
-    DalvikLocalVarReg(DexLang& dex_lang, unsigned reg_idx);
-
-    virtual llvm::Value* GetValue(JType jty, JTypeSpace space);
-    virtual void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
-
-   private:
-    llvm::Value* GetRawAddr(RegCategory cat);
-
-   private:
-    llvm::Value* reg_32_;
-    llvm::Value* reg_64_;
-    llvm::Value* reg_obj_;
-  };
-} // anonymous namespace
-
+namespace art {
+namespace greenland {
 
 //----------------------------------------------------------------------------
 // Dalvik Register
 //----------------------------------------------------------------------------
 
-DalvikReg* DalvikReg::CreateArgReg(DexLang& dex_lang, unsigned reg_idx,
-                                   JType jty) {
-  return new DalvikArgReg(dex_lang, reg_idx, jty);
-}
-
-DalvikReg* DalvikReg::CreateLocalVarReg(DexLang& dex_lang, unsigned reg_idx) {
-  return new DalvikLocalVarReg(dex_lang, reg_idx);
-}
-
 DalvikReg::DalvikReg(DexLang& dex_lang, unsigned reg_idx)
-    : dex_lang_(dex_lang), irb_(dex_lang.GetIRBuilder()), reg_idx_(reg_idx),
-      shadow_frame_entry_idx_(-1) {
+: dex_lang_(dex_lang), irb_(dex_lang.GetIRBuilder()),
+  reg_idx_(reg_idx), shadow_frame_entry_idx_(-1),
+  reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
 }
 
-void DalvikReg::SetShadowEntry(llvm::Value* root_object) {
+DalvikReg::~DalvikReg() {
+}
+
+void DalvikReg::SetShadowEntry(llvm::Value* object) {
   if (shadow_frame_entry_idx_ < 0) {
     shadow_frame_entry_idx_ = dex_lang_.AllocShadowFrameEntry(reg_idx_);
   }
 
   irb_.CreateCall2(irb_.GetIntrinsics(IntrinsicHelper::SetShadowFrameEntry),
-                  root_object, irb_.getInt32(shadow_frame_entry_idx_));
+                   object, irb_.getInt32(shadow_frame_entry_idx_));
 
   return;
 }
 
-//----------------------------------------------------------------------------
-// Dalvik Argument Register
-//----------------------------------------------------------------------------
-DalvikArgReg::DalvikArgReg(DexLang& dex_lang, unsigned reg_idx, JType jty)
-    : DalvikReg(dex_lang, reg_idx), jty_(jty) {
-  reg_addr_ = dex_lang_.AllocateDalvikReg(jty, reg_idx);
-  DCHECK(reg_addr_ != NULL);
+llvm::Type* DalvikReg::GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat) {
+  switch (reg_cat) {
+  case kRegCat1nr:  return irb.GetJIntTy();
+  case kRegCat2:    return irb.GetJLongTy();
+  case kRegObject:  return irb.GetJObjectTy();
+  default:
+    LOG(FATAL) << "Unknown register category: " << reg_cat;
+    return NULL;
+  }
 }
 
-llvm::Value* DalvikArgReg::GetValue(JType jty, JTypeSpace space) {
+char DalvikReg::GetRegCategoryNamePrefix(RegCategory reg_cat) {
+  switch (reg_cat) {
+  case kRegCat1nr:  return 'r';
+  case kRegCat2:    return 'w';
+  case kRegObject:  return 'p';
+  default:
+    LOG(FATAL) << "Unknown register category: " << reg_cat;
+    return '\0';
+  }
+}
+
+inline llvm::Value* DalvikReg::RegCat1SExt(llvm::Value* value) {
+  return irb_.CreateSExt(value, irb_.GetJIntTy());
+}
+
+inline llvm::Value* DalvikReg::RegCat1ZExt(llvm::Value* value) {
+  return irb_.CreateZExt(value, irb_.GetJIntTy());
+}
+
+inline llvm::Value* DalvikReg::RegCat1Trunc(llvm::Value* value,
+                                            llvm::Type* ty) {
+  return irb_.CreateTrunc(value, ty);
+}
+
+llvm::Value* DalvikReg::GetValue(JType jty, JTypeSpace space) {
   DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
 
+  llvm::Value* value = NULL;
   switch (space) {
-    case kReg:
-    case kField: {
-      // Currently, kField is almost the same with kReg.
-      RegCategory cat = GetRegCategoryFromJType(jty_);
-      CHECK_EQ(cat, GetRegCategoryFromJType(jty)) << "Get value of type " << jty
-                                                  << "has different register "
-                                                     "category from the value "
-                                                     "contained in the register"
-                                                  << reg_idx_ << "(type: "
-                                                  << jty_ << ")";
-      switch (jty_) {
-        case kVoid: {
-          break;
-        }
-        case kBoolean:
-        case kChar: {
-          return irb_.CreateZExt(irb_.CreateLoad(reg_addr_), irb_.GetJIntTy());
-        }
-        case kByte:
-        case kShort: {
-          return irb_.CreateSExt(irb_.CreateLoad(reg_addr_), irb_.GetJIntTy());
-        }
-        case kFloat: {
-          return irb_.CreateBitCast(irb_.CreateLoad(reg_addr_),
-                                    irb_.GetJIntTy());
-        }
-        case kDouble: {
-          return irb_.CreateBitCast(irb_.CreateLoad(reg_addr_),
-                                    irb_.GetJLongTy());
-        }
-        case kInt:
-        case kLong:
-        case kObject: {
-          return irb_.CreateLoad(reg_addr_);
-        }
-        default: {
-          LOG(FATAL) << "Unexpected register type: " << jty;
-          break;
-        }
-      }
+  case kReg:
+  case kField:
+    value = irb_.CreateLoad(GetAddr(jty));
+    break;
+
+  case kAccurate:
+  case kArray:
+    switch (jty) {
+    case kVoid:
+      LOG(FATAL) << "Dalvik register with void type has no value";
+      return NULL;
+
+    case kBoolean:
+    case kChar:
+    case kByte:
+    case kShort:
+      // NOTE: In array type space, boolean is truncated from i32 to i8, while
+      // in accurate type space, boolean is truncated from i32 to i1.
+      // For the other cases, array type space is equal to accurate type space.
+      value = RegCat1Trunc(irb_.CreateLoad(GetAddr(jty)),
+                           irb_.GetJType(jty, space));
       break;
-    }
-    case kArray: {
-      switch (jty) {
-        case kVoid: {
-          LOG(FATAL) << "Dalvik register with void type has no value";
-          return NULL;
-        }
-        case kBoolean: {
-          CheckJType(jty);
-          // NOTE: In array type space, boolean is i8, while in accurate type
-          // space, boolean is i1. For the other cases, array type space is
-          // equal to accurate type space.
-          return irb_.CreateZExt(irb_.CreateLoad(reg_addr_), irb_.GetJByteTy());
-        }
-        case kByte:
-        case kChar:
-        case kShort:
-        case kInt:
-        case kLong:
-        case kFloat:
-        case kDouble:
-        case kObject: {
-          CheckJType(jty);
-          return irb_.CreateLoad(reg_addr_);
-        }
-        default: {
-          LOG(FATAL) << "Unexpected register type: " << jty;
-          break;
-        }
-      }
-    }
-    case kAccurate: {
-      CheckJType(jty);
-      return irb_.CreateLoad(reg_addr_);
-    }
-  }
-  return NULL;
-}
 
-void DalvikArgReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
-  if ((jty == jty_) && (space == kAccurate)) {
-    irb_.CreateStore(value, reg_addr_);
-    if (jty == kObject) {
-      SetShadowEntry(value);
-    }
-  } else {
-    LOG(FATAL) << "Normal .dex file doesn't use argument register for method-"
-                  "local variable!";
-  }
-  return;
-}
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kObject:
+      value = irb_.CreateLoad(GetAddr(jty));
+      break;
 
-//----------------------------------------------------------------------------
-// Dalvik Local Variable Register
-//----------------------------------------------------------------------------
-
-DalvikLocalVarReg::DalvikLocalVarReg(DexLang& dex_lang, unsigned reg_idx)
-    : DalvikReg(dex_lang, reg_idx), reg_32_(NULL), reg_64_(NULL),
-      reg_obj_(NULL) {
-}
-
-llvm::Value* DalvikLocalVarReg::GetRawAddr(RegCategory cat) {
-  switch (cat) {
-    case kRegCat1nr: {
-      if (reg_32_ == NULL) {
-        reg_32_ = dex_lang_.AllocateDalvikReg(kInt, reg_idx_);
-      }
-      return reg_32_;
-    }
-    case kRegCat2: {
-      if (reg_64_ == NULL) {
-        reg_64_ = dex_lang_.AllocateDalvikReg(kLong, reg_idx_);
-      }
-      return reg_64_;
-    }
-    case kRegObject: {
-      if (reg_obj_ == NULL) {
-        reg_obj_ = dex_lang_.AllocateDalvikReg(kObject, reg_idx_);
-      }
-      return reg_obj_;
-    }
-    default: {
-      LOG(FATAL) << "Unexpected register category: " << cat;
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
       return NULL;
     }
+    break;
+
+  default:
+    LOG(FATAL) << "Couldn't GetValue of JType " << jty;
+    return NULL;
   }
-  return NULL;
+
+  if (jty == kFloat || jty == kDouble) {
+    value = irb_.CreateBitCast(value, irb_.GetJType(jty, space));
+  }
+  return value;
 }
 
-llvm::Value* DalvikLocalVarReg::GetValue(JType jty, JTypeSpace space) {
+void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
   DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
 
-  switch (space) {
-    case kReg:
-    case kField: {
-      // float and double require bitcast to get their value from the integer
-      // register.
-      DCHECK((jty != kFloat) && (jty != kDouble));
-      return irb_.CreateLoad(GetRawAddr(GetRegCategoryFromJType(jty)));
-    }
-    case kAccurate:
-    case kArray: {
-      switch (jty) {
-        case kVoid: {
-          LOG(FATAL) << "Dalvik register with void type has no value";
-          return NULL;
-        }
-        case kBoolean:
-        case kChar:
-        case kByte:
-        case kShort: {
-          // NOTE: In array type space, boolean is truncated from i32 to i8,
-          // while in accurate type space, boolean is truncated from i32 to i1.
-          // For the other cases, array type space is equal to accurate type
-          // space.
-          return irb_.CreateTrunc(irb_.CreateLoad(GetRawAddr(kRegCat1nr)),
-                                  irb_.GetJType(jty, space));
-        }
-        case kFloat: {
-          return irb_.CreateBitCast(irb_.CreateLoad(GetRawAddr(kRegCat1nr)),
-                                    irb_.GetJType(jty, space));
-        }
-        case kDouble: {
-          return irb_.CreateBitCast(irb_.CreateLoad(GetRawAddr(kRegCat2)),
-                                    irb_.GetJType(jty, space));
-        }
-        case kInt:
-        case kLong:
-        case kObject: {
-          return irb_.CreateLoad(GetRawAddr(GetRegCategoryFromJType(jty)));
-        }
-        default: {
-          LOG(FATAL) << "Unexpected register type: " << jty;
-          break;
-        }
-      }
-    }
-    default: {
-      LOG(FATAL) << "Unexpected register space: " << space;
-      break;
-    }
-  }
-  return NULL;
-}
-
-void DalvikLocalVarReg::SetValue(JType jty, JTypeSpace space,
-                                 llvm::Value* value) {
-  DCHECK_NE(jty, kVoid) << "Dalvik register should never hold void type";
-
   if (jty == kObject) {
     SetShadowEntry(value);
+  } else if (jty == kFloat || jty == kDouble) {
+    value = irb_.CreateBitCast(value, irb_.GetJType(jty, kReg));
   }
 
   switch (space) {
-    case kReg:
-    case kField: {
-      // float and double require bitcast to get their value from the integer
-      // register.
-      DCHECK((jty != kFloat) && (jty != kDouble));
-      irb_.CreateStore(value, GetRawAddr(GetRegCategoryFromJType(jty)));
-      return;
-    }
-    case kAccurate:
-    case kArray: {
-      switch (jty) {
-        case kVoid: {
-          break;
-        }
-        case kBoolean:
-        case kChar: {
-          // NOTE: In accurate type space, we have to zero extend boolean from
-          // i1 to i32, and char from i16 to i32.  In array type space, we have
-          // to zero extend boolean from i8 to i32, and char from i16 to i32.
-          value = irb_.CreateZExt(value, irb_.GetJIntTy());
-          irb_.CreateStore(value, GetRawAddr(kRegCat1nr));
-          break;
-        }
-        case kByte:
-        case kShort: {
-          // NOTE: In accurate type space, we have to signed extend byte from
-          // i8 to i32, and short from i16 to i32.  In array type space, we have
-          // to sign extend byte from i8 to i32, and short from i16 to i32.
-          value = irb_.CreateSExt(value, irb_.GetJIntTy());
-          irb_.CreateStore(value, GetRawAddr(kRegCat1nr));
-          break;
-        }
-        case kFloat: {
-          value = irb_.CreateBitCast(value, irb_.GetJIntTy());
-          irb_.CreateStore(value, GetRawAddr(kRegCat1nr));
-          break;
-        }
-        case kDouble: {
-          value = irb_.CreateBitCast(value, irb_.GetJLongTy());
-          irb_.CreateStore(value, GetRawAddr(kRegCat2));
-          break;
-        }
-        case kInt:
-        case kLong:
-        case kObject: {
-          irb_.CreateStore(value, GetRawAddr(GetRegCategoryFromJType(jty)));
-          break;
-        }
-        default: {
-          LOG(FATAL) << "Unexpected register type: " << jty;
-          return;
-        }
-      }
-      return;
-    }
-    default: {
-      LOG(FATAL) << "Unexpected register space: " << space;
-      return;
+  case kReg:
+  case kField:
+    irb_.CreateStore(value, GetAddr(jty));
+    return;
+
+  case kAccurate:
+  case kArray:
+    switch (jty) {
+    case kVoid:
+      break;
+
+    case kBoolean:
+    case kChar:
+      // NOTE: In accurate type space, we have to zero extend boolean from
+      // i1 to i32, and char from i16 to i32.  In array type space, we have
+      // to zero extend boolean from i8 to i32, and char from i16 to i32.
+      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty));
+      break;
+
+    case kByte:
+    case kShort:
+      // NOTE: In accurate type space, we have to signed extend byte from
+      // i8 to i32, and short from i16 to i32.  In array type space, we have
+      // to sign extend byte from i8 to i32, and short from i16 to i32.
+      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty));
+      break;
+
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kObject:
+      irb_.CreateStore(value, GetAddr(jty));
+      break;
+
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
     }
   }
 }
 
+llvm::Value* DalvikReg::GetAddr(JType jty) {
+  switch (GetRegCategoryFromJType(jty)) {
+  case kRegCat1nr:
+    if (reg_32_ == NULL) {
+      reg_32_ = dex_lang_.AllocateDalvikReg(kRegCat1nr, reg_idx_);
+    }
+    return reg_32_;
+
+  case kRegCat2:
+    if (reg_64_ == NULL) {
+      reg_64_ = dex_lang_.AllocateDalvikReg(kRegCat2, reg_idx_);
+    }
+    return reg_64_;
+
+  case kRegObject:
+    if (reg_obj_ == NULL) {
+      reg_obj_ = dex_lang_.AllocateDalvikReg(kRegObject, reg_idx_);
+    }
+    return reg_obj_;
+
+  default:
+    LOG(FATAL) << "Unexpected register category: "
+               << GetRegCategoryFromJType(jty);
+    return NULL;
+  }
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/dalvik_reg.h b/src/greenland/dalvik_reg.h
index 78247cc..93524cc 100644
--- a/src/greenland/dalvik_reg.h
+++ b/src/greenland/dalvik_reg.h
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_GREENLAND_DALVIK_REG_H_
-#define ART_SRC_GREENLAND_DALVIK_REG_H_
+#ifndef ART_SRC_COMPILER_LLVM_DALVIK_REG_H_
+#define ART_SRC_COMPILER_LLVM_DALVIK_REG_H_
 
 #include "backend_types.h"
 
+#include <stdint.h>
+#include <string>
+
 namespace llvm {
   class Type;
   class Value;
@@ -27,41 +30,54 @@
 namespace art {
 namespace greenland {
 
-class DexLang;
 class IRBuilder;
+class DexLang;
 
 class DalvikReg {
  public:
-  static DalvikReg* CreateArgReg(DexLang& dex_lang, unsigned reg_idx,
-                                 JType jty);
+  static llvm::Type* GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat);
 
-  static DalvikReg* CreateLocalVarReg(DexLang& dex_lang, unsigned reg_idx);
+  static char GetRegCategoryNamePrefix(RegCategory reg_cat);
 
-  virtual ~DalvikReg() { }
+  DalvikReg(DexLang& dex_lang, unsigned reg_idx);
 
-  virtual llvm::Value* GetValue(JType jty, JTypeSpace space) = 0;
+  ~DalvikReg();
+
+  llvm::Value* GetValue(JType jty, JTypeSpace space);
+
   llvm::Value* GetValue(char shorty, JTypeSpace space) {
     return GetValue(GetJTypeFromShorty(shorty), space);
   }
 
-  virtual void SetValue(JType jty, JTypeSpace space, llvm::Value* value) = 0;
+  void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
+
   void SetValue(char shorty, JTypeSpace space, llvm::Value* value) {
     return SetValue(GetJTypeFromShorty(shorty), space, value);
   }
 
- protected:
-  DalvikReg(DexLang& dex_lang, unsigned reg_idx);
+ private:
+  void SetShadowEntry(llvm::Value* object);
 
-  void SetShadowEntry(llvm::Value* root_object);
+  llvm::Value* GetAddr(JType jty);
 
- protected:
+  llvm::Value* RegCat1SExt(llvm::Value* value);
+  llvm::Value* RegCat1ZExt(llvm::Value* value);
+
+  llvm::Value* RegCat1Trunc(llvm::Value* value, llvm::Type* ty);
+
   DexLang& dex_lang_;
   IRBuilder& irb_;
+
   unsigned reg_idx_;
+
   int shadow_frame_entry_idx_;
+
+  llvm::Value* reg_32_;
+  llvm::Value* reg_64_;
+  llvm::Value* reg_obj_;
 };
 
 } // namespace greenland
 } // namespace art
 
-#endif // ART_SRC_GREENLAND_DALVIK_REG_H_
+#endif // ART_SRC_COMPILER_LLVM_DALVIK_REG_H_
diff --git a/src/greenland/dex_lang.cc b/src/greenland/dex_lang.cc
index 135cbd7..0e34492 100644
--- a/src/greenland/dex_lang.cc
+++ b/src/greenland/dex_lang.cc
@@ -18,8 +18,7 @@
 
 #include "intrinsic_helper.h"
 
-#include "atomic.h"
-#include "inferred_reg_category_map.h"
+#include "compiler_llvm/inferred_reg_category_map.h"
 #include "object.h" // FIXME: include this in oat_compilation_unit.h
 #include "oat_compilation_unit.h"
 #include "stl_util.h"
@@ -41,21 +40,10 @@
 //----------------------------------------------------------------------------
 // DexLang::Context
 //----------------------------------------------------------------------------
-DexLang::Context::Context()
-    : context_(), module_(NULL), ref_count_(1), mem_usage_(0) {
-  module_ = new llvm::Module("art", context_);
-
-  // Initialize the contents of an empty module
-  // Type of "JavaObject"
-  llvm::StructType::create(context_, "JavaObject");
-  // Type of "Method"
-  llvm::StructType::create(context_, "Method");
-  // Type of "Thread"
-  llvm::StructType::create(context_, "Thread");
-
+DexLang::Context::Context(llvm::Module& module)
+    : module_(module), intrinsic_helper_(NULL) {
   // Initalize the DexLang intrinsics
-  intrinsic_helper_ = new IntrinsicHelper(context_, *module_);
-
+  intrinsic_helper_ = new IntrinsicHelper(GetLLVMContext(), module_);
   return;
 }
 
@@ -64,42 +52,24 @@
   return;
 }
 
-DexLang::Context& DexLang::Context::IncRef() {
-  android_atomic_inc(&ref_count_);
-  return *this;
-}
-
-void DexLang::Context::DecRef() {
-  int32_t old_ref_count = android_atomic_dec(&ref_count_);
-  if (old_ref_count <= 1) {
-    delete this;
-  }
-  return;
-}
-
-void DexLang::Context::AddMemUsageApproximation(size_t usage) {
-  android_atomic_add(static_cast<int32_t>(usage), &mem_usage_);
-  return;
-}
-
 //----------------------------------------------------------------------------
 // Constructor, Destructor and APIs
 //----------------------------------------------------------------------------
 DexLang::DexLang(DexLang::Context& context, Compiler& compiler,
                  OatCompilationUnit& cunit)
-    : dex_lang_ctx_(context.IncRef()), compiler_(compiler), cunit_(cunit),
+    : dex_lang_ctx_(context), compiler_(compiler), cunit_(cunit),
       dex_file_(cunit.GetDexFile()), code_item_(cunit.GetCodeItem()),
-      dex_cache_(cunit.GetDexCache()),
+      dex_cache_(cunit.GetDexCache()), method_idx_(cunit.GetDexMethodIndex()),
       context_(context.GetLLVMContext()), module_(context.GetOutputModule()),
       intrinsic_helper_(context.GetIntrinsicHelper()),
       irb_(context.GetLLVMContext(), context.GetOutputModule(),
            context.GetIntrinsicHelper()),
       func_(NULL), reg_alloc_bb_(NULL), arg_reg_init_bb_(NULL),
       basic_blocks_(cunit.GetCodeItem()->insns_size_in_code_units_),
-      retval_(NULL), retval_jty_(kVoid),
+      retval_reg_(NULL),
       landing_pads_bb_(cunit.GetCodeItem()->tries_size_, NULL),
       exception_unwind_bb_(NULL), cur_try_item_offset(-1),
-      require_shadow_frame(false), num_shadow_frame_entries_(0) {
+      num_shadow_frame_entries_(0) {
   if (cunit.GetCodeItem()->tries_size_ > 0) {
     cur_try_item_offset = 0;
   }
@@ -107,7 +77,7 @@
 }
 
 DexLang::~DexLang() {
-  dex_lang_ctx_.DecRef();
+  delete retval_reg_;
   return;
 }
 
@@ -119,44 +89,27 @@
       !EmitPrologueLinkBasicBlocks() ||
       !PrettyLayoutExceptionBasicBlocks() ||
       !VerifyFunction() ||
+      // CompilerLLVM has its own optimizer
+#ifndef ART_USE_LLVM_COMPILER
       !OptimizeFunction() ||
-      !RemoveRedundantPendingExceptionChecks()) {
+      !RemoveRedundantPendingExceptionChecks() ||
+#endif
+      0) {
     return NULL;
   }
 
-  // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
-  // Dex file.  Besides, we have to convert the code unit into bytes.
-  // Thus, we got our magic number 9.
-  dex_lang_ctx_.AddMemUsageApproximation(
-      code_item_->insns_size_in_code_units_ * 900);
-
   return func_;
 }
 
-llvm::Value* DexLang::AllocateDalvikReg(JType jty, unsigned reg_idx) {
-  RegCategory cat = GetRegCategoryFromJType(jty);
-  llvm::Type* type = irb_.GetJType(jty, kAccurate);
-
-  DCHECK_NE(type, static_cast<llvm::Type*>(NULL));
-
+llvm::Value* DexLang::AllocateDalvikReg(RegCategory cat, unsigned reg_idx) {
+  // Get reg_type and reg_name from DalvikReg
+  llvm::Type* reg_type = DalvikReg::GetRegCategoryEquivSizeTy(irb_, cat);
   std::string reg_name;
-  switch (cat) {
-    case kRegCat1nr: {
-      reg_name = StringPrintf("r%u", reg_idx);
-      break;
-    }
-    case kRegCat2: {
-      reg_name = StringPrintf("w%u", reg_idx);
-      break;
-    }
-    case kRegObject: {
-      reg_name = StringPrintf("p%u", reg_idx);
-      break;
-    }
-    default: {
-      LOG(FATAL) << "Unknown register category for allocation: " << cat;
-    }
-  }
+
+#if !defined(NDEBUG)
+  StringAppendF(&reg_name, "%c%u",
+                DalvikReg::GetRegCategoryNamePrefix(cat), reg_idx);
+#endif
 
   // Save current IR builder insert point
   DCHECK(reg_alloc_bb_ != NULL);
@@ -164,13 +117,12 @@
   irb_.SetInsertPoint(reg_alloc_bb_);
 
   // Alloca
-  llvm::Value* reg_addr = irb_.CreateAlloca(type, 0, reg_name);
+  llvm::Value* reg_addr = irb_.CreateAlloca(reg_type, 0, reg_name);
 
   // Restore IRBuilder insert point
   irb_.restoreIP(irb_ip_original);
 
   DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
-
   return reg_addr;
 }
 
@@ -278,8 +230,8 @@
   llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
 
   llvm::Value* catch_handler_index_value =
-      EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::FindCatchBlock,
-                           method_object_addr, ti_offset_value);
+      EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::FindCatchBlock,
+                                  method_object_addr, ti_offset_value);
 
   // Switch instruction (Go to unwind basic block by default)
   llvm::SwitchInst* sw =
@@ -356,11 +308,10 @@
   irb_.CreateCondBr(equal_zero, block_exception, block_continue);
 
   irb_.SetInsertPoint(block_exception);
-  EmitUpdateDexPC(dex_pc);
   EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::ThrowDivZeroException);
-  EmitBranchExceptionLandingPad(dex_pc);
 
   irb_.SetInsertPoint(block_continue);
+  return;
 }
 
 void DexLang::EmitGuard_NullPointerException(unsigned dex_pc,
@@ -377,12 +328,11 @@
 
   irb_.SetInsertPoint(block_exception);
 
-  EmitUpdateDexPC(dex_pc);
   EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::ThrowNullPointerException,
                       irb_.getInt32(dex_pc));
-  EmitBranchExceptionLandingPad(dex_pc);
 
   irb_.SetInsertPoint(block_continue);
+  return;
 }
 
 void
@@ -403,10 +353,8 @@
 
   irb_.SetInsertPoint(block_exception);
 
-  EmitUpdateDexPC(dex_pc);
   EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::ThrowIndexOutOfBounds,
                        index, array_len);
-  EmitBranchExceptionLandingPad(dex_pc);
 
   irb_.SetInsertPoint(block_continue);
   return;
@@ -420,7 +368,7 @@
 
 void DexLang::EmitGuard_ExceptionLandingPad(unsigned dex_pc) {
   llvm::Value* exception_pending =
-      EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::IsExceptionPending);
+      EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IsExceptionPending);
 
   llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
 
@@ -431,6 +379,7 @@
   }
 
   irb_.SetInsertPoint(block_cont);
+  return;
 }
 
 //----------------------------------------------------------------------------
@@ -446,7 +395,6 @@
 // Shadow Frame
 //----------------------------------------------------------------------------
 void DexLang::EmitUpdateDexPC(unsigned dex_pc) {
-  require_shadow_frame = true;
   EmitInvokeIntrinsicNoThrow(IntrinsicHelper::UpdateDexPC,
                              irb_.getInt32(dex_pc));
   return;
@@ -465,7 +413,7 @@
 // Code Generation
 //----------------------------------------------------------------------------
 bool DexLang::CreateFunction() {
-  std::string func_name(PrettyMethod(cunit_.GetDexMethodIndex(), *dex_file_,
+  std::string func_name(PrettyMethod(method_idx_, *dex_file_,
                                      /* with_signature */false));
   llvm::FunctionType* func_type = GetFunctionType();
 
@@ -521,54 +469,22 @@
   return llvm::FunctionType::get(ret_type, args_type, false);
 }
 
-bool DexLang::PrepareDalvikRegs() {
-  const unsigned num_regs = code_item_->registers_size_;
-  const unsigned num_ins = code_item_->ins_size_;
-  unsigned reg_idx = 0;
-
-  // Registers v[0..(num_regs - num_ins - 1)] are used for local variable
-  for (; reg_idx < (num_regs - num_ins); reg_idx++) {
-    regs_.push_back(DalvikReg::CreateLocalVarReg(*this, reg_idx));
-  }
-
-  // Registers v[(num_regs - num_ins)..(num_regs - 1)] are used for input
-  // argument
-  uint32_t shorty_size;
-  const char* shorty = cunit_.GetShorty(&shorty_size);
-
-  if (!cunit_.IsStatic()) {
-    // The first argument to non-static method is "this" object pointer
-    regs_.push_back(DalvikReg::CreateArgReg(*this, reg_idx++, kObject));
-  }
-
-  for (unsigned i = 1; i < shorty_size; i++) {
-    JType jty = GetJTypeFromShorty(shorty[i]);
-    regs_.push_back(DalvikReg::CreateArgReg(*this, reg_idx++, jty));
-    reg_idx++;
-
-    if (GetRegCategoryFromJType(jty) == kRegCat2) {
-      // Need a register pair to hold the value
-      regs_.push_back(NULL);
-      reg_idx++;
-    }
-  }
-
-  CHECK_EQ(num_regs, regs_.size());
-
-  return true;
-}
-
 bool DexLang::EmitPrologue() {
   reg_alloc_bb_ = llvm::BasicBlock::Create(context_, "prologue.alloca", func_);
 
   arg_reg_init_bb_ =
       llvm::BasicBlock::Create(context_, "prologue.arginit", func_);
 
-  if (!PrepareDalvikRegs()) {
-    return false;
+  // Create register array
+  const unsigned num_regs = code_item_->registers_size_;
+  for (unsigned i = 0; i < num_regs; i++) {
+    regs_.push_back(new DalvikReg(*this, i));
   }
 
-  //Store argument to dalvik register
+  // Register hold return value from invoke and filled-new-array
+  retval_reg_ = new DalvikReg(*this, num_regs);
+
+  // Store argument to dalvik register
   irb_.SetInsertPoint(arg_reg_init_bb_);
   if (!EmitPrologueAssignArgRegister()) {
     return false;
@@ -617,10 +533,6 @@
 }
 
 bool DexLang::EmitPrologueAllcaShadowFrame() {
-  if (!require_shadow_frame) {
-    return true;
-  }
-
   // Save current IR builder insert point
   llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
 
@@ -644,7 +556,13 @@
   llvm::BasicBlock* last_non_exception_bb = &func_->back();
   DCHECK(last_non_exception_bb != NULL);
 
-  DCHECK_NE(last_non_exception_bb, exception_unwind_bb_);
+  if (last_non_exception_bb == exception_unwind_bb_) {
+    // There's no other expcetion landing pads therefore the only exception
+    // basic blocks is for exception unwinding which is already the tail basic
+    // block of the function
+    return true;
+  }
+
   if (exception_unwind_bb_ != NULL) {
     exception_unwind_bb_->moveAfter(last_non_exception_bb);
   }
@@ -654,9 +572,14 @@
           landing_pads_bb_end = landing_pads_bb_.rend();
        landing_pads_bb_iter != landing_pads_bb_end; landing_pads_bb_iter++) {
     llvm::BasicBlock* landing_pads_bb = *landing_pads_bb_iter;
+    if (landing_pads_bb == NULL) {
+      continue;
+    }
+
     // Move the successors (the cache handlers) first
     llvm::TerminatorInst* inst = landing_pads_bb->getTerminator();
     CHECK(inst != NULL);
+
     for (unsigned i = 0, e = inst->getNumSuccessors(); i != e; i++) {
       llvm::BasicBlock* catch_handler = inst->getSuccessor(i);
       // One of the catch handler is the unwind basic block which is settled
@@ -665,8 +588,7 @@
         catch_handler->moveAfter(last_non_exception_bb);
       }
     }
-    if (landing_pads_bb != NULL) {
-      DCHECK_NE(last_non_exception_bb, landing_pads_bb);
+    if (last_non_exception_bb != landing_pads_bb) {
       landing_pads_bb->moveAfter(last_non_exception_bb);
     }
   }
@@ -677,7 +599,7 @@
 bool DexLang::VerifyFunction() {
   if (llvm::verifyFunction(*func_, llvm::PrintMessageAction)) {
     LOG(INFO) << "Verification failed on function: "
-              << PrettyMethod(cunit_.GetDexMethodIndex(), *dex_file_);
+              << PrettyMethod(method_idx_, *dex_file_);
     return false;
   }
   return true;
@@ -813,39 +735,18 @@
   return EmitInvokeIntrinsicNoThrow(IntrinsicHelper::GetCurrentThread);
 }
 
-llvm::Value*
-DexLang::EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IntrinsicId intr_id) {
-  DCHECK(IntrinsicHelper::GetAttr(intr_id) & IntrinsicHelper::kAttrNoThrow);
-  return irb_.CreateCall(intrinsic_helper_.GetIntrinsicFunction(intr_id));
+void DexLang::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
+  EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::MarkGCCard, value, target_addr);
+  return;
 }
 
 llvm::Value*
 DexLang::EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IntrinsicId intr_id,
                                     llvm::ArrayRef<llvm::Value*> args) {
-  llvm::Function* intr = intrinsic_helper_.GetIntrinsicFunction(intr_id);
   DCHECK(IntrinsicHelper::GetAttr(intr_id) & IntrinsicHelper::kAttrNoThrow);
-  return irb_.CreateCall(intr, args);
-}
 
-llvm::Value*
-DexLang::EmitInvokeIntrinsic(unsigned dex_pc,
-                             IntrinsicHelper::IntrinsicId intr_id) {
   llvm::Function* intr = intrinsic_helper_.GetIntrinsicFunction(intr_id);
-  unsigned intr_attr = IntrinsicHelper::GetAttr(intr_id);
-  bool may_throw = !(intr_attr & IntrinsicHelper::kAttrNoThrow);
-
-  // Setup PC before invocation when the intrinsics may generate the exception
-  if (may_throw) {
-    EmitUpdateDexPC(dex_pc);
-  }
-
-  llvm::Value* ret_val = irb_.CreateCall(intr);
-
-  if (may_throw) {
-    EmitGuard_ExceptionLandingPad(dex_pc);
-  }
-
-  return ret_val;
+  return ((args.empty()) ? irb_.CreateCall(intr) : irb_.CreateCall(intr, args));
 }
 
 llvm::Value* DexLang::EmitInvokeIntrinsic(unsigned dex_pc,
@@ -853,38 +754,155 @@
                                           llvm::ArrayRef<llvm::Value*> args) {
   llvm::Function* intr = intrinsic_helper_.GetIntrinsicFunction(intr_id);
   unsigned intr_attr = IntrinsicHelper::GetAttr(intr_id);
-  bool may_throw = !(intr_attr & IntrinsicHelper::kAttrNoThrow);
+  DCHECK(!(intr_attr & IntrinsicHelper::kAttrNoThrow));
 
   // Setup PC before invocation when the intrinsics may generate the exception
-  if (may_throw) {
-    EmitUpdateDexPC(dex_pc);
-  }
+  EmitUpdateDexPC(dex_pc);
 
-  llvm::Value* ret_val = irb_.CreateCall(intr, args);
+  llvm::Value* ret_val = ((args.empty()) ? irb_.CreateCall(intr) :
+                                           irb_.CreateCall(intr, args));
 
-  if (may_throw) {
+  if (intr_attr & IntrinsicHelper::kAttrDoThrow) {
+    // Directly branch to exception landingpad when the intrinsic is known to
+    // throw exception always
+    EmitBranchExceptionLandingPad(dex_pc);
+  } else {
     EmitGuard_ExceptionLandingPad(dex_pc);
   }
 
   return ret_val;
 }
 
-RegCategory DexLang::GetInferredRegCategory(unsigned dex_pc, unsigned reg_idx) {
-  Compiler::MethodReference mref(dex_file_, cunit_.GetDexMethodIndex());
+compiler_llvm::RegCategory DexLang::GetInferredRegCategory(unsigned dex_pc,
+                                                           unsigned reg_idx) {
+  Compiler::MethodReference mref(dex_file_, method_idx_);
 
-  const InferredRegCategoryMap* map =
+  const compiler_llvm::InferredRegCategoryMap* map =
     verifier::MethodVerifier::GetInferredRegCategoryMap(mref);
 
-  CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
+  CHECK_NE(map, static_cast<compiler_llvm::InferredRegCategoryMap*>(NULL));
 
   return map->GetRegCategory(dex_pc, reg_idx);
 }
 
+llvm::Value* DexLang::EmitLoadConstantClass(unsigned dex_pc,
+                                            uint32_t type_idx) {
+  llvm::Value* type_idx_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = EmitGetCurrentThread();
+
+  if (!compiler_.CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
+                                            *dex_file_, type_idx)) {
+    return EmitInvokeIntrinsic3(dex_pc, IntrinsicHelper::InitializeTypeAndVerifyAccess,
+                                type_idx_value, method_object_addr,
+                                thread_object_addr);
+  } else {
+    // Try to load the class (type) object from the dex cache
+    llvm::Value* type_object_addr =
+        EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadTypeFromDexCache,
+                                   type_idx_value);
+
+    if (compiler_.CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) {
+      return type_object_addr;
+    }
+
+    llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+
+    // Test whether class (type) object is in the dex cache or not
+    llvm::Value* equal_null =
+        irb_.CreateICmpEQ(type_object_addr, irb_.GetJNull());
+
+    llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    llvm::BasicBlock* block_load_class =
+      CreateBasicBlockWithDexPC(dex_pc, "load_class");
+
+    irb_.CreateCondBr(equal_null, block_load_class, block_cont);
+
+    // Failback routine to load the class object
+    irb_.SetInsertPoint(block_load_class);
+
+    llvm::Value* loaded_type_object_addr =
+        EmitInvokeIntrinsic3(dex_pc, IntrinsicHelper::InitializeType,
+                             type_idx_value, method_object_addr,
+                             thread_object_addr);
+
+    llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
+
+    irb_.CreateBr(block_cont);
+
+    // Now the class object must be loaded
+    irb_.SetInsertPoint(block_cont);
+
+    llvm::PHINode* phi = irb_.CreatePHI(irb_.GetJObjectTy(), 2);
+
+    phi->addIncoming(type_object_addr, block_original);
+    phi->addIncoming(loaded_type_object_addr, block_after_load_class);
+
+    return phi;
+  }
+}
+
 llvm::Value* DexLang::EmitLoadArrayLength(llvm::Value* array) {
   // Load array length
   return EmitInvokeIntrinsicNoThrow(IntrinsicHelper::ArrayLength, array);
 }
 
+llvm::Value* DexLang::EmitAllocNewArray(unsigned dex_pc, int32_t length,
+                                        uint32_t type_idx,
+                                        bool is_filled_new_array) {
+  bool skip_access_check = compiler_.CanAccessTypeWithoutChecks(method_idx_,
+                                                                dex_cache_,
+                                                                *dex_file_,
+                                                                type_idx);
+
+  llvm::Value* array_length_value;
+  IntrinsicHelper::IntrinsicId intrinsic;
+
+  // Select intrinsic and load the array length
+  if (is_filled_new_array) {
+    intrinsic =
+        skip_access_check ? IntrinsicHelper::CheckAndAllocArray :
+                            IntrinsicHelper::CheckAndAllocArrayWithAccessCheck;
+    array_length_value = irb_.getInt32(length);
+  } else {
+    intrinsic =
+        skip_access_check ? IntrinsicHelper::AllocArray :
+                            IntrinsicHelper::AllocArrayWithAccessCheck;
+    array_length_value = EmitLoadDalvikReg(length, kInt, kAccurate);
+  }
+
+  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = EmitGetCurrentThread();
+
+  llvm::Value* array_addr = EmitInvokeIntrinsic4(dex_pc, intrinsic,
+                                                 type_index_value,
+                                                 method_object_addr,
+                                                 array_length_value,
+                                                 thread_object_addr);
+
+  return array_addr;
+}
+
+llvm::Value* DexLang::EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                                 llvm::Value* cmp_lt) {
+
+  llvm::Constant* zero = irb_.GetJInt(0);
+  llvm::Constant* pos1 = irb_.GetJInt(1);
+  llvm::Constant* neg1 = irb_.GetJInt(-1);
+
+  llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
+  llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
+
+  return result_eq;
+}
+
 llvm::Value*
 DexLang::EmitLoadStaticStorage(unsigned dex_pc, unsigned type_idx) {
   llvm::BasicBlock* block_load_static =
@@ -896,8 +914,8 @@
 
   // Load static storage from dex cache
   llvm::Value* storage_object_addr =
-      EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::LoadClassSSBFromDexCache,
-                          type_idx_value);
+      EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadClassSSBFromDexCache,
+                                 type_idx_value);
 
   llvm::BasicBlock* block_original = irb_.GetInsertBlock();
 
@@ -1002,6 +1020,38 @@
   return NULL;
 }
 
+llvm::Value*
+DexLang::EmitIntShiftArithmResultComputation(uint32_t dex_pc,
+                                             llvm::Value* lhs,
+                                             llvm::Value* rhs,
+                                             IntShiftArithmKind arithm,
+                                             JType op_jty) {
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  if (op_jty == kInt) {
+    rhs = irb_.CreateAnd(rhs, 0x1f);
+  } else {
+    llvm::Value* masked_rhs = irb_.CreateAnd(rhs, 0x3f);
+    rhs = irb_.CreateZExt(masked_rhs, irb_.GetJLongTy());
+  }
+
+  switch (arithm) {
+    case kIntArithm_Shl: {
+      return irb_.CreateShl(lhs, rhs);
+    }
+    case kIntArithm_Shr: {
+      return irb_.CreateAShr(lhs, rhs);
+    }
+    case kIntArithm_UShr: {
+      return irb_.CreateLShr(lhs, rhs);
+    }
+    default: {
+      LOG(FATAL) << "Unknown integer shift arithmetic kind: " << arithm;
+      return NULL;
+    }
+  }
+}
+
 llvm::Value* DexLang::EmitIntDivRemResultComputation(unsigned dex_pc,
                                                      llvm::Value* dividend,
                                                      llvm::Value* divisor,
@@ -1035,7 +1085,7 @@
     }
   }
 
-  return EmitInvokeIntrinsic2(dex_pc, arithm_intrinsic, dividend, divisor);
+  return EmitInvokeIntrinsic2NoThrow(arithm_intrinsic, dividend, divisor);
 }
 
 //----------------------------------------------------------------------------
@@ -1069,17 +1119,8 @@
                                   JType jty) {
   DecodedInstruction dec_insn(insn);
 
-  CHECK(retval_ != NULL) << "move-result must immediately after an invoke-kind "
-                            "instruction";
-  // Check the type
-  CHECK_EQ(irb_.GetJType(jty, kReg), irb_.GetJType(retval_jty_, kReg))
-      << "Mismatch type between the value from the most recent invoke-kind "
-         "instruction (" << retval_jty_ << ") and the kind of move-result "
-         "used! (" << jty << ")";
-
-  EmitStoreDalvikReg(dec_insn.vA, retval_jty_, kReg, retval_);
-
-  retval_ = NULL;
+  llvm::Value* src_value = EmitLoadDalvikRetValReg(jty, kReg);
+  EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
   return;
@@ -1097,6 +1138,18 @@
   return;
 }
 
+void DexLang::EmitInsn_ThrowException(unsigned dex_pc,
+                                      const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* exception_addr =
+      EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
+
+  EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::ThrowException, exception_addr);
+
+  return;
+}
+
 void DexLang::EmitInsn_ReturnVoid(unsigned dex_pc, const Instruction* insn) {
   // Garbage collection safe-point
   EmitGuard_GarbageCollectionSuspend();
@@ -1192,16 +1245,36 @@
 
   uint32_t string_idx = dec_insn.vB;
   llvm::Value* string_idx_value = irb_.getInt32(string_idx);
-  IntrinsicHelper::IntrinsicId intrinsic = IntrinsicHelper::UnknownId;
-
-  if (compiler_.CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
-    intrinsic = IntrinsicHelper::ConstStringFast;
-  } else {
-    intrinsic = IntrinsicHelper::ConstString;
-  }
 
   llvm::Value* string_addr =
-      EmitInvokeIntrinsic(dex_pc, intrinsic, string_idx_value);
+      EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadStringFromDexCache,
+                                 string_idx_value);
+
+  if (!compiler_.CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
+    llvm::BasicBlock* block_str_exist =
+        CreateBasicBlockWithDexPC(dex_pc, "str_exist");
+
+    llvm::BasicBlock* block_str_resolve =
+        CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
+
+    // Test: Is the string resolved and in the dex cache?
+    llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.GetJNull());
+
+    irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist);
+
+    // String is resolved, go to next basic block.
+    irb_.SetInsertPoint(block_str_exist);
+    EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
+    irb_.CreateBr(GetNextBasicBlock(dex_pc));
+
+    // String is not resolved yet, resolve it now.
+    irb_.SetInsertPoint(block_str_resolve);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    string_addr = EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::ResolveString,
+                                       method_object_addr, string_idx_value);
+  }
 
   EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
 
@@ -1209,6 +1282,198 @@
   return;
 }
 
+void DexLang::EmitInsn_LoadConstantClass(unsigned dex_pc,
+                                         const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
+  EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, type_object_addr);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_MonitorEnter(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* object_addr =
+      EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
+
+  EmitGuard_NullPointerException(dex_pc, object_addr);
+
+  llvm::Value* thread_object_addr = EmitGetCurrentThread();
+
+  EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::LockObject,
+                              object_addr, thread_object_addr);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_MonitorExit(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* object_addr =
+      EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
+
+  EmitGuard_NullPointerException(dex_pc, object_addr);
+
+  llvm::Value* thread_object_addr = EmitGetCurrentThread();
+
+  EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::UnlockObject,
+                       object_addr, thread_object_addr);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_CheckCast(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::BasicBlock* block_test_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_class");
+
+  llvm::BasicBlock* block_test_sub_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
+
+  llvm::Value* object_addr =
+      EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
+
+  // Test: Is the reference equal to null?  Act as no-op when it is null.
+  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.GetJNull());
+
+  irb_.CreateCondBr(equal_null,
+                    GetNextBasicBlock(dex_pc),
+                    block_test_class);
+
+  // Test: Is the object instantiated from the given class?
+  irb_.SetInsertPoint(block_test_class);
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
+  DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
+
+  llvm::PointerType* jobject_ptr_ty = irb_.GetJObjectTy();
+
+  llvm::Value* object_type_field_addr =
+      irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
+
+  llvm::Value* object_type_object_addr =
+      irb_.CreateLoad(object_type_field_addr);
+
+  llvm::Value* equal_class =
+      irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
+
+  irb_.CreateCondBr(equal_class,
+                    GetNextBasicBlock(dex_pc),
+                    block_test_sub_class);
+
+  // Test: Is the object instantiated from the subclass of the given class?
+  irb_.SetInsertPoint(block_test_sub_class);
+
+  EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::CheckCast,
+                       type_object_addr, object_type_object_addr);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_InstanceOf(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Constant* zero = irb_.GetJInt(0);
+  llvm::Constant* one = irb_.GetJInt(1);
+
+  llvm::BasicBlock* block_nullp = CreateBasicBlockWithDexPC(dex_pc, "nullp");
+
+  llvm::BasicBlock* block_test_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_class");
+
+  llvm::BasicBlock* block_class_equals =
+      CreateBasicBlockWithDexPC(dex_pc, "class_eq");
+
+  llvm::BasicBlock* block_test_sub_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
+
+  llvm::Value* object_addr =
+      EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
+
+  // Overview of the following code :
+  // We check for null, if so, then false, otherwise check for class == . If so
+  // then true, otherwise do callout slowpath.
+  //
+  // Test: Is the reference equal to null?  Set 0 when it is null.
+  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.GetJNull());
+
+  irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
+
+  irb_.SetInsertPoint(block_nullp);
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, zero);
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+
+  // Test: Is the object instantiated from the given class?
+  irb_.SetInsertPoint(block_test_class);
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vC);
+  DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
+
+  llvm::PointerType* jobject_ptr_ty = irb_.GetJObjectTy();
+
+  llvm::Value* object_type_field_addr =
+      irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
+
+  llvm::Value* object_type_object_addr =
+      irb_.CreateLoad(object_type_field_addr);
+
+  llvm::Value* equal_class =
+      irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
+
+  irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
+
+  irb_.SetInsertPoint(block_class_equals);
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, one);
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+
+  // Test: Is the object instantiated from the subclass of the given class?
+  irb_.SetInsertPoint(block_test_sub_class);
+
+  llvm::Value* result =
+      EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::IsAssignable,
+                                  type_object_addr, object_type_object_addr);
+
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_NewInstance(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  IntrinsicHelper::IntrinsicId alloc_intrinsic;
+  if (compiler_.CanAccessInstantiableTypeWithoutChecks(method_idx_,
+                                                       dex_cache_,
+                                                       *dex_file_,
+                                                       dec_insn.vB)) {
+    alloc_intrinsic = IntrinsicHelper::AllocObject;
+  } else {
+    alloc_intrinsic = IntrinsicHelper::AllocObjectWithAccessCheck;
+  }
+
+  llvm::Constant* type_index_value = irb_.getInt32(dec_insn.vB);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = EmitGetCurrentThread();
+
+  llvm::Value* object_addr = EmitInvokeIntrinsic3(dex_pc, alloc_intrinsic,
+                                                  type_index_value,
+                                                  method_object_addr,
+                                                  thread_object_addr);
+
+  EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, object_addr);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
 void DexLang::EmitInsn_UnconditionalBranch(unsigned dex_pc,
                                            const Instruction* insn) {
   DecodedInstruction dec_insn(insn);
@@ -1239,13 +1504,8 @@
 void DexLang::EmitInsn_NewArray(unsigned dex_pc, const Instruction* insn) {
   DecodedInstruction dec_insn(insn);
 
-  // Prepare argument to intrinsic
-  llvm::Value* array_length = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
-  llvm::Value* type_idx = irb_.getInt32(dec_insn.vC);
-
-  llvm::Value* array_addr =
-      EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::NewArray,
-                           array_length, type_idx);
+  llvm::Value* array_addr = EmitAllocNewArray(dex_pc, dec_insn.vB, dec_insn.vC,
+                                              /* is_filled_new_array */false);
 
   EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, array_addr);
 
@@ -1253,25 +1513,116 @@
   return;
 }
 
+void DexLang::EmitInsn_FilledNewArray(unsigned dex_pc, const Instruction* insn,
+                                      bool is_range) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* object_addr = EmitAllocNewArray(dex_pc, dec_insn.vA, dec_insn.vB,
+                                               /* is_filled_new_array */true);
+
+  if (dec_insn.vA > 0) {
+    // Check for the element type
+    uint32_t type_desc_len = 0;
+    const char* type_desc =
+        dex_file_->StringByTypeIdx(dec_insn.vB, &type_desc_len);
+
+    DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
+    DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
+
+    // NOTE: Currently filled-new-array only supports 'L', '[', and 'I' as the
+    // element, therefore the element is either a primitive int or a reference
+    JType element_jty = ((type_desc[1] == 'I') ? kInt : kObject);
+
+    std::vector<llvm::Value*> args;
+    // Destination array object
+    args.push_back(object_addr);
+    // Type of the array element
+    //
+    // FIXME: Actually, dec_insn.vB (type_idx of the element) should be here to
+    // the intrinsic instead of element_jty. However, since GBCExpander cannot
+    // know which dex_file this filled-new-array instruction associated with, it
+    // is unable to know the exact type of the type_idx is. In the near future,
+    // metadata will be used to record the type information (i.e., type_desc)
+    args.push_back(irb_.getInt32(element_jty));
+
+    for (uint32_t i = 0; i < dec_insn.vA; ++i) {
+      int reg_index;
+      if (is_range) {
+        reg_index = dec_insn.vC + i;
+      } else {
+        reg_index = dec_insn.arg[i];
+      }
+
+      llvm::Value* reg_value =
+          EmitLoadDalvikReg(reg_index, element_jty, kAccurate);
+
+      args.push_back(reg_value);
+    }
+
+    EmitInvokeIntrinsicNoThrow(IntrinsicHelper::FilledNewArray, args);
+  }
+
+  EmitStoreDalvikRetValReg(kObject, kAccurate, object_addr);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_FillArrayData(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  // Read the payload
+  int32_t payload_offset = static_cast<int32_t>(dex_pc) +
+                           static_cast<int32_t>(dec_insn.vB);
+
+  const Instruction::ArrayDataPayload* payload =
+    reinterpret_cast<const Instruction::ArrayDataPayload*>(
+        code_item_->insns_ + payload_offset);
+
+  // Load array object
+  llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
+
+  if (payload->element_count == 0) {
+    // When the number of the elements in the payload is zero, we don't have
+    // to copy any numbers.  However, we should check whether the array object
+    // address is equal to null or not.
+    EmitGuard_NullPointerException(dex_pc, array_addr);
+  } else {
+    // To save the code size, we are going to call the runtime function to
+    // copy the content from DexFile.
+
+    // NOTE: We will check for the NullPointerException in the runtime.
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitInvokeIntrinsic4(dex_pc, IntrinsicHelper::FillArrayData,
+                         method_object_addr, irb_.getInt32(dex_pc), array_addr,
+                         irb_.getInt32(payload_offset));
+  }
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
 void DexLang::EmitInsn_UnaryConditionalBranch(unsigned dex_pc,
                                               const Instruction* insn,
                                               CondBranchKind cond) {
   DecodedInstruction dec_insn(insn);
 
-  int8_t src_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
+  compiler_llvm::RegCategory src_reg_cat =
+      GetInferredRegCategory(dex_pc, dec_insn.vA);
 
-  DCHECK_NE(kRegUnknown, src_reg_cat);
-  DCHECK_NE(kRegCat2, src_reg_cat);
+  DCHECK_NE(compiler_llvm::kRegUnknown, src_reg_cat);
+  DCHECK_NE(compiler_llvm::kRegCat2, src_reg_cat);
 
   int32_t branch_offset = dec_insn.vB;
 
   llvm::Value* src1_value;
   llvm::Value* src2_value;
 
-  if (src_reg_cat == kRegZero) {
+  if (src_reg_cat == compiler_llvm::kRegZero) {
     src1_value = irb_.getInt32(0);
     src2_value = irb_.getInt32(0);
-  } else if (src_reg_cat == kRegCat1nr) {
+  } else if (src_reg_cat == compiler_llvm::kRegCat1nr) {
     src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kReg);
     src2_value = irb_.getInt32(0);
   } else {
@@ -1341,8 +1692,7 @@
     }
   }
 
-  llvm::Value* cond_value =
-    EmitConditionResult(src1_value, src2_value, cond);
+  llvm::Value* cond_value = EmitConditionResult(src1_value, src2_value, cond);
 
   irb_.CreateCondBr(cond_value,
                     GetBasicBlock(dex_pc + branch_offset),
@@ -1350,6 +1700,93 @@
   return;
 }
 
+void DexLang::EmitInsn_PackedSwitch(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  int32_t payload_offset = static_cast<int32_t>(dex_pc) +
+                           static_cast<int32_t>(dec_insn.vB);
+
+  const Instruction::PackedSwitchPayload* payload =
+    reinterpret_cast<const Instruction::PackedSwitchPayload*>(
+        code_item_->insns_ + payload_offset);
+
+  llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
+
+  llvm::SwitchInst* sw =
+    irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->case_count);
+
+  for (uint16_t i = 0; i < payload->case_count; ++i) {
+    sw->addCase(irb_.getInt32(payload->first_key + i),
+                GetBasicBlock(dex_pc + payload->targets[i]));
+  }
+  return;
+}
+
+void DexLang::EmitInsn_SparseSwitch(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  int32_t payload_offset = static_cast<int32_t>(dex_pc) +
+                           static_cast<int32_t>(dec_insn.vB);
+
+  const Instruction::SparseSwitchPayload* payload =
+    reinterpret_cast<const Instruction::SparseSwitchPayload*>(
+        code_item_->insns_ + payload_offset);
+
+  const int32_t* keys = payload->GetKeys();
+  const int32_t* targets = payload->GetTargets();
+
+  llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
+
+  llvm::SwitchInst* sw =
+    irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->case_count);
+
+  for (size_t i = 0; i < payload->case_count; ++i) {
+    sw->addCase(irb_.getInt32(keys[i]), GetBasicBlock(dex_pc + targets[i]));
+  }
+  return;
+}
+
+void DexLang::EmitInsn_FPCompare(unsigned dex_pc, const Instruction* insn,
+                                 JType fp_jty, bool gt_bias) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(fp_jty == kFloat || fp_jty == kDouble) << "JType: " << fp_jty;
+
+  llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, fp_jty, kAccurate);
+  llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, fp_jty, kAccurate);
+
+  llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt;
+
+  if (gt_bias) {
+    cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
+  } else {
+    cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
+  }
+
+  llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_LongCompare(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
+  llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, kLong, kAccurate);
+
+  llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
+
+  llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
 void DexLang::EmitInsn_AGet(unsigned dex_pc, const Instruction* insn,
                             JType elem_jty) {
   DecodedInstruction dec_insn(insn);
@@ -1398,10 +1835,9 @@
 
   EmitGuard_ArrayException(dex_pc, array_addr, index_value);
 
-  llvm::Value* array_element_value = EmitInvokeIntrinsic2(dex_pc,
-                                                          aget_intrinsic,
-                                                          array_addr,
-                                                          index_value);
+  llvm::Value* array_element_value = EmitInvokeIntrinsic2NoThrow(aget_intrinsic,
+                                                                 array_addr,
+                                                                 index_value);
 
   EmitStoreDalvikReg(dec_insn.vA, elem_jty, kArray, array_element_value);
 
@@ -1451,24 +1887,218 @@
     }
   }
 
-  // Construct argument list passed to the intrinsic
-  llvm::Value* elem_addr = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kAccurate);
   llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
   llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
 
   EmitGuard_ArrayException(dex_pc, array_addr, index_value);
 
+  llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
+
   // Check the type if an object is putting
   if (elem_jty == kObject) {
     EmitInvokeIntrinsic2(dex_pc, IntrinsicHelper::CheckPutArrayElement,
-                         elem_addr, array_addr);
+                         new_value, array_addr);
+
+    EmitMarkGCCard(new_value, array_addr);
   }
 
-  EmitInvokeIntrinsic3(dex_pc, aput_intrinsic,
-                       elem_addr, array_addr, index_value);
+  EmitInvokeIntrinsic3NoThrow(aput_intrinsic, new_value, array_addr, index_value);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
 
+void DexLang::EmitInsn_IGet(unsigned dex_pc, const Instruction* insn,
+                            JType field_jty) {
+  DecodedInstruction dec_insn(insn);
+
+  uint32_t reg_idx = dec_insn.vB;
+  uint32_t field_idx = dec_insn.vC;
+
+  llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
+
+  EmitGuard_NullPointerException(dex_pc, object_addr);
+
+  int field_offset;
+  bool is_volatile;
+  bool is_fast_path = compiler_.ComputeInstanceFieldInfo(field_idx, &cunit_,
+                                                         field_offset,
+                                                         is_volatile,
+                                                         /* is_put */false);
+
+  // Select corresponding intrinsic accroding to the field type and is_fast_path
+  IntrinsicHelper::IntrinsicId iget_intrinsic = IntrinsicHelper::UnknownId;
+
+  switch (field_jty) {
+    case kInt: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetFast :
+                           IntrinsicHelper::InstanceFieldGet;
+      break;
+    }
+    case kLong: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetWideFast :
+                           IntrinsicHelper::InstanceFieldGetWide;
+      break;
+    }
+    case kObject: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetObjectFast :
+                           IntrinsicHelper::InstanceFieldGetObject;
+      break;
+    }
+    case kBoolean: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetBooleanFast :
+                           IntrinsicHelper::InstanceFieldGetBoolean;
+      break;
+    }
+    case kByte: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetByteFast :
+                           IntrinsicHelper::InstanceFieldGetByte;
+      break;
+    }
+    case kChar: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetCharFast :
+                           IntrinsicHelper::InstanceFieldGetChar;
+      break;
+    }
+    case kShort: {
+      iget_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldGetShortFast :
+                           IntrinsicHelper::InstanceFieldGetShort;
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Unexpected element type got in iget instruction!";
+      return;
+    }
+  }
+
+  llvm::Value* instance_field_value;
+
+  if (!is_fast_path) {
+    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    instance_field_value = EmitInvokeIntrinsic3(dex_pc, iget_intrinsic,
+                                                field_idx_value,
+                                                method_object_addr,
+                                                object_addr);
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    instance_field_value =
+        EmitInvokeIntrinsic3NoThrow(iget_intrinsic,
+                                    irb_.getInt32(field_offset),
+                                    irb_.getInt1(is_volatile),
+                                    object_addr);
+  }
+
+  EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, instance_field_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_IPut(unsigned dex_pc, const Instruction* insn,
+                            JType field_jty) {
+  DecodedInstruction dec_insn(insn);
+
+  uint32_t reg_idx = dec_insn.vB;
+  uint32_t field_idx = dec_insn.vC;
+
+  llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
+
+  EmitGuard_NullPointerException(dex_pc, object_addr);
+
+  llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
+
+  int field_offset;
+  bool is_volatile;
+  bool is_fast_path = compiler_.ComputeInstanceFieldInfo(field_idx, &cunit_,
+                                                         field_offset,
+                                                         is_volatile,
+                                                         /* is_iput */true);
+
+  // Select corresponding intrinsic accroding to the field type and is_fast_path
+  IntrinsicHelper::IntrinsicId iput_intrinsic = IntrinsicHelper::UnknownId;
+
+  switch (field_jty) {
+    case kInt: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutFast :
+                           IntrinsicHelper::InstanceFieldPut;
+      break;
+    }
+    case kLong: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutWideFast :
+                           IntrinsicHelper::InstanceFieldPutWide;
+      break;
+    }
+    case kObject: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutObjectFast :
+                           IntrinsicHelper::InstanceFieldPutObject;
+      break;
+    }
+    case kBoolean: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutBooleanFast :
+                           IntrinsicHelper::InstanceFieldPutBoolean;
+      break;
+    }
+    case kByte: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutByteFast :
+                           IntrinsicHelper::InstanceFieldPutByte;
+      break;
+    }
+    case kChar: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutCharFast :
+                           IntrinsicHelper::InstanceFieldPutChar;
+      break;
+    }
+    case kShort: {
+      iput_intrinsic =
+          (is_fast_path) ? IntrinsicHelper::InstanceFieldPutShortFast :
+                           IntrinsicHelper::InstanceFieldPutShort;
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Unexpected element type got in iput instruction!";
+      return;
+    }
+  }
+
+  if (!is_fast_path) {
+    llvm::Value* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitInvokeIntrinsic4(dex_pc, iput_intrinsic, field_idx_value,
+                         method_object_addr, object_addr, new_value);
+
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    EmitInvokeIntrinsic4NoThrow(iput_intrinsic, irb_.getInt32(field_offset),
+                                irb_.getInt1(is_volatile), object_addr,
+                                new_value);
+
+    // If put an object, mark the GC card table
+    if (field_jty == kObject) {
+      EmitMarkGCCard(new_value, object_addr);
+    }
+  }
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
   return;
 }
 
@@ -1560,8 +2190,8 @@
       llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
 
       static_storage_addr =
-        EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::LoadDeclaringClassSSB,
-                            method_object_addr);
+          EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadDeclaringClassSSB,
+                                     method_object_addr);
     } else {
       // Medium path, static storage base in a different class which
       // requires checks that the other class is initialized
@@ -1570,9 +2200,10 @@
     }
 
     static_field_value =
-        EmitInvokeIntrinsic3(dex_pc, sget_intrinsic,
-                             static_storage_addr, irb_.getInt32(field_offset),
-                             irb_.getInt1(is_volatile));
+        EmitInvokeIntrinsic3NoThrow(sget_intrinsic,
+                                    static_storage_addr,
+                                    irb_.getInt32(field_offset),
+                                    irb_.getInt1(is_volatile));
   }
 
   EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, static_field_value);
@@ -1668,8 +2299,8 @@
       llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
 
       static_storage_addr =
-        EmitInvokeIntrinsic(dex_pc, IntrinsicHelper::LoadDeclaringClassSSB,
-                            method_object_addr);
+        EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadDeclaringClassSSB,
+                                   method_object_addr);
     } else {
       // Medium path, static storage base in a different class which
       // requires checks that the other class is initialized
@@ -1677,9 +2308,14 @@
       static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
     }
 
-    EmitInvokeIntrinsic4(dex_pc, sput_intrinsic,
-                         static_storage_addr, irb_.getInt32(field_offset),
-                         irb_.getInt1(is_volatile), new_value);
+    EmitInvokeIntrinsic4NoThrow(sput_intrinsic, static_storage_addr,
+                                irb_.getInt32(field_offset),
+                                irb_.getInt1(is_volatile), new_value);
+
+    // If put an object, mark the GC card table
+    if (field_jty == kObject) {
+      EmitMarkGCCard(new_value, static_storage_addr);
+    }
   }
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
@@ -1725,13 +2361,40 @@
 
     llvm::Value* thread_object_addr = EmitGetCurrentThread();
 
+    // Select intrinsic according to the invoke_type
+    IntrinsicHelper::IntrinsicId invoke_intr = IntrinsicHelper::UnknownId;
+    switch (invoke_type) {
+      case kStatic: {
+        invoke_intr = IntrinsicHelper::FindStaticMethodWithAccessCheck;
+        break;
+      }
+      case kDirect: {
+        invoke_intr = IntrinsicHelper::FindDirectMethodWithAccessCheck;
+        break;
+      }
+      case kVirtual: {
+        invoke_intr = IntrinsicHelper::FindVirtualMethodWithAccessCheck;
+        break;
+      }
+      case kSuper: {
+        invoke_intr = IntrinsicHelper::FindSuperMethodWithAccessCheck;
+        break;
+      }
+      case kInterface: {
+        invoke_intr = IntrinsicHelper::FindInterfaceMethodWithAccessCheck;
+        break;
+      }
+      default: {
+        LOG(FATAL) << "Unknown type of invoke: " << invoke_type;
+      }
+    }
+
     callee_method_object_addr =
-        EmitInvokeIntrinsic5(dex_pc, IntrinsicHelper::GetCalleeMethodObjAddr,
-                             this_addr,
+        EmitInvokeIntrinsic4(dex_pc, invoke_intr,
                              callee_method_idx_value,
+                             this_addr,
                              caller_method_object_addr,
-                             thread_object_addr,
-                             irb_.getInt32(static_cast<unsigned>(invoke_type)));
+                             thread_object_addr);
   } else {
     switch (invoke_type) {
       case kStatic:
@@ -1743,18 +2406,16 @@
                                 irb_.GetJMethodTy());
         } else {
           callee_method_object_addr =
-              EmitInvokeIntrinsic(dex_pc,
-                                  IntrinsicHelper::GetSDCalleeMethodObjAddrFast,
-                                  callee_method_idx_value);
+              EmitInvokeIntrinsicNoThrow(IntrinsicHelper::GetSDCalleeMethodObjAddrFast,
+                                         callee_method_idx_value);
         }
         break;
       }
       case kVirtual: {
         DCHECK(vtable_idx != -1);
         callee_method_object_addr =
-            EmitInvokeIntrinsic2(dex_pc,
-                                 IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast,
-                                 irb_.getInt32(vtable_idx), this_addr);
+            EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast,
+                                        irb_.getInt32(vtable_idx), this_addr);
         break;
       }
       case kSuper: {
@@ -1770,8 +2431,8 @@
         callee_method_object_addr =
             EmitInvokeIntrinsic4(dex_pc,
                                  IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast,
-                                 this_addr,
                                  callee_method_idx_value,
+                                 this_addr,
                                  caller_method_object_addr,
                                  thread_object_addr);
         break;
@@ -1792,27 +2453,50 @@
   // Select the corresponding intrinsic according to the return type
   IntrinsicHelper::IntrinsicId invoke_intrinsic = IntrinsicHelper::UnknownId;
 
-  if (callee_ret_jty == kVoid) {
-    invoke_intrinsic = IntrinsicHelper::InvokeRetVoid;
-  } else {
-    switch (GetRegCategoryFromJType(callee_ret_jty)) {
-      case kRegCat1nr: {
-        invoke_intrinsic = IntrinsicHelper::InvokeRetCat1;
-        break;
-      }
-      case kRegCat2: {
-        invoke_intrinsic = IntrinsicHelper::InvokeRetCat2;
-        break;
-      }
-      case kRegObject: {
-        invoke_intrinsic = IntrinsicHelper::InvokeRetObject;
-        break;
-      }
-      default: {
-        LOG(FATAL) << "Unknown register category for type: "
-                   << callee_ret_jty;
-        break;
-      }
+  switch (callee_ret_jty) {
+    case kVoid: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetVoid;
+      break;
+    }
+    case kBoolean: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetBoolean;
+      break;
+    }
+    case kByte: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetByte;
+      break;
+    }
+    case kChar: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetChar;
+      break;
+    }
+    case kShort: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetShort;
+      break;
+    }
+    case kInt: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetInt;
+      break;
+    }
+    case kLong: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetLong;
+      break;
+    }
+    case kFloat: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetFloat;
+      break;
+    }
+    case kDouble: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetDouble;
+      break;
+    }
+    case kObject: {
+      invoke_intrinsic = IntrinsicHelper::InvokeRetObject;
+      break;
+    }
+    default: {
+      LOG(FATAL) << "Unknown register category for type: " << callee_ret_jty;
+      break;
     }
   }
 
@@ -1833,8 +2517,8 @@
 
   // Load argument values according to the shorty
   for (uint32_t i = 1; i < callee_shorty_size; i++) {
-    unsigned reg_idx = (arg_fmt == kArgReg) ? (dec_insn.vC + arg_idx) :
-                                              (dec_insn.arg[arg_idx]);
+    unsigned reg_idx = (arg_fmt == kArgRange) ? (dec_insn.vC + arg_idx) :
+                                                (dec_insn.arg[arg_idx]);
     JType jty = GetJTypeFromShorty(callee_shorty[i]);
     args.push_back(EmitLoadDalvikReg(reg_idx, jty, kAccurate));
     arg_idx++;
@@ -1853,16 +2537,166 @@
 
   // Store the return value for the subsequent move-result
   if (callee_shorty[0] != 'V') {
-    retval_ = retval;
-    retval_jty_ = GetJTypeFromShorty(callee_shorty[0]);
-  } else {
-    retval_ = NULL;
+    EmitStoreDalvikRetValReg(callee_ret_jty, kAccurate, retval);
   }
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
   return;
 }
 
+void DexLang::EmitInsn_Neg(unsigned dex_pc, const Instruction* insn,
+                           JType op_jty) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
+  llvm::Value* result_value = irb_.CreateNeg(src_value);
+  EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_Not(unsigned dex_pc, const Instruction* insn,
+                           JType op_jty) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
+  llvm::Value* result_value = irb_.CreateXor(src_value, 0xFFFFFFFFFFFFFFFFLL);
+
+  EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_SExt(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+  llvm::Value* result_value = irb_.CreateSExt(src_value, irb_.GetJLongTy());
+  EmitStoreDalvikReg(dec_insn.vA, kLong, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_Trunc(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
+  llvm::Value* result_value = irb_.CreateTrunc(src_value, irb_.GetJIntTy());
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_TruncAndSExt(unsigned dex_pc, const Instruction* insn,
+                                    unsigned N) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+
+  llvm::Value* trunc_value =
+    irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(context_, N));
+
+  llvm::Value* result_value = irb_.CreateSExt(trunc_value, irb_.GetJIntTy());
+
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_TruncAndZExt(unsigned dex_pc, const Instruction* insn,
+                                    unsigned N) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+
+  llvm::Value* trunc_value =
+    irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(context_, N));
+
+  llvm::Value* result_value = irb_.CreateZExt(trunc_value, irb_.GetJIntTy());
+
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_FNeg(unsigned dex_pc, const Instruction* insn,
+                            JType op_jty) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
+  llvm::Value* result_value = irb_.CreateFNeg(src_value);
+  EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_IntToFP(unsigned dex_pc, const Instruction* insn,
+                               JType src_jty, JType dest_jty) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(src_jty == kInt || src_jty == kLong) << src_jty;
+  DCHECK(dest_jty == kFloat || dest_jty == kDouble) << dest_jty;
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
+  llvm::Type* dest_type = irb_.GetJType(dest_jty, kAccurate);
+  llvm::Value* dest_value = irb_.CreateSIToFP(src_value, dest_type);
+  EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_FPToInt(unsigned dex_pc, const Instruction* insn,
+                               JType src_jty, JType dest_jty,
+                               IntrinsicHelper::IntrinsicId intr_id) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(src_jty == kFloat || src_jty == kDouble) << src_jty;
+  DCHECK(dest_jty == kInt || dest_jty == kLong) << dest_jty;
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
+  llvm::Value* dest_value = EmitInvokeIntrinsicNoThrow(intr_id, src_value);
+  EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_FExt(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kFloat, kAccurate);
+  llvm::Value* result_value = irb_.CreateFPExt(src_value, irb_.GetJDoubleTy());
+  EmitStoreDalvikReg(dec_insn.vA, kDouble, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_FTrunc(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kDouble, kAccurate);
+  llvm::Value* result_value = irb_.CreateFPTrunc(src_value, irb_.GetJFloatTy());
+  EmitStoreDalvikReg(dec_insn.vA, kFloat, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
 void DexLang::EmitInsn_IntArithm(unsigned dex_pc, const Instruction* insn,
                                  IntArithmKind arithm, JType op_jty,
                                  bool is_2addr) {
@@ -1909,6 +2743,70 @@
   return;
 }
 
+void DexLang::EmitInsn_IntShiftArithm(unsigned dex_pc, const Instruction* insn,
+                                      IntShiftArithmKind arithm, JType op_jty,
+                                      bool is_2addr) {
+  DecodedInstruction dec_insn(insn);
+
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  llvm::Value* src1_value;
+  llvm::Value* src2_value;
+
+  // NOTE: The 2nd operand of the shift arithmetic instruction is
+  // 32-bit integer regardless of the 1st operand.
+  if (is_2addr) {
+    src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
+    src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+  } else {
+    src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
+    src2_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
+  }
+
+  llvm::Value* result_value = EmitIntShiftArithmResultComputation(dex_pc,
+                                                                  src1_value,
+                                                                  src2_value,
+                                                                  arithm,
+                                                                  op_jty);
+
+  EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_IntShiftArithmImmediate(unsigned dex_pc,
+                                               const Instruction* insn,
+                                               IntShiftArithmKind arithm) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+
+  llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
+
+  llvm::Value* result_value = EmitIntShiftArithmResultComputation(dex_pc,
+                                                                  src_value,
+                                                                  imm_value,
+                                                                  arithm, kInt);
+
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
+void DexLang::EmitInsn_RSubImmediate(unsigned dex_pc, const Instruction* insn) {
+  DecodedInstruction dec_insn(insn);
+
+  llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
+  llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
+  llvm::Value* result_value = irb_.CreateSub(imm_value, src_value);
+  EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
+
+  irb_.CreateBr(GetNextBasicBlock(dex_pc));
+  return;
+}
+
 void DexLang::EmitInsn_FPArithm(unsigned dex_pc, const Instruction* insn,
                                 FPArithmKind arithm, JType op_jty,
                                 bool is_2addr) {
@@ -2048,32 +2946,32 @@
       EmitInsn_LoadConstantString(ARGS);
       break;
     }
-    case Instruction::CONST_CLASS:
-      //EmitInsn_LoadConstantClass(ARGS);
+    case Instruction::CONST_CLASS: {
+      EmitInsn_LoadConstantClass(ARGS);
       break;
-
-    case Instruction::MONITOR_ENTER:
-      //EmitInsn_MonitorEnter(ARGS);
+    }
+    case Instruction::MONITOR_ENTER: {
+      EmitInsn_MonitorEnter(ARGS);
       break;
-
-    case Instruction::MONITOR_EXIT:
-      //EmitInsn_MonitorExit(ARGS);
+    }
+    case Instruction::MONITOR_EXIT: {
+      EmitInsn_MonitorExit(ARGS);
       break;
-
-    case Instruction::CHECK_CAST:
-      //EmitInsn_CheckCast(ARGS);
+    }
+    case Instruction::CHECK_CAST: {
+      EmitInsn_CheckCast(ARGS);
       break;
-
-    case Instruction::INSTANCE_OF:
-      //EmitInsn_InstanceOf(ARGS);
+    }
+    case Instruction::INSTANCE_OF: {
+      EmitInsn_InstanceOf(ARGS);
       break;
-
+    }
     case Instruction::ARRAY_LENGTH: {
       EmitInsn_ArrayLength(ARGS);
       break;
     }
     case Instruction::NEW_INSTANCE:
-      //EmitInsn_NewInstance(ARGS);
+      EmitInsn_NewInstance(ARGS);
       break;
 
     case Instruction::NEW_ARRAY: {
@@ -2081,55 +2979,55 @@
       break;
     }
     case Instruction::FILLED_NEW_ARRAY:
-      //EmitInsn_FilledNewArray(ARGS, false);
+      EmitInsn_FilledNewArray(ARGS, /* is_range */false);
       break;
 
     case Instruction::FILLED_NEW_ARRAY_RANGE:
-      //EmitInsn_FilledNewArray(ARGS, true);
+      EmitInsn_FilledNewArray(ARGS, /* is_range */true);
       break;
 
     case Instruction::FILL_ARRAY_DATA:
-      //EmitInsn_FillArrayData(ARGS);
+      EmitInsn_FillArrayData(ARGS);
       break;
 
-    case Instruction::THROW:
-      //EmitInsn_ThrowException(ARGS);
+    case Instruction::THROW: {
+      EmitInsn_ThrowException(ARGS);
       break;
-
+    }
     case Instruction::GOTO:
     case Instruction::GOTO_16:
     case Instruction::GOTO_32: {
       EmitInsn_UnconditionalBranch(ARGS);
       break;
     }
-    case Instruction::PACKED_SWITCH:
-      //EmitInsn_PackedSwitch(ARGS);
+    case Instruction::PACKED_SWITCH: {
+      EmitInsn_PackedSwitch(ARGS);
       break;
-
-    case Instruction::SPARSE_SWITCH:
-      //EmitInsn_SparseSwitch(ARGS);
+    }
+    case Instruction::SPARSE_SWITCH: {
+      EmitInsn_SparseSwitch(ARGS);
       break;
-
-    case Instruction::CMPL_FLOAT:
-      //EmitInsn_FPCompare(ARGS, kFloat, false);
+    }
+    case Instruction::CMPL_FLOAT: {
+      EmitInsn_FPCompare(ARGS, kFloat, false);
       break;
-
-    case Instruction::CMPG_FLOAT:
-      //EmitInsn_FPCompare(ARGS, kFloat, true);
+    }
+    case Instruction::CMPG_FLOAT: {
+      EmitInsn_FPCompare(ARGS, kFloat, true);
       break;
-
-    case Instruction::CMPL_DOUBLE:
-      //EmitInsn_FPCompare(ARGS, kDouble, false);
+    }
+    case Instruction::CMPL_DOUBLE: {
+      EmitInsn_FPCompare(ARGS, kDouble, false);
       break;
-
-    case Instruction::CMPG_DOUBLE:
-      //EmitInsn_FPCompare(ARGS, kDouble, true);
+    }
+    case Instruction::CMPG_DOUBLE: {
+      EmitInsn_FPCompare(ARGS, kDouble, true);
       break;
-
-    case Instruction::CMP_LONG:
-      //EmitInsn_LongCompare(ARGS);
+    }
+    case Instruction::CMP_LONG: {
+      EmitInsn_LongCompare(ARGS);
       break;
-
+    }
     case Instruction::IF_EQ: {
       EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_EQ);
       break;
@@ -2234,62 +3132,62 @@
       EmitInsn_APut(ARGS, kShort);
       break;
     }
-    case Instruction::IGET:
-      //EmitInsn_IGet(ARGS, kInt);
+    case Instruction::IGET: {
+      EmitInsn_IGet(ARGS, kInt);
       break;
-
-    case Instruction::IGET_WIDE:
-      //EmitInsn_IGet(ARGS, kLong);
+    }
+    case Instruction::IGET_WIDE: {
+      EmitInsn_IGet(ARGS, kLong);
       break;
-
-    case Instruction::IGET_OBJECT:
-      //EmitInsn_IGet(ARGS, kObject);
+    }
+    case Instruction::IGET_OBJECT: {
+      EmitInsn_IGet(ARGS, kObject);
       break;
-
-    case Instruction::IGET_BOOLEAN:
-      //EmitInsn_IGet(ARGS, kBoolean);
+    }
+    case Instruction::IGET_BOOLEAN: {
+      EmitInsn_IGet(ARGS, kBoolean);
       break;
-
-    case Instruction::IGET_BYTE:
-      //EmitInsn_IGet(ARGS, kByte);
+    }
+    case Instruction::IGET_BYTE: {
+      EmitInsn_IGet(ARGS, kByte);
       break;
-
-    case Instruction::IGET_CHAR:
-      //EmitInsn_IGet(ARGS, kChar);
+    }
+    case Instruction::IGET_CHAR: {
+      EmitInsn_IGet(ARGS, kChar);
       break;
-
-    case Instruction::IGET_SHORT:
-      //EmitInsn_IGet(ARGS, kShort);
+    }
+    case Instruction::IGET_SHORT: {
+      EmitInsn_IGet(ARGS, kShort);
       break;
-
-    case Instruction::IPUT:
-      //EmitInsn_IPut(ARGS, kInt);
+    }
+    case Instruction::IPUT: {
+      EmitInsn_IPut(ARGS, kInt);
       break;
-
-    case Instruction::IPUT_WIDE:
-      //EmitInsn_IPut(ARGS, kLong);
+    }
+    case Instruction::IPUT_WIDE: {
+      EmitInsn_IPut(ARGS, kLong);
       break;
-
-    case Instruction::IPUT_OBJECT:
-      //EmitInsn_IPut(ARGS, kObject);
+    }
+    case Instruction::IPUT_OBJECT: {
+      EmitInsn_IPut(ARGS, kObject);
       break;
-
-    case Instruction::IPUT_BOOLEAN:
-      //EmitInsn_IPut(ARGS, kBoolean);
+    }
+    case Instruction::IPUT_BOOLEAN: {
+      EmitInsn_IPut(ARGS, kBoolean);
       break;
-
-    case Instruction::IPUT_BYTE:
-      //EmitInsn_IPut(ARGS, kByte);
+    }
+    case Instruction::IPUT_BYTE: {
+      EmitInsn_IPut(ARGS, kByte);
       break;
-
-    case Instruction::IPUT_CHAR:
-      //EmitInsn_IPut(ARGS, kChar);
+    }
+    case Instruction::IPUT_CHAR: {
+      EmitInsn_IPut(ARGS, kChar);
       break;
-
-    case Instruction::IPUT_SHORT:
-      //EmitInsn_IPut(ARGS, kShort);
+    }
+    case Instruction::IPUT_SHORT: {
+      EmitInsn_IPut(ARGS, kShort);
       break;
-
+    }
     case Instruction::SGET: {
       EmitInsn_SGet(ARGS, kInt);
       break;
@@ -2386,90 +3284,90 @@
       EmitInsn_Invoke(ARGS, kInterface, kArgRange);
       break;
     }
-    case Instruction::NEG_INT:
-      //EmitInsn_Neg(ARGS, kInt);
+    case Instruction::NEG_INT: {
+      EmitInsn_Neg(ARGS, kInt);
       break;
-
-    case Instruction::NOT_INT:
-      //EmitInsn_Not(ARGS, kInt);
+    }
+    case Instruction::NOT_INT: {
+      EmitInsn_Not(ARGS, kInt);
       break;
-
-    case Instruction::NEG_LONG:
-      //EmitInsn_Neg(ARGS, kLong);
+    }
+    case Instruction::NEG_LONG: {
+      EmitInsn_Neg(ARGS, kLong);
       break;
-
-    case Instruction::NOT_LONG:
-      //EmitInsn_Not(ARGS, kLong);
+    }
+    case Instruction::NOT_LONG: {
+      EmitInsn_Not(ARGS, kLong);
       break;
-
-    case Instruction::NEG_FLOAT:
-      //EmitInsn_FNeg(ARGS, kFloat);
+    }
+    case Instruction::NEG_FLOAT: {
+      EmitInsn_FNeg(ARGS, kFloat);
       break;
-
-    case Instruction::NEG_DOUBLE:
-      //EmitInsn_FNeg(ARGS, kDouble);
+    }
+    case Instruction::NEG_DOUBLE: {
+      EmitInsn_FNeg(ARGS, kDouble);
       break;
-
-    case Instruction::INT_TO_LONG:
-      //EmitInsn_SExt(ARGS);
+    }
+    case Instruction::INT_TO_LONG: {
+      EmitInsn_SExt(ARGS);
       break;
-
-    case Instruction::INT_TO_FLOAT:
-      //EmitInsn_IntToFP(ARGS, kInt, kFloat);
+    }
+    case Instruction::INT_TO_FLOAT: {
+      EmitInsn_IntToFP(ARGS, kInt, kFloat);
       break;
-
-    case Instruction::INT_TO_DOUBLE:
-      //EmitInsn_IntToFP(ARGS, kInt, kDouble);
+    }
+    case Instruction::INT_TO_DOUBLE: {
+      EmitInsn_IntToFP(ARGS, kInt, kDouble);
       break;
-
-    case Instruction::LONG_TO_INT:
-      //EmitInsn_Trunc(ARGS);
+    }
+    case Instruction::LONG_TO_INT: {
+      EmitInsn_Trunc(ARGS);
       break;
-
-    case Instruction::LONG_TO_FLOAT:
-      //EmitInsn_IntToFP(ARGS, kLong, kFloat);
+    }
+    case Instruction::LONG_TO_FLOAT: {
+      EmitInsn_IntToFP(ARGS, kLong, kFloat);
       break;
-
-    case Instruction::LONG_TO_DOUBLE:
-      //EmitInsn_IntToFP(ARGS, kLong, kDouble);
+    }
+    case Instruction::LONG_TO_DOUBLE: {
+      EmitInsn_IntToFP(ARGS, kLong, kDouble);
       break;
-
-    case Instruction::FLOAT_TO_INT:
-      //EmitInsn_FPToInt(ARGS, kFloat, kInt, F2I);
+    }
+    case Instruction::FLOAT_TO_INT: {
+      EmitInsn_FPToInt(ARGS, kFloat, kInt, IntrinsicHelper::F2I);
       break;
-
-    case Instruction::FLOAT_TO_LONG:
-      //EmitInsn_FPToInt(ARGS, kFloat, kLong, F2L);
+    }
+    case Instruction::FLOAT_TO_LONG: {
+      EmitInsn_FPToInt(ARGS, kFloat, kLong, IntrinsicHelper::F2L);
       break;
-
-    case Instruction::FLOAT_TO_DOUBLE:
-      //EmitInsn_FExt(ARGS);
+    }
+    case Instruction::FLOAT_TO_DOUBLE: {
+      EmitInsn_FExt(ARGS);
       break;
-
-    case Instruction::DOUBLE_TO_INT:
-      //EmitInsn_FPToInt(ARGS, kDouble, kInt, D2I);
+    }
+    case Instruction::DOUBLE_TO_INT: {
+      EmitInsn_FPToInt(ARGS, kDouble, kInt, IntrinsicHelper::D2I);
       break;
-
-    case Instruction::DOUBLE_TO_LONG:
-      //EmitInsn_FPToInt(ARGS, kDouble, kLong, D2L);
+    }
+    case Instruction::DOUBLE_TO_LONG: {
+      EmitInsn_FPToInt(ARGS, kDouble, kLong, IntrinsicHelper::D2L);
       break;
-
-    case Instruction::DOUBLE_TO_FLOAT:
-      //EmitInsn_FTrunc(ARGS);
+    }
+    case Instruction::DOUBLE_TO_FLOAT: {
+      EmitInsn_FTrunc(ARGS);
       break;
-
-    case Instruction::INT_TO_BYTE:
-      //EmitInsn_TruncAndSExt(ARGS, 8);
+    }
+    case Instruction::INT_TO_BYTE: {
+      EmitInsn_TruncAndSExt(ARGS, 8);
       break;
-
-    case Instruction::INT_TO_CHAR:
-      //EmitInsn_TruncAndZExt(ARGS, 16);
+    }
+    case Instruction::INT_TO_CHAR: {
+      EmitInsn_TruncAndZExt(ARGS, 16);
       break;
-
-    case Instruction::INT_TO_SHORT:
-      //EmitInsn_TruncAndSExt(ARGS, 16);
+    }
+    case Instruction::INT_TO_SHORT: {
+      EmitInsn_TruncAndSExt(ARGS, 16);
       break;
-
+    }
     case Instruction::ADD_INT: {
       EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, false);
       break;
@@ -2502,18 +3400,18 @@
       EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, false);
       break;
     }
-    case Instruction::SHL_INT:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, false);
+    case Instruction::SHL_INT: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, false);
       break;
-
-    case Instruction::SHR_INT:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, false);
+    }
+    case Instruction::SHR_INT: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, false);
       break;
-
-    case Instruction::USHR_INT:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, false);
+    }
+    case Instruction::USHR_INT: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, false);
       break;
-
+    }
     case Instruction::ADD_LONG: {
       EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, false);
       break;
@@ -2546,18 +3444,18 @@
       EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, false);
       break;
     }
-    case Instruction::SHL_LONG:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, false);
+    case Instruction::SHL_LONG: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, false);
       break;
-
-    case Instruction::SHR_LONG:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, false);
+    }
+    case Instruction::SHR_LONG: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, false);
       break;
-
-    case Instruction::USHR_LONG:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, false);
+    }
+    case Instruction::USHR_LONG: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, false);
       break;
-
+    }
     case Instruction::ADD_FLOAT: {
       EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, false);
       break;
@@ -2630,18 +3528,18 @@
       EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, true);
       break;
     }
-    case Instruction::SHL_INT_2ADDR:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, true);
+    case Instruction::SHL_INT_2ADDR: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, true);
       break;
-
-    case Instruction::SHR_INT_2ADDR:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, true);
+    }
+    case Instruction::SHR_INT_2ADDR: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, true);
       break;
-
-    case Instruction::USHR_INT_2ADDR:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, true);
+    }
+    case Instruction::USHR_INT_2ADDR: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, true);
       break;
-
+    }
     case Instruction::ADD_LONG_2ADDR: {
       EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, true);
       break;
@@ -2674,18 +3572,18 @@
       EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, true);
       break;
     }
-    case Instruction::SHL_LONG_2ADDR:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, true);
+    case Instruction::SHL_LONG_2ADDR: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, true);
       break;
-
-    case Instruction::SHR_LONG_2ADDR:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, true);
+    }
+    case Instruction::SHR_LONG_2ADDR: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, true);
       break;
-
-    case Instruction::USHR_LONG_2ADDR:
-      //EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, true);
+    }
+    case Instruction::USHR_LONG_2ADDR: {
+      EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, true);
       break;
-
+    }
     case Instruction::ADD_FLOAT_2ADDR: {
       EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, true);
       break;
@@ -2732,10 +3630,10 @@
       break;
     }
     case Instruction::RSUB_INT:
-    case Instruction::RSUB_INT_LIT8:
-      //EmitInsn_RSubImmediate(ARGS);
+    case Instruction::RSUB_INT_LIT8: {
+      EmitInsn_RSubImmediate(ARGS);
       break;
-
+    }
     case Instruction::MUL_INT_LIT16:
     case Instruction::MUL_INT_LIT8: {
       EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Mul);
@@ -2766,17 +3664,18 @@
       EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Xor);
       break;
     }
-    case Instruction::SHL_INT_LIT8:
-      //EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shl);
+    case Instruction::SHL_INT_LIT8: {
+      EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shl);
       break;
-
-    case Instruction::SHR_INT_LIT8:
-      //EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shr);
+    }
+    case Instruction::SHR_INT_LIT8: {
+      EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shr);
       break;
-
-    case Instruction::USHR_INT_LIT8:
-      //EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_UShr);
+    }
+    case Instruction::USHR_INT_LIT8: {
+      EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_UShr);
       break;
+    }
 
     case Instruction::UNUSED_3E:
     case Instruction::UNUSED_3F:
diff --git a/src/greenland/dex_lang.h b/src/greenland/dex_lang.h
index ce4b462..6b212d0 100644
--- a/src/greenland/dex_lang.h
+++ b/src/greenland/dex_lang.h
@@ -18,6 +18,7 @@
 #define ART_SRC_GREENLAND_DEX_LANG_H_
 
 #include "backend_types.h"
+#include "compiler_llvm/backend_types.h"
 #include "dalvik_reg.h"
 #include "ir_builder.h"
 
@@ -28,14 +29,13 @@
 
 #include <vector>
 
-#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
 #include <llvm/ADT/ArrayRef.h>
 
 namespace llvm {
   class BasicBlock;
   class Function;
   class LLVMContext;
-  class Module;
   class Type;
 }
 
@@ -54,34 +54,26 @@
  public:
   class Context {
    private:
-    llvm::LLVMContext context_;
-    llvm::Module* module_;
+    llvm::Module& module_;
     IntrinsicHelper* intrinsic_helper_;
 
-    volatile int32_t ref_count_;
-    volatile int32_t mem_usage_;
-
+   public:
+    Context(llvm::Module& module);
     ~Context();
 
-    DISALLOW_COPY_AND_ASSIGN(Context);
-
-   public:
-    Context();
-
     inline llvm::LLVMContext& GetLLVMContext()
-    { return context_; }
+    { return module_.getContext(); }
+
     inline llvm::Module& GetOutputModule()
-    { return *module_; }
+    { return module_; }
+
     inline IntrinsicHelper& GetIntrinsicHelper()
     { return *intrinsic_helper_; }
+    inline const IntrinsicHelper& GetIntrinsicHelper() const
+    { return *intrinsic_helper_; }
 
-    Context& IncRef();
-    void DecRef();
-
-    void AddMemUsageApproximation(size_t usage);
-    inline bool IsMemUsageThresholdReached() const {
-      return (mem_usage_ > (30 << 20)); // (threshold: 30MiB)
-    }
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Context);
   };
 
  public:
@@ -94,7 +86,7 @@
   inline IRBuilder& GetIRBuilder() {
     return irb_;
   }
-  llvm::Value* AllocateDalvikReg(JType jty, unsigned reg_idx);
+  llvm::Value* AllocateDalvikReg(RegCategory cat, unsigned reg_idx);
 
  private:
   Context& dex_lang_ctx_;
@@ -104,6 +96,7 @@
   const DexFile* dex_file_;
   const DexFile::CodeItem* code_item_;
   DexCache* dex_cache_;
+  uint32_t method_idx_;
 
   llvm::LLVMContext& context_;
   llvm::Module& module_;
@@ -161,9 +154,27 @@
   // Return Value Related
   //----------------------------------------------------------------------------
   // Hold the return value returned from the lastest invoke-* instruction
-  llvm::Value* retval_;
-  // The type of ret_val_
-  JType retval_jty_;
+  DalvikReg* retval_reg_;
+
+  llvm::Value* EmitLoadDalvikRetValReg(JType jty, JTypeSpace space) {
+    return retval_reg_->GetValue(jty, space);
+  }
+
+  llvm::Value* EmitLoadDalvikRetValReg(char shorty, JTypeSpace space) {
+    return EmitLoadDalvikRetValReg(GetJTypeFromShorty(shorty), space);
+  }
+
+  void EmitStoreDalvikRetValReg(JType jty, JTypeSpace space,
+                                llvm::Value* new_value) {
+    retval_reg_->SetValue(jty, space, new_value);
+    return;
+  }
+
+  void EmitStoreDalvikRetValReg(char shorty, JTypeSpace space,
+                                llvm::Value* new_value) {
+    EmitStoreDalvikRetValReg(GetJTypeFromShorty(shorty), space, new_value);
+    return;
+  }
 
  private:
   //----------------------------------------------------------------------------
@@ -211,7 +222,6 @@
   //----------------------------------------------------------------------------
   // Shadow Frame
   //----------------------------------------------------------------------------
-  bool require_shadow_frame;
   unsigned num_shadow_frame_entries_;
 
   void EmitUpdateDexPC(unsigned dex_pc);
@@ -228,8 +238,6 @@
   bool CreateFunction();
   llvm::FunctionType* GetFunctionType();
 
-  bool PrepareDalvikRegs();
-
   bool EmitPrologue();
   bool EmitPrologueAssignArgRegister();
   bool EmitPrologueAllcaShadowFrame();
@@ -263,6 +271,12 @@
     kIntArithm_Xor,
   };
 
+  enum IntShiftArithmKind {
+    kIntArithm_Shl,
+    kIntArithm_Shr,
+    kIntArithm_UShr,
+  };
+
   enum FPArithmKind {
     kFPArithm_Add,
     kFPArithm_Sub,
@@ -280,14 +294,37 @@
 
   llvm::Value* EmitGetCurrentThread();
 
-  llvm::Value* EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IntrinsicId intr_id);
+  void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
+
   llvm::Value* EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IntrinsicId intr_id,
-                                          llvm::ArrayRef<llvm::Value*> args);
-  llvm::Value* EmitInvokeIntrinsic(unsigned dex_pc,
-                                   IntrinsicHelper::IntrinsicId intr_id);
+                                          llvm::ArrayRef<llvm::Value*> args
+                                              = llvm::ArrayRef<llvm::Value*>());
+  llvm::Value* EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::IntrinsicId intr_id,
+                                           llvm::Value* arg1,
+                                           llvm::Value* arg2) {
+    llvm::Value* args[] = { arg1, arg2 };
+    return EmitInvokeIntrinsicNoThrow(intr_id, args);
+  }
+  llvm::Value* EmitInvokeIntrinsic3NoThrow(IntrinsicHelper::IntrinsicId intr_id,
+                                           llvm::Value* arg1,
+                                           llvm::Value* arg2,
+                                           llvm::Value* arg3) {
+    llvm::Value* args[] = { arg1, arg2, arg3 };
+    return EmitInvokeIntrinsicNoThrow(intr_id, args);
+  }
+  llvm::Value* EmitInvokeIntrinsic4NoThrow(IntrinsicHelper::IntrinsicId intr_id,
+                                           llvm::Value* arg1,
+                                           llvm::Value* arg2,
+                                           llvm::Value* arg3,
+                                           llvm::Value* arg4) {
+    llvm::Value* args[] = { arg1, arg2, arg3, arg4 };
+    return EmitInvokeIntrinsicNoThrow(intr_id, args);
+  }
+
   llvm::Value* EmitInvokeIntrinsic(unsigned dex_pc,
                                    IntrinsicHelper::IntrinsicId intr_id,
-                                   llvm::ArrayRef<llvm::Value*> args);
+                                   llvm::ArrayRef<llvm::Value*> args
+                                        = llvm::ArrayRef<llvm::Value*>());
   llvm::Value* EmitInvokeIntrinsic2(unsigned dex_pc,
                                     IntrinsicHelper::IntrinsicId intr_id,
                                     llvm::Value* arg1,
@@ -323,10 +360,19 @@
     return EmitInvokeIntrinsic(dex_pc, intr_id, args);
   }
 
-  RegCategory GetInferredRegCategory(unsigned dex_pc, unsigned reg_idx);
+  compiler_llvm::RegCategory GetInferredRegCategory(unsigned dex_pc,
+                                                    unsigned reg_idx);
+
+  llvm::Value* EmitLoadConstantClass(unsigned dex_pc, uint32_t type_idx);
 
   llvm::Value* EmitLoadArrayLength(llvm::Value* array);
 
+  llvm::Value* EmitAllocNewArray(unsigned dex_pc, int32_t length,
+                                 uint32_t type_idx, bool is_filled_new_array);
+
+  llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                          llvm::Value* cmp_lt);
+
   llvm::Value* EmitLoadStaticStorage(unsigned dex_pc, unsigned type_idx);
 
   llvm::Value* EmitConditionResult(llvm::Value* lhs, llvm::Value* rhs,
@@ -338,6 +384,12 @@
                                               IntArithmKind arithm,
                                               JType op_jty);
 
+  llvm::Value* EmitIntShiftArithmResultComputation(uint32_t dex_pc,
+                                                   llvm::Value* lhs,
+                                                   llvm::Value* rhs,
+                                                   IntShiftArithmKind arithm,
+                                                   JType op_jty);
+
   llvm::Value* EmitIntDivRemResultComputation(unsigned dex_pc,
                                               llvm::Value* dividend,
                                               llvm::Value* divisor,
@@ -354,18 +406,15 @@
 
   // MOVE_EXCEPTION, THROW instructions
   void EmitInsn_MoveException(GEN_INSN_ARGS);
-#if 0
   void EmitInsn_ThrowException(GEN_INSN_ARGS);
 
   // RETURN instructions
-#endif
   void EmitInsn_ReturnVoid(GEN_INSN_ARGS);
   void EmitInsn_Return(GEN_INSN_ARGS);
 
   // CONST, CONST_CLASS, CONST_STRING instructions
   void EmitInsn_LoadConstant(GEN_INSN_ARGS, JType imm_jty);
   void EmitInsn_LoadConstantString(GEN_INSN_ARGS);
-#if 0
   void EmitInsn_LoadConstantClass(GEN_INSN_ARGS);
 
   // MONITOR_ENTER, MONITOR_EXIT instructions
@@ -378,22 +427,18 @@
 
   // NEW_INSTANCE instructions
   void EmitInsn_NewInstance(GEN_INSN_ARGS);
-#endif
 
   // ARRAY_LEN, NEW_ARRAY, FILLED_NEW_ARRAY, FILL_ARRAY_DATA instructions
   void EmitInsn_ArrayLength(GEN_INSN_ARGS);
   void EmitInsn_NewArray(GEN_INSN_ARGS);
-#if 0
   void EmitInsn_FilledNewArray(GEN_INSN_ARGS, bool is_range);
   void EmitInsn_FillArrayData(GEN_INSN_ARGS);
 
-#endif
   // GOTO, IF_TEST, IF_TESTZ instructions
   void EmitInsn_UnconditionalBranch(GEN_INSN_ARGS);
-  void EmitInsn_BinaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
   void EmitInsn_UnaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
+  void EmitInsn_BinaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
 
-#if 0
   // PACKED_SWITCH, SPARSE_SWITCH instrutions
   void EmitInsn_PackedSwitch(GEN_INSN_ARGS);
   void EmitInsn_SparseSwitch(GEN_INSN_ARGS);
@@ -402,48 +447,22 @@
   void EmitInsn_FPCompare(GEN_INSN_ARGS, JType fp_jty, bool gt_bias);
   void EmitInsn_LongCompare(GEN_INSN_ARGS);
 
-#endif
   // AGET, APUT instrutions
   void EmitInsn_AGet(GEN_INSN_ARGS, JType elem_jty);
   void EmitInsn_APut(GEN_INSN_ARGS, JType elem_jty);
 
-#if 0
   // IGET, IPUT instructions
   void EmitInsn_IGet(GEN_INSN_ARGS, JType field_jty);
   void EmitInsn_IPut(GEN_INSN_ARGS, JType field_jty);
-#endif
 
   // SGET, SPUT instructions
   void EmitInsn_SGet(GEN_INSN_ARGS, JType field_jty);
   void EmitInsn_SPut(GEN_INSN_ARGS, JType field_jty);
 
-#if 0
-  // INVOKE instructions
-  llvm::Value* EmitFixStub(llvm::Value* callee_method_object_addr,
-                           uint32_t method_idx,
-                           bool is_static);
-  llvm::Value* EmitEnsureResolved(llvm::Value* callee,
-                                  llvm::Value* caller,
-                                  uint32_t dex_method_idx,
-                                  bool is_virtual);
-#endif
-
   void EmitInsn_Invoke(GEN_INSN_ARGS,
                        InvokeType invoke_type,
                        InvokeArgFmt arg_fmt);
 
-#if 0
-  llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
-
-  llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
-                                                     llvm::Value* this_addr);
-
-  llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
-                                                        InvokeType invoke_type,
-                                                        llvm::Value* this_addr,
-                                                        unsigned dex_pc,
-                                                        bool is_fast_path);
-
   // Unary instructions
   void EmitInsn_Neg(GEN_INSN_ARGS, JType op_jty);
   void EmitInsn_Not(GEN_INSN_ARGS, JType op_jty);
@@ -455,18 +474,16 @@
   void EmitInsn_FNeg(GEN_INSN_ARGS, JType op_jty);
   void EmitInsn_IntToFP(GEN_INSN_ARGS, JType src_jty, JType dest_jty);
   void EmitInsn_FPToInt(GEN_INSN_ARGS, JType src_jty, JType dest_jty,
-                        runtime_support::RuntimeId runtime_func_id);
+                        IntrinsicHelper::IntrinsicId intr_id);
   void EmitInsn_FExt(GEN_INSN_ARGS);
   void EmitInsn_FTrunc(GEN_INSN_ARGS);
 
-#endif
   // Integer binary arithmetic instructions
   void EmitInsn_IntArithm(GEN_INSN_ARGS, IntArithmKind arithm,
                           JType op_jty, bool is_2addr);
 
   void EmitInsn_IntArithmImmediate(GEN_INSN_ARGS, IntArithmKind arithm);
 
-#if 0
   void EmitInsn_IntShiftArithm(GEN_INSN_ARGS, IntShiftArithmKind arithm,
                                JType op_jty, bool is_2addr);
 
@@ -475,7 +492,6 @@
 
   void EmitInsn_RSubImmediate(GEN_INSN_ARGS);
 
-#endif
   // Floating-point binary arithmetic instructions
   void EmitInsn_FPArithm(GEN_INSN_ARGS, FPArithmKind arithm,
                          JType op_jty, bool is_2addr);
diff --git a/src/greenland/gbc_context.cc b/src/greenland/gbc_context.cc
new file mode 100644
index 0000000..ec86bfb
--- /dev/null
+++ b/src/greenland/gbc_context.cc
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#include "gbc_context.h"
+
+#include "atomic.h"
+
+namespace art {
+namespace greenland {
+
+GBCContext::GBCContext()
+    : context_(), module_(NULL), ref_count_(1), mem_usage_(0) {
+  module_ = new llvm::Module("art", context_);
+
+  // Initialize the contents of an empty module
+  // Type of "JavaObject"
+  llvm::StructType::create(context_, "JavaObject");
+  // Type of "Method"
+  llvm::StructType::create(context_, "Method");
+  // Type of "Thread"
+  llvm::StructType::create(context_, "Thread");
+
+  dex_lang_ctx_ = new DexLang::Context(*module_);
+  return;
+}
+
+GBCContext::~GBCContext() {
+  delete dex_lang_ctx_;
+  return;
+}
+
+GBCContext& GBCContext::IncRef() {
+  android_atomic_inc(&ref_count_);
+  return *this;
+}
+
+const GBCContext& GBCContext::IncRef() const {
+  android_atomic_inc(&ref_count_);
+  return *this;
+}
+
+void GBCContext::DecRef() const {
+  int32_t old_ref_count = android_atomic_dec(&ref_count_);
+  if (old_ref_count <= 1) {
+    delete this;
+  }
+  return;
+}
+
+void GBCContext::AddMemUsageApproximation(size_t usage) {
+  android_atomic_add(static_cast<int32_t>(usage), &mem_usage_);
+  return;
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/gbc_context.h b/src/greenland/gbc_context.h
new file mode 100644
index 0000000..7c31816
--- /dev/null
+++ b/src/greenland/gbc_context.h
@@ -0,0 +1,80 @@
+/*
+ * 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_GREENLAND_GBC_CONTEXT_H_
+#define ART_SRC_GREENLAND_GBC_CONTEXT_H_
+
+#include "dex_lang.h"
+
+#include "macros.h"
+
+#include <llvm/LLVMContext.h>
+
+namespace llvm {
+  class Module;
+} // namespace llvm
+
+namespace art {
+namespace greenland {
+
+class IntrinsicHelper;
+
+class GBCContext {
+ private:
+  llvm::LLVMContext context_;
+  llvm::Module* module_;
+  DexLang::Context* dex_lang_ctx_;
+
+  mutable volatile int32_t ref_count_;
+  volatile int32_t mem_usage_;
+
+  ~GBCContext();
+
+ public:
+  GBCContext();
+
+  inline llvm::LLVMContext& GetLLVMContext()
+  { return context_; }
+  inline llvm::Module& GetOutputModule()
+  { return *module_; }
+
+  inline IntrinsicHelper& GetIntrinsicHelper()
+  { return dex_lang_ctx_->GetIntrinsicHelper(); }
+  inline const IntrinsicHelper& GetIntrinsicHelper() const
+  { return dex_lang_ctx_->GetIntrinsicHelper(); }
+
+  inline DexLang::Context& GetDexLangContext()
+  { return *dex_lang_ctx_; }
+  inline const DexLang::Context& GetDexLangContext() const
+  { return *dex_lang_ctx_; }
+
+  GBCContext& IncRef();
+  const GBCContext& IncRef() const;
+  void DecRef() const;
+
+  void AddMemUsageApproximation(size_t usage);
+  inline bool IsMemUsageThresholdReached() const {
+    return (mem_usage_ > (30 << 20)); // (threshold: 30MiB)
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GBCContext);
+};
+
+} // namespace greenland
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_GBC_CONTEXT_H_
diff --git a/src/greenland/gbc_function.h b/src/greenland/gbc_function.h
new file mode 100644
index 0000000..b7cbea6
--- /dev/null
+++ b/src/greenland/gbc_function.h
@@ -0,0 +1,78 @@
+/*
+ * 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_GREENLAND_GBC_FUNCTION_H_
+#define ART_SRC_GREENLAND_GBC_FUNCTION_H_
+
+#include "gbc_context.h"
+
+namespace llvm {
+  class Function;
+} // namespace llvm
+
+namespace art {
+  class OatCompilationUnit;
+} // namespace art
+
+namespace art {
+namespace greenland {
+
+class GBCContext;
+
+class GBCFunction {
+ private:
+  // The GBCContext associated with this GBCFunction
+  GBCContext& context_;
+
+  // The LLVM Function in Greenland bitcode
+  llvm::Function& func_;
+
+  // The associated OatCompilationUnit
+  const OatCompilationUnit& cunit_;
+
+ public:
+  GBCFunction(GBCContext& context, llvm::Function& func,
+              const OatCompilationUnit& cunit)
+    : context_(context.IncRef()), func_(func), cunit_(cunit) { }
+
+  ~GBCFunction() {
+    context_.DecRef();
+    return;
+  }
+
+  IntrinsicHelper& GetIntrinsicHelper() {
+    return context_.GetIntrinsicHelper();
+  }
+  const IntrinsicHelper& GetIntrinsicHelper() const {
+    return context_.GetIntrinsicHelper();
+  }
+
+  llvm::Function& GetBitcode() {
+    return func_;
+  }
+  const llvm::Function& GetBitcode() const {
+    return func_;
+  }
+
+  const OatCompilationUnit& GetOatCompilationUnit() const {
+    return cunit_;
+  }
+};
+
+} // namespace greenland
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_GBC_FUNCTION_H_
diff --git a/src/greenland/greenland.cc b/src/greenland/greenland.cc
index bbf990d..469f7d5 100644
--- a/src/greenland/greenland.cc
+++ b/src/greenland/greenland.cc
@@ -16,6 +16,8 @@
 
 #include "greenland.h"
 
+#include "gbc_context.h"
+#include "gbc_function.h"
 #include "target_codegen_machine.h"
 #include "target_registry.h"
 
@@ -63,6 +65,9 @@
 }
 
 void InitializeGreenland() {
+  // Initialize LLVM internal data structure for multithreading
+  llvm::llvm_start_multithreaded();
+
   // Initialize passes
   llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();
 
@@ -83,9 +88,6 @@
   InitializeAllCodeGenMachines();
   InitializeAllInvokeStubCompilers();
 
-  // Initialize LLVM internal data structure for multithreading
-  llvm::llvm_start_multithreaded();
-
   return;
 }
 
@@ -96,7 +98,7 @@
 
 Greenland::Greenland(art::Compiler& compiler)
     : compiler_(compiler), codegen_machine_(NULL),
-      lock_("greenland_compiler_lock"), cur_dex_lang_ctx_(NULL) {
+      lock_("greenland_compiler_lock"), cur_gbc_ctx_(NULL) {
   // Initialize Greenland
   pthread_once(&greenland_initialized, InitializeGreenland);
 
@@ -107,7 +109,7 @@
 }
 
 Greenland::~Greenland() {
-  cur_dex_lang_ctx_->DecRef();
+  cur_gbc_ctx_->DecRef();
   delete codegen_machine_;
 }
 
@@ -115,9 +117,10 @@
   MutexLock GUARD(lock_);
 
   // Dex to LLVM IR
-  DexLang::Context& dex_lang_ctx = GetDexLangContext();
+  GBCContext& gbc_ctx = GetGBCContext();
 
-  UniquePtr<DexLang> dex_lang(new DexLang(dex_lang_ctx, compiler_, cunit));
+  UniquePtr<DexLang> dex_lang(new DexLang(gbc_ctx.GetDexLangContext(),
+                                          compiler_, cunit));
 
   llvm::Function* func = dex_lang->Build();
 
@@ -127,40 +130,47 @@
     return NULL;
   }
 
-  dex_lang_ctx.GetOutputModule().dump();
+  func->dump();
 
-  UniquePtr<CompiledMethod> result(codegen_machine_->Run(*this, *func, cunit,
-                                                         dex_lang_ctx));
+  // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
+  // Dex file.  Besides, we have to convert the code unit into bytes.
+  // Thus, we got our magic number 9.
+  gbc_ctx.AddMemUsageApproximation(
+      cunit.GetCodeItem()->insns_size_in_code_units_ * 900);
 
-  // dex_lang_ctx was no longer needed
-  dex_lang_ctx.DecRef();
+  GBCFunction gbc_func(gbc_ctx, *func, cunit);
+
+  UniquePtr<CompiledMethod> result(codegen_machine_->Run(compiler_, gbc_func));
+
+  // gbc_ctx was no longer needed
+  gbc_ctx.DecRef();
 
   return result.release();
 }
 
-DexLang::Context& Greenland::GetDexLangContext() {
+GBCContext& Greenland::GetGBCContext() {
   //MutexLock GUARD(lock_);
 
-  ResetDexLangContextIfThresholdReached();
+  ResetGBCContextIfThresholdReached();
 
-  if (cur_dex_lang_ctx_ == NULL) {
-    cur_dex_lang_ctx_ = new DexLang::Context();
+  if (cur_gbc_ctx_ == NULL) {
+    cur_gbc_ctx_ = new GBCContext();
   }
-  CHECK(cur_dex_lang_ctx_ != NULL);
+  CHECK(cur_gbc_ctx_ != NULL);
 
-  return cur_dex_lang_ctx_->IncRef();
+  return cur_gbc_ctx_->IncRef();
 }
 
-void Greenland::ResetDexLangContextIfThresholdReached() {
+void Greenland::ResetGBCContextIfThresholdReached() {
   lock_.AssertHeld();
 
-  if (cur_dex_lang_ctx_ == NULL) {
+  if (cur_gbc_ctx_ == NULL) {
     return;
   }
 
-  if (cur_dex_lang_ctx_->IsMemUsageThresholdReached()) {
-    cur_dex_lang_ctx_->DecRef();
-    cur_dex_lang_ctx_ = NULL;
+  if (cur_gbc_ctx_->IsMemUsageThresholdReached()) {
+    cur_gbc_ctx_->DecRef();
+    cur_gbc_ctx_ = NULL;
   }
   return;
 }
diff --git a/src/greenland/greenland.h b/src/greenland/greenland.h
index 4407c92..1d6f8e5 100644
--- a/src/greenland/greenland.h
+++ b/src/greenland/greenland.h
@@ -17,8 +17,6 @@
 #ifndef ART_SRC_GREENLAND_GREENLAND_H_
 #define ART_SRC_GREENLAND_GREENLAND_H_
 
-#include "dex_lang.h"
-
 #include "macros.h"
 #include "object.h"
 
@@ -31,6 +29,7 @@
 namespace art {
 namespace greenland {
 
+class GBCContext;
 class TargetCodeGenMachine;
 
 class Greenland {
@@ -54,11 +53,11 @@
 
   Mutex lock_;
 
-  // NOTE: Ensure that the lock_ is held before altering cur_dex_lang_ctx_
-  DexLang::Context *cur_dex_lang_ctx_;
+  // NOTE: Ensure that the lock_ is held before altering cur_gbc_ctx
+  GBCContext *cur_gbc_ctx_;
 
-  DexLang::Context& GetDexLangContext();
-  void ResetDexLangContextIfThresholdReached();
+  GBCContext& GetGBCContext();
+  void ResetGBCContextIfThresholdReached();
 
   DISALLOW_COPY_AND_ASSIGN(Greenland);
 };
diff --git a/src/greenland/inferred_reg_category_map.cc b/src/greenland/inferred_reg_category_map.cc
deleted file mode 100644
index 4f7f4ff..0000000
--- a/src/greenland/inferred_reg_category_map.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-#include "inferred_reg_category_map.h"
-
-#include "backend_types.h"
-#include "stl_util.h"
-
-#include <stdint.h>
-#include <vector>
-
-namespace art {
-namespace greenland {
-
-InferredRegCategoryMap::InferredRegCategoryMap(uint32_t insns_size,
-                                               uint8_t regs_size)
-: registers_size_(regs_size), lines_(insns_size, NULL), can_be_object_(regs_size) {
-}
-
-InferredRegCategoryMap::~InferredRegCategoryMap() {
-  STLDeleteElements(&lines_);
-}
-
-RegCategory InferredRegCategoryMap::GetRegCategory(uint32_t dex_pc,
-                                                   uint16_t reg_idx) const {
-  if (lines_[dex_pc] == NULL) {
-    return kRegUnknown;
-  }
-  return lines_[dex_pc]->GetRegCategory(reg_idx);
-}
-
-void InferredRegCategoryMap::SetRegCategory(uint32_t dex_pc,
-                                            uint16_t reg_idx,
-                                            RegCategory cat) {
-  if (cat != kRegUnknown) {
-    if (lines_[dex_pc] == NULL) {
-      lines_[dex_pc] = new RegCategoryLine();
-    }
-
-    (*lines_[dex_pc]).SetRegCategory(reg_idx, cat);
-  }
-}
-
-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 {
-
-  if (registers_size_ != rhs.registers_size_) {
-    return false;
-  }
-
-  if (lines_.size() != rhs.lines_.size()) {
-    return false;
-  }
-
-  for (size_t i = 0; i < lines_.size(); ++i) {
-    if (lines_[i] == NULL && rhs.lines_[i] == NULL) {
-      continue;
-    }
-
-    if ((lines_[i] == NULL && rhs.lines_[i] != NULL) ||
-        (lines_[i] != NULL && rhs.lines_[i] == NULL)) {
-      return false;
-    }
-
-    if (*lines_[i] != *rhs.lines_[i]) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool InferredRegCategoryMap::
-operator!=(InferredRegCategoryMap const& rhs) const {
-
-  return !(*this == rhs);
-}
-
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/inferred_reg_category_map.h b/src/greenland/inferred_reg_category_map.h
deleted file mode 100644
index 57e0c30..0000000
--- a/src/greenland/inferred_reg_category_map.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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_GREENLAND_INFERRED_REG_CATEGORY_MAP_H_
-#define ART_SRC_GREENLAND_INFERRED_REG_CATEGORY_MAP_H_
-
-#include "backend_types.h"
-
-#include <stdint.h>
-#include <vector>
-
-#include "safe_map.h"
-
-namespace art {
-namespace greenland {
-
-class InferredRegCategoryMap {
- private:
-  class RegCategoryLine {
-   private:
-    typedef SafeMap<uint16_t, uint8_t> Table;
-    Table reg_category_line_;
-
-   public:
-    RegCategory GetRegCategory(uint16_t reg_idx) const {
-      // TODO: C++0x auto
-      Table::const_iterator result = reg_category_line_.find(reg_idx);
-      if (result == reg_category_line_.end()) {
-        return kRegUnknown;
-      }
-      return static_cast<RegCategory>(result->second);
-    }
-
-    void SetRegCategory(uint16_t reg_idx, RegCategory cat) {
-      if (cat != kRegUnknown) {
-        reg_category_line_.Put(reg_idx, cat);
-      }
-    }
-
-    bool operator==(RegCategoryLine const& rhs) const {
-      return reg_category_line_ == rhs.reg_category_line_;
-    }
-    bool operator!=(RegCategoryLine const& rhs) const {
-      return reg_category_line_ != rhs.reg_category_line_;
-    }
-  };
-
- public:
-  InferredRegCategoryMap(uint32_t insns_size_in_code_units, uint8_t regs_size);
-
-  ~InferredRegCategoryMap();
-
-  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;
-
- private:
-  uint16_t registers_size_;
-
-  std::vector<RegCategoryLine*> lines_;
-
-  std::vector<bool> can_be_object_;
-
-  DISALLOW_COPY_AND_ASSIGN(InferredRegCategoryMap);
-};
-
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_INFERRED_REG_CATEGORY_MAP_H_
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index 3f3fae1..f288bbc 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -58,10 +58,31 @@
 // Thread* dex_lang_get_current_thread()
 _EVAL_DEF_INTRINSICS_FUNC(GetCurrentThread,
                           dex_lang_get_current_thread,
-                          kAttrReadOnly | kAttrNoThrow,
-                           kJavaThreadTy,
+                          kAttrReadNone | kAttrNoThrow,
+                          kJavaThreadTy,
                           _EXPAND_ARG0())
 
+// void dex_lang_test_suspend(Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(TestSuspend,
+                          dex_lang_test_suspend,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kJavaThreadTy))
+
+// void dex_lang_check_suspend() /* Expands to GetCurrentThread/TestSuspend */
+_EVAL_DEF_INTRINSICS_FUNC(CheckSuspend,
+                          dex_lang_check_suspend,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
+// void dex_lang_mark_gc_card(Object* new_value, Object* object)
+_EVAL_DEF_INTRINSICS_FUNC(MarkGCCard,
+                          dex_lang_mark_gc_card,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
 //----------------------------------------------------------------------------
 // Exception
 //----------------------------------------------------------------------------
@@ -78,6 +99,13 @@
                           kInt32Ty,
                           _EXPAND_ARG1(kInt32ConstantTy))
 
+// void dex_lang_throw_exception(JavaObject* exception)
+_EVAL_DEF_INTRINSICS_FUNC(ThrowException,
+                          dex_lang_throw_exception,
+                          kAttrDoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kJavaObjectTy))
+
 // JavaObject* dex_lang_get_current_exception()
 _EVAL_DEF_INTRINSICS_FUNC(GetException,
                           dex_lang_get_current_exception,
@@ -102,31 +130,24 @@
 // void dex_lang_throw_div_zero()
 _EVAL_DEF_INTRINSICS_FUNC(ThrowDivZeroException,
                           dex_lang_throw_div_zero,
-                          kAttrNoThrow,
+                          kAttrDoThrow,
                           kVoidTy,
                           _EXPAND_ARG0())
 
 // void dex_lang_throw_null_pointer_exception(uint32_t dex_pc)
 _EVAL_DEF_INTRINSICS_FUNC(ThrowNullPointerException,
                           dex_lang_throw_null_pointer_exception,
-                          kAttrNoThrow,
+                          kAttrDoThrow,
                           kVoidTy,
                           _EXPAND_ARG1(kInt32ConstantTy))
 
 // void dex_lang_throw_array_bounds(int index, int array_len)
 _EVAL_DEF_INTRINSICS_FUNC(ThrowIndexOutOfBounds,
                           dex_lang_throw_array_bounds,
-                          kAttrNoThrow,
+                          kAttrDoThrow,
                           kVoidTy,
                           _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
-// void dex_lang_throw(exception_object)
-_EVAL_DEF_INTRINSICS_FUNC(Throw,
-                          dex_lang_throw,
-                          kAttrNoThrow,
-                          kVoidTy,
-                          _EXPAND_ARG1(kJavaObjectTy))
-
 //----------------------------------------------------------------------------
 // ConstString
 //----------------------------------------------------------------------------
@@ -138,16 +159,24 @@
                           kJavaObjectTy,
                           _EXPAND_ARG1(kInt32ConstantTy))
 
-// JavaObject* dex_lang_const_string(uint32_t string_idx)
-_EVAL_DEF_INTRINSICS_FUNC(ConstStringFast,
-                          dex_lang_const_string.fast,
+// JavaObject* dex_lang_load_string_from_dex_cache(Method* method, uint32_t string_idx)
+_EVAL_DEF_INTRINSICS_FUNC(LoadStringFromDexCache,
+                          dex_lang_load_string_from_dex_cache,
                           kAttrReadOnly | kAttrNoThrow,
                           kJavaObjectTy,
                           _EXPAND_ARG1(kInt32ConstantTy))
 
+// JavaObject* dex_lang_resolve_string(Method* method, uint32_t string_idx)
+_EVAL_DEF_INTRINSICS_FUNC(ResolveString,
+                          dex_lang_resolve_string,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kInt32ConstantTy))
+
 //----------------------------------------------------------------------------
 // ConstClass
 //----------------------------------------------------------------------------
+
 // JavaObject* dex_lang_const_class(uint32_t type_idx)
 _EVAL_DEF_INTRINSICS_FUNC(ConstClass,
                           dex_lang_const_class,
@@ -155,16 +184,96 @@
                           kJavaObjectTy,
                           _EXPAND_ARG1(kInt32ConstantTy))
 
+// JavaObject* dex_lang_initialize_type_and_verify_access(uint32_t type_idx,
+//                                                        Method* referrer,
+//                                                        Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(InitializeTypeAndVerifyAccess,
+                          dex_lang_initialize_type_and_verify_access,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+// JavaObject* dex_lang_load_type_from_dex_cache(uint32_t type_idx)
+_EVAL_DEF_INTRINSICS_FUNC(LoadTypeFromDexCache,
+                          dex_lang_load_type_from_dex_cache,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// JavaObject* dex_lang_initialize_type(uint32_t type_idx,
+//                                      Method* referrer,
+//                                      Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(InitializeType,
+                          dex_lang_initialize_type,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
 //----------------------------------------------------------------------------
-// CheckCast
+// Lock
 //----------------------------------------------------------------------------
-// void dex_lang_check_cast(uint32_t type_idx, JavaObject* obj)
+
+// void dex_lang_lock_object(JavaObject* obj, Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(LockObject,
+                          dex_lang_lock_object,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaThreadTy))
+
+// void dex_lang_unlock_object(JavaObject* obj, Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(UnlockObject,
+                          dex_lang_unlock_object,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaThreadTy))
+
+//----------------------------------------------------------------------------
+// Cast
+//----------------------------------------------------------------------------
+
+// void dex_lang_check_cast(JavaObject* dest_type, JavaObject* src_type)
 _EVAL_DEF_INTRINSICS_FUNC(CheckCast,
                           dex_lang_check_cast,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
+// void dex_lang_hl_check_cast(uint32_t type_idx, JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(HLCheckCast,
+                          dex_lang_hl_check_cast,
                           kAttrReadOnly | kAttrNoThrow,
                           kVoidTy,
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaObjectTy))
 
+// int dex_lang_is_assignable(JavaObject* dest_type, JavaObject* src_type)
+_EVAL_DEF_INTRINSICS_FUNC(IsAssignable,
+                          dex_lang_is_assignable,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Allocation
+//----------------------------------------------------------------------------
+
+// JavaObject* dex_lang_alloc_object(uint32_t type_idx,
+//                                   Method* referrer,
+//                                   Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocObject,
+                          dex_lang_alloc_object,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+// JavaObject* dex_lang_alloc_object_with_access_check(uint32_t type_idx,
+//                                                     Method* referrer,
+//                                                     Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocObjectWithAccessCheck,
+                          dex_lang_alloc_object_with_access_check,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
 //----------------------------------------------------------------------------
 // Instance
 //----------------------------------------------------------------------------
@@ -187,13 +296,6 @@
 // Array
 //----------------------------------------------------------------------------
 
-// uint32_t dex_lang_array_length(int32_t opt_flags, JavaObject* array)
-_EVAL_DEF_INTRINSICS_FUNC(ArrayLength,
-                          dex_lang_array_length,
-                          kAttrReadOnly | kAttrNoThrow,
-                          kInt32Ty,
-                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
-
 // JavaObject* dex_lang_new_array(uint32_t type_idx, uint32_t array_size)
 _EVAL_DEF_INTRINSICS_FUNC(NewArray,
                           dex_lang_new_array,
@@ -201,12 +303,59 @@
                           kJavaObjectTy,
                           _EXPAND_ARG2(kInt32ConstantTy, kInt32Ty))
 
-// void dex_lang_fill_array_data(int32_t offset, JavaObject* array)
-_EVAL_DEF_INTRINSICS_FUNC(FillArrayData,
-                          dex_lang_fill_array_data,
+// uint32_t dex_lang_opt_array_length(int32_t opt_flags, JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(OptArrayLength,
+                          dex_lang_opt_array_length,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
+
+// uint32_t dex_lang_array_length(JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(ArrayLength,
+                          dex_lang_array_length,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kJavaObjectTy))
+
+// JavaObject* dex_lang_alloc_array(uint32_t type_idx,
+//                                  Method* referrer,
+//                                  uint32_t length,
+//                                  Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocArray,
+                          dex_lang_alloc_array,
                           kAttrNone,
-                          kVoidTy,
-                          _EXPAND_ARG2(kInt32ConstantTy, kJavaObjectTy))
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32Ty, kJavaThreadTy))
+
+// JavaObject* dex_lang_alloc_array_with_access_check(uint32_t type_idx,
+//                                                    Method* referrer,
+//                                                    uint32_t length,
+//                                                    Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocArrayWithAccessCheck,
+                          dex_lang_alloc_array_with_access_check,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32Ty, kJavaThreadTy))
+
+// JavaObject* dex_lang_check_and_alloc_array(uint32_t type_idx,
+//                                            Method* referrer,
+//                                            uint32_t length,
+//                                            Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(CheckAndAllocArray,
+                          dex_lang_check_and_alloc_array,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32ConstantTy, kJavaThreadTy))
+
+// JavaObject* dex_lang_check_and_alloc_array_with_access_check(uint32_t type_idx,
+//                                                              Method* referrer,
+//                                                              uint32_t length,
+//                                                              Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(CheckAndAllocArrayWithAccessCheck,
+                          dex_lang_check_and_alloc_array_with_access_check,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32ConstantTy, kJavaThreadTy))
 
 // dex_lang_aget_* and dex_lang_aput_* never generate exception since the
 // necessary checking on arguments (e.g., array and index) has already done
@@ -301,10 +450,221 @@
 // void dex_lang_check_put_array_element(JavaObject* value, JavaObject* array)
 _EVAL_DEF_INTRINSICS_FUNC(CheckPutArrayElement,
                           dex_lang_check_put_array_element,
-                          kAttrReadOnly | kAttrNoThrow,
+                          kAttrNone,
                           kVoidTy,
                           _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
 
+// void dex_lang_filled_new_array(Array* array,
+//                                uint32_t elem_jty, ...)
+_EVAL_DEF_INTRINSICS_FUNC(FilledNewArray,
+                          dex_lang_filled_new_array,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kVarArgTy))
+
+// void dex_lang_fill_array_data(Method* referrer,
+//                               uint32_t dex_pc,
+//                               Array* array,
+//                               uint32_t payload_offset)
+_EVAL_DEF_INTRINSICS_FUNC(FillArrayData,
+                          dex_lang_fill_array_data,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaMethodTy, kInt32ConstantTy, kJavaObjectTy, kInt32ConstantTy))
+
+// void dex_lang_hl_fill_array_data(int32_t offset, JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(HLFillArrayData,
+                          dex_lang_hl_fill_array_data,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Instance Field
+//----------------------------------------------------------------------------
+
+// [type] dex_lang_iget_[type](uint32_t field_idx,
+//                             Method* referrer,
+//                             JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGet,
+                          dex_lang_iget,
+                          kAttrNone,
+                          _JTYPE(kInt32Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetWide,
+                          dex_lang_iget_wide,
+                          kAttrNone,
+                          _JTYPE(kInt64Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetObject,
+                          dex_lang_iget_object,
+                          kAttrNone,
+                          _JTYPE(kJavaObjectTy, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetBoolean,
+                          dex_lang_iget_boolean,
+                          kAttrNone,
+                          _JTYPE(kInt1Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetByte,
+                          dex_lang_iget_byte,
+                          kAttrNone,
+                          _JTYPE(kInt8Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetChar,
+                          dex_lang_iget_char,
+                          kAttrNone,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetShort,
+                          dex_lang_iget_short,
+                          kAttrNone,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+// [type] dex_lang_iget_[type].fast(int field_offset,
+//                                  bool is_volatile,
+//                                  JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetFast,
+                          dex_lang_iget.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt32Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetWideFast,
+                          dex_lang_iget_wide.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt64Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetObjectFast,
+                          dex_lang_iget_object.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kJavaObjectTy, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetBooleanFast,
+                          dex_lang_iget_boolean.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt1Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetByteFast,
+                          dex_lang_iget_byte.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt8Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetCharFast,
+                          dex_lang_iget_char.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetShortFast,
+                          dex_lang_iget_short.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+// void dex_lang_iput_[type](uint32_t field_idx,
+//                           Method* referrer,
+//                           JavaObject* obj,
+//                           [type] new_value)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPut,
+                          dex_lang_iput,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt32Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutWide,
+                          dex_lang_iput_wide,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt64Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutObject,
+                          dex_lang_iput_object,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kJavaObjectTy, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutBoolean,
+                          dex_lang_iput_boolean,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt1Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutByte,
+                          dex_lang_iput_byte,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt8Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutChar,
+                          dex_lang_iput_char,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutShort,
+                          dex_lang_iput_short,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+// void dex_lang_iput_[type].fast(int field_offset,
+//                                bool is_volatile,
+//                                JavaObject* obj,
+//                                [type] new_value)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutFast,
+                          dex_lang_iput.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt32Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutWideFast,
+                          dex_lang_iput_wide.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt64Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutObjectFast,
+                          dex_lang_iput_object.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kJavaObjectTy, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutBooleanFast,
+                          dex_lang_iput_boolean.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt1Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutByteFast,
+                          dex_lang_iput_byte.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt8Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutCharFast,
+                          dex_lang_iput_char.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutShortFast,
+                          dex_lang_iput_short.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
 //----------------------------------------------------------------------------
 // Static Field
 //----------------------------------------------------------------------------
@@ -312,43 +672,43 @@
 // [type] dex_lang_sget_[type](uint32_t field_idx, Method* referrer)
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGet,
                           dex_lang_sget,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kInt32Ty, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetWide,
                           dex_lang_sget_wide,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kInt64Ty, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetObject,
                           dex_lang_sget_object,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kJavaObjectTy, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetBoolean,
                           dex_lang_sget_boolean,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kInt1Ty, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetByte,
                           dex_lang_sget_byte,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kInt8Ty, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetChar,
                           dex_lang_sget_char,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kInt16Ty, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
 _EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetShort,
                           dex_lang_sget_short,
-                          kAttrReadOnly,
+                          kAttrNone,
                           _JTYPE(kInt16Ty, kField),
                           _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
 
@@ -802,7 +1162,7 @@
                           _EXPAND_ARG1(kVarArgTy))
 
 // FILLED_NEW_ARRAY returns object
-_EVAL_DEF_INTRINSICS_FUNC(FilledNewArray,
+_EVAL_DEF_INTRINSICS_FUNC(HLFilledNewArray,
                           dex_lang_hl_filled_new_array,
                           kAttrNone,
                           kJavaObjectTy,
@@ -812,21 +1172,60 @@
 // Invoke
 //----------------------------------------------------------------------------
 
-// Method* dex_lang_get_callee_method_obj_addr(uint32_t method_idx,
-//                                             JavaObject* this,
-//                                             Method* referrer,
-//                                             Thread* thread,
-//                                             InvokeType type)
-_EVAL_DEF_INTRINSICS_FUNC(GetCalleeMethodObjAddr,
-                          dex_lang_get_callee_method_obj_addr,
-                          kAttrReadOnly,
+// Method* dex_lang_find_static_method_with_access_check(uint32_t method_idx,
+//                                                       JavaObject* this,
+//                                                       Method* referrer,
+//                                                       Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindStaticMethodWithAccessCheck,
+                          dex_lang_find_static_method_with_access_check,
+                          kAttrNone,
                           kJavaMethodTy,
-                          _EXPAND_ARG5(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy, kInt32ConstantTy))
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* dex_lang_find_direct_method_with_access_check(uint32_t method_idx,
+//                                                       JavaObject* this,
+//                                                       Method* referrer,
+//                                                       Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindDirectMethodWithAccessCheck,
+                          dex_lang_find_direct_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* dex_lang_find_virtual_method_with_access_check(uint32_t method_idx,
+//                                                        JavaObject* this,
+//                                                        Method* referrer,
+//                                                        Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindVirtualMethodWithAccessCheck,
+                          dex_lang_find_virtual_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* dex_lang_find_super_method_with_access_check(uint32_t method_idx,
+//                                                      JavaObject* this,
+//                                                      Method* referrer,
+//                                                      Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindSuperMethodWithAccessCheck,
+                          dex_lang_find_super_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* dex_lang_find_interface_method_with_access_check(uint32_t method_idx,
+//                                                          JavaObject* this,
+//                                                          Method* referrer,
+//                                                          Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindInterfaceMethodWithAccessCheck,
+                          dex_lang_find_interface_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
 
 // Method* dex_lang_get_sd_callee_method_obj_addr(uint32_t method_idx)
 _EVAL_DEF_INTRINSICS_FUNC(GetSDCalleeMethodObjAddrFast,
                           dex_lang_get_sd_callee_method_obj_addr_fast,
-                          kAttrReadOnly,
+                          kAttrReadOnly | kAttrNoThrow,
                           kJavaMethodTy,
                           _EXPAND_ARG1(kInt32ConstantTy))
 
@@ -844,7 +1243,7 @@
 //                                                       Thread* thread)
 _EVAL_DEF_INTRINSICS_FUNC(GetInterfaceCalleeMethodObjAddrFast,
                           dex_lang_get_interface_callee_method_obj_addr_fast,
-                          kAttrReadOnly,
+                          kAttrNone,
                           kJavaMethodTy,
                           _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
 
@@ -856,21 +1255,63 @@
                           kVoidTy,
                           _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
 
-// INVOKE method returns the value of type in Dalvik register category 1
-_EVAL_DEF_INTRINSICS_FUNC(InvokeRetCat1,
-                          dex_lang_invoke.i32,
+// INVOKE method returns the value of type boolean
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetBoolean,
+                          dex_lang_invoke.bool,
+                          kAttrNone,
+                          kInt1Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type byte
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetByte,
+                          dex_lang_invoke.byte,
+                          kAttrNone,
+                          kInt8Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type char
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetChar,
+                          dex_lang_invoke.char,
+                          kAttrNone,
+                          kInt16Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type short
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetShort,
+                          dex_lang_invoke.short,
+                          kAttrNone,
+                          kInt16Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type int
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetInt,
+                          dex_lang_invoke.int,
                           kAttrNone,
                           kInt32Ty,
                           _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
 
-// INVOKE method returns the value of type in Dalvik register category 2
-_EVAL_DEF_INTRINSICS_FUNC(InvokeRetCat2,
-                          dex_lang_invoke.i64,
+// INVOKE method returns the value of type long
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetLong,
+                          dex_lang_invoke.long,
                           kAttrNone,
                           kInt64Ty,
                           _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
 
-// INVOKE method returns the value of type in Dalvik register category "object"
+// INVOKE method returns the value of type float
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetFloat,
+                          dex_lang_invoke.float,
+                          kAttrNone,
+                          kFloatTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type double
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetDouble,
+                          dex_lang_invoke.double,
+                          kAttrNone,
+                          kDoubleTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type "object"
 _EVAL_DEF_INTRINSICS_FUNC(InvokeRetObject,
                           dex_lang_invoke.object,
                           kAttrNone,
@@ -884,46 +1325,57 @@
 // int dex_lang_{div,rem}_int(int a, int b)
 _EVAL_DEF_INTRINSICS_FUNC(DivInt,
                           dex_lang_div_int,
-                          kAttrReadOnly | kAttrNoThrow,
+                          kAttrReadNone | kAttrNoThrow,
                           kInt32Ty,
                           _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(RemInt,
                           dex_lang_rem_int,
-                          kAttrReadOnly | kAttrNoThrow,
+                          kAttrReadNone | kAttrNoThrow,
                           kInt32Ty,
                           _EXPAND_ARG2(kInt32Ty, kInt32Ty))
 
 // long dex_lang_{div,rem}_long(long a, long b)
 _EVAL_DEF_INTRINSICS_FUNC(DivLong,
                           dex_lang_div_long,
-                          kAttrReadOnly | kAttrNoThrow,
+                          kAttrReadNone | kAttrNoThrow,
                           kInt64Ty,
                           _EXPAND_ARG2(kInt64Ty, kInt64Ty))
 
 _EVAL_DEF_INTRINSICS_FUNC(RemLong,
                           dex_lang_rem_long,
-                          kAttrReadOnly | kAttrNoThrow,
+                          kAttrReadNone | kAttrNoThrow,
                           kInt64Ty,
                           _EXPAND_ARG2(kInt64Ty, kInt64Ty))
 
-//----------------------------------------------------------------------------
-// Suspend Test
-//----------------------------------------------------------------------------
+// int64_t dex_lang_d2l(double f)
+_EVAL_DEF_INTRINSICS_FUNC(D2L,
+                          dex_lang_d2l,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kDoubleTy))
 
-// void dex_lang_test_suspend(Thread* thread)
-_EVAL_DEF_INTRINSICS_FUNC(TestSuspend,
-                          dex_lang_test_suspend,
-                          kAttrNoThrow,
-                          kVoidTy,
-                          _EXPAND_ARG1(kJavaThreadTy))
+// int32_t dex_lang_d2l(double f)
+_EVAL_DEF_INTRINSICS_FUNC(D2I,
+                          dex_lang_d2i,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kDoubleTy))
 
-// void dex_lang_check_suspend() /* Expands to GetCurrentThread/TestSuspend */
-_EVAL_DEF_INTRINSICS_FUNC(CheckSuspend,
-                          dex_lang_check_suspend,
-                          kAttrNoThrow,
-                          kVoidTy,
-                          _EXPAND_ARG0())
+// int64_t dex_lang_f2l(float f)
+_EVAL_DEF_INTRINSICS_FUNC(F2L,
+                          dex_lang_f2l,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kFloatTy))
+
+// int32_t dex_lang_f2i(float f)
+_EVAL_DEF_INTRINSICS_FUNC(F2I,
+                          dex_lang_f2i,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kFloatTy))
+
 //----------------------------------------------------------------------------
 // sput intrinsics to assist MIR to Greenland_ir conversion.
 // "HL" versions - will be deprecated when fast/slow path handling done
diff --git a/src/greenland/intrinsic_helper.cc b/src/greenland/intrinsic_helper.cc
index b1837fb..7e926d6 100644
--- a/src/greenland/intrinsic_helper.cc
+++ b/src/greenland/intrinsic_helper.cc
@@ -21,7 +21,6 @@
 #include <llvm/DerivedTypes.h>
 #include <llvm/Function.h>
 #include <llvm/Intrinsics.h>
-#include <llvm/Module.h>
 #include <llvm/Support/IRBuilder.h>
 
 using namespace art;
@@ -65,10 +64,12 @@
     case IntrinsicHelper::kInt64ConstantTy: {
       return irb.getInt64Ty();
     }
-    case IntrinsicHelper::kFloatTy: {
+    case IntrinsicHelper::kFloatTy:
+    case IntrinsicHelper::kFloatConstantTy: {
       return irb.getFloatTy();
     }
-    case IntrinsicHelper::kDoubleTy: {
+    case IntrinsicHelper::kDoubleTy:
+    case IntrinsicHelper::kDoubleConstantTy: {
       return irb.getDoubleTy();
     }
     case IntrinsicHelper::kNone:
@@ -86,7 +87,7 @@
 namespace art {
 namespace greenland {
 
-const IntrinsicHelper::IntrinsicInfo IntrinsicHelper::Info[MaxIntrinsicId] = {
+const IntrinsicHelper::IntrinsicInfo IntrinsicHelper::Info[] = {
 #define DEF_INTRINSICS_FUNC(_, NAME, ATTR, RET_TYPE, ARG1_TYPE, ARG2_TYPE, \
                                                      ARG3_TYPE, ARG4_TYPE, \
                                                      ARG5_TYPE) \
@@ -144,6 +145,7 @@
                                                 info.name_, &module);
 
     fn->setOnlyReadsMemory(info.attr_ & kAttrReadOnly);
+    fn->setDoesNotAccessMemory(info.attr_ & kAttrReadNone);
     // None of the intrinsics throws exception
     fn->setDoesNotThrow(true);
 
diff --git a/src/greenland/intrinsic_helper.h b/src/greenland/intrinsic_helper.h
index 7e84cc9..365d529 100644
--- a/src/greenland/intrinsic_helper.h
+++ b/src/greenland/intrinsic_helper.h
@@ -47,11 +47,22 @@
   enum IntrinsicAttribute {
     kAttrNone     = 0,
 
-    // Intrinsic that doesn't modify the memory state
-    kAttrReadOnly = 1 << 0,
+    // Intrinsic that neither modified the memory state nor refer to the global
+    // state
+    kAttrReadNone = 1 << 0,
+
+    // Intrinsic that doesn't modify the memory state. Note that one should set
+    // this flag carefully when the intrinsic may throw exception. Since the
+    // thread state is implicitly modified when an exception is thrown.
+    kAttrReadOnly = 1 << 1,
+
+    // Note that intrinsic without kAttrNoThrow and kAttrDoThrow set means that
+    // intrinsic generates exception in some cases
 
     // Intrinsic that never generates exception
-    kAttrNoThrow  = 1 << 1,
+    kAttrNoThrow  = 1 << 2,
+    // Intrinsic that always generate exception
+    kAttrDoThrow  = 1 << 3,
   };
 
   enum IntrinsicValType {
@@ -68,15 +79,16 @@
     kInt16Ty,
     kInt32Ty,
     kInt64Ty,
+    kFloatTy,
+    kDoubleTy,
 
     kInt1ConstantTy,
     kInt8ConstantTy,
     kInt16ConstantTy,
     kInt32ConstantTy,
     kInt64ConstantTy,
-
-    kFloatTy,
-    kDoubleTy,
+    kFloatConstantTy,
+    kDoubleConstantTy,
 
     kVarArgTy,
   };
@@ -93,7 +105,7 @@
   } IntrinsicInfo;
 
  private:
-  static const IntrinsicInfo Info[MaxIntrinsicId];
+  static const IntrinsicInfo Info[];
 
  public:
   static const IntrinsicInfo& GetInfo(IntrinsicId id) {
@@ -130,7 +142,10 @@
   }
 
  private:
-  llvm::Function* intrinsic_funcs_[MaxIntrinsicId];
+  // FIXME: "+1" is to workaround the GCC bugs:
+  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
+  // Remove this when uses newer GCC (> 4.4.3)
+  llvm::Function* intrinsic_funcs_[MaxIntrinsicId + 1];
 
   // Map a llvm::Function to its intrinsic id
   llvm::DenseMap<const llvm::Function*, IntrinsicId> intrinsic_funcs_map_;
diff --git a/src/greenland/ir_builder.cc b/src/greenland/ir_builder.cc
index d47a458..e83996a 100644
--- a/src/greenland/ir_builder.cc
+++ b/src/greenland/ir_builder.cc
@@ -25,9 +25,24 @@
                      IntrinsicHelper& intrinsic_helper)
     : LLVMIRBuilder(context), java_object_type_(NULL), java_method_type_(NULL),
       java_thread_type_(NULL), intrinsic_helper_(intrinsic_helper) {
+  // JavaObject must be defined in the module
   java_object_type_ = module.getTypeByName("JavaObject")->getPointerTo();
-  java_method_type_ = module.getTypeByName("Method")->getPointerTo();
-  java_thread_type_ = module.getTypeByName("Thread")->getPointerTo();
+
+  // If type of Method is not explicitly defined in the module, use JavaObject*
+  llvm::Type* type = module.getTypeByName("Method");
+  if (type != NULL) {
+    java_method_type_ = type->getPointerTo();
+  } else {
+    java_method_type_ = java_object_type_;
+  }
+
+  // If type of Thread is not explicitly defined in the module, use JavaObject*
+  type = module.getTypeByName("Thread");
+  if (type != NULL) {
+    java_thread_type_ = type->getPointerTo();
+  } else {
+    java_thread_type_ = java_object_type_;
+  }
 }
 
 llvm::Type* IRBuilder::GetJTypeInAccurateSpace(JType jty) {
diff --git a/src/greenland/lir.h b/src/greenland/lir.h
deleted file mode 100644
index 82116b2..0000000
--- a/src/greenland/lir.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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_GREENLAND_LIR_H_
-#define ART_SRC_GREENLAND_LIR_H_
-
-#include "logging.h"
-#include "macros.h"
-#include "object.h"
-
-#include "lir_desc.h"
-#include "lir_operand.h"
-
-#include <vector>
-
-#include <llvm/ADT/ilist_node.h>
-
-namespace art {
-namespace greenland {
-
-class LIRFunction;
-
-class LIR : public llvm::ilist_node<LIR> {
- private:
-  // LIRs are allocated and owned by LIRFunction.
-  friend class LIRFunction;
-
-  LIR(const LIRDesc& desc);
-
-  ~LIR() { }
-
- private:
-  LIRFunction* parent_;
-
-  const LIRDesc& desc_; // Instruction descriptor
-
-  std::vector<LIROperand> operands_;
-
-#if 0
-  struct {
-    bool is_nop:1;          // LIR is optimized away
-    bool pc_rel_fixup:1;    // May need pc-relative fixup
-    unsigned int age:4;     // default is 0, set lazily by the optimizer
-    unsigned int size:5;    // in bytes
-    unsigned int unused:21;
-  } flags_;
-
-  int alias_info_;          // For Dalvik register & litpool disambiguation
-  uint8_t use_mask_;        // Resource mask for use
-  uint8_t def_mask_;        // Resource mask for def
-#endif
-
- private:
-  // Intrusive list support
-  friend struct llvm::ilist_traits<LIR>;
-  friend struct llvm::ilist_traits<LIRFunction>;
-  void SetParent(LIRFunction *parent) {
-    parent_ = parent;
-  }
-
- public:
-  const LIRFunction* GetParent() const {
-    return parent_;
-  }
-
-  LIRFunction* GetParent() {
-    return parent_;
-  }
-
-  const LIRDesc& GetDesc() const {
-    return desc_;
-  }
-
-  int GetOpcode() const {
-    return desc_.opcode_;
-  }
-
- public:
-  //----------------------------------------------------------------------------
-  // Operand Operations
-  //----------------------------------------------------------------------------
-  unsigned GetNumOperands() const {
-    return static_cast<unsigned>(operands_.size());
-  }
-
-  const LIROperand& GetOperand(unsigned i) const {
-    DCHECK(i < GetNumOperands()) << "GetOperand() out of range!";
-    return operands_[i];
-  }
-
-  LIROperand& GetOperand(unsigned i) {
-    DCHECK(i < GetNumOperands()) << "GetOperand() out of range!";
-    return operands_[i];
-  }
-
-  /// iterator/begin/end - Iterate over all operands of a machine instruction.
-  typedef std::vector<LIROperand>::iterator op_iterator;
-  typedef std::vector<LIROperand>::const_iterator const_op_iterator;
-
-  op_iterator operands_begin() { return operands_.begin(); }
-  op_iterator operands_end() { return operands_.end(); }
-
-  const_op_iterator operands_begin() const { return operands_.begin(); }
-  const_op_iterator operands_end() const { return operands_.end(); }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LIR);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_LIR_H_
diff --git a/src/greenland/lir_desc.h b/src/greenland/lir_desc.h
deleted file mode 100644
index 84b7af6..0000000
--- a/src/greenland/lir_desc.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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_GREENLAND_LIR_DESC_H_
-#define ART_SRC_GREENLAND_LIR_DESC_H_
-
-namespace art {
-namespace greenland {
-
-class LIRDesc {
- public:
-  unsigned opcode_;             // The opcode number
-  unsigned short num_operands_; // Num of args (may be more if variable_ops)
-
-  unsigned GetOpcode() const {
-    return opcode_;
-  }
-
-  unsigned GetNumOperands() const {
-    return num_operands_;
-  }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_LIR_DESC_H_
diff --git a/src/greenland/lir_frame_info.h b/src/greenland/lir_frame_info.h
deleted file mode 100644
index ecaa7f3..0000000
--- a/src/greenland/lir_frame_info.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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_GREENLAND_LIR_FRAME_INFO_H_
-#define ART_SRC_GREENLAND_LIR_FRAME_INFO_H_
-
-#include "logging.h"
-
-#include <vector>
-
-namespace art {
-namespace greenland {
-
-class LIRFrameInfo {
- private:
-  struct StackObject {
-    // The offset from the stack pointer
-    off_t sp_offset_;
-
-    // The object is a dead object if its size is 0
-    size_t size_;
-
-    unsigned alignment_;
-
-    StackObject(size_t size, unsigned alignment)
-        : size_(size), alignment_(alignment) { }
-  };
-
-  // stack_size_ and sp_offset_ in each StackObject will be updated by ...
-  size_t stack_size_;
-
-  std::vector<StackObject> objects_;
-
- public:
-  LIRFrameInfo() : stack_size_(0) { }
-
-  bool HasStackObjects() const {
-    return !objects_.empty();
-  }
-
-  unsigned GetNumObjects() const {
-    return objects_.size();
-  }
-
-  size_t GetStackSize() const {
-    return stack_size_;
-  }
-  void SetStackSize(size_t stack_size) {
-    stack_size_ = stack_size;
-    return;
-  }
-
-  //----------------------------------------------------------------------------
-  // Stack Object
-  //----------------------------------------------------------------------------
-  size_t GetObjectOffset(unsigned idx) const {
-    DCHECK(idx < GetNumObjects()) << "Invalid frame index!";
-    return objects_[idx].sp_offset_;
-  }
-  void SetObjectOffset(unsigned idx, off_t sp_offset) {
-    DCHECK(idx < GetNumObjects()) << "Invalid frame index!";
-    objects_[idx].sp_offset_ = sp_offset;
-    return;
-  }
-
-  size_t GetObjectSize(unsigned idx) const {
-    DCHECK(idx < GetNumObjects()) << "Invalid frame index!";
-    return objects_[idx].size_;
-  }
-
-  size_t GetObjectAlignment(unsigned idx) const {
-    DCHECK(idx < GetNumObjects()) << "Invalid frame index!";
-    return objects_[idx].alignment_;
-  }
-
-  unsigned AllocateStackObject(size_t size, unsigned alignment = 1) {
-    DCHECK(size > 0);
-    objects_.push_back(StackObject(size, alignment));
-    return objects_.size() - 1;
-  }
-
-  void RemoveStackObject(unsigned idx) {
-    DCHECK(idx < GetNumObjects()) << "Invalid frame index!";
-    objects_[idx].size_ = 0;
-    return;
-  }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_LIR_FRAME_INFO_H_
diff --git a/src/greenland/lir_function.cc b/src/greenland/lir_function.cc
deleted file mode 100644
index 5def2ac..0000000
--- a/src/greenland/lir_function.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.
- */
-
-#include "lir_function.h"
-
-#include "lir_frame_info.h"
-
-#include "logging.h"
-
-namespace llvm {
-
-using art::greenland::LIR;
-using art::greenland::LIRFunction;
-
-void ilist_traits<LIR>::addNodeToList(LIR* lir) {
-  DCHECK(lir->GetParent() == 0) << "LIR already in a function";
-  // Update the LIR::parent_
-  lir->SetParent(parent_);
-  return;
-}
-
-void ilist_traits<LIR>::removeNodeFromList(LIR* lir) {
-  DCHECK(lir->GetParent() == 0) << "LIR is not in a function";
-  // Update the LIR::parent_
-  lir->SetParent(NULL);
-  return;
-}
-
-void ilist_traits<LIR>::transferNodesFromList(ilist_traits &src_traits,
-                                              ilist_iterator<LIR> first,
-                                              ilist_iterator<LIR> last) {
-  UNIMPLEMENTED(FATAL);
-  return;
-}
-
-void ilist_traits<LIR>::deleteNode(LIR* lir) {
-  CHECK(!lir->GetParent()) << "LIR is still in a block!";
-  parent_->DeleteLIR(lir);
-  return;
-}
-
-} // namespace llvm
-
-namespace art {
-namespace greenland {
-
-LIRFunction::LIRFunction() : frame_info_(NULL) {
-  lirs_.parent_ = this;
-  frame_info_ = new (allocator_) LIRFrameInfo();
-  return;
-}
-
-LIRFunction::~LIRFunction() {
-  lirs_.clear();
-  lir_recycler_.clear(allocator_);
-
-  frame_info_->~LIRFrameInfo();
-  allocator_.Deallocate(frame_info_);
-
-  return;
-}
-
-LIR* LIRFunction::CreateLIR(const LIRDesc& desc) {
-  return new (lir_recycler_.Allocate<LIR>(allocator_)) LIR(desc);
-}
-
-void LIRFunction::DeleteLIR(LIR* lir) {
-  lir->~LIR();
-  lir_recycler_.Deallocate(allocator_, lir);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/lir_function.h b/src/greenland/lir_function.h
deleted file mode 100644
index 0e77f17..0000000
--- a/src/greenland/lir_function.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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_GREENLAND_LIR_FUNCTION_H_
-#define ART_SRC_GREENLAND_LIR_FUNCTION_H_
-
-#include "lir.h"
-
-#include <llvm/ADT/ilist.h>
-#include <llvm/Support/Allocator.h>
-#include <llvm/Support/Recycler.h>
-
-namespace llvm {
-
-template <>
-struct ilist_traits<art::greenland::LIR> :
-    public ilist_default_traits<art::greenland::LIR> {
- private:
-  mutable ilist_half_node<art::greenland::LIR> sentinel_;
-
-  friend class art::greenland::LIRFunction;
-  art::greenland::LIRFunction* parent_;
-
- public:
-  art::greenland::LIR *createSentinel() const {
-    return static_cast<art::greenland::LIR*>(&sentinel_);
-  }
-  void destroySentinel(art::greenland::LIR *) const {}
-
-  art::greenland::LIR *provideInitialHead() const {
-    return createSentinel();
-  }
-  art::greenland::LIR *ensureHead(art::greenland::LIR*) const {
-    return createSentinel();
-  }
-  static void noteHead(art::greenland::LIR*, art::greenland::LIR*) {}
-
-  void addNodeToList(art::greenland::LIR* N);
-  void removeNodeFromList(art::greenland::LIR* N);
-  void transferNodesFromList(ilist_traits &src_traits,
-                             ilist_iterator<art::greenland::LIR> first,
-                             ilist_iterator<art::greenland::LIR> last);
-  void deleteNode(art::greenland::LIR *N);
-private:
-  void createNode(const art::greenland::LIR &);
-};
-
-} // namespace llvm
-
-namespace art {
-namespace greenland {
-
-class LIRFrameInfo;
-
-class LIRFunction {
- private:
-  llvm::ilist<LIR> lirs_;
-
-  // Pool-allocate the objects reside in this instance
-  llvm::BumpPtrAllocator allocator_;
-
-  // Allocation management for instructions in function.
-  llvm::Recycler<LIR> lir_recycler_;
-
-  // The stack information
-  LIRFrameInfo* frame_info_;
-
- public:
-  LIRFunction();
-  ~LIRFunction();
-
- public:
-  //----------------------------------------------------------------------------
-  // LIR Accessor Functions
-  //----------------------------------------------------------------------------
-  typedef llvm::ilist<LIR>::iterator                          iterator;
-  typedef llvm::ilist<LIR>::const_iterator              const_iterator;
-  typedef std::reverse_iterator<iterator>             reverse_iterator;
-  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-  unsigned GetNumLIRs() const {
-    return static_cast<unsigned>(lirs_.size());
-  }
-  bool IsEmpty() const {
-    return lirs_.empty();
-  }
-
-  LIR& front() { return lirs_.front(); }
-  LIR& back()  { return lirs_.back(); }
-  const LIR& front() const { return lirs_.front(); }
-  const LIR& back()  const { return lirs_.back(); }
-
-  iterator                begin()       { return lirs_.begin();  }
-  const_iterator          begin() const { return lirs_.begin();  }
-  iterator                  end()       { return lirs_.end();    }
-  const_iterator            end() const { return lirs_.end();    }
-  reverse_iterator       rbegin()       { return lirs_.rbegin(); }
-  const_reverse_iterator rbegin() const { return lirs_.rbegin(); }
-  reverse_iterator       rend  ()       { return lirs_.rend();   }
-  const_reverse_iterator rend  () const { return lirs_.rend();   }
-
-  void pop_front() {
-    lirs_.pop_front();
-  }
-
-  void push_back(LIR *lir) {
-    lirs_.push_back(lir);
-  }
-
-  iterator insert(iterator i, LIR* lir) {
-    return lirs_.insert(i, lir);
-  }
-
-  iterator erase(iterator i) {
-    return lirs_.erase(i);
-  }
-
-  LIR* remove(iterator i) {
-    return lirs_.remove(i);
-  }
-
- public:
-  //----------------------------------------------------------------------------
-  // LIR Memory Allocation
-  //----------------------------------------------------------------------------
-  LIR* CreateLIR(const LIRDesc& desc);
-
-  void DeleteLIR(LIR* lir);
-
- public:
-  const LIRFrameInfo& GetFrameInfo() const {
-    return *frame_info_;
-  }
-  LIRFrameInfo& GetFrameInfo() {
-    return *frame_info_;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LIRFunction);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_LIR_FUNCTION_H_
diff --git a/src/greenland/lir_operand.h b/src/greenland/lir_operand.h
deleted file mode 100644
index d6d9232..0000000
--- a/src/greenland/lir_operand.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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_GREENLAND_LIR_OPERAND_H_
-#define ART_SRC_GREENLAND_LIR_OPERAND_H_
-
-#include "logging.h"
-
-namespace llvm {
-  class ConstantFP;
-}
-
-namespace art {
-namespace greenland {
-
-class LIR;
-
-class LIROperand {
- public:
-  enum Type {
-    UnknownType,
-    RegisterType,
-    ImmediateType,
-    FPImmediateType,
-    LabelType,
-  };
-
- private:
-  Type type_;
-
-  union {
-    // RegisterType
-    unsigned reg_no_;
-
-    // ImmediateType
-    int64_t imm_val_;
-
-    // FPImmediateType
-    const llvm::ConstantFP *fp_imm_val_;
-
-    // LabelType
-    const LIR* target_;
-  } contents_;
-
-  friend class LIR;
-  LIROperand() : type_(UnknownType) { }
-
-  void SetType(enum Type type) {
-    type_ = type;
-    return;
-  }
-
- public:
-  enum Type GetType() const {
-    return type_;
-  }
-
-  bool IsReg() const {
-    return (type_ == RegisterType);
-  }
-  bool IsImm() const {
-    return (type_ == ImmediateType);
-  }
-  bool IsFPImm() const {
-    return (type_ == FPImmediateType);
-  }
-  bool IsLabel() const {
-    return (type_ == LabelType);
-  }
-
-  //----------------------------------------------------------------------------
-  //  Accessors
-  //----------------------------------------------------------------------------
-  unsigned GetReg() const {
-    CHECK(IsReg()) << "This is not a register operand!";
-    return contents_.reg_no_;
-  }
-
-  int64_t GetImm() const {
-    CHECK(IsImm()) << "This is not a immediate operand!";
-    return contents_.imm_val_;
-  }
-
-  const llvm::ConstantFP* GetFPImm() const {
-    CHECK(IsFPImm()) << "This is not a FP immediate operand!";
-    return contents_.fp_imm_val_;
-  }
-
-  const LIR* GetLabelTarget() const {
-    CHECK(IsFPImm()) << "This is not a label operand!";
-    return contents_.target_;
-  }
-
-  //----------------------------------------------------------------------------
-  //  Mutators
-  //----------------------------------------------------------------------------
-  void SetReg(unsigned reg_no) {
-    if (type_ == UnknownType) {
-      type_ = RegisterType;
-    }
-    CHECK(IsReg()) << "This is not a register operand!";
-    contents_.reg_no_ = reg_no;
-    return;
-  }
-
-  void SetImm(int64_t imm_val) {
-    if (type_ == UnknownType) {
-      type_ = ImmediateType;
-    }
-    CHECK(IsImm()) << "This is not a immediate operand!";
-    contents_.imm_val_ = imm_val;
-    return;
-  }
-
-  void SetFPImm(const llvm::ConstantFP* fp_imm_val) {
-    if (type_ == UnknownType) {
-      type_ = FPImmediateType;
-    }
-    CHECK(IsFPImm()) << "This is not a FP immediate operand!";
-    contents_.fp_imm_val_ = fp_imm_val;
-    return;
-  }
-
-  void SetLabelTarget(LIR* target) {
-    if (type_ == UnknownType) {
-      type_ = LabelType;
-    }
-    CHECK(IsLabel()) << "This is not a label operand!";
-    contents_.target_ = target;
-    return;
-  }
-
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_LIR_OPERAND_H_
diff --git a/src/greenland/mips/mips_codegen_machine.h b/src/greenland/mips/mips_codegen_machine.h
index e3412e9..c9f0abf 100644
--- a/src/greenland/mips/mips_codegen_machine.h
+++ b/src/greenland/mips/mips_codegen_machine.h
@@ -29,9 +29,27 @@
   MipsCodeGenMachine();
   virtual ~MipsCodeGenMachine();
 
-  virtual TargetLIREmitter* CreateLIREmitter(const llvm::Function& func,
-                                             const OatCompilationUnit& cunit,
-                                             DexLang::Context& dex_lang_ctx) {
+  virtual TargetLIREmitter* CreateLIREmitter() {
+    return NULL;
+  }
+
+  virtual const TargetDataLayout* GetDataLayout() const {
+    return NULL;
+  }
+
+  virtual const TargetLIRInfo* GetLIRInfo() const {
+    return NULL;
+  }
+
+  virtual const TargetRegisterInfo* GetRegisterInfo() const {
+    return NULL;
+  }
+
+  virtual const char* GetConditionCodeName(unsigned cond) const {
+    return NULL;
+  }
+
+  virtual TargetLIRBuilder* CreateLIRBuilder() {
     return NULL;
   }
 
@@ -42,6 +60,10 @@
   virtual TargetAssembler* GetAssembler() {
     return NULL;
   }
+
+  virtual std::string PrettyTargeteLIR(const LIR& lir) const {
+    return "";
+  }
 };
 
 } // namespace greenland
diff --git a/src/greenland/target_lir.def b/src/greenland/mips/mips_lir.def
similarity index 81%
rename from src/greenland/target_lir.def
rename to src/greenland/mips/mips_lir.def
index a3838c6..0741f1b 100644
--- a/src/greenland/target_lir.def
+++ b/src/greenland/mips/mips_lir.def
@@ -14,9 +14,5 @@
  * limitations under the License.
  */
 
-// DEF_LIR_DESC(OPCODE, NUM_OPS)
-#ifndef DEF_LIR_DESC
-# error "missing DEF_LIR_DESC definition!"
-#endif
-
-DEF_LIR_DESC(kBlockLabel, 1)
+#include "greenland/target_lir.def"
+#include "greenland/clear_target_lir.def"
diff --git a/src/greenland/register_allocator.cc b/src/greenland/register_allocator.cc
new file mode 100644
index 0000000..b19f111
--- /dev/null
+++ b/src/greenland/register_allocator.cc
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+
+#include "register_allocator.h"
+#include "lir_function.h"
+#include "lir_frame_info.h"
+#include "lir_reg.h"
+
+#include "target_register_info.h"
+
+#include "logging.h"
+#include "stl_util.h"
+
+namespace art {
+namespace greenland {
+
+void RegisterAllocator::BuildKillInfo(LIRFunction& lir_func) {
+  //TODO: Build Register KillInfo
+}
+
+static LIRBasicBlock::iterator
+GetSourceIterator(LIRBasicBlock& sourceBB, LIRBasicBlock& targetBB) {
+  LIRBasicBlock::iterator it;
+  for (it = sourceBB.back(); it != sourceBB.begin(); --it) {
+    if (it->IsBranch() && (it->GetOperand(0).GetLabelTarget() == &targetBB))
+      break;
+  }
+  return it;
+}
+
+void RegisterAllocator::PHIElimination(LIRFunction& lir_func) {
+  for (LIRFunction::iterator bb = lir_func.begin(); bb != lir_func.end(); ++bb) {
+    if (bb->IsEmpty() || !bb->front().IsPHI())
+      continue;
+
+    LIRBasicBlock::iterator it; // current LIR
+    LIRBasicBlock::iterator next_it; // next LIR
+    for(it = bb->begin(); it != bb->end(); it = next_it) {
+      next_it = it; ++next_it;
+      if (!it->IsPHI())
+        break;
+
+      for (unsigned i = 1; i < it->GetNumOperands(); i+=2) {
+        const LIROperand& dst = it->GetOperand(0);
+        const LIROperand& src = it->GetOperand(i);
+        LIRBasicBlock* sourceBB =
+            const_cast<LIRBasicBlock*> (it->GetOperand(i + 1).GetLabelTarget());
+
+        LIR* lir = reg_info_.CreateCopy(lir_func, dst.GetReg(), src);
+        LOG(INFO) << "PHIElimination: Insert COPY into BB: " << sourceBB->GetName();
+        sourceBB->insert(GetSourceIterator(*sourceBB, *bb), lir);
+      }
+
+      bb->erase(it);
+    }
+  }
+}
+
+RegisterAllocator::Storage
+RegisterAllocator::AllocateStorage(LIRFunction &lir_func, unsigned vreg_idx) {
+  // The virtual register is allocated, return it.
+  if (allocated_map_.find(vreg_idx) != allocated_map_.end()) {
+    return allocated_map_[vreg_idx];
+  }
+
+  Storage s;
+  // Have free register(s).
+  if (!allocatable_list_.empty()) {
+    s.regTag = kPhyRegType;
+    s.index = allocatable_list_.front();
+    allocatable_list_.pop_front();
+  }
+  else {
+    s.regTag = kFrameType;
+    if (stackstorage_list_.empty()) {
+      // FIXME: Get register subword
+      s.index = lir_func.GetFrameInfo().AllocateStackObject(4);
+    }
+    else {
+      s.index = stackstorage_list_.front();
+      stackstorage_list_.pop_front();
+    }
+  }
+  allocated_map_[vreg_idx] = s;
+  return s;
+}
+
+void RegisterAllocator::KeepStorage(const LIR& lir) {
+  unsigned reg_value = lir.GetOperand(0).GetReg();
+  int frame_idx =  lir.GetOperand(1).GetFrameIndex();
+
+  if (!LIRReg::IsVirtualReg(reg_value))
+    return;
+
+  unsigned vreg_idx = LIRReg::GetRegNo(reg_value);
+
+  LOG(INFO) << "VIRTUAL REG " << vreg_idx << " Keep in Stack Frame [" <<  frame_idx << "];";
+
+  Storage s;
+  s.regTag = kInStackType;
+  s.index = frame_idx;
+  allocated_map_[vreg_idx] = s;
+}
+
+void RegisterAllocator::FreeStorage(unsigned vreg_idx) {
+  //TODO: Check vreg_idx must be allocated
+  Storage s = allocated_map_[vreg_idx];
+
+  if (s.regTag == kInStackType)
+    return;
+
+  if (s.regTag == kPhyRegType)
+    allocatable_list_.push_front(s.index);
+  else
+    stackstorage_list_.push_front(s.index);
+
+  allocated_map_.erase(vreg_idx);
+}
+
+void RegisterAllocator::InitializeAllocation(LIRFunction &lir_func) {
+  allocatable_list_ = reg_info_.GetAllocatableList();
+  stackstorage_list_.clear();
+  allocated_map_.clear();
+}
+
+void RegisterAllocator::PreRegisterAllocation(LIRFunction &lir_func) {
+  PHIElimination(lir_func);
+}
+
+void
+RegisterAllocator::HandleInsnCopy(LIRBasicBlock &bb,
+                                  LIRBasicBlock::iterator it,
+                                  LIRBasicBlock::iterator next_it) {
+  unsigned reg_dst = it->GetOperand(0).GetReg();
+  unsigned reg_src = it->GetOperand(1).GetReg();
+
+  Storage stor_dst = {-1, kNoneType};
+  Storage stor_src = {-1, kNoneType};
+  unsigned vidx_dst = 0, vidx_src = 0;
+
+  if (LIRReg::IsVirtualReg(reg_dst)) {
+    vidx_dst = LIRReg::GetRegNo(reg_dst);
+    LOG(INFO) << "VIRTUAL REG " << vidx_dst << " in COPY need allocated !!";
+    stor_dst = AllocateStorage(bb.GetParent(), vidx_dst);
+  }
+
+  if (LIRReg::IsVirtualReg(reg_src)) {
+    vidx_src = LIRReg::GetRegNo(reg_src);
+    LOG(INFO) << "VIRTUAL REG " << vidx_src << " in COPY need allocated !!";
+    stor_src = AllocateStorage(bb.GetParent(), vidx_src);
+  }
+
+  if ((LIRReg::IsPhysicalReg(reg_dst) || (stor_dst.regTag == kPhyRegType))
+      && (LIRReg::IsPhysicalReg(reg_src) || (stor_src.regTag == kPhyRegType))) {
+    // MovRR
+    unsigned idx_dst = (LIRReg::IsPhysicalReg(reg_dst)) ?
+        LIRReg::GetRegNo(reg_dst) : stor_dst.index;
+    unsigned idx_src = (LIRReg::IsPhysicalReg(reg_src)) ?
+        LIRReg::GetRegNo(reg_src) : stor_src.index;
+    LOG(INFO) << "\t [COPY] create MOVE: move " << idx_dst << ", "<< idx_src;
+    LIR* lir = reg_info_.CreateMoveReg(bb.GetParent(), idx_dst, idx_src);
+    bb.insert(next_it, lir);
+    bb.erase(it);
+
+    if(LIRReg::IsVirtualReg(reg_src)) {
+      FreeStorage(vidx_src);
+    }
+    return;
+  }
+
+  if ((stor_dst.regTag == stor_src.regTag) && (stor_dst.index == stor_src.index)) {
+    // Redundant move
+    FreeStorage(vidx_dst);
+    FreeStorage(vidx_src);
+    bb.erase(it);
+    return;
+  }
+
+  if (stor_dst.regTag != kPhyRegType && stor_src.regTag != kPhyRegType) {
+    unsigned idx = reg_info_.GetTempRegsiter(0);
+    LIR* lir = reg_info_.CreateLoadStack(bb.GetParent(), idx, stor_src.index);
+    bb.insert(it, lir);
+    lir = reg_info_.CreateStoreStack(bb.GetParent(), idx, stor_dst.index);
+    bb.insert(next_it, lir);
+    bb.erase(it);
+    return;
+  }
+
+  if (stor_dst.regTag != kPhyRegType) {
+    unsigned idx = (LIRReg::IsPhysicalReg(reg_src)) ?
+        LIRReg::GetRegNo(reg_src) : stor_src.index;
+    LOG(INFO) << "\t [COPY] create StoreStack: move " << idx << ", "<< stor_dst.index;
+    LIR* lir = reg_info_.CreateStoreStack(bb.GetParent(), idx, stor_dst.index);
+    bb.insert(next_it, lir);
+    bb.erase(it);
+    return;
+  }
+
+  if (stor_src.regTag != kPhyRegType) {
+    unsigned idx = (LIRReg::IsPhysicalReg(reg_dst)) ?
+        LIRReg::GetRegNo(reg_dst) : stor_dst.index;
+    LOG(INFO) << "\t [COPY] create LoadStack: move " << idx << ", "<< stor_src.index;
+    LIR* lir = reg_info_.CreateLoadStack(bb.GetParent(), idx, stor_src.index);
+    bb.insert(next_it, lir);
+    bb.erase(it);
+    return;
+  }
+}
+
+void RegisterAllocator::FunctionRegisterAllocation(LIRFunction &lir_func) {
+  for (LIRFunction::iterator bb =  lir_func.begin(); bb != lir_func.end(); ++bb) {
+    LIRBasicBlock::iterator it; // current LIR
+    LIRBasicBlock::iterator next_it; // next LIR
+    for (LIRBasicBlock::iterator it = bb->begin(); it != bb->end(); it = next_it) {
+      next_it = it; ++next_it;
+
+      // Handle Incoming Args
+      if (reg_info_.IsLoadIncomingArgs(it)) {
+        KeepStorage(*it);
+        bb->erase(it);
+        continue;
+      }
+
+      // Handle Copy
+      if (it->GetOpcode() == opcode::kCOPY) {
+        HandleInsnCopy(*bb, *it, *next_it);
+        continue;
+      }
+
+      std::vector<unsigned> free_list;
+      //for (LIR::op_iterator opi = i->operands_begin(); opi != i->operands_end(); ++opi) {
+      for (unsigned i = 0 ; i < it->GetNumOperands(); i++) {
+        LIROperand& lir_opd = it->GetOperand(i);
+        unsigned temp_count = 0;
+
+        if (!lir_opd.IsReg())
+          continue;
+
+        unsigned reg_value = lir_opd.GetReg();
+        if (!LIRReg::IsVirtualReg(reg_value))
+          continue;
+        unsigned vreg_idx = LIRReg::GetRegNo(reg_value);
+        LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " need allocated !!";
+        Storage s = AllocateStorage(lir_func, vreg_idx);
+        if (!s.regTag) {
+          LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " is map to REG[" << s.index << "]!!";
+          lir_opd.SetReg(s.index);
+        } else {
+          unsigned temp_idx = reg_info_.GetTempRegsiter(temp_count++);
+          if ( lir_opd.IsDef() ) {
+            LIR* lir = reg_info_.CreateStoreStack(lir_func, temp_idx, s.index);
+            bb->insert(next_it, lir);
+            lir_opd.SetReg(temp_idx);
+          } else {
+            LIR* lir = reg_info_.CreateLoadStack(lir_func, temp_idx, s.index);
+            bb->insert(it, lir);
+            lir_opd.SetReg(temp_idx);
+          }
+
+          LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " is map to Frame[" << s.index << "]!!";
+        }
+
+        if (lir_opd.IsKill()) {
+          free_list.push_back(vreg_idx);
+          LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " is mark kill!!";
+        }
+      }
+
+      for (size_t i = 0 ; i < free_list.size(); i++) {
+        LOG(INFO) << "\t" << "VIRTUAL REG " << free_list[i] << " is kill!!";
+        FreeStorage(free_list[i]);
+      }
+    }
+  }
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/register_allocator.h b/src/greenland/register_allocator.h
new file mode 100644
index 0000000..ffe0914
--- /dev/null
+++ b/src/greenland/register_allocator.h
@@ -0,0 +1,82 @@
+/*
+ * 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_GREENLAND_REGISTER_ALLOCATOR_H_
+#define ART_SRC_GREENLAND_REGISTER_ALLOCATOR_H_
+
+#include "backend_types.h"
+
+#include "lir_basic_block.h"
+
+#include <stdint.h>
+#include <list>
+#include <map>
+
+namespace art {
+namespace greenland {
+
+class LIR;
+class LIRFunction;
+class TargetRegisterInfo;
+
+class RegisterAllocator  {
+ private:
+  enum RegTypeTag {
+    kPhyRegType = 0, kFrameType, kInStackType, kNoneType = -1
+  };
+
+  struct Storage {
+    int index;
+    RegTypeTag regTag;
+  };
+
+  // Storage Allocation
+  Storage AllocateStorage(LIRFunction &lir_func, unsigned vreg_idx);
+  void KeepStorage(const LIR& lir);
+  void FreeStorage(unsigned vreg_idx);
+  void HandleInsnCopy(LIRBasicBlock& bb,
+                      LIRBasicBlock::iterator it,
+                      LIRBasicBlock::iterator next_lir);
+
+  // Pre-RA
+  void BuildKillInfo(LIRFunction& lir_func);
+  void PHIElimination(LIRFunction& lir_func);
+
+  void InitializeAllocation(LIRFunction& lir_func);
+  void PreRegisterAllocation(LIRFunction& lir_func);
+  void FunctionRegisterAllocation(LIRFunction& lir_func);
+ public:
+  RegisterAllocator(const TargetRegisterInfo& info) : reg_info_(info) { }
+  ~RegisterAllocator() { }
+
+  void AllocateRegisters(LIRFunction& lir_func) {
+    InitializeAllocation(lir_func);
+    PreRegisterAllocation(lir_func);
+    FunctionRegisterAllocation(lir_func);
+  }
+
+ private:
+  std::list<unsigned> allocatable_list_;
+  std::list<unsigned> stackstorage_list_;
+  std::map<unsigned, Storage> allocated_map_;
+  const TargetRegisterInfo& reg_info_;
+  DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
+};
+
+} // namespace greenland
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_REGISTER_ALLOCATOR_H_
diff --git a/src/greenland/lir.cc b/src/greenland/runtime/runtime_utils.h
similarity index 60%
copy from src/greenland/lir.cc
copy to src/greenland/runtime/runtime_utils.h
index 72fb03b..cbdfcc6 100644
--- a/src/greenland/lir.cc
+++ b/src/greenland/runtime/runtime_utils.h
@@ -14,17 +14,29 @@
  * limitations under the License.
  */
 
-#include "lir.h"
+#ifndef ART_SRC_GREENLAND_RUNTIME_UTILS_H_
+#define ART_SRC_GREENLAND_RUNTIME_UTILS_H_
 
-#include "lir_desc.h"
-#include "lir_function.h"
+#include "asm_support.h"
+#include "thread.h"
 
 namespace art {
 namespace greenland {
 
-LIR::LIR(const LIRDesc& desc) : parent_(NULL), desc_(desc) {
-  operands_.reserve(desc_.GetNumOperands());
+static inline Thread* art_get_current_thread() {
+#if defined(__i386__)
+  Thread* ptr;
+  __asm__ __volatile__("movl %%fs:(%1), %0"
+      : "=r"(ptr)  // output
+      : "r"(THREAD_SELF_OFFSET)  // input
+      :);  // clobber
+  return ptr;
+#else
+  return Thread::Current();
+#endif
 }
 
 } // namespace greenland
 } // namespace art
+
+#endif // ART_SRC_GREENLAND_RUNTIME_UTILS_H_
diff --git a/src/greenland/runtime/support_alloc.cc b/src/greenland/runtime/support_alloc.cc
new file mode 100644
index 0000000..5198903
--- /dev/null
+++ b/src/greenland/runtime/support_alloc.cc
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#include "greenland/runtime_entry_points.h"
+
+#include "runtime_utils.h"
+#include "runtime_support.h"
+
+using namespace art;
+using namespace art::greenland;
+
+namespace {
+
+Object* art_alloc_array_from_code(uint32_t type_idx,
+                                  Method* referrer,
+                                  uint32_t length,
+                                  Thread* thread) {
+  return AllocArrayFromCode(type_idx, referrer, length, thread, false);
+}
+
+Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
+                                                    Method* referrer,
+                                                    uint32_t length,
+                                                    Thread* thread) {
+  return AllocArrayFromCode(type_idx, referrer, length, thread, true);
+}
+
+Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
+                                            Method* referrer,
+                                            uint32_t length,
+                                            Thread* thread) {
+  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
+}
+
+Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
+                                                              Method* referrer,
+                                                              uint32_t length,
+                                                              Thread* thread) {
+  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace greenland {
+
+void InitAllocRuntimes(RuntimeEntryPoints* entry_points) {
+  entry_points->AllocArray = art_alloc_array_from_code;
+  entry_points->AllocArrayWithAccessCheck = art_alloc_array_from_code_with_access_check;
+  entry_points->CheckAndAllocArray = art_check_and_alloc_array_from_code;
+  entry_points->CheckAndAllocArrayWithAccessCheck = art_check_and_alloc_array_from_code_with_access_check;
+  return;
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/runtime/support_cast.cc b/src/greenland/runtime/support_cast.cc
new file mode 100644
index 0000000..d74dbe7
--- /dev/null
+++ b/src/greenland/runtime/support_cast.cc
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include "greenland/runtime_entry_points.h"
+
+#include "runtime_utils.h"
+#include "runtime_support.h"
+
+using namespace art;
+using namespace art::greenland;
+
+namespace {
+
+void art_check_put_array_element_from_code(const Object* element,
+                                           const Object* array) {
+  if (element == NULL) {
+    return;
+  }
+  DCHECK(array != NULL);
+  Class* array_class = array->GetClass();
+  DCHECK(array_class != NULL);
+  Class* component_type = array_class->GetComponentType();
+  Class* element_class = element->GetClass();
+  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
+    Thread* thread = art_get_current_thread();
+    thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+                               "%s cannot be stored in an array of type %s",
+                               PrettyDescriptor(element_class).c_str(),
+                               PrettyDescriptor(array_class).c_str());
+  }
+  return;
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace greenland {
+
+void InitCastRuntimes(RuntimeEntryPoints* entry_points) {
+  entry_points->CheckPutArrayElement = art_check_put_array_element_from_code;
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/lir.cc b/src/greenland/runtime/support_dexcache.cc
similarity index 61%
copy from src/greenland/lir.cc
copy to src/greenland/runtime/support_dexcache.cc
index 72fb03b..903e5cc 100644
--- a/src/greenland/lir.cc
+++ b/src/greenland/runtime/support_dexcache.cc
@@ -14,16 +14,27 @@
  * limitations under the License.
  */
 
-#include "lir.h"
+#include "greenland/runtime_entry_points.h"
 
-#include "lir_desc.h"
-#include "lir_function.h"
+#include "runtime_utils.h"
+#include "runtime_support.h"
+
+using namespace art;
+using namespace art::greenland;
+
+namespace {
+
+Object* art_resolve_string(Method* referrer, uint32_t string_idx) {
+  return ResolveStringFromCode(referrer, string_idx);
+}
+
+} // anonymous namespace
 
 namespace art {
 namespace greenland {
 
-LIR::LIR(const LIRDesc& desc) : parent_(NULL), desc_(desc) {
-  operands_.reserve(desc_.GetNumOperands());
+void InitDexCacheRuntimes(RuntimeEntryPoints* entry_points) {
+  entry_points->ResolveString = art_resolve_string;
 }
 
 } // namespace greenland
diff --git a/src/greenland/runtime/support_exception.cc b/src/greenland/runtime/support_exception.cc
new file mode 100644
index 0000000..2470051
--- /dev/null
+++ b/src/greenland/runtime/support_exception.cc
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "greenland/runtime_entry_points.h"
+
+#include "nth_caller_visitor.h"
+#include "runtime_utils.h"
+#include "runtime_support.h"
+
+using namespace art;
+using namespace art::greenland;
+
+namespace {
+
+int32_t art_find_catch_block(Method* current_method, uint32_t ti_offset) {
+  Thread* thread = art_get_current_thread();
+  Class* exception_type = thread->GetException()->GetClass();
+  MethodHelper mh(current_method);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  DCHECK_LT(ti_offset, code_item->tries_size_);
+  const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
+
+  int iter_index = 0;
+  // Iterate over the catch handlers associated with dex_pc
+  for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
+    uint16_t iter_type_idx = it.GetHandlerTypeIndex();
+    // Catch all case
+    if (iter_type_idx == DexFile::kDexNoIndex16) {
+      return iter_index;
+    }
+    // Does this catch exception type apply?
+    Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
+    if (iter_exception_type == NULL) {
+      // The verifier should take care of resolving all exception classes early
+      LOG(WARNING) << "Unresolved exception class when finding catch block: "
+          << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
+    } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
+      return iter_index;
+    }
+    ++iter_index;
+  }
+  // Handler not found
+  return -1;
+}
+
+void art_throw_array_bounds(int32_t length, int32_t index) {
+  Thread* thread = art_get_current_thread();
+  thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "length=%d; index=%d", length, index);
+}
+
+void art_throw_null_pointer_exception(uint32_t dex_pc) {
+  Thread* thread = art_get_current_thread();
+  NthCallerVisitor visitor(0);
+  thread->WalkStack(&visitor);
+  Method* throw_method = visitor.caller;
+  ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace greenland {
+
+void InitExceptionRuntimes(RuntimeEntryPoints* entry_points) {
+  entry_points->FindCatchBlock = art_find_catch_block;
+  entry_points->ThrowIndexOutOfBounds = art_throw_array_bounds;
+  entry_points->ThrowNullPointerException = art_throw_null_pointer_exception;
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/runtime/support_field.cc b/src/greenland/runtime/support_field.cc
new file mode 100644
index 0000000..523740f
--- /dev/null
+++ b/src/greenland/runtime/support_field.cc
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#include "greenland/runtime_entry_points.h"
+
+#include "runtime_utils.h"
+#include "runtime_support.h"
+
+using namespace art;
+using namespace art::greenland;
+
+namespace {
+
+Object* art_get_obj_static_from_code(uint32_t field_idx, Method* referrer) {
+  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(NULL);
+  }
+  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread(),
+                            true, false, false, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(NULL);
+  }
+  return 0;
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace greenland {
+
+void InitFieldRuntimes(RuntimeEntryPoints* entry_points) {
+  entry_points->GetObjectStatic = art_get_obj_static_from_code;
+}
+
+} // namespace greenland
+} // namespace art
diff --git a/src/greenland/lir.cc b/src/greenland/runtime/support_thread.cc
similarity index 61%
rename from src/greenland/lir.cc
rename to src/greenland/runtime/support_thread.cc
index 72fb03b..25fb698 100644
--- a/src/greenland/lir.cc
+++ b/src/greenland/runtime/support_thread.cc
@@ -14,16 +14,28 @@
  * limitations under the License.
  */
 
-#include "lir.h"
+#include "greenland/runtime_entry_points.h"
 
-#include "lir_desc.h"
-#include "lir_function.h"
+#include "runtime_utils.h"
+#include "runtime_support.h"
+#include "thread_list.h"
+
+using namespace art;
+using namespace art::greenland;
+
+namespace {
+
+void art_test_suspend(Thread* thread) {
+  Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
+}
+
+} // anonymous namespace
 
 namespace art {
 namespace greenland {
 
-LIR::LIR(const LIRDesc& desc) : parent_(NULL), desc_(desc) {
-  operands_.reserve(desc_.GetNumOperands());
+void InitThreadRuntimes(RuntimeEntryPoints* entry_points) {
+  entry_points->TestSuspend = art_test_suspend;
 }
 
 } // namespace greenland
diff --git a/src/greenland/runtime_entry_points.cc b/src/greenland/runtime_entry_points.cc
new file mode 100644
index 0000000..a9b1edc
--- /dev/null
+++ b/src/greenland/runtime_entry_points.cc
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#include "runtime_entry_points.h"
+
+namespace art {
+
+// Forward Declarations
+namespace greenland {
+
+void InitThreadRuntimes(RuntimeEntryPoints* entry_points);
+void InitExceptionRuntimes(RuntimeEntryPoints* entry_points);
+void InitAllocRuntimes(RuntimeEntryPoints* entry_points);
+void InitDexCacheRuntimes(RuntimeEntryPoints* entry_points);
+void InitFieldRuntimes(RuntimeEntryPoints* entry_points);
+void InitCastRuntimes(RuntimeEntryPoints* entry_points);
+
+} // namespace greenland
+
+void InitRuntimeEntryPoints(RuntimeEntryPoints* entry_points) {
+  // Defined in runtime/support_thread.cc
+  greenland::InitThreadRuntimes(entry_points);
+  // Defined in runtime/support_exception.cc
+  greenland::InitExceptionRuntimes(entry_points);
+  // Defined in runtime/support_alloc.cc
+  greenland::InitAllocRuntimes(entry_points);
+  // Defined in runtime/support_dexcache.cc
+  greenland::InitDexCacheRuntimes(entry_points);
+  // Defined in runtime/support_field.cc
+  greenland::InitFieldRuntimes(entry_points);
+  // Defined in runtime/support_case.cc
+  greenland::InitCastRuntimes(entry_points);
+  return;
+}
+
+} // namespace art
diff --git a/src/greenland/runtime_entry_points.h b/src/greenland/runtime_entry_points.h
new file mode 100644
index 0000000..8cd8ce44
--- /dev/null
+++ b/src/greenland/runtime_entry_points.h
@@ -0,0 +1,89 @@
+/*
+ * 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_GREENLAND_RUNTIME_ENTRY_POINTS_H_
+#define ART_SRC_GREENLAND_RUNTIME_ENTRY_POINTS_H_
+
+#include "macros.h"
+
+#include <stdint.h>
+
+#define RUNTIME_ENTRYPOINT(x) \
+  (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, runtime_entry_points_)) + \
+   static_cast<uintptr_t>(OFFSETOF_MEMBER(RuntimeEntryPoints, x)))
+
+namespace art {
+
+class Method;
+class Object;
+class Thread;
+
+struct PACKED RuntimeEntryPoints {
+  //----------------------------------------------------------------------------
+  // Thread
+  //----------------------------------------------------------------------------
+  void (*TestSuspend)(Thread* thread);
+
+  //----------------------------------------------------------------------------
+  // Exception
+  //----------------------------------------------------------------------------
+  int32_t (*FindCatchBlock)(Method* current_method, uint32_t ti_offset);
+  void (*ThrowIndexOutOfBounds)(int32_t length, int32_t index);
+  void (*ThrowNullPointerException)(unsigned dex_pc);
+
+  //----------------------------------------------------------------------------
+  // Alloc
+  //----------------------------------------------------------------------------
+  Object* (*AllocArray)(uint32_t type_idx, Method* referrer,
+                        uint32_t length, Thread* thread);
+
+  Object* (*AllocArrayWithAccessCheck)(uint32_t type_idx, Method* referrer,
+                                       uint32_t length, Thread* thread);
+
+  Object* (*CheckAndAllocArray)(uint32_t type_idx, Method* referrer,
+                                uint32_t length, Thread* thread);
+
+  Object* (*CheckAndAllocArrayWithAccessCheck)(uint32_t type_idx,
+                                               Method* referrer,
+                                               uint32_t length,
+                                               Thread* thread);
+
+  //----------------------------------------------------------------------------
+  // DexCache
+  //----------------------------------------------------------------------------
+  Object* (*ResolveString)(Method* referrer, uint32_t string_idx);
+
+  //----------------------------------------------------------------------------
+  // Field
+  //----------------------------------------------------------------------------
+  Object* (*GetObjectStatic)(uint32_t field_idx, Method* referrer);
+
+  //----------------------------------------------------------------------------
+  // Cast
+  //----------------------------------------------------------------------------
+  void (*CheckPutArrayElement)(const Object* element, const Object* array);
+
+  //----------------------------------------------------------------------------
+  // JNI
+  //----------------------------------------------------------------------------
+};
+
+// Initialize an entry point data structure.
+void InitRuntimeEntryPoints(RuntimeEntryPoints* entry_points);
+
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_RUNTIME_ENTRY_POINTS_H_
diff --git a/src/greenland/target_codegen_machine.cc b/src/greenland/target_codegen_machine.cc
index 87a215e..3c65a68 100644
--- a/src/greenland/target_codegen_machine.cc
+++ b/src/greenland/target_codegen_machine.cc
@@ -16,12 +16,16 @@
 
 #include "target_codegen_machine.h"
 
-#include "greenland.h"
+#include "lir_function.h"
+#include "lir_pass_manager.h"
 #include "target_lir_emitter.h"
+#include "target_lir_opcodes.h"
 #include "target_registry.h"
 
 #include "compiled_method.h"
 #include "compiler.h"
+#include "oat_compilation_unit.h"
+#include "utils.h"
 
 #include <UniquePtr.h>
 
@@ -39,23 +43,24 @@
   return (*ctor)();
 }
 
-CompiledMethod* TargetCodeGenMachine::Run(const Greenland& parent,
-                                          const llvm::Function& func,
-                                          const OatCompilationUnit& cunit,
-                                          DexLang::Context& dex_lang_ctx) {
-#if 0
-  UniquePtr<TargetLIREmitter> emitter(CreateLIREmitter(func, cunit,
-                                                       dex_lang_ctx));
-  LIRFunction* lir_func = emitter->Emit();
-  if (lir_func == NULL) {
+CompiledMethod* TargetCodeGenMachine::Run(const Compiler& compiler,
+                                          const GBCFunction& gbc_func) {
+  LIRPassManager lir_pm;
+
+  lir_pm.Add(CreateLIREmitter());
+
+  LIRFunction lir_func(*this, gbc_func);
+
+  if (!lir_pm.Run(lir_func)) {
     return NULL;
   }
-#endif
+
+  lir_func.Dump();
 
   // 0x90 is the NOP in x86
   std::vector<uint8_t> code(10, 0x90);
 
-  return new CompiledMethod(parent.GetCompiler().GetInstructionSet(), code,
+  return new CompiledMethod(compiler.GetInstructionSet(), code,
                             /* frame_size_in_bytes */0,
                             /* core_spill_mask */0,
                             /* fp_spill_mask */0);
diff --git a/src/greenland/target_codegen_machine.h b/src/greenland/target_codegen_machine.h
index a0962fe..8cae791 100644
--- a/src/greenland/target_codegen_machine.h
+++ b/src/greenland/target_codegen_machine.h
@@ -17,26 +17,27 @@
 #ifndef ART_SRC_GREENLAND_TARGET_CODEGEN_MACHINE_H_
 #define ART_SRC_GREENLAND_TARGET_CODEGEN_MACHINE_H_
 
-#include "dex_lang.h"
-
 #include "instruction_set.h"
 
+#include <string>
+
 namespace art {
   class CompiledMethod;
-  class OatCompilationUnit;
-}
-
-namespace llvm {
-  class Function;
+  class Compiler;
 }
 
 namespace art {
 namespace greenland {
 
-class Greenland;
-class TargetLIREmitter;
+class GBCFunction;
+class LIR;
 class RegisterAllocator;
 class TargetAssembler;
+class TargetDataLayout;
+class TargetLIRBuilder;
+class TargetLIREmitter;
+class TargetLIRInfo;
+class TargetRegisterInfo;
 
 class TargetCodeGenMachine {
  protected:
@@ -45,9 +46,17 @@
  public:
   virtual ~TargetCodeGenMachine() { }
 
-  virtual TargetLIREmitter* CreateLIREmitter(const llvm::Function& func,
-                                             const OatCompilationUnit& cunit,
-                                             DexLang::Context& dex_lang_ctx) =0;
+  virtual TargetLIREmitter* CreateLIREmitter() = 0;
+
+  virtual const TargetDataLayout* GetDataLayout() const = 0;
+
+  virtual const TargetLIRInfo* GetLIRInfo() const = 0;
+
+  virtual const TargetRegisterInfo* GetRegisterInfo() const = 0;
+
+  virtual const char* GetConditionCodeName(unsigned cond) const = 0;
+
+  virtual TargetLIRBuilder* CreateLIRBuilder() = 0;
 
   virtual RegisterAllocator* GetRegisterAllocator() = 0;
 
@@ -56,10 +65,7 @@
   static TargetCodeGenMachine* Create(InstructionSet insn_set);
 
  public:
-  CompiledMethod* Run(const Greenland& parent,
-                      const llvm::Function& func,
-                      const OatCompilationUnit& cunit,
-                      DexLang::Context& dex_lang_ctx);
+  CompiledMethod* Run(const Compiler& compiler, const GBCFunction& gbc_func);
 };
 
 } // namespace greenland
diff --git a/src/greenland/target_data_layout.h b/src/greenland/target_data_layout.h
new file mode 100644
index 0000000..7b634cf
--- /dev/null
+++ b/src/greenland/target_data_layout.h
@@ -0,0 +1,74 @@
+/*
+ * 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_GREENLAND_TARGET_DATA_LAYOUT_H_
+#define ART_SRC_GREENLAND_TARGET_DATA_LAYOUT_H_
+
+#include "lir.h"
+
+#include "logging.h"
+
+namespace art {
+namespace greenland {
+
+class TargetDataLayout {
+ private:
+  // Size of pointer in bytes
+  unsigned pointer_size_;
+
+  // Stack alignment in bytes
+  unsigned stack_alignment_;
+
+ public:
+  TargetDataLayout(unsigned pointer_size, unsigned stack_alignment)
+      : pointer_size_(pointer_size), stack_alignment_(stack_alignment) { }
+
+  unsigned GetPointerSize() const {
+    return pointer_size_;
+  }
+  unsigned GetPointerSizeInBits() const {
+    return (pointer_size_ << 3);
+  }
+
+  unsigned GetStackAlignment() const {
+    return stack_alignment_;
+  }
+
+  unsigned GetOpTypeSize(LIR::OperationType op_type) const {
+    switch (op_type) {
+      case LIR::kUInt8TypeOp:   return 1;   break;
+      case LIR::kSInt8TypeOp:   return 1;   break;
+      case LIR::kUInt16TypeOp:  return 2;   break;
+      case LIR::kSInt16TypeOp:  return 2;   break;
+      case LIR::kInt32TypeOp:   return 4;   break;
+      case LIR::kInt64TypeOp:   return 8;   break;
+      case LIR::kFloatTypeOp:   return 4;   break;
+      case LIR::kDoubleTypeOp:  return 8;   break;
+      case LIR::kPointerTypeOp: return pointer_size_;   break;
+      case LIR::kUnknownTypeOp:
+      default: {
+        LOG(FATAL) << "Unknown operation type: " << op_type;
+        return 0;
+      }
+    }
+    // unreachable
+  }
+};
+
+} // namespace greenland
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_TARGET_DATA_LAYOUT_H_
diff --git a/src/greenland/target_lir_emitter.cc b/src/greenland/target_lir_emitter.cc
deleted file mode 100644
index babb114..0000000
--- a/src/greenland/target_lir_emitter.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.
- */
-
-#include "target_lir_emitter.h"
-
-#include "target_lir_info.h"
-#include "target_lir_opcodes.h"
-
-#include "intrinsic_helper.h"
-#include "lir_function.h"
-
-#include <llvm/Function.h>
-
-namespace art {
-namespace greenland {
-
-TargetLIREmitter::TargetLIREmitter(const llvm::Function& func,
-                                   const OatCompilationUnit& cunit,
-                                   DexLang::Context& dex_lang_ctx,
-                                   TargetLIRInfo& target_lir_info)
-    : func_(func), cunit_(cunit), dex_lang_ctx_(dex_lang_ctx.IncRef()),
-      info_(target_lir_info), lir_func_() {
-  return;
-}
-
-TargetLIREmitter::~TargetLIREmitter() {
-  dex_lang_ctx_.DecRef();
-  return;
-}
-
-bool TargetLIREmitter::visitBasicBlock(const llvm::BasicBlock& bb) {
-  // Place the corresponding block label to the output
-  llvm::DenseMap<const llvm::BasicBlock*, LIR*>::const_iterator label_iter =
-      block_labels_.find(&bb);
-
-  DCHECK(label_iter != block_labels_.end());
-  lir_func_.push_back(label_iter->second);
-
-  // Now, iterate over and process all instructions within the basic block
-  for (llvm::BasicBlock::const_iterator inst_iter = bb.begin(),
-          inst_end = bb.end(); inst_iter != inst_end; inst_iter++) {
-    const llvm::Instruction& inst = *inst_iter;
-    switch (inst.getOpcode()) {
-#define VISIT(OPCODE, CLASS)                                          \
-      case llvm::Instruction::OPCODE: {                               \
-        if (!visit ## CLASS(static_cast<const llvm::CLASS&>(inst))) { \
-          return false;                                               \
-        }                                                             \
-        break;                                                        \
-      }
-
-      VISIT(Ret,      ReturnInst);
-      VISIT(Br,       BranchInst);
-      VISIT(ICmp,     ICmpInst);
-      VISIT(IntToPtr, IntToPtrInst);
-      VISIT(Call,     CallInst);
-
-#undef VISIT
-      default : {
-        LOG(INFO) << "Unhandled instruction hit!";
-        inst.dump();
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-bool TargetLIREmitter::visitReturnInst(const llvm::ReturnInst& inst) {
-  inst.dump();
-  return true;
-}
-
-bool TargetLIREmitter::visitBranchInst(const llvm::BranchInst& inst) {
-  inst.dump();
-  return true;
-}
-
-bool TargetLIREmitter::visitICmpInst(const llvm::ICmpInst& inst) {
-  inst.dump();
-  return true;
-}
-
-bool TargetLIREmitter::visitIntToPtrInst(const llvm::IntToPtrInst& inst) {
-  inst.dump();
-  return true;
-}
-
-bool TargetLIREmitter::visitCallInst(const llvm::CallInst& inst) {
-  // The callee must be a DexLang intrinsic
-  return visitDexLangIntrinsics(inst);
-}
-
-bool TargetLIREmitter::visitDexLangIntrinsics(const llvm::CallInst& inst) {
-  const llvm::Function* callee = inst.getCalledFunction();
-  IntrinsicHelper::IntrinsicId intr_id =
-      dex_lang_ctx_.GetIntrinsicHelper().GetIntrinsicId(callee);
-
-  if (intr_id == IntrinsicHelper::UnknownId) {
-    LOG(INFO) << "Unexpected call instruction to '"
-              << callee->getName().str() << "'";
-    return false;
-  }
-
-  //const IntrinsicHelper::IntrinsicInfo& intr_info =
-  //    IntrinsicHelper::GetInfo(intr_id);
-
-
-  return true;
-}
-
-LIRFunction* TargetLIREmitter::Emit() {
-  if (EmitBasicBlockLabels() &&
-      EmitEntrySequence() &&
-      EmitInstructions() &&
-      EmitExitSequence()) {
-    return &lir_func_;
-  }
-
-  return NULL;
-}
-
-bool TargetLIREmitter::EmitBasicBlockLabels() {
-  for (llvm::Function::const_iterator bb_iter = func_.begin(),
-          bb_end = func_.end(); bb_iter != bb_end; bb_iter++) {
-    LIR* lir = lir_func_.CreateLIR(info_.GetLIRDesc(opcode::kBlockLabel));
-    CHECK(block_labels_.insert(std::make_pair(bb_iter, lir)).second);
-  }
-  return true;
-}
-
-bool TargetLIREmitter::EmitEntrySequence() {
-  // Flush all function arguments to the virtual registers
-  return true;
-}
-
-bool TargetLIREmitter::EmitInstructions() {
-  // Iterator over all basic blocks
-  for (llvm::Function::const_iterator bb_iter = func_.begin(),
-          bb_end = func_.end(); bb_iter != bb_end; bb_iter++) {
-    if (!visitBasicBlock(*bb_iter)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-bool TargetLIREmitter::EmitExitSequence() {
-  return true;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/target_lir_emitter.h b/src/greenland/target_lir_emitter.h
deleted file mode 100644
index 8e39e4c..0000000
--- a/src/greenland/target_lir_emitter.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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_GREENLAND_TARGET_LIR_EMITTER_H_
-#define ART_SRC_GREENLAND_TARGET_LIR_EMITTER_H_
-
-#include "dex_lang.h"
-
-#include "lir_function.h"
-
-#include <llvm/ADT/DenseMap.h>
-
-namespace art {
-  class OatCompilationUnit;
-}
-
-namespace llvm {
-  class BasicBlock;
-  class BranchInst;
-  class CallInst;
-  class Function;
-  class ICmpInst;
-  class Instruction;
-  class IntToPtrInst;
-  class ReturnInst;
-}
-
-namespace art {
-namespace greenland {
-
-class LIRFunction;
-class TargetLIRInfo;
-
-class TargetLIREmitter {
- private:
-  const llvm::Function& func_;
-  const OatCompilationUnit& cunit_;
-  DexLang::Context& dex_lang_ctx_;
-  TargetLIRInfo& info_;
-
- private:
-  llvm::DenseMap<const llvm::BasicBlock*, LIR*> block_labels_;
-
- protected:
-  LIRFunction lir_func_;
-
-  TargetLIREmitter(const llvm::Function& func,
-                   const OatCompilationUnit& cunit,
-                   DexLang::Context& dex_lang_ctx,
-                   TargetLIRInfo& target_lir_info);
-
- private:
-  bool visitBasicBlock(const llvm::BasicBlock& bb);
-
-  bool visitReturnInst(const llvm::ReturnInst& inst);
-  bool visitBranchInst(const llvm::BranchInst& inst);
-  //bool visitSwitchInst(SwitchInst &I)            { DELEGATE(TerminatorInst);}
-  //bool visitIndirectBrInst(IndirectBrInst &I)    { DELEGATE(TerminatorInst);}
-  //bool visitInvokeInst(InvokeInst &I)            { DELEGATE(TerminatorInst);}
-  //bool visitResumeInst(ResumeInst &I)            { DELEGATE(TerminatorInst);}
-  //bool visitUnreachableInst(UnreachableInst &I)  { DELEGATE(TerminatorInst);}
-  bool visitICmpInst(const llvm::ICmpInst& inst);
-  //bool visitFCmpInst(FCmpInst &I)                { DELEGATE(CmpInst);}
-  //bool visitAllocaInst(AllocaInst &I)            { DELEGATE(UnaryInstruction);}
-  //bool visitLoadInst(LoadInst     &I)            { DELEGATE(UnaryInstruction);}
-  //bool visitStoreInst(StoreInst   &I)            { DELEGATE(Instruction);}
-  //bool visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { DELEGATE(Instruction);}
-  //bool visitAtomicRMWInst(AtomicRMWInst &I)      { DELEGATE(Instruction);}
-  //bool visitFenceInst(FenceInst   &I)            { DELEGATE(Instruction);}
-  //bool visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction);}
-  //bool visitPHINode(PHINode       &I)            { DELEGATE(Instruction);}
-  //bool visitTruncInst(TruncInst &I)              { DELEGATE(CastInst);}
-  //bool visitZExtInst(ZExtInst &I)                { DELEGATE(CastInst);}
-  //bool visitSExtInst(SExtInst &I)                { DELEGATE(CastInst);}
-  //bool visitFPTruncInst(FPTruncInst &I)          { DELEGATE(CastInst);}
-  //bool visitFPExtInst(FPExtInst &I)              { DELEGATE(CastInst);}
-  //bool visitFPToUIInst(FPToUIInst &I)            { DELEGATE(CastInst);}
-  //bool visitFPToSIInst(FPToSIInst &I)            { DELEGATE(CastInst);}
-  //bool visitUIToFPInst(UIToFPInst &I)            { DELEGATE(CastInst);}
-  //bool visitSIToFPInst(SIToFPInst &I)            { DELEGATE(CastInst);}
-  //bool visitPtrToIntInst(PtrToIntInst &I)        { DELEGATE(CastInst);}
-  bool visitIntToPtrInst(const llvm::IntToPtrInst& inst);
-  //bool visitBitCastInst(BitCastInst &I)          { DELEGATE(CastInst);}
-  //bool visitSelectInst(SelectInst &I)            { DELEGATE(Instruction);}
-  bool visitCallInst(const llvm::CallInst& inst);
-  //bool visitVAArgInst(VAArgInst   &I)            { DELEGATE(UnaryInstruction);}
-  //bool visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);}
-  //bool visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction);}
-  //bool visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction);}
-  //bool visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);}
-  //bool visitInsertValueInst(InsertValueInst &I)  { DELEGATE(Instruction); }
-  //bool visitLandingPadInst(LandingPadInst &I)    { DELEGATE(Instruction); }
-
-  bool visitDexLangIntrinsics(const llvm::CallInst& inst);
-
- public:
-  virtual ~TargetLIREmitter();
-
-  LIRFunction* Emit();
-
- private:
-  bool EmitBasicBlockLabels();
-  bool EmitEntrySequence();
-  bool EmitInstructions();
-  bool EmitExitSequence();
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_LIR_EMITTER_H_
diff --git a/src/greenland/target_lir_info.h b/src/greenland/target_lir_info.h
deleted file mode 100644
index 1ed86fa..0000000
--- a/src/greenland/target_lir_info.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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_GREENLAND_TARGET_LIR_INFO_H_
-#define ART_SRC_GREENLAND_TARGET_LIR_INFO_H_
-
-#include "lir_desc.h"
-
-#include "logging.h"
-
-namespace art {
-namespace greenland {
-
-class TargetLIRInfo {
- private:
-  // An array of target's LIR instruction description
-  const LIRDesc* desc_;
-
-  unsigned num_desc_;
-
- public:
-  TargetLIRInfo(const LIRDesc* desc, unsigned num_desc)
-      : desc_(desc), num_desc_(num_desc) {
-  }
-
-  virtual ~TargetLIRInfo() { }
-
-  const LIRDesc& GetLIRDesc(unsigned opcode) {
-    DCHECK(opcode < num_desc_) << "Invalid opcode: " << opcode;
-    return desc_[opcode];
-  }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_LIR_INFO_H_
diff --git a/src/greenland/target_lir_opcodes.h b/src/greenland/target_lir_opcodes.h
deleted file mode 100644
index 27027ca..0000000
--- a/src/greenland/target_lir_opcodes.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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_GREENLAND_TARGET_LIR_OPCODES_H_
-#define ART_SRC_GREENLAND_TARGET_LIR_OPCODES_H_
-
-namespace art {
-namespace greenland {
-namespace opcode {
-
-enum {
-#define DEF_LIR_DESC(OPCODE, ...) OPCODE,
-#include "target_lir.def"
-#undef DEF_LIR_DESC
-};
-
-} // namespace opcode
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_LIR_OPCODES_H_
diff --git a/src/greenland/target_register_info.h b/src/greenland/target_register_info.h
new file mode 100644
index 0000000..41d69e1
--- /dev/null
+++ b/src/greenland/target_register_info.h
@@ -0,0 +1,79 @@
+/*
+ * 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_GREENLAND_TARGET_REGISTER_INFO_H_
+#define ART_SRC_GREENLAND_TARGET_REGISTER_INFO_H_
+
+#include "lir_function.h"
+#include "lir_reg.h"
+
+#include "target_lir_builder.h"
+#include "target_lir_info.h"
+
+#include <string>
+
+namespace art {
+namespace greenland {
+
+class TargetRegisterInfo {
+ protected:
+  const TargetLIRInfo& lir_info_;
+  TargetRegisterInfo(const TargetLIRInfo& info) :lir_info_(info) { }
+
+ public:
+  virtual const char* GetPhyRegName(unsigned reg) const = 0;
+
+  std::string GetRegName(unsigned reg) const {
+    if (LIRReg::IsVirtualReg(reg)) {
+      return LIRReg::GetVirtualRegName(reg);
+    } else {
+      return GetPhyRegName(reg);
+    }
+  }
+
+  virtual LIR*
+  CreateLoadStack(LIRFunction& lir_func,
+                  unsigned reg,
+                  int frame_idx) const = 0;
+
+  virtual LIR*
+  CreateStoreStack(LIRFunction& lir_func,
+                   unsigned reg,
+                   int frame_idx) const = 0;
+
+  virtual LIR*
+  CreateMoveReg(LIRFunction& lir_func,
+                unsigned dst,
+                unsigned src) const = 0;
+
+  virtual bool
+  IsLoadIncomingArgs(const LIR* lir) const = 0;
+
+  virtual LIR*
+  CreateCopy(LIRFunction& lir_func,
+             unsigned dst,
+             const LIROperand& src) const = 0;
+
+  virtual std::list<unsigned> GetAllocatableList() const = 0;
+  virtual unsigned GetTempRegsiter(unsigned idx) const = 0;
+
+  virtual ~TargetRegisterInfo() { }
+};
+
+} // namespace greenland
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_TARGET_REGISTER_INFO_H_
diff --git a/src/greenland/target_registry.h b/src/greenland/target_registry.h
index 1f93665..0f490e0 100644
--- a/src/greenland/target_registry.h
+++ b/src/greenland/target_registry.h
@@ -40,7 +40,7 @@
                                                     uint32_t shorty_len);
 
   static void RegisterTargetCodeGenMachine(InstructionSet insn_set,
-                                     TargetCodeGenMachineCtorTy ctor);
+                                           TargetCodeGenMachineCtorTy ctor);
   static TargetCodeGenMachineCtorTy GetTargetCodeGenMachineCtor(InstructionSet insn_set);
 
   static void RegisterInvokeStubCompiler(InstructionSet insn_set,
diff --git a/src/greenland/tools/target_lir_builder_generator.cc b/src/greenland/tools/target_lir_builder_generator.cc
new file mode 100644
index 0000000..2a48136
--- /dev/null
+++ b/src/greenland/tools/target_lir_builder_generator.cc
@@ -0,0 +1,574 @@
+/*
+ * 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.
+ */
+
+#include <cassert>
+#include <cctype>
+#include <cstring>
+#include <iostream>
+#include <string>
+
+// Should be synced with the one in lir_desc.h
+#define MAX_LIR_OPERANDS  6
+
+//----------------------------------------------------------------------------
+// Operand Info
+//----------------------------------------------------------------------------
+class LIROperand {
+ public:
+  enum Type {
+    UnknownType,
+    RegisterType,
+    ImmediateType,
+    LabelType,
+    FrameIndexType,
+  };
+};
+
+// Copy from lir_desc.h
+class LIRDescFlag {
+ public:
+  enum Flag {
+    kNone,
+    kPseudo,
+    kVariadic,
+
+    kIsLoad,
+    kIsStore,
+    kIsBranch,
+
+    kDefReg0,
+    kDefReg1,
+
+    kUseReg0,
+    kUseReg1,
+    kUseReg2,
+    kUseReg3,
+    kUseReg4,
+    kUseReg5,
+
+    kSetCCodes,
+    kUseCCodes,
+
+    kNeedRelax,
+  };
+};
+
+class LIROperandInfo {
+ public:
+  class TypeStrings {
+   public:
+    // Take RegisterType as example:
+    //  type_string_ is "unsigned"
+    //  var_string_ is "reg"
+    //  set_method_ is "SetReg"
+    const char* type_string_;
+    const char* var_string_;
+    const char* set_method_;
+  };
+
+  LIROperand::Type GetOperandType(unsigned i) const {
+    assert((i < num_operands_) && "Invalid operand index!");
+    return info_[i].type_;
+  }
+
+  const TypeStrings& GetOperandTypeStrings(unsigned i) const {
+    return OperandTypeStrings[GetOperandType(i)];
+  }
+
+ private:
+  static const TypeStrings OperandTypeStrings[];
+
+ public:
+  const char* name_;
+  unsigned num_operands_;
+  struct {
+    enum LIROperand::Type type_;
+  } info_[MAX_LIR_OPERANDS];
+};
+
+const LIROperandInfo::TypeStrings LIROperandInfo::OperandTypeStrings[] = {
+  /* UnknownType    */ { "void",           "",            "",              },
+  /* RegisterType   */ { "unsigned",       "reg",         "SetReg"         },
+  /* ImmediateType  */ { "int32_t" ,       "imm_val",     "SetImm"         },
+  /* LabelType      */ { "LIRBasicBlock*", "target",      "SetLabelTarget" },
+  /* FrameIndexType */ { "int",            "frame_index", "SetFrameIndex"  }
+};
+
+#define DEF_LIR_OPERAND_INFO(INFO_ID, NUM_OPS, INFO_DEF) \
+static const LIROperandInfo OpInfo ## INFO_ID = \
+  { #INFO_ID, NUM_OPS, INFO_DEF };
+#include "greenland/target_lir.def"
+#include "greenland/clear_target_lir.def"
+
+static const LIROperandInfo* const OpInfos[] = {
+#define DEF_LIR_OPERAND_INFO(INFO_ID, NUM_OPS, INFO_DEF) \
+  &OpInfo ## INFO_ID,
+#include "greenland/target_lir.def"
+#include "greenland/clear_target_lir.def"
+};
+
+static const unsigned NumObInfos = sizeof(OpInfos) / sizeof(OpInfos[0]);
+
+//----------------------------------------------------------------------------
+// Data structure of LIRDesc to load {target}_lir.def
+//----------------------------------------------------------------------------
+
+class LIRDesc {
+ public:
+  const char* opcode_name_;
+  const char* name_;
+  const char* format_;
+  unsigned flags;
+  const LIROperandInfo& operand_info_;
+
+  bool IsPseudo() const {
+    return (flags & (1 << LIRDescFlag::kPseudo));
+  }
+};
+
+//----------------------------------------------------------------------------
+// Target-independent LIR Enumeration
+//----------------------------------------------------------------------------
+// This is here to get the number of target-independent LIRs
+// (i.e., kNumTargetIndependentLIR)
+enum {
+#define DEF_LIR_DESC(OPCODE, ...) OPCODE,
+#include "greenland/target_lir.def"
+#include "greenland/clear_target_lir.def"
+
+  kNumTargetIndependentLIR
+};
+
+//----------------------------------------------------------------------------
+// ARM
+//----------------------------------------------------------------------------
+static const LIRDesc ARMLIR[] = {
+#define DEF_LIR_DESC(OPCODE, KIND, FLAGS, NAME, FORMAT, OPS_INFO) \
+  { #OPCODE, NAME, FORMAT, FLAGS, OpInfo ## OPS_INFO },
+#include "greenland/arm/arm_lir.def"
+};
+
+//----------------------------------------------------------------------------
+// Mips
+//----------------------------------------------------------------------------
+static const LIRDesc MipsLIR[] = {
+#define DEF_LIR_DESC(OPCODE, KIND, FLAGS, NAME, FORMAT, OPS_INFO) \
+  { #OPCODE, NAME, FORMAT, FLAGS, OpInfo ## OPS_INFO },
+#include "greenland/mips/mips_lir.def"
+};
+
+//----------------------------------------------------------------------------
+// X86
+//----------------------------------------------------------------------------
+static const LIRDesc X86LIR[] = {
+#define DEF_LIR_DESC(OPCODE, KIND, FLAGS, NAME, FORMAT, OPS_INFO) \
+  { #OPCODE, NAME, FORMAT, FLAGS, OpInfo ## OPS_INFO },
+#include "greenland/x86/x86_lir.def"
+};
+
+class Context {
+ private:
+  std::ostream& out_;
+  unsigned indent_;
+
+ public:
+  Context(std::ostream& out) : out_(out), indent_(0) { }
+
+  void IncIndent() {
+    indent_ += 2;
+    return;
+  }
+
+  void DecIndent() {
+    indent_ -= 2;
+  }
+
+  std::ostream& Indent() {
+    for (unsigned i = 0; i < indent_; i += 2) {
+      out_.write("  ", 2);
+    }
+    return out_;
+  }
+
+  std::ostream& Newline() {
+    return out_ << std::endl;
+  }
+
+  std::ostream& Out() {
+    return out_;
+  }
+
+  const LIRDesc* target_lirs_;
+  unsigned num_target_lirs_;
+
+  std::string lowercase_target_string_;
+  std::string uppercase_target_string_;
+  std::string class_name_;
+};
+
+class GenPrototype {
+  const LIROperandInfo& op_info_;
+  const char* preface_;
+ public:
+  GenPrototype(const LIROperandInfo& op_info, const char* preface = NULL)
+      : op_info_(op_info), preface_(preface) { }
+
+  friend std::ostream& operator<<(std::ostream& out, const GenPrototype& obj);
+};
+
+std::ostream& operator<<(std::ostream& out, const GenPrototype& obj) {
+  out << "(";
+
+  unsigned num_ops = obj.op_info_.num_operands_;
+  if (obj.preface_ != NULL) {
+    out << obj.preface_;
+    if (num_ops > 0) {
+      out << ", ";
+    }
+  }
+
+  for (unsigned i = 0; i < num_ops; i++) {
+    const LIROperandInfo::TypeStrings& type_strings =
+        obj.op_info_.GetOperandTypeStrings(i);
+
+    out << type_strings.type_string_ << " " << type_strings.var_string_ << i;
+
+    if (i != (num_ops - 1)) {
+      // Append "," if not the last one
+      out << ", ";
+    }
+  }
+
+  out << ")";
+  return out;
+}
+
+//----------------------------------------------------------------------------
+
+// Forward Declarations
+static void GenBeginNamespace(Context& C);
+static void GenCreateTargetLIR(Context& C, const LIRDesc& lir, bool proto_only);
+static void GenCallSetOperands(Context& C, const LIROperandInfo& operand_info);
+static void GenEndNamespace(Context& C);
+
+static void GenLicenseNote(Context& C) {
+  C.Indent() << "/*" << std::endl;
+  C.Indent() << " * Copyright (C) 2012 The Android Open Source Project" << std::endl;
+  C.Indent() << " *" << std::endl;
+  C.Indent() << " * Licensed under the Apache License, Version 2.0 (the \"License\"" << std::endl;
+  C.Indent() << " * you may not use this file except in compliance with the License." << std::endl;
+  C.Indent() << " * You may obtain a copy of the License at" << std::endl;
+  C.Indent() << " *" << std::endl;
+  C.Indent() << " *      http://www.apache.org/licenses/LICENSE-2.0" << std::endl;
+  C.Indent() << " *" << std::endl;
+  C.Indent() << " * Unless required by applicable law or agreed to in writing, software" << std::endl;
+  C.Indent() << " * distributed under the License is distributed on an \"AS IS\" BASIS," << std::endl;
+  C.Indent() << " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." << std::endl;
+  C.Indent() << " * See the License for the specific language governing permissions and" << std::endl;
+  C.Indent() << " * limitations under the License." << std::endl;
+  C.Indent() << " */" << std::endl;
+  C.Newline();
+  return;
+}
+
+//----------------------------------------------------------------------------
+
+static void GenTargetLIRBuilderHeader(Context& C) {
+  C.Indent() << "#ifdef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_HEADER";
+  C.Newline();
+
+  //----------------------------------------------------------------------------
+  // Include Files
+  //----------------------------------------------------------------------------
+  C.Indent() << "#include \"greenland/target_lir_builder.h\"" << std::endl;;
+  C.Indent() << "#include \"greenland/target_lir_info.h\"" << std::endl;
+  C.Newline();
+
+  GenBeginNamespace(C);
+
+  //----------------------------------------------------------------------------
+  // Forward Declarations
+  //----------------------------------------------------------------------------
+  C.Indent() << "class TargetLIRInfo;" << std::endl;
+  C.Newline();
+
+  C.Indent() << "class " << C.class_name_ << " : public TargetLIRBuilder {"
+             << std::endl;
+
+  //----------------------------------------------------------------------------
+  // Members
+  //----------------------------------------------------------------------------
+  C.Indent() << " private:" << std::endl;
+  C.IncIndent();
+  C.Indent() << "const TargetLIRInfo& info_;" << std::endl;
+  C.DecIndent();
+  C.Newline();
+
+  //----------------------------------------------------------------------------
+  // APIs
+  //----------------------------------------------------------------------------
+  C.Indent() << " public:" << std::endl;
+
+  C.IncIndent();
+
+  //----------------------------------------------------------------------------
+  // Constructor
+  //----------------------------------------------------------------------------
+  C.Indent() << C.class_name_ << "(const TargetLIRInfo& info) "
+                                 ": TargetLIRBuilder(), info_(info) { }"
+             << std::endl;
+  C.Newline();
+
+  //----------------------------------------------------------------------------
+  // LIR* Create(unsigned opcode)
+  //----------------------------------------------------------------------------
+  C.Indent() << "LIR* Create(unsigned opcode) {" << std::endl;
+  C.IncIndent();
+
+  C.Indent() << "return bb_->GetParent().CreateLIR(*bb_, info_.GetLIRDesc(opcode));" << std::endl;
+
+  C.DecIndent();
+  C.Indent() << "}" << std::endl;
+  C.Newline();
+
+  //----------------------------------------------------------------------------
+  // LIR* Create(LIRDesc& desc)
+  //----------------------------------------------------------------------------
+  C.Indent() << "LIR* Create(const LIRDesc& desc) {" << std::endl;
+  C.IncIndent();
+
+  C.Indent() << "return bb_->GetParent().CreateLIR(*bb_, desc);" << std::endl;
+
+  C.DecIndent();
+  C.Indent() << "}" << std::endl;
+  C.Newline();
+
+  //----------------------------------------------------------------------------
+  // LIR* Create_*([operand...])
+  //----------------------------------------------------------------------------
+  for (unsigned i = 0; i < C.num_target_lirs_; i++) {
+    const LIRDesc& lir = C.target_lirs_[i];
+    if (!lir.IsPseudo() || (i > kNumTargetIndependentLIR)) {
+      GenCreateTargetLIR(C, lir, /* proto_only */true);
+    }
+  }
+
+  C.DecIndent();
+
+  C.Indent() << "};" << std::endl;
+  C.Newline();
+
+  GenEndNamespace(C);
+
+  C.Indent() << "#undef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_HEADER" << std::endl;
+  C.Indent() << "#endif // GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_HEADER" << std::endl;
+  return;
+}
+
+static void GenTargetLIRBuilderImpl(Context& C) {
+  C.Indent() << "#ifdef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_IMPL";
+  C.Newline();
+
+  //----------------------------------------------------------------------------
+  // Include Files
+  //----------------------------------------------------------------------------
+  C.Indent() << "#include \"greenland/lir_desc.h\"" << std::endl;
+  C.Indent() << "#include \"greenland/lir_function.h\"" << std::endl;
+  C.Indent() << "#include \"greenland/" << C.lowercase_target_string_
+             << "/" << C.lowercase_target_string_ << "_lir_opcodes.h\""
+             << std::endl;
+  C.Newline();
+
+  GenBeginNamespace(C);
+
+  for (unsigned i = 0; i < C.num_target_lirs_; i++) {
+    const LIRDesc& lir = C.target_lirs_[i];
+    if (!lir.IsPseudo() || (i > kNumTargetIndependentLIR)) {
+      GenCreateTargetLIR(C, lir, /* proto_only */false);
+    }
+  }
+
+  C.Newline();
+
+  GenEndNamespace(C);
+
+  C.Indent() << "#undef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_IMPL" << std::endl;
+  C.Indent() << "#endif // GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_IMPL" << std::endl;
+  C.Newline();
+  return;
+}
+
+//----------------------------------------------------------------------------
+
+static void GenBeginNamespace(Context& C) {
+  C.Indent() << "namespace art {" << std::endl;
+  C.Indent() << "namespace greenland {" << std::endl;
+  C.Newline();
+  return;
+}
+
+static void GenCreateTargetLIR(Context& C, const LIRDesc& lir, bool proto_only){
+  C.Indent() << "// " << lir.name_ << " " << lir.format_ << std::endl;
+
+  if (proto_only) {
+    C.Indent() << "LIR* Create_" << &lir.opcode_name_[1] /* hack: skip 'k' */
+               << GenPrototype(lir.operand_info_) << ";" << std::endl;
+    return;
+  } else {
+    C.Indent() << "LIR* " << C.class_name_ << "::Create_"
+               << &lir.opcode_name_[1] /* hack: skip 'k' */
+               << GenPrototype(lir.operand_info_) << " {" << std::endl;
+  }
+
+  C.IncIndent();
+  C.Indent() << "LIR* lir = Create("
+             << C.lowercase_target_string_ << "::" << lir.opcode_name_<< ");"
+             << std::endl;
+  GenCallSetOperands(C, lir.operand_info_);
+  C.Indent() << "return lir;" << std::endl;
+  C.DecIndent();
+
+  C.Indent() << "}" << std::endl;
+  C.Newline();
+  return;
+}
+
+static void
+GenCallSetOperands(Context& C, const LIROperandInfo& operand_info) {
+  if (operand_info.num_operands_ > 0) {
+    C.Indent() << "Set" << operand_info.name_ << "Operands(*lir, ";
+
+    for (unsigned i = 0; i < operand_info.num_operands_; i++) {
+      const LIROperandInfo::TypeStrings& type_strings =
+        operand_info.GetOperandTypeStrings(i);
+
+      C.Out() << type_strings.var_string_ << i;
+
+      if (i != (operand_info.num_operands_ - 1)) {
+        // Append "," if not the last one
+        C.Out() << ", ";
+      }
+    }
+
+    C.Out() << ");" << std::endl;
+  }
+  return;
+}
+
+static void GenEndNamespace(Context& C) {
+  C.Newline();
+  C.Indent() << "} // namespace greenland" << std::endl;
+  C.Indent() << "} // namespace art" << std::endl;
+  C.Newline();
+  return;
+}
+
+//----------------------------------------------------------------------------
+// Special functionality to generate Set*Operands in TargetLIRBuilder
+//----------------------------------------------------------------------------
+static void GenSetOperandsImpl(Context& C, const LIROperandInfo& operand_info);
+
+static void GenSetOperands(Context& C) {
+  for (unsigned i = 0; i < NumObInfos; i++) {
+    const LIROperandInfo& op_info = *OpInfos[i];
+    C.Indent() << "static inline void Set" << op_info.name_
+               << "Operands" << GenPrototype(op_info, /* preface */"LIR& lir")
+               << " {" << std::endl;
+    C.IncIndent();
+    GenSetOperandsImpl(C, op_info);
+    C.DecIndent();
+    C.Indent() << "}" << std::endl;
+    C.Newline();
+  }
+
+  return;
+}
+
+static void GenSetOperandsImpl(Context& C, const LIROperandInfo& operand_info) {
+  if (operand_info.num_operands_ <= 0) {
+    return;
+  }
+
+  C.Indent() << "lir";
+  for (unsigned i = 0; i < operand_info.num_operands_; i++) {
+    const LIROperandInfo::TypeStrings& type_strings =
+      operand_info.GetOperandTypeStrings(i);
+
+    if (i != 0) {
+      C.Indent() << "   ";
+    }
+
+    C.Out() << "." << type_strings.set_method_ << "(" << i << ", "
+                                               << type_strings.var_string_ << i
+                                               << ")";
+    if (i == (operand_info.num_operands_ - 1)) {
+      // Append ";" if not the last one
+      C.Out() << ";";
+    }
+    C.Out() << std::endl;
+  }
+
+  C.Indent() << "return;" << std::endl;
+
+  return;
+}
+
+int main(int argc, char** argv) {
+  if (argc < 2) {
+    std::cerr << "usage: " << argv[0] << " [target]" << std::endl;
+    return 1;
+  }
+
+  Context C(std::cout);
+
+  C.lowercase_target_string_ = argv[1];
+  for (size_t i = 0, e = C.lowercase_target_string_.length(); i != e; i++) {
+    C.lowercase_target_string_[i] = ::tolower(C.lowercase_target_string_[i]);
+  }
+
+  // Special function to generate TargetLIRBuilder::Set*Operands(...).
+  if (C.lowercase_target_string_ == "gen_set_operands") {
+    GenSetOperands(C);
+    return 0;
+  }
+
+  // Setup the context according to the target supplied
+  if (C.lowercase_target_string_ == "arm") {
+    C.target_lirs_ = ARMLIR;
+    C.num_target_lirs_ = sizeof(ARMLIR) / sizeof(ARMLIR[0]);
+    C.uppercase_target_string_ = "ARM";
+    C.class_name_ = "ARMLIRBuilderBase";
+  } else if (C.lowercase_target_string_ == "mips") {
+    C.target_lirs_ = MipsLIR;
+    C.num_target_lirs_ = sizeof(MipsLIR) / sizeof(MipsLIR[0]);
+    C.uppercase_target_string_ = "MIPS";
+    C.class_name_ = "MipsLIRBuilderBase";
+  } else if (C.lowercase_target_string_ == "x86") {
+    C.target_lirs_ = X86LIR;
+    C.num_target_lirs_ = sizeof(X86LIR) / sizeof(X86LIR[0]);
+    C.uppercase_target_string_ = "X86";
+    C.class_name_ = "X86LIRBuilderBase";
+  } else {
+    std::cerr << "unknown target `" << argv[1] << "'!" << std::endl;
+    return 1;
+  }
+
+  GenLicenseNote(C);
+  GenTargetLIRBuilderHeader(C);
+  GenTargetLIRBuilderImpl(C);
+
+  return 0;
+}
diff --git a/src/thread.cc b/src/thread.cc
index 13b9fb7..f215783 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -260,6 +260,9 @@
   SetUpAlternateSignalStack();
   InitCpu();
   InitFunctionPointers();
+#ifdef ART_USE_GREENLAND_COMPILER
+  InitRuntimeEntryPoints(&runtime_entry_points_);
+#endif
   InitCardTable();
 
   Runtime* runtime = Runtime::Current();
diff --git a/src/thread.h b/src/thread.h
index e37e17a..6fbf1d2 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -38,6 +38,9 @@
 #include "stack.h"
 #include "trace.h"
 #include "UniquePtr.h"
+#ifdef ART_USE_GREENLAND_COMPILER
+#include "greenland/runtime_entry_points.h"
+#endif
 
 namespace art {
 
@@ -791,6 +794,9 @@
   // Runtime support function pointers
   // TODO: move this near the top, since changing its offset requires all oats to be recompiled!
   EntryPoints entrypoints_;
+#ifdef ART_USE_GREENLAND_COMPILER
+  RuntimeEntryPoints runtime_entry_points_;
+#endif
 
  private:
   // How many times has our pthread key's destructor been called?
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index ce5129d..8695d16 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -32,18 +32,12 @@
 #include "runtime.h"
 #include "stringpiece.h"
 
-#if defined(ART_USE_LLVM_COMPILER)
+#if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER)
 #include "compiler_llvm/backend_types.h"
 #include "compiler_llvm/inferred_reg_category_map.h"
 using namespace art::compiler_llvm;
 #endif
 
-#if defined(ART_USE_GREENLAND_COMPILER)
-#include "greenland/backend_types.h"
-#include "greenland/inferred_reg_category_map.h"
-using namespace art::greenland;
-#endif
-
 namespace art {
 namespace verifier {
 
@@ -3323,8 +3317,7 @@
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
   uint16_t regs_size = code_item_->registers_size_;
 
-  UniquePtr<InferredRegCategoryMap> table(
-    new InferredRegCategoryMap(insns_size, regs_size));
+  UniquePtr<InferredRegCategoryMap> table(new InferredRegCategoryMap(insns_size, regs_size));
 
   for (size_t i = 0; i < insns_size; ++i) {
     if (RegisterLine* line = reg_table_.GetLine(i)) {
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index 51bed6e..385326d 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -39,18 +39,12 @@
 
 struct ReferenceMap2Visitor;
 
-#if defined(ART_USE_LLVM_COMPILER)
+#if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER)
 namespace compiler_llvm {
   class InferredRegCategoryMap;
 }  // namespace compiler_llvm
 #endif
 
-#if defined(ART_USE_GREENLAND_COMPILER)
-namespace greenland {
-  class InferredRegCategoryMap;
-}  // namespace greenland
-#endif
-
 namespace verifier {
 
 class MethodVerifier;
@@ -149,10 +143,8 @@
 
 // The verifier
 class MethodVerifier {
-#if defined(ART_USE_LLVM_COMPILER)
+#if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER)
   typedef compiler_llvm::InferredRegCategoryMap InferredRegCategoryMap;
-#elif defined(ART_USE_GREENLAND_COMPILER)
-  typedef greenland::InferredRegCategoryMap InferredRegCategoryMap;
 #endif
 
  public: