Special-case Object.<init> invoke

Identify direct invokes to Object.<init> and handle them similar
to the old-word OP_INVOKE_OBJECT_INIT_xxx.  Also, added missing
null check for range-style invoke-direct and invoke-interface.

Change-Id: I5789db4e85609b780063c4788fa40d627a6988c4
diff --git a/src/asm_support.h b/src/asm_support.h
index 32c3abe..1ef10b8 100644
--- a/src/asm_support.h
+++ b/src/asm_support.h
@@ -9,13 +9,13 @@
 #define rLR r14
 #define SUSPEND_CHECK_INTERVAL (1000)
 // Offset of field Thread::top_of_managed_stack_ verified in InitCpu
-#define THREAD_TOP_OF_MANAGED_STACK_OFFSET 272
+#define THREAD_TOP_OF_MANAGED_STACK_OFFSET 276
 // Offset of field Thread::top_of_managed_stack_pc_ verified in InitCpu
-#define THREAD_TOP_OF_MANAGED_STACK_PC_OFFSET 276
+#define THREAD_TOP_OF_MANAGED_STACK_PC_OFFSET 280
 
 #elif defined(__i386__)
 // Offset of field Thread::self_ verified in InitCpu
-#define THREAD_SELF_OFFSET 368
+#define THREAD_SELF_OFFSET 372
 #endif
 
 #endif  // ART_SRC_ASM_SUPPORT_H_
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 922e25b..fb665e6 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -817,8 +817,6 @@
     callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
                             rollback, skipThis);
 
-    //TODO: better to move this into CallInsn lists
-    // Load direct & need a "this" null check?
     if (pcrLabel) {
         *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
     }
@@ -920,6 +918,9 @@
                             rollback, skipThis);
 
     callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
+    if (pcrLabel) {
+        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
+    }
     return callState;
 }
 
@@ -947,6 +948,24 @@
     // Explicit register usage
     oatLockCallTemps(cUnit);
 
+    // Is this the special "Ljava/lang/Object;.<init>:()V" case?
+    if (mir->dalvikInsn.opcode == OP_INVOKE_DIRECT) {
+        int idx = mir->dalvikInsn.vB;
+        Method* target = cUnit->method->GetDexCacheResolvedMethods()->Get(idx);
+        if (target) {
+            if (PrettyMethod(target) == "java.lang.Object.<init>()V") {
+                RegLocation rlArg = oatGetSrc(cUnit, mir, 0);
+                loadValueDirectFixed(cUnit, rlArg, r0);
+                loadWordDisp(cUnit, rSELF,
+                         OFFSETOF_MEMBER(Thread, pObjectInit), rLR);
+                genNullCheck(cUnit, oatSSASrc(mir,0), r0, mir);
+                opReg(cUnit, kOpBlx, rLR);
+                oatClobberCalleeSave(cUnit);
+                return;
+            }
+        }
+    }
+
     if (range) {
         callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
                                        nextCallInsn, NULL, false);
diff --git a/src/thread.cc b/src/thread.cc
index 29531f4..cc5ded2 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -61,8 +61,21 @@
 
 // TODO: flesh out and move to appropriate location
 String* ResolveStringFromCode(Method* method, int32_t string_idx) {
-    UNIMPLEMENTED(FATAL) << "Resolve string; handle OOM";
-    return NULL;  // Must return valid string or if exception, doesn't return
+  UNIMPLEMENTED(FATAL) << "Resolve string; handle OOM";
+  return NULL;  // Must return valid string or if exception, doesn't return
+}
+
+// TODO: move to appropriate location
+static void ObjectInitFromCode(Object* o) {
+  Class* c = o->GetClass();
+  if (c->IsFinalizable()) {
+    o->AddFinalizerReference();
+  }
+  /*
+   * 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() {
@@ -129,6 +142,7 @@
   pFindNativeMethod = FindNativeMethod;
   pDecodeJObjectInThread = DecodeJObjectInThread;
   pResolveStringFromCode = ResolveStringFromCode;
+  pObjectInit = ObjectInitFromCode;
   pDebugMe = DebugMe;
 }
 
diff --git a/src/thread.h b/src/thread.h
index e1939c8..c546d08 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -237,6 +237,7 @@
   void* (*pFindNativeMethod)(Thread* thread);
   Object* (*pDecodeJObjectInThread)(Thread* thread, jobject obj);
   String* (*pResolveStringFromCode)(Method*, int32_t);
+  void (*pObjectInit)(Object*);
 
   class StackVisitor {
    public: