Portable refactorings.

Separate quick from portable entrypoints.
Move architectural dependencies into arch.

Change-Id: I9adbc0a9782e2959fdc3308215f01e3107632b7c
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
new file mode 100644
index 0000000..c297841
--- /dev/null
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -0,0 +1,407 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+
+#include "class_linker-inl.h"
+#include "dex_file-inl.h"
+#include "gc/accounting/card_table-inl.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/field-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/proxy.h"
+#include "reflection.h"
+#include "scoped_thread_state_change.h"
+#include "ScopedLocalRef.h"
+#include "well_known_classes.h"
+
+namespace art {
+
+// Helper function to allocate array for FILLED_NEW_ARRAY.
+mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* referrer,
+                                          int32_t component_count, Thread* self,
+                                          bool access_check) {
+  if (UNLIKELY(component_count < 0)) {
+    ThrowNegativeArraySizeException(component_count);
+    return NULL;  // Failure
+  }
+  mirror::Class* klass = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
+  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
+    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, referrer);
+    if (klass == NULL) {  // Error
+      DCHECK(self->IsExceptionPending());
+      return NULL;  // Failure
+    }
+  }
+  if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
+    if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
+      ThrowRuntimeException("Bad filled array request for type %s",
+                            PrettyDescriptor(klass).c_str());
+    } else {
+      ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+      DCHECK(throw_location.GetMethod() == referrer);
+      self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;",
+                               "Found type %s; filled-new-array not implemented for anything but \'int\'",
+                               PrettyDescriptor(klass).c_str());
+    }
+    return NULL;  // Failure
+  } else {
+    if (access_check) {
+      mirror::Class* referrer_klass = referrer->GetDeclaringClass();
+      if (UNLIKELY(!referrer_klass->CanAccess(klass))) {
+        ThrowIllegalAccessErrorClass(referrer_klass, klass);
+        return NULL;  // Failure
+      }
+    }
+    DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
+    return mirror::Array::Alloc(self, klass, component_count);
+  }
+}
+
+mirror::Field* FindFieldFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer,
+                                 Thread* self, FindFieldType type, size_t expected_size,
+                                 bool access_check) {
+  bool is_primitive;
+  bool is_set;
+  bool is_static;
+  switch (type) {
+    case InstanceObjectRead:     is_primitive = false; is_set = false; is_static = false; break;
+    case InstanceObjectWrite:    is_primitive = false; is_set = true;  is_static = false; break;
+    case InstancePrimitiveRead:  is_primitive = true;  is_set = false; is_static = false; break;
+    case InstancePrimitiveWrite: is_primitive = true;  is_set = true;  is_static = false; break;
+    case StaticObjectRead:       is_primitive = false; is_set = false; is_static = true;  break;
+    case StaticObjectWrite:      is_primitive = false; is_set = true;  is_static = true;  break;
+    case StaticPrimitiveRead:    is_primitive = true;  is_set = false; is_static = true;  break;
+    case StaticPrimitiveWrite:   // Keep GCC happy by having a default handler, fall-through.
+    default:                     is_primitive = true;  is_set = true;  is_static = true;  break;
+  }
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  mirror::Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
+  if (UNLIKELY(resolved_field == NULL)) {
+    DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
+    return NULL;  // Failure.
+  }
+  mirror::Class* fields_class = resolved_field->GetDeclaringClass();
+  if (access_check) {
+    if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
+      ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
+      return NULL;
+    }
+    mirror::Class* referring_class = referrer->GetDeclaringClass();
+    if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
+                 !referring_class->CanAccessMember(fields_class,
+                                                   resolved_field->GetAccessFlags()))) {
+      // The referring class can't access the resolved field, this may occur as a result of a
+      // protected field being made public by a sub-class. Resort to the dex file to determine
+      // the correct class for the access check.
+      const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
+      fields_class = class_linker->ResolveType(dex_file,
+                                               dex_file.GetFieldId(field_idx).class_idx_,
+                                               referring_class);
+      if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
+        ThrowIllegalAccessErrorClass(referring_class, fields_class);
+        return NULL;  // failure
+      } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
+                                                            resolved_field->GetAccessFlags()))) {
+        ThrowIllegalAccessErrorField(referring_class, resolved_field);
+        return NULL;  // failure
+      }
+    }
+    if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
+      ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
+      return NULL;  // failure
+    } else {
+      FieldHelper fh(resolved_field);
+      if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
+                   fh.FieldSize() != expected_size)) {
+        ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+        DCHECK(throw_location.GetMethod() == referrer);
+        self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
+                                 "Attempted read of %zd-bit %s on field '%s'",
+                                 expected_size * (32 / sizeof(int32_t)),
+                                 is_primitive ? "primitive" : "non-primitive",
+                                 PrettyField(resolved_field, true).c_str());
+        return NULL;  // failure
+      }
+    }
+  }
+  if (!is_static) {
+    // instance fields must be being accessed on an initialized class
+    return resolved_field;
+  } else {
+    // If the class is initialized we're done.
+    if (fields_class->IsInitialized()) {
+      return resolved_field;
+    } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
+      // Otherwise let's ensure the class is initialized before resolving the field.
+      return resolved_field;
+    } else {
+      DCHECK(self->IsExceptionPending());  // Throw exception and unwind
+      return NULL;  // failure
+    }
+  }
+}
+
+// Slow path method resolution
+mirror::AbstractMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
+                                           mirror::AbstractMethod* referrer,
+                                           Thread* self, bool access_check, InvokeType type) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  bool is_direct = type == kStatic || type == kDirect;
+  mirror::AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
+  if (UNLIKELY(resolved_method == NULL)) {
+    DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
+    return NULL;  // Failure.
+  } else if (UNLIKELY(this_object == NULL && type != kStatic)) {
+    // Maintain interpreter-like semantics where NullPointerException is thrown
+    // after potential NoSuchMethodError from class linker.
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    DCHECK(referrer == throw_location.GetMethod());
+    ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type);
+    return NULL;  // Failure.
+  } else {
+    if (!access_check) {
+      if (is_direct) {
+        return resolved_method;
+      } else if (type == kInterface) {
+        mirror::AbstractMethod* interface_method =
+            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+        if (UNLIKELY(interface_method == NULL)) {
+          ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
+                                                                     referrer);
+          return NULL;  // Failure.
+        } else {
+          return interface_method;
+        }
+      } else {
+        mirror::ObjectArray<mirror::AbstractMethod>* vtable;
+        uint16_t vtable_index = resolved_method->GetMethodIndex();
+        if (type == kSuper) {
+          vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
+        } else {
+          vtable = this_object->GetClass()->GetVTable();
+        }
+        // TODO: eliminate bounds check?
+        return vtable->Get(vtable_index);
+      }
+    } else {
+      // Incompatible class change should have been handled in resolve method.
+      if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
+        ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
+                                          referrer);
+        return NULL;  // Failure.
+      }
+      mirror::Class* methods_class = resolved_method->GetDeclaringClass();
+      mirror::Class* referring_class = referrer->GetDeclaringClass();
+      if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
+                   !referring_class->CanAccessMember(methods_class,
+                                                     resolved_method->GetAccessFlags()))) {
+        // The referring class can't access the resolved method, this may occur as a result of a
+        // protected method being made public by implementing an interface that re-declares the
+        // method public. Resort to the dex file to determine the correct class for the access check
+        const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
+        methods_class = class_linker->ResolveType(dex_file,
+                                                  dex_file.GetMethodId(method_idx).class_idx_,
+                                                  referring_class);
+        if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
+          ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
+                                                        referrer, resolved_method, type);
+          return NULL;  // Failure.
+        } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
+                                                              resolved_method->GetAccessFlags()))) {
+          ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
+          return NULL;  // Failure.
+        }
+      }
+      if (is_direct) {
+        return resolved_method;
+      } else if (type == kInterface) {
+        mirror::AbstractMethod* interface_method =
+            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+        if (UNLIKELY(interface_method == NULL)) {
+          ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
+                                                                     referrer);
+          return NULL;  // Failure.
+        } else {
+          return interface_method;
+        }
+      } else {
+        mirror::ObjectArray<mirror::AbstractMethod>* vtable;
+        uint16_t vtable_index = resolved_method->GetMethodIndex();
+        if (type == kSuper) {
+          mirror::Class* super_class = referring_class->GetSuperClass();
+          if (LIKELY(super_class != NULL)) {
+            vtable = referring_class->GetSuperClass()->GetVTable();
+          } else {
+            vtable = NULL;
+          }
+        } else {
+          vtable = this_object->GetClass()->GetVTable();
+        }
+        if (LIKELY(vtable != NULL &&
+                   vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
+          return vtable->GetWithoutChecks(vtable_index);
+        } else {
+          // Behavior to agree with that of the verifier.
+          MethodHelper mh(resolved_method);
+          ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
+                                 mh.GetSignature());
+          return NULL;  // Failure.
+        }
+      }
+    }
+  }
+}
+
+void ThrowStackOverflowError(Thread* self) {
+  CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
+
+  if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
+    // Remove extra entry pushed onto second stack during method tracing.
+    Runtime::Current()->GetInstrumentation()->PopMethodForUnwind(self, false);
+  }
+
+  self->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute.
+  JNIEnvExt* env = self->GetJniEnv();
+  std::string msg("stack size ");
+  msg += PrettySize(self->GetStackSize());
+  // Use low-level JNI routine and pre-baked error class to avoid class linking operations that
+  // would consume more stack.
+  int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError,
+                                    msg.c_str(), NULL);
+  if (rc != JNI_OK) {
+    // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME
+    //       or die in the CHECK below. We may want to throw a pre-baked StackOverflowError
+    //       instead.
+    LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed.";
+    CHECK(self->IsExceptionPending());
+  }
+  self->ResetDefaultStackEnd();  // Return to default stack size.
+}
+
+JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty,
+                                    jobject rcvr_jobj, jobject interface_method_jobj,
+                                    std::vector<jvalue>& args) {
+  DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
+
+  // Build argument array possibly triggering GC.
+  soa.Self()->AssertThreadSuspensionIsAllowable();
+  jobjectArray args_jobj = NULL;
+  const JValue zero;
+  if (args.size() > 0) {
+    args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL);
+    if (args_jobj == NULL) {
+      CHECK(soa.Self()->IsExceptionPending());
+      return zero;
+    }
+    for (size_t i = 0; i < args.size(); ++i) {
+      if (shorty[i + 1] == 'L') {
+        jobject val = args.at(i).l;
+        soa.Env()->SetObjectArrayElement(args_jobj, i, val);
+      } else {
+        JValue jv;
+        jv.SetJ(args.at(i).j);
+        mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
+        if (val == NULL) {
+          CHECK(soa.Self()->IsExceptionPending());
+          return zero;
+        }
+        soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set(i, val);
+      }
+    }
+  }
+
+  // Call InvocationHandler.invoke(Object proxy, Method method, Object[] args).
+  jobject inv_hand = soa.Env()->GetObjectField(rcvr_jobj,
+                                               WellKnownClasses::java_lang_reflect_Proxy_h);
+  jvalue invocation_args[3];
+  invocation_args[0].l = rcvr_jobj;
+  invocation_args[1].l = interface_method_jobj;
+  invocation_args[2].l = args_jobj;
+  jobject result =
+      soa.Env()->CallObjectMethodA(inv_hand,
+                                   WellKnownClasses::java_lang_reflect_InvocationHandler_invoke,
+                                   invocation_args);
+
+  // Unbox result and handle error conditions.
+  if (LIKELY(!soa.Self()->IsExceptionPending())) {
+    if (shorty[0] == 'V' || (shorty[0] == 'L' && result == NULL)) {
+      // Do nothing.
+      return zero;
+    } else {
+      mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
+      mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
+      mirror::AbstractMethod* interface_method =
+          soa.Decode<mirror::AbstractMethod*>(interface_method_jobj);
+      mirror::Class* result_type = MethodHelper(interface_method).GetReturnType();
+      mirror::AbstractMethod* proxy_method;
+      if (interface_method->GetDeclaringClass()->IsInterface()) {
+        proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
+      } else {
+        // Proxy dispatch to a method defined in Object.
+        DCHECK(interface_method->GetDeclaringClass()->IsObjectClass());
+        proxy_method = interface_method;
+      }
+      ThrowLocation throw_location(rcvr, proxy_method, -1);
+      JValue result_unboxed;
+      if (!UnboxPrimitiveForResult(throw_location, result_ref, result_type, result_unboxed)) {
+        DCHECK(soa.Self()->IsExceptionPending());
+        return zero;
+      }
+      return result_unboxed;
+    }
+  } else {
+    // In the case of checked exceptions that aren't declared, the exception must be wrapped by
+    // a UndeclaredThrowableException.
+    mirror::Throwable* exception = soa.Self()->GetException(NULL);
+    if (exception->IsCheckedException()) {
+      mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
+      mirror::SynthesizedProxyClass* proxy_class =
+          down_cast<mirror::SynthesizedProxyClass*>(rcvr->GetClass());
+      mirror::AbstractMethod* interface_method =
+          soa.Decode<mirror::AbstractMethod*>(interface_method_jobj);
+      mirror::AbstractMethod* proxy_method =
+          rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
+      int throws_index = -1;
+      size_t num_virt_methods = proxy_class->NumVirtualMethods();
+      for (size_t i = 0; i < num_virt_methods; i++) {
+        if (proxy_class->GetVirtualMethod(i) == proxy_method) {
+          throws_index = i;
+          break;
+        }
+      }
+      CHECK_NE(throws_index, -1);
+      mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
+      mirror::Class* exception_class = exception->GetClass();
+      bool declares_exception = false;
+      for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
+        mirror::Class* declared_exception = declared_exceptions->Get(i);
+        declares_exception = declared_exception->IsAssignableFrom(exception_class);
+      }
+      if (!declares_exception) {
+        ThrowLocation throw_location(rcvr, proxy_method, -1);
+        soa.Self()->ThrowNewWrappedException(throw_location,
+                                             "Ljava/lang/reflect/UndeclaredThrowableException;",
+                                             NULL);
+      }
+    }
+    return zero;
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
new file mode 100644
index 0000000..3f28b5e
--- /dev/null
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -0,0 +1,412 @@
+/*
+ * 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_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
+#define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
+
+#include "class_linker.h"
+#include "common_throws.h"
+#include "dex_file.h"
+#include "indirect_reference_table.h"
+#include "invoke_type.h"
+#include "jni_internal.h"
+#include "mirror/abstract_method.h"
+#include "mirror/array.h"
+#include "mirror/class-inl.h"
+#include "mirror/throwable.h"
+#include "object_utils.h"
+#include "thread.h"
+
+extern "C" void art_interpreter_invoke_handler();
+extern "C" void art_jni_dlsym_lookup_stub();
+extern "C" void art_portable_abstract_method_error_stub();
+extern "C" void art_portable_proxy_invoke_handler();
+extern "C" void art_quick_abstract_method_error_stub();
+extern "C" void art_quick_deoptimize();
+extern "C" void art_quick_instrumentation_entry_from_code(void*);
+extern "C" void art_quick_instrumentation_exit_from_code();
+extern "C" void art_quick_interpreter_entry(void*);
+extern "C" void art_quick_proxy_invoke_handler();
+extern "C" void art_work_around_app_jni_bugs();
+
+namespace art {
+namespace mirror {
+class Class;
+class Field;
+class Object;
+}
+
+// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
+// cannot be resolved, throw an error. If it can, use it to create an instance.
+// When verification/compiler hasn't been able to verify access, optionally perform an access
+// check.
+static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx, mirror::AbstractMethod* method,
+                                                  Thread* self,
+                                                  bool access_check)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  Runtime* runtime = Runtime::Current();
+  if (UNLIKELY(klass == NULL)) {
+    klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {
+      DCHECK(self->IsExceptionPending());
+      return NULL;  // Failure
+    }
+  }
+  if (access_check) {
+    if (UNLIKELY(!klass->IsInstantiable())) {
+      ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+      self->ThrowNewException(throw_location, "Ljava/lang/InstantiationError;",
+                              PrettyDescriptor(klass).c_str());
+      return NULL;  // Failure
+    }
+    mirror::Class* referrer = method->GetDeclaringClass();
+    if (UNLIKELY(!referrer->CanAccess(klass))) {
+      ThrowIllegalAccessErrorClass(referrer, klass);
+      return NULL;  // Failure
+    }
+  }
+  if (!klass->IsInitialized() &&
+      !runtime->GetClassLinker()->EnsureInitialized(klass, true, true)) {
+    DCHECK(self->IsExceptionPending());
+    return NULL;  // Failure
+  }
+  return klass->AllocObject(self);
+}
+
+// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
+// it cannot be resolved, throw an error. If it can, use it to create an array.
+// When verification/compiler hasn't been able to verify access, optionally perform an access
+// check.
+static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* method,
+                                                int32_t component_count,
+                                                Thread* self, bool access_check)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (UNLIKELY(component_count < 0)) {
+    ThrowNegativeArraySizeException(component_count);
+    return NULL;  // Failure
+  }
+  mirror::Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
+    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {  // Error
+      DCHECK(Thread::Current()->IsExceptionPending());
+      return NULL;  // Failure
+    }
+    CHECK(klass->IsArrayClass()) << PrettyClass(klass);
+  }
+  if (access_check) {
+    mirror::Class* referrer = method->GetDeclaringClass();
+    if (UNLIKELY(!referrer->CanAccess(klass))) {
+      ThrowIllegalAccessErrorClass(referrer, klass);
+      return NULL;  // Failure
+    }
+  }
+  return mirror::Array::Alloc(self, klass, component_count);
+}
+
+extern mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* method,
+                                                 int32_t component_count,
+                                                 Thread* self, bool access_check)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+// Type of find field operation for fast and slow case.
+enum FindFieldType {
+  InstanceObjectRead,
+  InstanceObjectWrite,
+  InstancePrimitiveRead,
+  InstancePrimitiveWrite,
+  StaticObjectRead,
+  StaticObjectWrite,
+  StaticPrimitiveRead,
+  StaticPrimitiveWrite,
+};
+
+// Slow field find that can initialize classes and may throw exceptions.
+extern mirror::Field* FindFieldFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer,
+                                        Thread* self, FindFieldType type, size_t expected_size,
+                                        bool access_check)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+// Fast path field resolution that can't initialize classes or throw exceptions.
+static inline mirror::Field* FindFieldFast(uint32_t field_idx,
+                                           const mirror::AbstractMethod* referrer,
+                                           FindFieldType type, size_t expected_size)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* resolved_field =
+      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
+  if (UNLIKELY(resolved_field == NULL)) {
+    return NULL;
+  }
+  mirror::Class* fields_class = resolved_field->GetDeclaringClass();
+  // Check class is initiliazed or initializing.
+  if (UNLIKELY(!fields_class->IsInitializing())) {
+    return NULL;
+  }
+  // Check for incompatible class change.
+  bool is_primitive;
+  bool is_set;
+  bool is_static;
+  switch (type) {
+    case InstanceObjectRead:     is_primitive = false; is_set = false; is_static = false; break;
+    case InstanceObjectWrite:    is_primitive = false; is_set = true;  is_static = false; break;
+    case InstancePrimitiveRead:  is_primitive = true;  is_set = false; is_static = false; break;
+    case InstancePrimitiveWrite: is_primitive = true;  is_set = true;  is_static = false; break;
+    case StaticObjectRead:       is_primitive = false; is_set = false; is_static = true;  break;
+    case StaticObjectWrite:      is_primitive = false; is_set = true;  is_static = true;  break;
+    case StaticPrimitiveRead:    is_primitive = true;  is_set = false; is_static = true;  break;
+    case StaticPrimitiveWrite:   is_primitive = true;  is_set = true;  is_static = true;  break;
+    default:
+      LOG(FATAL) << "UNREACHABLE";  // Assignment below to avoid GCC warnings.
+      is_primitive = true;
+      is_set = true;
+      is_static = true;
+      break;
+  }
+  if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
+    // Incompatible class change.
+    return NULL;
+  }
+  mirror::Class* referring_class = referrer->GetDeclaringClass();
+  if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
+               !referring_class->CanAccessMember(fields_class,
+                                                 resolved_field->GetAccessFlags()) ||
+               (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
+    // Illegal access.
+    return NULL;
+  }
+  FieldHelper fh(resolved_field);
+  if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
+               fh.FieldSize() != expected_size)) {
+    return NULL;
+  }
+  return resolved_field;
+}
+
+// Fast path method resolution that can't throw exceptions.
+static inline mirror::AbstractMethod* FindMethodFast(uint32_t method_idx,
+                                                     mirror::Object* this_object,
+                                                     const mirror::AbstractMethod* referrer,
+                                                     bool access_check, InvokeType type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  bool is_direct = type == kStatic || type == kDirect;
+  if (UNLIKELY(this_object == NULL && !is_direct)) {
+    return NULL;
+  }
+  mirror::AbstractMethod* resolved_method =
+      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx);
+  if (UNLIKELY(resolved_method == NULL)) {
+    return NULL;
+  }
+  if (access_check) {
+    // Check for incompatible class change errors and access.
+    bool icce = resolved_method->CheckIncompatibleClassChange(type);
+    if (UNLIKELY(icce)) {
+      return NULL;
+    }
+    mirror::Class* methods_class = resolved_method->GetDeclaringClass();
+    mirror::Class* referring_class = referrer->GetDeclaringClass();
+    if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
+                 !referring_class->CanAccessMember(methods_class,
+                                                   resolved_method->GetAccessFlags()))) {
+      // Potential illegal access, may need to refine the method's class.
+      return NULL;
+    }
+  }
+  if (type == kInterface) {  // Most common form of slow path dispatch.
+    return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+  } else if (is_direct) {
+    return resolved_method;
+  } else if (type == kSuper) {
+    return referrer->GetDeclaringClass()->GetSuperClass()->GetVTable()->
+        Get(resolved_method->GetMethodIndex());
+  } else {
+    DCHECK(type == kVirtual);
+    return this_object->GetClass()->GetVTable()->Get(resolved_method->GetMethodIndex());
+  }
+}
+
+extern mirror::AbstractMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
+                                                  mirror::AbstractMethod* referrer,
+                                                  Thread* self, bool access_check, InvokeType type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
+                                                    const mirror::AbstractMethod* referrer,
+                                                    Thread* self, bool can_run_clinit,
+                                                    bool verify_access)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  mirror::Class* klass = class_linker->ResolveType(type_idx, referrer);
+  if (UNLIKELY(klass == NULL)) {
+    CHECK(self->IsExceptionPending());
+    return NULL;  // Failure - Indicate to caller to deliver exception
+  }
+  // Perform access check if necessary.
+  mirror::Class* referring_class = referrer->GetDeclaringClass();
+  if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
+    ThrowIllegalAccessErrorClass(referring_class, klass);
+    return NULL;  // Failure - Indicate to caller to deliver exception
+  }
+  // If we're just implementing const-class, we shouldn't call <clinit>.
+  if (!can_run_clinit) {
+    return klass;
+  }
+  // If we are the <clinit> of this class, just return our storage.
+  //
+  // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
+  // running.
+  if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
+    return klass;
+  }
+  if (!class_linker->EnsureInitialized(klass, true, true)) {
+    CHECK(self->IsExceptionPending());
+    return NULL;  // Failure - Indicate to caller to deliver exception
+  }
+  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
+  return klass;
+}
+
+extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+static inline mirror::String* ResolveStringFromCode(const mirror::AbstractMethod* referrer,
+                                                    uint32_t string_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  return class_linker->ResolveString(string_idx, referrer);
+}
+
+static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+    UNLOCK_FUNCTION(monitor_lock_) {
+  // Save any pending exception over monitor exit call.
+  mirror::Throwable* saved_exception = NULL;
+  ThrowLocation saved_throw_location;
+  if (UNLIKELY(self->IsExceptionPending())) {
+    saved_exception = self->GetException(&saved_throw_location);
+    self->ClearException();
+  }
+  // Decode locked object and unlock, before popping local references.
+  self->DecodeJObject(locked)->MonitorExit(self);
+  if (UNLIKELY(self->IsExceptionPending())) {
+    LOG(FATAL) << "Synchronized JNI code returning with an exception:\n"
+        << saved_exception->Dump()
+        << "\nEncountered second exception during implicit MonitorExit:\n"
+        << self->GetException(NULL)->Dump();
+  }
+  // Restore pending exception.
+  if (saved_exception != NULL) {
+    self->SetException(saved_throw_location, saved_exception);
+  }
+}
+
+static inline void CheckReferenceResult(mirror::Object* o, Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (o == NULL) {
+    return;
+  }
+  mirror::AbstractMethod* m = self->GetCurrentMethod(NULL);
+  if (o == kInvalidIndirectRefObject) {
+    JniAbortF(NULL, "invalid reference returned from %s", PrettyMethod(m).c_str());
+  }
+  // Make sure that the result is an instance of the type this method was expected to return.
+  mirror::Class* return_type = MethodHelper(m).GetReturnType();
+
+  if (!o->InstanceOf(return_type)) {
+    JniAbortF(NULL, "attempt to return an instance of %s from %s",
+              PrettyTypeOf(o).c_str(), PrettyMethod(m).c_str());
+  }
+}
+
+static inline void CheckSuspend(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  for (;;) {
+    if (thread->ReadFlag(kCheckpointRequest)) {
+      thread->RunCheckpointFunction();
+      thread->AtomicClearFlag(kCheckpointRequest);
+    } else if (thread->ReadFlag(kSuspendRequest)) {
+      thread->FullSuspendCheck();
+    } else {
+      break;
+    }
+  }
+}
+
+JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty,
+                                    jobject rcvr_jobj, jobject interface_method_jobj,
+                                    std::vector<jvalue>& args)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+// Entry point for deoptimization.
+static inline uintptr_t GetDeoptimizationEntryPoint() {
+  return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
+}
+
+// Return address of instrumentation stub.
+static inline void* GetInstrumentationEntryPoint() {
+  return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
+}
+
+// The return_pc of instrumentation exit stub.
+static inline uintptr_t GetInstrumentationExitPc() {
+  return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
+}
+
+// Return address of interpreter stub.
+static inline void* GetInterpreterEntryPoint() {
+  return reinterpret_cast<void*>(art_quick_interpreter_entry);
+}
+
+static inline const void* GetPortableResolutionTrampoline(ClassLinker* class_linker) {
+  return class_linker->GetPortableResolutionTrampoline();
+}
+
+static inline const void* GetQuickResolutionTrampoline(ClassLinker* class_linker) {
+  return class_linker->GetQuickResolutionTrampoline();
+}
+
+// Return address of resolution trampoline stub for defined compiler.
+static inline const void* GetResolutionTrampoline(ClassLinker* class_linker) {
+#if defined(ART_USE_PORTABLE_COMPILER)
+  return GetPortableResolutionTrampoline(class_linker);
+#else
+  return GetQuickResolutionTrampoline(class_linker);
+#endif
+}
+
+static inline void* GetPortableAbstractMethodErrorStub() {
+  return reinterpret_cast<void*>(art_portable_abstract_method_error_stub);
+}
+
+static inline void* GetQuickAbstractMethodErrorStub() {
+  return reinterpret_cast<void*>(art_quick_abstract_method_error_stub);
+}
+
+// Return address of abstract method error stub for defined compiler.
+static inline void* GetAbstractMethodErrorStub() {
+#if defined(ART_USE_PORTABLE_COMPILER)
+  return GetPortableAbstractMethodErrorStub();
+#else
+  return GetQuickAbstractMethodErrorStub();
+#endif
+}
+
+static inline void* GetJniDlsymLookupStub() {
+  return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
new file mode 100644
index 0000000..98f7b12
--- /dev/null
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -0,0 +1,46 @@
+/*
+ * 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 "base/logging.h"
+#include "mirror/abstract_method.h"
+#include "scoped_thread_state_change.h"
+#include "thread.h"
+
+namespace art {
+
+// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
+extern "C" void* artFindNativeMethod(Thread* self) {
+  Locks::mutator_lock_->AssertNotHeld(self);  // We come here as Native.
+  DCHECK(Thread::Current() == self);
+  ScopedObjectAccess soa(self);
+
+  mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
+  DCHECK(method != NULL);
+
+  // Lookup symbol address for method, on failure we'll return NULL with an
+  // exception set, otherwise we return the address of the method we found.
+  void* native_code = soa.Vm()->FindCodeForNativeMethod(method);
+  if (native_code == NULL) {
+    DCHECK(self->IsExceptionPending());
+    return NULL;
+  } else {
+    // Register so that future calls don't come here
+    method->RegisterNative(self, native_code);
+    return native_code;
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/math_entrypoints.cc b/runtime/entrypoints/math_entrypoints.cc
new file mode 100644
index 0000000..31d13c8
--- /dev/null
+++ b/runtime/entrypoints/math_entrypoints.cc
@@ -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.
+ */
+
+#include "math_entrypoints.h"
+
+namespace art {
+
+extern "C" double art_l2d(int64_t l) {
+  return static_cast<double>(l);
+}
+
+extern "C" float art_l2f(int64_t l) {
+  return static_cast<float>(l);
+}
+
+/*
+ * Float/double conversion requires clamping to min and max of integer form.  If
+ * target doesn't support this normally, use these.
+ */
+extern "C" int64_t art_d2l(double d) {
+  static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
+  static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
+  if (d >= kMaxLong) {
+    return static_cast<int64_t>(0x7fffffffffffffffULL);
+  } else if (d <= kMinLong) {
+    return static_cast<int64_t>(0x8000000000000000ULL);
+  } else if (d != d)  {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int64_t>(d);
+  }
+}
+
+extern "C" int64_t art_f2l(float f) {
+  static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
+  static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
+  if (f >= kMaxLong) {
+    return static_cast<int64_t>(0x7fffffffffffffffULL);
+  } else if (f <= kMinLong) {
+    return static_cast<int64_t>(0x8000000000000000ULL);
+  } else if (f != f) {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int64_t>(f);
+  }
+}
+
+extern "C" int32_t art_d2i(double d) {
+  static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
+  static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
+  if (d >= kMaxInt) {
+    return static_cast<int32_t>(0x7fffffffUL);
+  } else if (d <= kMinInt) {
+    return static_cast<int32_t>(0x80000000UL);
+  } else if (d != d)  {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int32_t>(d);
+  }
+}
+
+extern "C" int32_t art_f2i(float f) {
+  static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
+  static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
+  if (f >= kMaxInt) {
+    return static_cast<int32_t>(0x7fffffffUL);
+  } else if (f <= kMinInt) {
+    return static_cast<int32_t>(0x80000000UL);
+  } else if (f != f) {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int32_t>(f);
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/math_entrypoints.h b/runtime/entrypoints/math_entrypoints.h
new file mode 100644
index 0000000..717c734
--- /dev/null
+++ b/runtime/entrypoints/math_entrypoints.h
@@ -0,0 +1,29 @@
+/*
+ * 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_RUNTIME_ENTRYPOINTS_MATH_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_MATH_ENTRYPOINTS_H_
+
+#include <stdint.h>
+
+extern "C" double art_l2d(int64_t l);
+extern "C" float art_l2f(int64_t l);
+extern "C" int64_t art_d2l(double d);
+extern "C" int32_t art_d2i(double d);
+extern "C" int64_t art_f2l(float f);
+extern "C" int32_t art_f2i(float f);
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_MATH_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/math_entrypoints_test.cc b/runtime/entrypoints/math_entrypoints_test.cc
new file mode 100644
index 0000000..ca8b931
--- /dev/null
+++ b/runtime/entrypoints/math_entrypoints_test.cc
@@ -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.
+ */
+
+#include "math_entrypoints.h"
+
+#include "common_test.h"
+#include <limits>
+
+namespace art {
+
+class MathEntrypointsTest : public CommonTest {};
+
+TEST_F(MathEntrypointsTest, DoubleToLong) {
+  EXPECT_EQ(std::numeric_limits<int64_t>::max(), art_d2l(1.85e19));
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(), art_d2l(-1.85e19));
+  EXPECT_EQ(0LL, art_d2l(0));
+  EXPECT_EQ(1LL, art_d2l(1.0));
+  EXPECT_EQ(10LL, art_d2l(10.0));
+  EXPECT_EQ(100LL, art_d2l(100.0));
+  EXPECT_EQ(-1LL, art_d2l(-1.0));
+  EXPECT_EQ(-10LL, art_d2l(-10.0));
+  EXPECT_EQ(-100LL, art_d2l(-100.0));
+}
+
+TEST_F(MathEntrypointsTest, FloatToLong) {
+  EXPECT_EQ(std::numeric_limits<int64_t>::max(), art_f2l(1.85e19));
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(), art_f2l(-1.85e19));
+  EXPECT_EQ(0LL, art_f2l(0));
+  EXPECT_EQ(1LL, art_f2l(1.0));
+  EXPECT_EQ(10LL, art_f2l(10.0));
+  EXPECT_EQ(100LL, art_f2l(100.0));
+  EXPECT_EQ(-1LL, art_f2l(-1.0));
+  EXPECT_EQ(-10LL, art_f2l(-10.0));
+  EXPECT_EQ(-100LL, art_f2l(-100.0));
+}
+
+TEST_F(MathEntrypointsTest, DoubleToInt) {
+  EXPECT_EQ(std::numeric_limits<int32_t>::max(), art_d2i(4.3e9));
+  EXPECT_EQ(std::numeric_limits<int32_t>::min(), art_d2i(-4.3e9));
+  EXPECT_EQ(0L, art_d2i(0));
+  EXPECT_EQ(1L, art_d2i(1.0));
+  EXPECT_EQ(10L, art_d2i(10.0));
+  EXPECT_EQ(100L, art_d2i(100.0));
+  EXPECT_EQ(-1L, art_d2i(-1.0));
+  EXPECT_EQ(-10L, art_d2i(-10.0));
+  EXPECT_EQ(-100L, art_d2i(-100.0));
+}
+
+TEST_F(MathEntrypointsTest, FloatToInt) {
+  EXPECT_EQ(std::numeric_limits<int32_t>::max(), art_f2i(4.3e9));
+  EXPECT_EQ(std::numeric_limits<int32_t>::min(), art_f2i(-4.3e9));
+  EXPECT_EQ(0L, art_f2i(0));
+  EXPECT_EQ(1L, art_f2i(1.0));
+  EXPECT_EQ(10L, art_f2i(10.0));
+  EXPECT_EQ(100L, art_f2i(100.0));
+  EXPECT_EQ(-1L, art_f2i(-1.0));
+  EXPECT_EQ(-10L, art_f2i(-10.0));
+  EXPECT_EQ(-100L, art_f2i(-100.0));
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_alloc_entrypoints.cc b/runtime/entrypoints/portable/portable_alloc_entrypoints.cc
new file mode 100644
index 0000000..2869269
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_alloc_entrypoints.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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" mirror::Object* art_portable_alloc_object_from_code(uint32_t type_idx,
+                                                               mirror::AbstractMethod* referrer,
+                                                               Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocObjectFromCode(type_idx, referrer, thread, false);
+}
+
+extern "C" mirror::Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx,
+                                                                                 mirror::AbstractMethod* referrer,
+                                                                                 Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocObjectFromCode(type_idx, referrer, thread, true);
+}
+
+extern "C" mirror::Object* art_portable_alloc_array_from_code(uint32_t type_idx,
+                                                              mirror::AbstractMethod* referrer,
+                                                              uint32_t length,
+                                                              Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocArrayFromCode(type_idx, referrer, length, self, false);
+}
+
+extern "C" mirror::Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx,
+                                                                                mirror::AbstractMethod* referrer,
+                                                                                uint32_t length,
+                                                                                Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocArrayFromCode(type_idx, referrer, length, self, true);
+}
+
+extern "C" mirror::Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx,
+                                                                        mirror::AbstractMethod* referrer,
+                                                                        uint32_t length,
+                                                                        Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
+}
+
+extern "C" mirror::Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
+                                                                                          mirror::AbstractMethod* referrer,
+                                                                                          uint32_t length,
+                                                                                          Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_argument_visitor.h b/runtime/entrypoints/portable/portable_argument_visitor.h
new file mode 100644
index 0000000..f268baf
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_argument_visitor.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013 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_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_
+#define ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_
+
+#include "object_utils.h"
+
+namespace art {
+
+// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
+class PortableArgumentVisitor {
+ public:
+// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
+// Size of Runtime::kRefAndArgs callee save frame.
+// Size of Method* and register parameters in out stack arguments.
+#if defined(__arm__)
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48
+#define PORTABLE_STACK_ARG_SKIP 0
+#elif defined(__mips__)
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
+#define PORTABLE_STACK_ARG_SKIP 16
+#elif defined(__i386__)
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
+#define PORTABLE_STACK_ARG_SKIP 4
+#else
+#error "Unsupported architecture"
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
+#define PORTABLE_STACK_ARG_SKIP 0
+#endif
+
+  PortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
+    caller_mh_(caller_mh),
+    args_in_regs_(ComputeArgsInRegs(caller_mh)),
+    num_params_(caller_mh.NumArgs()),
+    reg_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET),
+    stack_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE
+                + PORTABLE_STACK_ARG_SKIP),
+    cur_args_(reg_args_),
+    cur_arg_index_(0),
+    param_index_(0) {
+  }
+
+  virtual ~PortableArgumentVisitor() {}
+
+  virtual void Visit() = 0;
+
+  bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return caller_mh_.IsParamAReference(param_index_);
+  }
+
+  bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return caller_mh_.IsParamALongOrDouble(param_index_);
+  }
+
+  Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return caller_mh_.GetParamPrimitiveType(param_index_);
+  }
+
+  byte* GetParamAddress() const {
+    return cur_args_ + (cur_arg_index_ * kPointerSize);
+  }
+
+  void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    for (cur_arg_index_ = 0;  cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) {
+#if (defined(__arm__) || defined(__mips__))
+      if (IsParamALongOrDouble() && cur_arg_index_ == 2) {
+        break;
+      }
+#endif
+      Visit();
+      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
+      param_index_++;
+    }
+    cur_args_ = stack_args_;
+    cur_arg_index_ = 0;
+    while (param_index_ < num_params_) {
+#if (defined(__arm__) || defined(__mips__))
+      if (IsParamALongOrDouble() && cur_arg_index_ % 2 != 0) {
+        cur_arg_index_++;
+      }
+#endif
+      Visit();
+      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
+      param_index_++;
+    }
+  }
+
+ private:
+  static size_t ComputeArgsInRegs(MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+#if (defined(__i386__))
+    return 0;
+#else
+    size_t args_in_regs = 0;
+    size_t num_params = mh.NumArgs();
+    for (size_t i = 0; i < num_params; i++) {
+      args_in_regs = args_in_regs + (mh.IsParamALongOrDouble(i) ? 2 : 1);
+      if (args_in_regs > 3) {
+        args_in_regs = 3;
+        break;
+      }
+    }
+    return args_in_regs;
+#endif
+  }
+  MethodHelper& caller_mh_;
+  const size_t args_in_regs_;
+  const size_t num_params_;
+  byte* const reg_args_;
+  byte* const stack_args_;
+  byte* cur_args_;
+  size_t cur_arg_index_;
+  size_t param_index_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_
diff --git a/runtime/entrypoints/portable/portable_cast_entrypoints.cc b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
new file mode 100644
index 0000000..d343c5d
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_cast_entrypoints.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 "common_throws.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" int32_t art_portable_is_assignable_from_code(const mirror::Class* dest_type,
+                                                        const mirror::Class* src_type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(dest_type != NULL);
+  DCHECK(src_type != NULL);
+  return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
+}
+
+extern "C" void art_portable_check_cast_from_code(const mirror::Class* dest_type,
+                                                  const mirror::Class* src_type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
+  DCHECK(src_type->IsClass()) << PrettyClass(src_type);
+  if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
+    ThrowClassCastException(dest_type, src_type);
+  }
+}
+
+extern "C" void art_portable_check_put_array_element_from_code(const mirror::Object* element,
+                                                               const mirror::Object* array)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (element == NULL) {
+    return;
+  }
+  DCHECK(array != NULL);
+  mirror::Class* array_class = array->GetClass();
+  DCHECK(array_class != NULL);
+  mirror::Class* component_type = array_class->GetComponentType();
+  mirror::Class* element_class = element->GetClass();
+  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
+    ThrowArrayStoreException(element_class, array_class);
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc b/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc
new file mode 100644
index 0000000..bdab587
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc
@@ -0,0 +1,53 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "gc/accounting/card_table-inl.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" mirror::Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx,
+                                                                            mirror::AbstractMethod* referrer,
+                                                                            Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
+}
+
+extern "C" mirror::Object* art_portable_initialize_type_from_code(uint32_t type_idx,
+                                                                  mirror::AbstractMethod* referrer,
+                                                                  Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
+}
+
+extern "C" mirror::Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx,
+                                                                                    mirror::AbstractMethod* referrer,
+                                                                                    Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
+  // unpopulated
+  return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
+}
+
+extern "C" mirror::Object* art_portable_resolve_string_from_code(mirror::AbstractMethod* referrer,
+                                                                 uint32_t string_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return ResolveStringFromCode(referrer, string_idx);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_entrypoints.h b/runtime/entrypoints/portable/portable_entrypoints.h
new file mode 100644
index 0000000..a229c76
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_entrypoints.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 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_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_
+
+#include "dex_file-inl.h"
+#include "runtime.h"
+
+namespace art {
+namespace mirror {
+  class AbstractMethod;
+  class Object;
+}  // namespace mirror
+class Thread;
+
+#define PORTABLE_ENTRYPOINT_OFFSET(x) \
+    (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, portable_entrypoints_)) + \
+        static_cast<uintptr_t>(OFFSETOF_MEMBER(PortableEntryPoints, x)))
+
+// Pointers to functions that are called by code generated by compiler's adhering to the portable
+// compiler ABI.
+struct PACKED(4) PortableEntryPoints {
+  // Invocation
+  const void* (*pPortableResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
+                                                       mirror::AbstractMethod**, Thread*);
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/portable/portable_field_entrypoints.cc b/runtime/entrypoints/portable/portable_field_entrypoints.cc
new file mode 100644
index 0000000..aa0f03c
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_field_entrypoints.cc
@@ -0,0 +1,241 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/field-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" int32_t art_portable_set32_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer,
+                                                       int32_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx,
+                               referrer,
+                               StaticPrimitiveWrite,
+                               sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    field->Set32(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx,
+                            referrer,
+                            Thread::Current(),
+                            StaticPrimitiveWrite,
+                            sizeof(uint32_t),
+                            true);
+  if (LIKELY(field != NULL)) {
+    field->Set32(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set64_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer,
+                                                       int64_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    field->Set64(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx,
+                            referrer,
+                            Thread::Current(),
+                            StaticPrimitiveWrite,
+                            sizeof(uint64_t),
+                            true);
+  if (LIKELY(field != NULL)) {
+    field->Set64(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    field->SetObj(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticObjectWrite, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    field->SetObj(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_get32_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get32(field->GetDeclaringClass());
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticPrimitiveRead, sizeof(uint32_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get32(field->GetDeclaringClass());
+  }
+  return 0;
+}
+
+extern "C" int64_t art_portable_get64_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get64(field->GetDeclaringClass());
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticPrimitiveRead, sizeof(uint64_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get64(field->GetDeclaringClass());
+  }
+  return 0;
+}
+
+extern "C" mirror::Object* art_portable_get_obj_static_from_code(uint32_t field_idx,
+                                                                 mirror::AbstractMethod* referrer)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(field->GetDeclaringClass());
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticObjectRead, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(field->GetDeclaringClass());
+  }
+  return 0;
+}
+
+extern "C" int32_t art_portable_set32_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj, uint32_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    field->Set32(obj, new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveWrite, sizeof(uint32_t), true);
+  if (LIKELY(field != NULL)) {
+    field->Set32(obj, new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set64_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj, int64_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    field->Set64(obj, new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveWrite, sizeof(uint64_t), true);
+  if (LIKELY(field != NULL)) {
+    field->Set64(obj, new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx,
+                                                           mirror::AbstractMethod* referrer,
+                                                           mirror::Object* obj,
+                                                           mirror::Object* new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    field->SetObj(obj, new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstanceObjectWrite, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    field->SetObj(obj, new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_get32_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get32(obj);
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveRead, sizeof(uint32_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get32(obj);
+  }
+  return 0;
+}
+
+extern "C" int64_t art_portable_get64_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get64(obj);
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveRead, sizeof(uint64_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get64(obj);
+  }
+  return 0;
+}
+
+extern "C" mirror::Object* art_portable_get_obj_instance_from_code(uint32_t field_idx,
+                                                                   mirror::AbstractMethod* referrer,
+                                                                   mirror::Object* obj)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(obj);
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstanceObjectRead, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(obj);
+  }
+  return 0;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
new file mode 100644
index 0000000..771608b
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.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 "dex_instruction.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" void art_portable_fill_array_data_from_code(mirror::AbstractMethod* method,
+                                                       uint32_t dex_pc,
+                                                       mirror::Array* array,
+                                                       uint32_t payload_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
+  const Instruction::ArrayDataPayload* payload =
+      reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item->insns_ + payload_offset);
+  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
+  if (UNLIKELY(array == NULL)) {
+    ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
+    return;  // Error
+  }
+  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
+  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
+    Thread* self = Thread::Current();
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
+                             array->GetLength(), payload->element_count - 1);
+    return;  // Error
+  }
+  uint32_t size_in_bytes = payload->element_count * payload->element_width;
+  memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
new file mode 100644
index 0000000..5911ba3
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
@@ -0,0 +1,104 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/dex_cache-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+static mirror::AbstractMethod* FindMethodHelper(uint32_t method_idx,
+                                                mirror::Object* this_object,
+                                                mirror::AbstractMethod* caller_method,
+                                                bool access_check,
+                                                InvokeType type,
+                                                Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::AbstractMethod* method = FindMethodFast(method_idx,
+                                                  this_object,
+                                                  caller_method,
+                                                  access_check,
+                                                  type);
+  if (UNLIKELY(method == NULL)) {
+    method = FindMethodFromCode(method_idx, this_object, caller_method,
+                                thread, access_check, type);
+    if (UNLIKELY(method == NULL)) {
+      CHECK(thread->IsExceptionPending());
+      return 0;  // failure
+    }
+  }
+  DCHECK(!thread->IsExceptionPending());
+  const void* code = method->GetEntryPointFromCompiledCode();
+
+  // When we return, the caller will branch to this address, so it had better not be 0!
+  if (UNLIKELY(code == NULL)) {
+      MethodHelper mh(method);
+      LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
+                 << " location: " << mh.GetDexFile().GetLocation();
+  }
+  return method;
+}
+
+extern "C" mirror::Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                       mirror::Object* this_object,
+                                                                                       mirror::AbstractMethod* referrer,
+                                                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                       mirror::Object* this_object,
+                                                                                       mirror::AbstractMethod* referrer,
+                                                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                        mirror::Object* this_object,
+                                                                                        mirror::AbstractMethod* referrer,
+                                                                                        Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                      mirror::Object* this_object,
+                                                                                      mirror::AbstractMethod* referrer,
+                                                                                      Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                          mirror::Object* this_object,
+                                                                                          mirror::AbstractMethod* referrer,
+                                                                                          Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
+                                                                        mirror::Object* this_object,
+                                                                        mirror::AbstractMethod* referrer,
+                                                                        Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_jni_entrypoints.cc b/runtime/entrypoints/portable/portable_jni_entrypoints.cc
new file mode 100644
index 0000000..8df16ae
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_jni_entrypoints.cc
@@ -0,0 +1,98 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+#include "thread-inl.h"
+
+namespace art {
+
+// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
+extern "C" uint32_t art_portable_jni_method_start(Thread* self)
+    UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
+  JNIEnvExt* env = self->GetJniEnv();
+  uint32_t saved_local_ref_cookie = env->local_ref_cookie;
+  env->local_ref_cookie = env->locals.GetSegmentState();
+  self->TransitionFromRunnableToSuspended(kNative);
+  return saved_local_ref_cookie;
+}
+
+extern "C" uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self)
+    UNLOCK_FUNCTION(Locks::mutator_lock_) {
+  self->DecodeJObject(to_lock)->MonitorEnter(self);
+  return art_portable_jni_method_start(self);
+}
+
+static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
+  JNIEnvExt* env = self->GetJniEnv();
+  env->locals.SetSegmentState(env->local_ref_cookie);
+  env->local_ref_cookie = saved_local_ref_cookie;
+}
+
+extern "C" void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  PopLocalReferences(saved_local_ref_cookie, self);
+}
+
+
+extern "C" void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie,
+                                              jobject locked,
+                                              Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
+  PopLocalReferences(saved_local_ref_cookie, self);
+}
+
+extern "C" mirror::Object* art_portable_jni_method_end_with_reference(jobject result,
+                                                                      uint32_t saved_local_ref_cookie,
+                                                                      Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  mirror::Object* o = self->DecodeJObject(result);  // Must decode before pop.
+  PopLocalReferences(saved_local_ref_cookie, self);
+  // Process result.
+  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
+    if (self->IsExceptionPending()) {
+      return NULL;
+    }
+    CheckReferenceResult(o, self);
+  }
+  return o;
+}
+
+extern "C" mirror::Object* art_portable_jni_method_end_with_reference_synchronized(jobject result,
+                                                                                   uint32_t saved_local_ref_cookie,
+                                                                                   jobject locked,
+                                                                                   Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
+  mirror::Object* o = self->DecodeJObject(result);
+  PopLocalReferences(saved_local_ref_cookie, self);
+  // Process result.
+  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
+    if (self->IsExceptionPending()) {
+      return NULL;
+    }
+    CheckReferenceResult(o, self);
+  }
+  return o;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_lock_entrypoints.cc b/runtime/entrypoints/portable/portable_lock_entrypoints.cc
new file mode 100644
index 0000000..44d3da9
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_lock_entrypoints.cc
@@ -0,0 +1,38 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" void art_portable_lock_object_from_code(mirror::Object* obj, Thread* thread)
+    EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
+  DCHECK(obj != NULL);        // Assumed to have been checked before entry.
+  obj->MonitorEnter(thread);  // May block.
+  DCHECK(thread->HoldsLock(obj));
+  // Only possible exception is NPE and is handled before entry.
+  DCHECK(!thread->IsExceptionPending());
+}
+
+extern "C" void art_portable_unlock_object_from_code(mirror::Object* obj, Thread* thread)
+    UNLOCK_FUNCTION(monitor_lock_) {
+  DCHECK(obj != NULL);  // Assumed to have been checked before entry.
+  // MonitorExit may throw exception.
+  obj->MonitorExit(thread);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_proxy_entrypoints.cc b/runtime/entrypoints/portable/portable_proxy_entrypoints.cc
new file mode 100644
index 0000000..3db39cd
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_proxy_entrypoints.cc
@@ -0,0 +1,109 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+#include "portable_argument_visitor.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+
+// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
+// to jobjects.
+class BuildPortableArgumentVisitor : public PortableArgumentVisitor {
+ public:
+  BuildPortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
+                               ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
+    PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
+
+  virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    jvalue val;
+    Primitive::Type type = GetParamPrimitiveType();
+    switch (type) {
+      case Primitive::kPrimNot: {
+        mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
+        val.l = soa_.AddLocalReference<jobject>(obj);
+        break;
+      }
+      case Primitive::kPrimLong:  // Fall-through.
+      case Primitive::kPrimDouble:
+        val.j = *reinterpret_cast<jlong*>(GetParamAddress());
+        break;
+      case Primitive::kPrimBoolean:  // Fall-through.
+      case Primitive::kPrimByte:     // Fall-through.
+      case Primitive::kPrimChar:     // Fall-through.
+      case Primitive::kPrimShort:    // Fall-through.
+      case Primitive::kPrimInt:      // Fall-through.
+      case Primitive::kPrimFloat:
+        val.i =  *reinterpret_cast<jint*>(GetParamAddress());
+        break;
+      case Primitive::kPrimVoid:
+        LOG(FATAL) << "UNREACHABLE";
+        val.j = 0;
+        break;
+    }
+    args_.push_back(val);
+  }
+
+ private:
+  ScopedObjectAccessUnchecked& soa_;
+  std::vector<jvalue>& args_;
+
+  DISALLOW_COPY_AND_ASSIGN(BuildPortableArgumentVisitor);
+};
+
+// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
+// which is responsible for recording callee save registers. We explicitly place into jobjects the
+// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
+// field within the proxy object, which will box the primitive arguments and deal with error cases.
+extern "C" uint64_t artPortableProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
+                                                  mirror::Object* receiver,
+                                                  Thread* self, mirror::AbstractMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
+  const char* old_cause =
+      self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
+  self->VerifyStack();
+  // Start new JNI local reference state.
+  JNIEnvExt* env = self->GetJniEnv();
+  ScopedObjectAccessUnchecked soa(env);
+  ScopedJniEnvLocalRefState env_state(env);
+  // Create local ref. copies of proxy method and the receiver.
+  jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
+
+  // Placing arguments into args vector and remove the receiver.
+  MethodHelper proxy_mh(proxy_method);
+  std::vector<jvalue> args;
+  BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
+  local_ref_visitor.VisitArguments();
+  args.erase(args.begin());
+
+  // Convert proxy method into expected interface method.
+  mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
+  DCHECK(interface_method != NULL);
+  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
+  jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
+
+  // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
+  // that performs allocations.
+  self->EndAssertNoThreadSuspension(old_cause);
+  JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
+                                               rcvr_jobj, interface_method_jobj, args);
+  return result.GetJ();
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_stub_entrypoints.cc b/runtime/entrypoints/portable/portable_stub_entrypoints.cc
new file mode 100644
index 0000000..c510c65
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_stub_entrypoints.cc
@@ -0,0 +1,145 @@
+/*
+ * 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 "dex_instruction-inl.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+// Lazily resolve a method for portable. Called by stub code.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+                                                       mirror::Object* receiver,
+                                                       mirror::AbstractMethod** called_addr,
+                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t dex_pc;
+  mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
+
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  InvokeType invoke_type;
+  bool is_range;
+  if (called->IsRuntimeMethod()) {
+    const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
+    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+    Instruction::Code instr_code = instr->Opcode();
+    switch (instr_code) {
+      case Instruction::INVOKE_DIRECT:
+        invoke_type = kDirect;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_DIRECT_RANGE:
+        invoke_type = kDirect;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_STATIC:
+        invoke_type = kStatic;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_STATIC_RANGE:
+        invoke_type = kStatic;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_SUPER:
+        invoke_type = kSuper;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_SUPER_RANGE:
+        invoke_type = kSuper;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_VIRTUAL:
+        invoke_type = kVirtual;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_VIRTUAL_RANGE:
+        invoke_type = kVirtual;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_INTERFACE:
+        invoke_type = kInterface;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_INTERFACE_RANGE:
+        invoke_type = kInterface;
+        is_range = true;
+        break;
+      default:
+        LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
+        // Avoid used uninitialized warnings.
+        invoke_type = kDirect;
+        is_range = true;
+    }
+    uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
+    called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
+    // Refine called method based on receiver.
+    if (invoke_type == kVirtual) {
+      called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
+    } else if (invoke_type == kInterface) {
+      called = receiver->GetClass()->FindVirtualMethodForInterface(called);
+    }
+  } else {
+    CHECK(called->IsStatic()) << PrettyMethod(called);
+    invoke_type = kStatic;
+  }
+  const void* code = NULL;
+  if (LIKELY(!thread->IsExceptionPending())) {
+    // Incompatible class change should have been handled in resolve method.
+    CHECK(!called->CheckIncompatibleClassChange(invoke_type));
+    // Ensure that the called method's class is initialized.
+    mirror::Class* called_class = called->GetDeclaringClass();
+    linker->EnsureInitialized(called_class, true, true);
+    if (LIKELY(called_class->IsInitialized())) {
+      code = called->GetEntryPointFromCompiledCode();
+      // TODO: remove this after we solve the link issue.
+      {  // for lazy link.
+        if (code == NULL) {
+          code = linker->GetOatCodeFor(called);
+        }
+      }
+    } else if (called_class->IsInitializing()) {
+      if (invoke_type == kStatic) {
+        // Class is still initializing, go to oat and grab code (trampoline must be left in place
+        // until class is initialized to stop races between threads).
+        code = linker->GetOatCodeFor(called);
+      } else {
+        // No trampoline for non-static methods.
+        code = called->GetEntryPointFromCompiledCode();
+        // TODO: remove this after we solve the link issue.
+        {  // for lazy link.
+          if (code == NULL) {
+            code = linker->GetOatCodeFor(called);
+          }
+        }
+      }
+    } else {
+      DCHECK(called_class->IsErroneous());
+    }
+  }
+  if (LIKELY(code != NULL)) {
+    // Expect class to at least be initializing.
+    DCHECK(called->GetDeclaringClass()->IsInitializing());
+    // Don't want infinite recursion.
+    DCHECK(code != GetResolutionTrampoline(linker));
+    // Set up entry into main method
+    *called_addr = called;
+  }
+  return code;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_thread_entrypoints.cc b/runtime/entrypoints/portable/portable_thread_entrypoints.cc
new file mode 100644
index 0000000..dac7388
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_thread_entrypoints.cc
@@ -0,0 +1,99 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method.h"
+#include "mirror/object-inl.h"
+#include "verifier/dex_gc_map.h"
+#include "stack.h"
+
+namespace art {
+
+class ShadowFrameCopyVisitor : public StackVisitor {
+ public:
+  explicit ShadowFrameCopyVisitor(Thread* self) : StackVisitor(self, NULL), prev_frame_(NULL),
+      top_frame_(NULL) {}
+
+  bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    if (IsShadowFrame()) {
+      ShadowFrame* cur_frame = GetCurrentShadowFrame();
+      size_t num_regs = cur_frame->NumberOfVRegs();
+      mirror::AbstractMethod* method = cur_frame->GetMethod();
+      uint32_t dex_pc = cur_frame->GetDexPC();
+      ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc);
+
+      const uint8_t* gc_map = method->GetNativeGcMap();
+      uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
+                                                     (gc_map[1] << 16) |
+                                                     (gc_map[2] << 8) |
+                                                     (gc_map[3] << 0));
+      verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
+      const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
+      for (size_t reg = 0; reg < num_regs; ++reg) {
+        if (TestBitmap(reg, reg_bitmap)) {
+          new_frame->SetVRegReference(reg, cur_frame->GetVRegReference(reg));
+        } else {
+          new_frame->SetVReg(reg, cur_frame->GetVReg(reg));
+        }
+      }
+
+      if (prev_frame_ != NULL) {
+        prev_frame_->SetLink(new_frame);
+      } else {
+        top_frame_ = new_frame;
+      }
+      prev_frame_ = new_frame;
+    }
+    return true;
+  }
+
+  ShadowFrame* GetShadowFrameCopy() {
+    return top_frame_;
+  }
+
+ private:
+  static bool TestBitmap(int reg, const uint8_t* reg_vector) {
+    return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
+  }
+
+  ShadowFrame* prev_frame_;
+  ShadowFrame* top_frame_;
+};
+
+extern "C" void art_portable_test_suspend_from_code(Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  CheckSuspend(self);
+  if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
+    // Save out the shadow frame to the heap
+    ShadowFrameCopyVisitor visitor(self);
+    visitor.WalkStack(true);
+    self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
+    self->SetDeoptimizationReturnValue(JValue());
+    self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1));
+  }
+}
+
+extern "C" ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
+                                                                 ShadowFrame* new_shadow_frame,
+                                                                 mirror::AbstractMethod* method,
+                                                                 uint32_t num_vregs) {
+  ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
+  new_shadow_frame->SetMethod(method);
+  new_shadow_frame->SetNumberOfVRegs(num_vregs);
+  return old_frame;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
new file mode 100644
index 0000000..4b2b46b
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
@@ -0,0 +1,123 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowArithmeticExceptionDivideByZero();
+}
+
+extern "C" void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowArrayIndexOutOfBoundsException(index, length);
+}
+
+extern "C" void art_portable_throw_no_such_method_from_code(int32_t method_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowNoSuchMethodError(method_idx);
+}
+
+extern "C" void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // TODO: remove dex_pc argument from caller.
+  UNUSED(dex_pc);
+  Thread* self = Thread::Current();
+  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+  ThrowNullPointerExceptionFromDexPC(throw_location);
+}
+
+extern "C" void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowStackOverflowError(Thread::Current());
+}
+
+extern "C" void art_portable_throw_exception_from_code(mirror::Throwable* exception)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Thread* self = Thread::Current();
+  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+  if (exception == NULL) {
+    ThrowNullPointerException(NULL, "throw with null exception");
+  } else {
+    self->SetException(throw_location, exception);
+  }
+}
+
+extern "C" void* art_portable_get_and_clear_exception(Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(self->IsExceptionPending());
+  // TODO: make this inline.
+  mirror::Throwable* exception = self->GetException(NULL);
+  self->ClearException();
+  return exception;
+}
+
+extern "C" int32_t art_portable_find_catch_block_from_code(mirror::AbstractMethod* current_method,
+                                                           uint32_t ti_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Thread* self = Thread::Current();  // TODO: make an argument.
+  ThrowLocation throw_location;
+  mirror::Throwable* exception = self->GetException(&throw_location);
+  // Check for special deoptimization exception.
+  if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
+    return -1;
+  }
+  mirror::Class* exception_type = exception->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;
+  int result = -1;
+  uint32_t catch_dex_pc = -1;
+  // 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) {
+      catch_dex_pc = it.GetHandlerAddress();
+      result = iter_index;
+      break;
+    }
+    // Does this catch exception type apply?
+    mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
+    if (UNLIKELY(iter_exception_type == NULL)) {
+      // TODO: check, the verifier (class linker?) 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)) {
+      catch_dex_pc = it.GetHandlerAddress();
+      result = iter_index;
+      break;
+    }
+    ++iter_index;
+  }
+  if (result != -1) {
+    // Handler found.
+    Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self,
+                                                                   throw_location,
+                                                                   current_method,
+                                                                   catch_dex_pc,
+                                                                   exception);
+  }
+  return result;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index f66fc84..9ed802a 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -15,11 +15,11 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_argument_visitor.h b/runtime/entrypoints/quick/quick_argument_visitor.h
index 4f81151..35fa972 100644
--- a/runtime/entrypoints/quick/quick_argument_visitor.h
+++ b/runtime/entrypoints/quick/quick_argument_visitor.h
@@ -22,116 +22,6 @@
 namespace art {
 
 // Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
-class PortableArgumentVisitor {
- public:
-// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
-// Size of Runtime::kRefAndArgs callee save frame.
-// Size of Method* and register parameters in out stack arguments.
-#if defined(__arm__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48
-#define PORTABLE_STACK_ARG_SKIP 0
-#elif defined(__mips__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
-#define PORTABLE_STACK_ARG_SKIP 16
-#elif defined(__i386__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
-#define PORTABLE_STACK_ARG_SKIP 4
-#else
-#error "Unsupported architecture"
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
-#define PORTABLE_STACK_ARG_SKIP 0
-#endif
-
-  PortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
-    caller_mh_(caller_mh),
-    args_in_regs_(ComputeArgsInRegs(caller_mh)),
-    num_params_(caller_mh.NumArgs()),
-    reg_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET),
-    stack_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE
-                + PORTABLE_STACK_ARG_SKIP),
-    cur_args_(reg_args_),
-    cur_arg_index_(0),
-    param_index_(0) {
-  }
-
-  virtual ~PortableArgumentVisitor() {}
-
-  virtual void Visit() = 0;
-
-  bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return caller_mh_.IsParamAReference(param_index_);
-  }
-
-  bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return caller_mh_.IsParamALongOrDouble(param_index_);
-  }
-
-  Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return caller_mh_.GetParamPrimitiveType(param_index_);
-  }
-
-  byte* GetParamAddress() const {
-    return cur_args_ + (cur_arg_index_ * kPointerSize);
-  }
-
-  void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (cur_arg_index_ = 0;  cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) {
-#if (defined(__arm__) || defined(__mips__))
-      if (IsParamALongOrDouble() && cur_arg_index_ == 2) {
-        break;
-      }
-#endif
-      Visit();
-      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
-      param_index_++;
-    }
-    cur_args_ = stack_args_;
-    cur_arg_index_ = 0;
-    while (param_index_ < num_params_) {
-#if (defined(__arm__) || defined(__mips__))
-      if (IsParamALongOrDouble() && cur_arg_index_ % 2 != 0) {
-        cur_arg_index_++;
-      }
-#endif
-      Visit();
-      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
-      param_index_++;
-    }
-  }
-
- private:
-  static size_t ComputeArgsInRegs(MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-#if (defined(__i386__))
-    return 0;
-#else
-    size_t args_in_regs = 0;
-    size_t num_params = mh.NumArgs();
-    for (size_t i = 0; i < num_params; i++) {
-      args_in_regs = args_in_regs + (mh.IsParamALongOrDouble(i) ? 2 : 1);
-      if (args_in_regs > 3) {
-        args_in_regs = 3;
-        break;
-      }
-    }
-    return args_in_regs;
-#endif
-  }
-  MethodHelper& caller_mh_;
-  const size_t args_in_regs_;
-  const size_t num_params_;
-  byte* const reg_args_;
-  byte* const stack_args_;
-  byte* cur_args_;
-  size_t cur_arg_index_;
-  size_t param_index_;
-};
-
-// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
 class QuickArgumentVisitor {
  public:
 // Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
diff --git a/runtime/entrypoints/quick/quick_cast_entrypoints.cc b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
index fe91e61..b810bb7 100644
--- a/runtime/entrypoints/quick/quick_cast_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
@@ -15,10 +15,10 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 0af7a62..6400161b 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -15,13 +15,13 @@
  */
 
 #include "callee_save_frame.h"
