Various tidy ups, add LIKELY/UNLIKELY macros.

Make more aggressive use of the dex cache when we have it.

Change-Id: I125a7bac031f7f0cec68194b5380bdfd83c92833
diff --git a/src/class_linker.h b/src/class_linker.h
index a3157cc..7c5acaa 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -21,6 +21,7 @@
 #include <utility>
 #include <vector>
 
+#include "dex_cache.h"
 #include "dex_file.h"
 #include "heap.h"
 #include "macros.h"
@@ -74,11 +75,14 @@
   // result in the DexCache. The referrer is used to identify the
   // target DexCache and ClassLoader to use for resolution.
   String* ResolveString(uint32_t string_idx, const Method* referrer) {
-    Class* declaring_class = referrer->GetDeclaringClass();
-    DexCache* dex_cache = declaring_class->GetDexCache();
-    // TODO: we could check for a dex cache hit here
-    const DexFile& dex_file = FindDexFile(dex_cache);
-    return ResolveString(dex_file, string_idx, dex_cache);
+    String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx);
+    if (UNLIKELY(resolved_string == NULL)) {
+      Class* declaring_class = referrer->GetDeclaringClass();
+      DexCache* dex_cache = declaring_class->GetDexCache();
+      const DexFile& dex_file = FindDexFile(dex_cache);
+      resolved_string = ResolveString(dex_file, string_idx, dex_cache);
+    }
+    return resolved_string;
   }
 
   // Resolve a String with the given index from the DexFile, storing the
@@ -101,21 +105,27 @@
   // result in the DexCache. The referrer is used to identify the
   // target DexCache and ClassLoader to use for resolution.
   Class* ResolveType(uint32_t type_idx, const Method* referrer) {
-    Class* declaring_class = referrer->GetDeclaringClass();
-    DexCache* dex_cache = declaring_class->GetDexCache();
-    // TODO: we could check for a dex cache hit here
-    const ClassLoader* class_loader = declaring_class->GetClassLoader();
-    const DexFile& dex_file = FindDexFile(dex_cache);
-    return ResolveType(dex_file, type_idx, dex_cache, class_loader);
+    Class* resolved_type = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
+    if (UNLIKELY(resolved_type == NULL)) {
+      Class* declaring_class = referrer->GetDeclaringClass();
+      DexCache* dex_cache = declaring_class->GetDexCache();
+      const ClassLoader* class_loader = declaring_class->GetClassLoader();
+      const DexFile& dex_file = FindDexFile(dex_cache);
+      resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
+    }
+    return resolved_type;
   }
 
   Class* ResolveType(uint32_t type_idx, const Field* referrer) {
     Class* declaring_class = referrer->GetDeclaringClass();
     DexCache* dex_cache = declaring_class->GetDexCache();
-    // TODO: we could check for a dex cache hit here
-    const ClassLoader* class_loader = declaring_class->GetClassLoader();
-    const DexFile& dex_file = FindDexFile(dex_cache);
-    return ResolveType(dex_file, type_idx, dex_cache, class_loader);
+    Class* resolved_type = dex_cache->GetResolvedType(type_idx);
+    if (UNLIKELY(resolved_type == NULL)) {
+      const ClassLoader* class_loader = declaring_class->GetClassLoader();
+      const DexFile& dex_file = FindDexFile(dex_cache);
+      resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
+    }
+    return resolved_type;
   }
 
   // Resolve a type with the given ID from the DexFile, storing the
@@ -139,21 +149,27 @@
                         bool is_direct);
 
   Method* ResolveMethod(uint32_t method_idx, const Method* referrer, bool is_direct) {
-    Class* declaring_class = referrer->GetDeclaringClass();
-    DexCache* dex_cache = declaring_class->GetDexCache();
-    // TODO: we could check for a dex cache hit here
-    const ClassLoader* class_loader = declaring_class->GetClassLoader();
-    const DexFile& dex_file = FindDexFile(dex_cache);
-    return ResolveMethod(dex_file, method_idx, dex_cache, class_loader, is_direct);
+    Method* resolved_method = referrer->GetDexCacheResolvedMethods()->Get(method_idx);
+    if (UNLIKELY(resolved_method == NULL)) {
+      Class* declaring_class = referrer->GetDeclaringClass();
+      DexCache* dex_cache = declaring_class->GetDexCache();
+      const ClassLoader* class_loader = declaring_class->GetClassLoader();
+      const DexFile& dex_file = FindDexFile(dex_cache);
+      resolved_method = ResolveMethod(dex_file, method_idx, dex_cache, class_loader, is_direct);
+    }
+    return resolved_method;
   }
 
   Field* ResolveField(uint32_t field_idx, const Method* referrer, bool is_static) {
-    Class* declaring_class = referrer->GetDeclaringClass();
-    DexCache* dex_cache = declaring_class->GetDexCache();
-    // TODO: we could check for a dex cache hit here
-    const ClassLoader* class_loader = declaring_class->GetClassLoader();
-    const DexFile& dex_file = FindDexFile(dex_cache);
-    return ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static);
+    Field* resolved_field = referrer->GetDexCacheResolvedFields()->Get(field_idx);
+    if (UNLIKELY(resolved_field == NULL)) {
+      Class* declaring_class = referrer->GetDeclaringClass();
+      DexCache* dex_cache = declaring_class->GetDexCache();
+      const ClassLoader* class_loader = declaring_class->GetClassLoader();
+      const DexFile& dex_file = FindDexFile(dex_cache);
+      resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static);
+    }
+    return resolved_field;
   }
 
   // Resolve a field with a given ID from the DexFile, storing the
diff --git a/src/logging.h b/src/logging.h
index b6306b2..a0b290d 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -25,12 +25,13 @@
 #include "macros.h"
 
 #define CHECK(x) \
-  if (!(x)) \
+  if (UNLIKELY(!(x))) \
     ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
         << "Check failed: " #x << " "
 
 #define CHECK_OP(LHS, RHS, OP) \
-  for (::art::EagerEvaluator<typeof(LHS), typeof(RHS)> _values(LHS, RHS); !(_values.lhs OP _values.rhs); ) \
+  for (::art::EagerEvaluator<typeof(LHS), typeof(RHS)> _values(LHS, RHS); \
+       UNLIKELY(!(_values.lhs OP _values.rhs)); ) \
     ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
         << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
         << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
@@ -43,7 +44,7 @@
 #define CHECK_GT(x, y) CHECK_OP(x, y, >)
 
 #define CHECK_STROP(s1, s2, sense) \
-  if ((strcmp(s1, s2) == 0) != sense) \
+  if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \
     LOG(FATAL) << "Check failed: " \
                << "\"" << s1 << "\"" \
                << (sense ? " == " : " != ") \
diff --git a/src/macros.h b/src/macros.h
index 9c5124b..f016f9e 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -125,4 +125,7 @@
 
 #define PACKED __attribute__ ((__packed__))
 
+#define LIKELY(x)       __builtin_expect((x),true)
+#define UNLIKELY(x)     __builtin_expect((x),false)
+
 #endif  // ART_SRC_MACROS_H_
diff --git a/src/object.h b/src/object.h
index c8f4375..35e355d 100644
--- a/src/object.h
+++ b/src/object.h
@@ -294,7 +294,7 @@
     Heap::VerifyObject(this);
     const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
     const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
-    if (is_volatile) {
+    if (UNLIKELY(is_volatile)) {
       return android_atomic_acquire_load(word_addr);
     } else {
       return *word_addr;
@@ -307,7 +307,7 @@
     }
     byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
     uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr);
-    if (is_volatile) {
+    if (UNLIKELY(is_volatile)) {
       /*
        * TODO: add an android_atomic_synchronization_store() function and
        * use it in the 32-bit volatile set handlers.  On some platforms we
@@ -325,7 +325,7 @@
     Heap::VerifyObject(this);
     const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
     const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
-    if (is_volatile) {
+    if (UNLIKELY(is_volatile)) {
       uint64_t result = QuasiAtomicRead64(addr);
       ANDROID_MEMBAR_FULL();
       return result;
@@ -338,7 +338,7 @@
     Heap::VerifyObject(this);
     byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
     int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
-    if (is_volatile) {
+    if (UNLIKELY(is_volatile)) {
       ANDROID_MEMBAR_STORE();
       QuasiAtomicSwap64(new_value, addr);
       // Post-store barrier not required due to use of atomic op or mutex.
@@ -1148,7 +1148,7 @@
 
  protected:
   bool IsValidIndex(int32_t index) const {
-    if (index < 0 || index >= length_) {
+    if (UNLIKELY(index < 0 || index >= length_)) {
       return ThrowArrayIndexOutOfBoundsException(index);
     }
     return true;
@@ -1565,14 +1565,6 @@
     }
   }
 
-  // Assignable test for code, won't throw.  Null and equality tests already performed
-  static uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class)
-  {
-    DCHECK(klass != NULL);
-    DCHECK(ref_class != NULL);
-    return klass->IsAssignableFrom(ref_class) ? 1 : 0;
-  }
-
   Class* GetSuperClass() const {
     // Can only get super class for loaded classes (hack for when runtime is
     // initializing)
diff --git a/src/object_test.cc b/src/object_test.cc
index 1c317e6..a180d5e 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -310,10 +310,10 @@
   ASSERT_TRUE(x != NULL);
   ASSERT_TRUE(y != NULL);
 
-  EXPECT_EQ(1U, Class::IsAssignableFromCode(X, x->GetClass()));
-  EXPECT_EQ(0U, Class::IsAssignableFromCode(Y, x->GetClass()));
-  EXPECT_EQ(1U, Class::IsAssignableFromCode(X, y->GetClass()));
-  EXPECT_EQ(1U, Class::IsAssignableFromCode(Y, y->GetClass()));
+  EXPECT_EQ(1U, IsAssignableFromCode(X, x->GetClass()));
+  EXPECT_EQ(0U, IsAssignableFromCode(Y, x->GetClass()));
+  EXPECT_EQ(1U, IsAssignableFromCode(X, y->GetClass()));
+  EXPECT_EQ(1U, IsAssignableFromCode(Y, y->GetClass()));
 
   EXPECT_TRUE(x->InstanceOf(X));
   EXPECT_FALSE(x->InstanceOf(Y));
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 964c646..8608eff 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -16,7 +16,9 @@
 
 #include "runtime_support.h"
 
+#include "dex_cache.h"
 #include "dex_verifier.h"
+#include "macros.h"
 #include "reflection.h"
 #include "ScopedLocalRef.h"
 
@@ -38,6 +40,18 @@
   LOG(INFO) << "Info: " << info;
 }
 
+void ObjectInitFromCode(Object* o) {
+  Class* c = o->GetClass();
+  if (UNLIKELY(c->IsFinalizable())) {
+    Heap::AddFinalizerReference(o);
+  }
+  /*
+   * NOTE: once debugger/profiler support is added, we'll need to check
+   * here and branch to actual compiled object.<init> to handle any
+   * breakpoint/logging activites if either is active.
+   */
+}
+
 // Return value helper for jobject return types
 extern Object* DecodeJObjectInThread(Thread* thread, jobject obj) {
   if (thread->IsExceptionPending()) {
@@ -347,7 +361,7 @@
   } else {
     is_static = type == Runtime::kStaticMethod;
   }
-  // Placing into local references incoming arguments from the caller's register arguments
+  // Place into local references incoming arguments from the caller's register arguments
   size_t cur_arg = 1;   // skip method_idx in R0, first arg is in R1
   if (!is_static) {
     Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
@@ -370,7 +384,7 @@
     }
     cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
   }
-  // Placing into local references incoming arguments from the caller's stack arguments
+  // Place into local references incoming arguments from the caller's stack arguments
   cur_arg += 5;  // skip LR, Method* and spills for R1 to R3
   while (shorty_index < shorty_len) {
     char c = shorty[shorty_index];
@@ -383,12 +397,12 @@
   }
   // Resolve method filling in dex cache
   Method* called = linker->ResolveMethod(method_idx, *caller_sp, true);
-  if (!thread->IsExceptionPending()) {
+  if (LIKELY(!thread->IsExceptionPending())) {
     // We got this far, ensure that the declaring class is initialized
     linker->EnsureInitialized(called->GetDeclaringClass(), true);
   }
   void* code;
-  if (thread->IsExceptionPending()) {
+  if (UNLIKELY(thread->IsExceptionPending())) {
     // Something went wrong, go into deliver exception with the pending exception in r0
     code = reinterpret_cast<void*>(art_deliver_exception_from_code);
     regs[0] =  reinterpret_cast<uintptr_t>(thread->GetException());
@@ -427,15 +441,33 @@
      */
 }
 
+// Fast path field resolution that can't throw exceptions
+static Field* FindFieldFast(uint32_t field_idx, const Method* referrer) {
+  Field* resolved_field = referrer->GetDexCacheResolvedFields()->Get(field_idx);
+  if (UNLIKELY(resolved_field == NULL)) {
+    return NULL;
+  }
+  Class* fields_class = resolved_field->GetDeclaringClass();
+  // Check class is initilaized or initializing
+  if (UNLIKELY(!fields_class->IsInitializing())) {
+    return NULL;
+  }
+  return resolved_field;
+}
+
+// Slow path field resolution and declaring class initialization
 Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Field* f = class_linker->ResolveField(field_idx, referrer, is_static);
-  if (f != NULL) {
-    Class* c = f->GetDeclaringClass();
+  Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
+  if (LIKELY(resolved_field != NULL)) {
+    Class* fields_class = resolved_field->GetDeclaringClass();
     // If the class is already initializing, we must be inside <clinit>, or
     // we'd still be waiting for the lock.
-    if (c->GetStatus() == Class::kStatusInitializing || class_linker->EnsureInitialized(c, true)) {
-      return f;
+    if (fields_class->IsInitializing()) {
+      return resolved_field;
+    }
+    if(Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true)) {
+      return resolved_field;
     }
   }
   DCHECK(Thread::Current()->IsExceptionPending()); // Throw exception and unwind
@@ -444,17 +476,28 @@
 
 extern "C" Field* artFindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer,
                                                Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return FindFieldFromCode(field_idx, referrer, false);
+  Field* resolved_field = FindFieldFast(field_idx, referrer);
+  if (UNLIKELY(resolved_field == NULL)) {
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+    resolved_field = FindFieldFromCode(field_idx, referrer, false);
+  }
+  return resolved_field;
 }
 
 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
                                            Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer);
+  if (LIKELY(field != NULL)) {
+    Class* type = field->GetType();
+    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) {
+      return field->Get32(NULL);
+    }
+  }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  Field* field = FindFieldFromCode(field_idx, referrer, true);
+  field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
     Class* type = field->GetType();
-    if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+    if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted read of 32-bit primitive on field '%s'",
                                PrettyField(field, true).c_str());
@@ -467,8 +510,15 @@
 
 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
                                            Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer);
+  if (LIKELY(field != NULL)) {
+    Class* type = field->GetType();
+    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) {
+      return field->Get64(NULL);
+    }
+  }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  Field* field = FindFieldFromCode(field_idx, referrer, true);
+  field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
     Class* type = field->GetType();
     if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
@@ -484,8 +534,15 @@
 
 extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
                                            Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer);
+  if (LIKELY(field != NULL)) {
+    Class* type = field->GetType();
+    if (LIKELY(!type->IsPrimitive())) {
+      return field->GetObj(NULL);
+    }
+  }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  Field* field = FindFieldFromCode(field_idx, referrer, true);
+  field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
     Class* type = field->GetType();
     if (type->IsPrimitive()) {
@@ -501,8 +558,16 @@
 
 extern "C" int artSet32StaticFromCode(uint32_t field_idx, const Method* referrer,
                                        uint32_t new_value, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer);
+  if (LIKELY(field != NULL)) {
+    Class* type = field->GetType();
+    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) {
+      field->Set32(NULL, new_value);
+      return 0;  // success
+    }
+  }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  Field* field = FindFieldFromCode(field_idx, referrer, true);
+  field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
     Class* type = field->GetType();
     if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
@@ -519,11 +584,19 @@
 
 extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
                                       uint64_t new_value, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  Field* field = FindFieldFromCode(field_idx, referrer, true);
-  if (field != NULL) {
+  Field* field = FindFieldFast(field_idx, referrer);
+  if (LIKELY(field != NULL)) {
     Class* type = field->GetType();
-    if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) {
+      field->Set64(NULL, new_value);
+      return 0;  // success
+    }
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, true);
+  if (LIKELY(field != NULL)) {
+    Class* type = field->GetType();
+    if (UNLIKELY(!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t))) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted write of 64-bit primitive to field '%s'",
                                PrettyField(field, true).c_str());
@@ -537,8 +610,16 @@
 
 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
                                        Object* new_value, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer);
+  if (LIKELY(field != NULL)) {
+    Class* type = field->GetType();
+    if (LIKELY(!type->IsPrimitive())) {
+      field->SetObj(NULL, new_value);
+      return 0;  // success
+    }
+  }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  Field* field = FindFieldFromCode(field_idx, referrer, true);
+  field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
     Class* type = field->GetType();
     if (type->IsPrimitive()) {
@@ -555,11 +636,12 @@
 
 // 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.
-extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method, Thread* self, Method** sp) {
+extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method,
+                                          Thread* self, Method** sp) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
   Runtime* runtime = Runtime::Current();
-  if (klass == NULL) {
+  if (UNLIKELY(klass == NULL)) {
     klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
     if (klass == NULL) {
       DCHECK(self->IsExceptionPending());
@@ -575,19 +657,19 @@
 
 Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
                                      Thread* self) {
-  if (component_count < 0) {
+  if (UNLIKELY(component_count < 0)) {
     self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
     return NULL;  // Failure
   }
   Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
-  if (klass == NULL) {  // Not in dex cache so try to resolve
+  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
     }
   }
-  if (klass->IsPrimitive() && !klass->IsPrimitiveInt()) {
+  if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
     if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
       Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
           "Bad filled array request for type %s",
@@ -599,7 +681,7 @@
     }
     return NULL;  // Failure
   } else {
-    CHECK(klass->IsArrayClass()) << PrettyClass(klass);
+    DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
     return Array::Alloc(klass, component_count);
   }
 }
@@ -616,13 +698,13 @@
 extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
                                         Thread* self, Method** sp) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  if (component_count < 0) {
+  if (UNLIKELY(component_count < 0)) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
                                          component_count);
     return NULL;  // Failure
   }
   Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
-  if (klass == NULL) {  // Not in dex cache so try to resolve
+  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());
@@ -633,14 +715,21 @@
   return Array::Alloc(klass, component_count);
 }
 
+// Assignable test for code, won't throw.  Null and equality tests already performed
+uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class) {
+  DCHECK(klass != NULL);
+  DCHECK(ref_class != NULL);
+  return klass->IsAssignableFrom(ref_class) ? 1 : 0;
+}
+
 // Check whether it is safe to cast one class to the other, throw exception and return -1 on failure
 extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   DCHECK(a->IsClass()) << PrettyClass(a);
   DCHECK(b->IsClass()) << PrettyClass(b);
