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/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()) {