-#include "gc/accounting/card_table-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
+#include "gc/accounting/card_table-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index 8692e92..74b8cfd 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -20,15 +20,15 @@
 #include "dex_file-inl.h"
 #include "runtime.h"
 
-#define ENTRYPOINT_OFFSET(x) \
-    (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, entrypoints_)) + \
+#define QUICK_ENTRYPOINT_OFFSET(x) \
+    (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, quick_entrypoints_)) + \
         static_cast<uintptr_t>(OFFSETOF_MEMBER(QuickEntryPoints, x)))
 
 namespace art {
 namespace mirror {
-class AbstractMethod;
-class Class;
-class Object;
+  class AbstractMethod;
+  class Class;
+  class Object;
 }  // namespace mirror
 class DvmDex;
 class MethodHelper;
@@ -123,8 +123,6 @@
   void* (*pMemcpy)(void*, const void*, size_t);
 
   // Invocation
-  const void* (*pPortableResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
-                                                       mirror::AbstractMethod**, Thread*);
   const void* (*pQuickResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
                                                     mirror::AbstractMethod**, Thread*);
   void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
@@ -167,9 +165,6 @@
                                                              jobject locked, Thread* self)
     SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
 
-// Initialize an entry point data structure, architecture specific.
-void InitEntryPoints(QuickEntryPoints* points);
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index c20326c..a4e9dc9 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -16,10 +16,10 @@
 
 #include "callee_save_frame.h"
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/field-inl.h"
-#include "runtime_support.h"
 
 #include <stdint.h>
 
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index a0b06fb..b81ad12 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -52,7 +52,7 @@
     ThrowLocation throw_location = self->GetCurrentLocationForThrow();
     self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
                              "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                             array->GetLength(), payload->element_count);
+                             array->GetLength(), payload->element_count - 1);
     return -1;  // Error
   }
   uint32_t size_in_bytes = payload->element_count * payload->element_width;
diff --git a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
index 6a95f3c..53b3628 100644
--- a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
@@ -16,12 +16,12 @@
 
 #include "callee_save_frame.h"
 #include "dex_instruction-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 2d31160..23a28f9 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -15,13 +15,13 @@
  */
 
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "object_utils.h"
-#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
 
diff --git a/runtime/entrypoints/quick/quick_proxy_entrypoints.cc b/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
index e4ef45f..4e3d749 100644
--- a/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
@@ -16,12 +16,12 @@
 
 #include "quick_argument_visitor.h"
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
 #include "object_utils.h"
 #include "reflection.h"
-#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
 #include "well_known_classes.h"
@@ -32,50 +32,6 @@
 
 // Visits arguments on the stack placing them into the args vector, Object* arguments are converted
 // to jobjects.
-class BuildPortableArgumentVisitor : public PortableArgumentVisitor {
- public:
-  BuildPortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
-                               ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
-    PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
-
-  virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    jvalue val;
-    Primitive::Type type = GetParamPrimitiveType();
-    switch (type) {
-      case Primitive::kPrimNot: {
-        mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
-        val.l = soa_.AddLocalReference<jobject>(obj);
-        break;
-      }
-      case Primitive::kPrimLong:  // Fall-through.
-      case Primitive::kPrimDouble:
-        val.j = *reinterpret_cast<jlong*>(GetParamAddress());
-        break;
-      case Primitive::kPrimBoolean:  // Fall-through.
-      case Primitive::kPrimByte:     // Fall-through.
-      case Primitive::kPrimChar:     // Fall-through.
-      case Primitive::kPrimShort:    // Fall-through.
-      case Primitive::kPrimInt:      // Fall-through.
-      case Primitive::kPrimFloat:
-        val.i =  *reinterpret_cast<jint*>(GetParamAddress());
-        break;
-      case Primitive::kPrimVoid:
-        LOG(FATAL) << "UNREACHABLE";
-        val.j = 0;
-        break;
-    }
-    args_.push_back(val);
-  }
-
- private:
-  ScopedObjectAccessUnchecked& soa_;
-  std::vector<jvalue>& args_;
-
-  DISALLOW_COPY_AND_ASSIGN(BuildPortableArgumentVisitor);
-};
-
-// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
-// to jobjects.
 class BuildQuickArgumentVisitor : public QuickArgumentVisitor {
  public:
   BuildQuickArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
@@ -126,46 +82,6 @@
 // which is responsible for recording callee save registers. We explicitly place into jobjects the
 // incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
 // field within the proxy object, which will box the primitive arguments and deal with error cases.
-extern "C" uint64_t artPortableProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
-                                                 mirror::Object* receiver,
-                                                Thread* self, mirror::AbstractMethod** sp)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
-  const char* old_cause =
-      self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
-  self->VerifyStack();
-  // Start new JNI local reference state.
-  JNIEnvExt* env = self->GetJniEnv();
-  ScopedObjectAccessUnchecked soa(env);
-  ScopedJniEnvLocalRefState env_state(env);
-  // Create local ref. copies of proxy method and the receiver.
-  jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
-
-  // Placing arguments into args vector and remove the receiver.
-  MethodHelper proxy_mh(proxy_method);
-  std::vector<jvalue> args;
-  BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
-  local_ref_visitor.VisitArguments();
-  args.erase(args.begin());
-
-  // Convert proxy method into expected interface method.
-  mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
-  DCHECK(interface_method != NULL);
-  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
-  jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
-
-  // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
-  // that performs allocations.
-  self->EndAssertNoThreadSuspension(old_cause);
-  JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
-                                               rcvr_jobj, interface_method_jobj, args);
-  return result.GetJ();
-}
-
-// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
-// which is responsible for recording callee save registers. We explicitly place into jobjects the
-// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
-// field within the proxy object, which will box the primitive arguments and deal with error cases.
 extern "C" uint64_t artQuickProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
                                           mirror::Object* receiver,
                                           Thread* self, mirror::AbstractMethod** sp)