-  if (b->IsAssignableFrom(a)) {
+  if (LIKELY(b->IsAssignableFrom(a))) {
     return 0;  // Success
   } else {
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
         "%s cannot be cast to %s",
         PrettyDescriptor(a->GetDescriptor()).c_str(),
@@ -653,14 +742,14 @@
 // Returns 0 on success and -1 if an exception is pending.
 extern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class,
                                              Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   DCHECK(array_class != NULL);
   // element can't be NULL as we catch this is screened in runtime_support
   Class* element_class = element->GetClass();
   Class* component_type = array_class->GetComponentType();
-  if (component_type->IsAssignableFrom(element_class)) {
+  if (LIKELY(component_type->IsAssignableFrom(element_class))) {
     return 0;  // Success
   } else {
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
         "Cannot store an object of type %s in to an array of type %s",
         PrettyDescriptor(element_class->GetDescriptor()).c_str(),
@@ -672,7 +761,7 @@
 Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* klass = class_linker->ResolveType(type_idx, referrer);
-  if (klass == NULL) {
+  if (UNLIKELY(klass == NULL)) {
     CHECK(self->IsExceptionPending());
     return NULL;  // Failure - Indicate to caller to deliver exception
   }
@@ -754,14 +843,14 @@
                                               Thread* self, Method** sp) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   DCHECK_EQ(table[0], 0x0300);
-  if (array == NULL) {
+  if (UNLIKELY(array == NULL)) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
         "null array in fill array");
     return -1;  // Error
   }
   DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
   uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
-  if (static_cast<int32_t>(size) > array->GetLength()) {
+  if (UNLIKELY(static_cast<int32_t>(size) > array->GetLength())) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
         "failed array fill. length=%d; index=%d", array->GetLength(), size);
     return -1;  // Error
@@ -774,32 +863,39 @@
 
 // See comments in runtime_support_asm.S
 extern "C" uint64_t artFindInterfaceMethodInCacheFromCode(uint32_t method_idx,
-                                                          Object* this_object ,
+                                                          Object* this_object,
+                                                          Method* caller_method,
                                                           Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
-  if (this_object == NULL) {
-    thread->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-        "null receiver during interface dispatch");
-    return 0;
+  Method* interface_method = caller_method->GetDexCacheResolvedMethods()->Get(method_idx);
+  Method* found_method = NULL;  // The found method
+  if (LIKELY(interface_method != NULL && this_object != NULL)) {
+    found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
   }
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Frame frame = thread->GetTopOfStack();  // Compute calling method
-  frame.Next();
-  Method* caller_method = frame.GetMethod();
-  Method* interface_method = class_linker->ResolveMethod(method_idx, caller_method, false);
-  if (interface_method == NULL) {
-    // Could not resolve interface method. Throw error and unwind
-    CHECK(thread->IsExceptionPending());
-    return 0;
+  if (UNLIKELY(found_method == NULL)) {
+    FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
+    if (this_object == NULL) {
+      thread->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
+          "null receiver during interface dispatch");
+      return 0;
+    }
+    if (interface_method == NULL) {
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      interface_method = class_linker->ResolveMethod(method_idx, caller_method, false);
+      if (interface_method == NULL) {
+        // Could not resolve interface method. Throw error and unwind
+        CHECK(thread->IsExceptionPending());
+        return 0;
+      }
+    }
+    found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
+    if (found_method == NULL) {
+      CHECK(thread->IsExceptionPending());
+      return 0;
+    }
   }
-  Method* method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
-  if (method == NULL) {
-    CHECK(thread->IsExceptionPending());
-    return 0;
-  }
-  const void* code = method->GetCode();
+  const void* code = found_method->GetCode();
 
-  uint32_t method_uint = reinterpret_cast<uint32_t>(method);
+  uint32_t method_uint = reinterpret_cast<uint32_t>(found_method);
   uint64_t code_uint = reinterpret_cast<uint32_t>(code);
   uint64_t result = ((code_uint << 32) | method_uint);
   return result;
@@ -886,7 +982,7 @@
         // long/double split over regs and stack, mask in high half from stack arguments
         // (7 = 2 reg args + LR + Method* + 3 arg reg spill slots)
         uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (7 * kPointerSize));
-        val.j = (val.j & 0xFFFFFFFFull) | (high_half << 32);
+        val.j = (val.j & 0xffffffffULL) | (high_half << 32);
       }
       BoxPrimitive(env, param_type, val);
       if (self->IsExceptionPending()) {
diff --git a/src/runtime_support.h b/src/runtime_support.h
index c1e0b27..de41f47 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -21,6 +21,8 @@
 void* UnresolvedDirectMethodTrampolineFromCode(int32_t, void*, Thread*, Runtime::TrampolineType);
 extern Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self);
 extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
+uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
+void ObjectInitFromCode(Object* o);
 extern void ResolveMethodFromCode(Method* method, uint32_t method_idx);
 extern void LockObjectFromCode(Thread* thread, Object* obj);
 extern int64_t D2L(double d);
diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S
index cc854e9..2076fad 100644
--- a/src/runtime_support_asm.S
+++ b/src/runtime_support_asm.S
@@ -176,9 +176,10 @@
      */
 art_invoke_interface_trampoline:
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  @ save callee saves in case allocation triggers GC
-    mov    r2, r9                                 @ pass Thread::Current
-    mov    r3, sp                                 @ pass SP
-    bl     artFindInterfaceMethodInCacheFromCode  @ (method_idx, this, Thread*, SP)
+    ldr    r2, [sp, #48]                          @ pass caller Method*
+    mov    r3, r9                                 @ pass Thread::Current
+    str    sp, [sp, #0]                           @ pass SP
+    bl     artFindInterfaceMethodInCacheFromCode  @ (method_idx, this, caller, Thread*, SP)
     mov    r12, r1                                @ save r0->code_
     RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
     cmp    r0, #0                                 @ did we find the target?
@@ -392,19 +393,20 @@
     .global art_resolve_string_from_code
     .extern artResolveStringFromCode
     /*
-     * Entry from managed code to resolve a string, this stub will
-     * allocate a String and deliver an exception on error. On
-     * success the String is returned.
+     * Entry from managed code to resolve a string, this stub will allocate a String and deliver an
+     * exception on error. On success the String is returned. R0 holds the referring method,
+     * R1 holds the string index. The fast path check for hit in strings cache has already been
+     * performed.
      */
 art_resolve_string_from_code:
-    SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
-    mov    r2, r9                              @ pass Thread::Current
-    mov    r3, sp                              @ pass SP
-    @ artResolveStringFromCode(Method* referrer, uint32_t type_idx, Thread*, SP)
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
+    mov    r2, r9                     @ pass Thread::Current
+    mov    r3, sp                     @ pass SP
+    @ artResolveStringFromCode(Method* referrer, uint32_t string_idx, Thread*, SP)
     bl     artResolveStringFromCode
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
-    cmp    r0, #0                              @ success if result is non-null
-    bxne   lr                                  @ return on success
+    cmp    r0, #0                     @ success if result is non-null
+    bxne   lr                         @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_alloc_object_from_code
diff --git a/src/thread.cc b/src/thread.cc
index 6473df0..3c19fe4 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -62,19 +62,6 @@
 static Method* gThreadGroup_removeThread = NULL;
 static Method* gUncaughtExceptionHandler_uncaughtException = NULL;
 
-// TODO: move to appropriate location
-static void ObjectInitFromCode(Object* o) {
-  Class* c = o->GetClass();
-  if (c->IsFinalizable()) {
-    Heap::AddFinalizerReference(o);
-  }
-  /*
-   * NOTE: once debugger/profiler support is added, we'll need to check
-   * here and branch to actual compiled object.<init> to handle any
-   * breakpoint/logging activites if either is active.
-   */
-}
-
 void Thread::InitFunctionPointers() {
 #if defined(__arm__)
   pShlLong = art_shl_long;
@@ -137,7 +124,7 @@
   pDeliverException = art_deliver_exception_from_code;
   pFindNativeMethod = FindNativeMethod;
   pInitializeTypeFromCode = InitializeTypeFromCode;
-  pInstanceofNonTrivialFromCode = Class::IsAssignableFromCode;
+  pInstanceofNonTrivialFromCode = IsAssignableFromCode;
   pObjectInit = ObjectInitFromCode;
   pResolveMethodFromCode = ResolveMethodFromCode;
   pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;