diff --git a/runtime/entrypoints/quick/quick_stub_entrypoints.cc b/runtime/entrypoints/quick/quick_stub_entrypoints.cc
index f2af6d2..d78bbf3 100644
--- a/runtime/entrypoints/quick/quick_stub_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_stub_entrypoints.cc
@@ -30,127 +30,6 @@
 
 namespace art {
 
-// Lazily resolve a method for portable. Called by stub code.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
-                                                       mirror::Object* receiver,
-                                                       mirror::AbstractMethod** called_addr,
-                                                       Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  uint32_t dex_pc;
-  mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
-
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  InvokeType invoke_type;
-  bool is_range;
-  if (called->IsRuntimeMethod()) {
-    const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
-    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-    Instruction::Code instr_code = instr->Opcode();
-    switch (instr_code) {
-      case Instruction::INVOKE_DIRECT:
-        invoke_type = kDirect;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_DIRECT_RANGE:
-        invoke_type = kDirect;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_STATIC:
-        invoke_type = kStatic;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_STATIC_RANGE:
-        invoke_type = kStatic;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_SUPER:
-        invoke_type = kSuper;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_SUPER_RANGE:
-        invoke_type = kSuper;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_VIRTUAL:
-        invoke_type = kVirtual;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_VIRTUAL_RANGE:
-        invoke_type = kVirtual;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_INTERFACE:
-        invoke_type = kInterface;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_INTERFACE_RANGE:
-        invoke_type = kInterface;
-        is_range = true;
-        break;
-      default:
-        LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
-        // Avoid used uninitialized warnings.
-        invoke_type = kDirect;
-        is_range = true;
-    }
-    uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
-    called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
-    // Refine called method based on receiver.
-    if (invoke_type == kVirtual) {
-      called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
-    } else if (invoke_type == kInterface) {
-      called = receiver->GetClass()->FindVirtualMethodForInterface(called);
-    }
-  } else {
-    CHECK(called->IsStatic()) << PrettyMethod(called);
-    invoke_type = kStatic;
-  }
-  const void* code = NULL;
-  if (LIKELY(!thread->IsExceptionPending())) {
-    // Incompatible class change should have been handled in resolve method.
-    CHECK(!called->CheckIncompatibleClassChange(invoke_type));
-    // Ensure that the called method's class is initialized.
-    mirror::Class* called_class = called->GetDeclaringClass();
-    linker->EnsureInitialized(called_class, true, true);
-    if (LIKELY(called_class->IsInitialized())) {
-      code = called->GetEntryPointFromCompiledCode();
-      // TODO: remove this after we solve the link issue.
-      {  // for lazy link.
-        if (code == NULL) {
-          code = linker->GetOatCodeFor(called);
-        }
-      }
-    } else if (called_class->IsInitializing()) {
-      if (invoke_type == kStatic) {
-        // Class is still initializing, go to oat and grab code (trampoline must be left in place
-        // until class is initialized to stop races between threads).
-        code = linker->GetOatCodeFor(called);
-      } else {
-        // No trampoline for non-static methods.
-        code = called->GetEntryPointFromCompiledCode();
-        // TODO: remove this after we solve the link issue.
-        {  // for lazy link.
-          if (code == NULL) {
-            code = linker->GetOatCodeFor(called);
-          }
-        }
-      }
-    } else {
-      DCHECK(called_class->IsErroneous());
-    }
-  }
-  if (LIKELY(code != NULL)) {
-    // Expect class to at least be initializing.
-    DCHECK(called->GetDeclaringClass()->IsInitializing());
-    // Don't want infinite recursion.
-    DCHECK(code != GetResolutionTrampoline(linker));
-    // Set up entry into main method
-    *called_addr = called;
-  }
-  return code;
-}
-
 // Lazily resolve a method for quick. Called by stub code.
 extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
                                                     mirror::Object* receiver,
@@ -413,26 +292,4 @@
   self->QuickDeliverException();
 }
 
-// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
-extern "C" void* artFindNativeMethod(Thread* self) {
-  Locks::mutator_lock_->AssertNotHeld(self);  // We come here as Native.
-  DCHECK(Thread::Current() == self);
-  ScopedObjectAccess soa(self);
-
-  mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
-  DCHECK(method != NULL);
-
-  // Lookup symbol address for method, on failure we'll return NULL with an
-  // exception set, otherwise we return the address of the method we found.
-  void* native_code = soa.Vm()->FindCodeForNativeMethod(method);
-  if (native_code == NULL) {
-    DCHECK(self->IsExceptionPending());
-    return NULL;
-  } else {
-    // Register so that future calls don't come here
-    method->RegisterNative(self, native_code);
-    return native_code;
-  }
-}
-
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_thread_entrypoints.cc b/runtime/entrypoints/quick/quick_thread_entrypoints.cc
index e711714..b4d6c0b 100644
--- a/runtime/entrypoints/quick/quick_thread_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_thread_entrypoints.cc
@@ -15,7 +15,7 @@
  */
 
 #include "callee_save_frame.h"
-#include "runtime_support.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "thread.h"
 #include "thread_list.h"
 
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 9588698..3bfa2f2 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -15,9 +15,9 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/object.h"
 #include "object_utils.h"
-#include "runtime_support.h"
 #include "thread.h"
 #include "well_known_classes.h"