Enable virtual invokes, use new alloc, misc

Make use of the new alloc routines.  Extended the filter to allow
simple virtual invoke test to get through.  Fixed a register allocation
problem.

Note that the invoke sequeces are still the verbose & long path.
Will start using the new CodeandDirectMethods mechanism in upcoming CL

Change-Id: I8ff79f6392ff3da14d7679dcf65029ae48f18eba
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 0fb6636..954f685 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -187,7 +187,7 @@
 void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
 {
     FILE* file;
-    std::string name = art::PrettyMethod(cUnit->method, true);
+    std::string name = art::PrettyMethod(cUnit->method);
     char startOffset[80];
     sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
     char* fileName = (char *) oatNew(
@@ -699,16 +699,25 @@
 {
     bool compiling = true;
     if (!method->IsStatic()) {
-        compiling = false;
+        compiling = false;  // assume skip
+        if (PrettyMethod(method).find("virtualCall") != std::string::npos) {
+            compiling = true;
+        }
+        if (PrettyMethod(method).find("IntMath.<init>") != std::string::npos) {
+            compiling = true;
+        }
+        if (PrettyMethod(method).find("java.lang.Object.<init>") != std::string::npos) {
+            compiling = true;
+        }
     } else if ( (method->GetName()->ToModifiedUtf8().find("foo") != std::string::npos) ||
         (method->GetName()->ToModifiedUtf8().find("main") != std::string::npos)) {
         compiling = false;
     }
 
     if (compiling) {
-        LOG(INFO) << "Compiling " << PrettyMethod(method, true);
+        LOG(INFO) << "Compiling " << PrettyMethod(method);
     } else {
-        LOG(INFO) << "not compiling " << PrettyMethod(method, true);
+        LOG(INFO) << "not compiling " << PrettyMethod(method);
         return false;
     }
 
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index c8b7632..a4ab76f 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -49,7 +49,7 @@
 
 static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
 
-static void dumpRegLocTable(RegLocation* table, int count)
+void oatDumpRegLocTable(RegLocation* table, int count)
 {
     for (int i = 0; i < count; i++) {
         char buf[100];
@@ -115,7 +115,7 @@
 
     if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
         LOG(INFO) << "After Promotion";
-        dumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
+        oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
     }
 
     /* Figure out the frame size */
diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc
index 9c010b5..6254b3d 100644
--- a/src/compiler/Utility.cc
+++ b/src/compiler/Utility.cc
@@ -164,7 +164,7 @@
         "Catch Block"
     };
 
-    LOG(INFO) << "Compiling " << art::PrettyMethod(cUnit->method, true);
+    LOG(INFO) << "Compiling " << art::PrettyMethod(cUnit->method);
     LOG(INFO) << cUnit->insns << " insns";
     LOG(INFO) << cUnit->numBlocks << " blocks in total";
     GrowableListIterator iterator;
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index cf606a3..c8c7e34 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -23,6 +23,20 @@
  */
 
 /*
+ * Utiltiy to load the current Method*.  Broken out
+ * to allow easy change between placing the current Method* in a
+ * dedicated register or its home location in the frame.
+ */
+static void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
+{
+#if defined(METHOD_IN_REG)
+    genRegCopy(cUnit, rTgt, rMETHOD);
+#else
+    loadWordDisp(cUnit, rSP, 0, rTgt);
+#endif
+}
+
+/*
  * Perform a "reg cmp imm" operation and jump to the PCR region if condition
  * satisfies.
  */
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index 21ed8aa..d643a90 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -316,7 +316,7 @@
     switch(lir->opcode) {
         case kArmPseudoMethodEntry:
             LOG(INFO) << "-------- method entry " <<
-                art::PrettyMethod(cUnit->method, true);
+                art::PrettyMethod(cUnit->method);
             break;
         case kArmPseudoMethodExit:
             LOG(INFO) << "-------- Method_Exit";
@@ -390,8 +390,7 @@
 {
     const Method *method = cUnit->method;
     LOG(INFO) << "/*";
-    LOG(INFO) << "Dumping LIR insns for " <<
-        art::PrettyMethod(cUnit->method, true);
+    LOG(INFO) << "Dumping LIR insns for " << art::PrettyMethod(cUnit->method);
     LIR* lirInsn;
     ArmLIR* armLIR;
     int insnsSize = cUnit->insnsSize;
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 400fff6..b2217d0 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -248,12 +248,12 @@
             if (base->fpLocation == kLocPhysReg) {
                 if (curr->wide) {
                     /* TUNING: consider alignment during allocation */
-                    if (base->fpLowReg & 1) {
-                        // Pair must start on even reg - don't promote
-                        continue;
-                    }
-                    /* Make sure upper half is also in reg or skip */
-                    if (baseNext->fpLocation != kLocPhysReg) {
+                    if ((base->fpLowReg & 1) ||
+                        (baseNext->fpLocation != kLocPhysReg)) {
+                        /* Half-promoted or bad alignment - demote */
+                        curr->location = kLocDalvikFrame;
+                        curr->lowReg = INVALID_REG;
+                        curr->highReg = INVALID_REG;
                         continue;
                     }
                     curr->highReg = baseNext->fpLowReg;
@@ -268,6 +268,10 @@
                 if (curr->wide) {
                     /* Make sure upper half is also in reg or skip */
                     if (baseNext->location != kLocPhysReg) {
+                        /* Only half promoted; demote to frame */
+                        curr->location = kLocDalvikFrame;
+                        curr->lowReg = INVALID_REG;
+                        curr->highReg = INVALID_REG;
                         continue;
                     }
                     curr->highReg = baseNext->lowReg;
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 4106e1d..c83a2a4 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -21,30 +21,24 @@
 static const RegLocation retLoc = LOC_DALVIK_RETURN_VAL;
 static const RegLocation retLocWide = LOC_DALVIK_RETURN_VAL_WIDE;
 
+/*
+ * Let helper function take care of everything.  Will call
+ * Array::AllocFromCode(type_idx, method, count);
+ * Note: AllocFromCode will handle checks for errNegativeArraySize.
+ */
 static void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                         RegLocation rlSrc)
 {
-    oatFlushAllRegs(cUnit);  /* All temps to home location */
-    UNIMPLEMENTED(WARNING) << "Need to handle unresolved";
-    /*
-     * Need new routine that passes Method*, type index, length.
-     * This is unconditional - always go this way.
-     */
-    Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
-        GetResolvedType(mir->dalvikInsn.vC);
-    if (classPtr == NULL) {
-         LOG(FATAL) << "Unexpected null classPtr";
-    } else {
-         loadValueDirectFixed(cUnit, rlSrc, r1);    /* get Len */
-         loadConstant(cUnit, r0, (int)classPtr);
-    }
-    UNIMPLEMENTED(WARNING) << "Support for throwing errNegativeArraySize";
-    genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocArrayByClass),
-                 rLR);
-    UNIMPLEMENTED(WARNING) << "Need NoThrow wrapper";
-    newLIR1(cUnit, kThumbBlxR, rLR); // (arrayClass, length, allocFlags)
-    storeValue(cUnit, rlDest, retLoc);
+    oatFlushAllRegs(cUnit);    /* Everything to home location */
+    loadWordDisp(cUnit, rSELF,
+                 OFFSETOF_MEMBER(Thread, pAllocFromCode), rLR);
+    loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
+    loadConstant(cUnit, r0, mir->dalvikInsn.vC);  // arg0 <- type_id
+    loadValueDirectFixed(cUnit, rlSrc, r2);       // arg2 <- count
+    opReg(cUnit, kOpBlx, rLR);
+    oatClobberCallRegs(cUnit);
+    RegLocation rlResult = oatGetReturn(cUnit);
+    storeValue(cUnit, rlDest, rlResult);
 }
 
 /*
@@ -57,36 +51,32 @@
 {
     DecodedInstruction* dInsn = &mir->dalvikInsn;
     int elems;
-    int typeIndex;
+    int typeId;
     if (isRange) {
         elems = dInsn->vA;
-        typeIndex = dInsn->vB;
+        typeId = dInsn->vB;
     } else {
         elems = dInsn->vB;
-        typeIndex = dInsn->vC;
+        typeId = dInsn->vC;
     }
-    oatFlushAllRegs(cUnit);  /* All temps to home location */
-    Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
-        GetResolvedType(typeIndex);
-    if (classPtr == NULL) {
-         LOG(FATAL) << "Unexpected null classPtr";
-    } else {
-         loadConstant(cUnit, r0, (int)classPtr);
-         loadConstant(cUnit, r1, elems);
-    }
-    if (elems < 0) {
-        LOG(FATAL) << "Unexpected empty array";
-    }
+    oatFlushAllRegs(cUnit);    /* Everything to home location */
+    // TODO: Alloc variant that checks types (see header comment) */
+    UNIMPLEMENTED(WARNING) << "Need AllocFromCode variant w/ extra checks";
+    loadWordDisp(cUnit, rSELF,
+                 OFFSETOF_MEMBER(Thread, pAllocFromCode), rLR);
+    loadCurrMethodDirect(cUnit, r1);              // arg1 <- Method*
+    loadConstant(cUnit, r0, typeId);              // arg0 <- type_id
+    loadConstant(cUnit, r2, elems);               // arg2 <- count
+    opReg(cUnit, kOpBlx, rLR);
     /*
-     * FIXME: Need a new NoThrow allocator that checks for and handles
-     * the above mentioned bad cases of 'D', 'J' or !('L' | '[' | 'I').
-     * That will keep us from wasting space generating an inline check here.
+     * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the
+     * return region.  Because AllocFromCode placed the new array
+     * in r0, we'll just lock it into place.  When debugger support is
+     * added, it may be necessary to additionally copy all return
+     * values to a home location in thread-local storage
      */
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocArrayByClass),
-                 rLR);
-    newLIR1(cUnit, kThumbBlxR, rLR); // (arrayClass, length, allocFlags)
-    // Reserve ret0 (r0) - we'll use it in place.
     oatLockTemp(cUnit, r0);
+
     // Having a range of 0 is legal
     if (isRange && (dInsn->vA > 0)) {
         /*
@@ -313,7 +303,7 @@
 #if 0
     switch(state) {
         case 0:  // Get the current Method* [sets r0]
-            loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+            loadCurrMethodDirect(cUnit, r0);
             break;
         case 1:  // Get the pResMethods pointer [uses r0, sets r0]
             UNIMPLEMENTED(FATAL) << "Update with new cache";
@@ -342,7 +332,7 @@
 {
     switch(state) {
         case 0:  // Get the current Method* [sets r0]
-            loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+            loadCurrMethodDirect(cUnit, r0);
             break;
         case 1:  // Get the current Method->DeclaringClass() [sets r0]
             loadBaseDisp(cUnit, mir, r0,
@@ -391,7 +381,7 @@
     RegLocation rlArg;
     switch(state) {
         case 0:  // Get the current Method* [set r0]
-            loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+            loadCurrMethodDirect(cUnit, r0);
             // Load "this" [set r1]
             rlArg = oatGetSrc(cUnit, mir, 0);
             loadValueDirectFixed(cUnit, rlArg, r1);
@@ -440,7 +430,7 @@
     RegLocation rlArg;
     switch(state) {
         case 0:  // Get the current Method* [sets r0]
-            loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+            loadCurrMethodDirect(cUnit, r0);
             break;
         case 1:  // Get the current Method->DeclaringClass() [uses/sets r0]
             loadBaseDisp(cUnit, mir, r0,
@@ -530,7 +520,7 @@
             rlArg = oatGetSrc(cUnit, mir, 0);
             loadValueDirectFixed(cUnit, rlArg, r12);
             // Get the current Method* [set arg2]
-            loadBaseDisp(cUnit, mir, rSP, 0, r2, kWord, INVALID_SREG);
+            loadCurrMethodDirect(cUnit, r2);
             // Is "this" null? [use r12]
             genNullCheck(cUnit, oatSSASrc(mir,0), r12,
                            mir->offset, NULL);
@@ -576,7 +566,7 @@
     switch(state) {
         case 0:
             // Get the current Method* [set r0]
-            loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+            loadCurrMethodDirect(cUnit, r0);
             // Load "this" [set r1]
             rlArg = oatGetSrc(cUnit, mir, 0);
             loadValueDirectFixed(cUnit, rlArg, r1);
@@ -1554,7 +1544,8 @@
 
 /* If there are any ins passed in registers that have not been promoted
  * to a callee-save register, flush them to the frame.
- * Note: at this pointCopy any ins that are passed in register to their home location */
+ * Note: at this pointCopy any ins that are passed in register to their
+ * home location */
 static void flushIns(CompilationUnit* cUnit)
 {
     if (cUnit->method->num_ins_ == 0)
@@ -1564,11 +1555,10 @@
     int startLoc = cUnit->method->num_registers_ - cUnit->method->num_ins_;
     for (int i = 0; i < inRegs; i++) {
         RegLocation loc = cUnit->regLocation[startLoc + i];
+        //TUNING: be smarter about flushing ins to frame
+        storeBaseDisp(cUnit, rSP, loc.spOffset, startReg + i, kWord);
         if (loc.location == kLocPhysReg) {
             genRegCopy(cUnit, loc.lowReg, startReg + i);
-        } else {
-            assert(loc.location == kLocDalvikFrame);
-            storeBaseDisp(cUnit, rSP, loc.spOffset, startReg + i, kWord);
         }
     }
 
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 2bdeee6..eb136b8 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -550,29 +550,18 @@
     storeValue(cUnit, rlDest, rlResult);
 }
 
+/*
+ * Let helper function take care of everything.  Will
+ * call Class::NewInstanceFromCode(type_idx, method);
+ */
 static void genNewInstance(CompilationUnit* cUnit, MIR* mir,
                            RegLocation rlDest)
 {
-    Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
-        GetResolvedType(mir->dalvikInsn.vB);
-
-    /*
-     * Need new routine that passes Method*, type index.
-     * Call unconditionally.
-     */
-    if (classPtr == NULL) {
-        /* Shouldn't happen */
-        LOG(FATAL) << "Unexpected null class pointer";
-    }
-
-    // Verifier should have already rejected abstract/interface
-    assert((classPtr->access_flags_ &
-           (art::kAccInterface|art::kAccAbstract)) == 0);
-    oatFlushAllRegs(cUnit);   /* Everything to home location */
+    oatFlushAllRegs(cUnit);    /* Everything to home location */
     loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pArtAllocObjectNoThrow), rLR);
-    loadConstant(cUnit, r0, (int) classPtr);
-    UNIMPLEMENTED(WARNING) << "Need NewWorld dvmAllocObject";
+                 OFFSETOF_MEMBER(Thread, pNewInstanceFromCode), rLR);
+    loadCurrMethodDirect(cUnit, r1);              // arg1 <= Method*
+    loadConstant(cUnit, r0, mir->dalvikInsn.vB);  // arg0 <- type_id
     opReg(cUnit, kOpBlx, rLR);
     oatClobberCallRegs(cUnit);
     RegLocation rlResult = oatGetReturn(cUnit);
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index f6dc5c7..8ab45b5 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -235,12 +235,10 @@
                         19, 20LL, 21LL, 22, 23, 24, 25, 26);
 }
 
-#if 0 // Need bdc's new Alloc(Method*, type_idx, [length])
 TEST_F(CompilerTest, VirtualCall) {
   CompileDex(kIntMathDex, "kIntMathDex");
   AssertStaticIntMethod("IntMath", "staticCall", "(I)I", 6,
                         3);
 }
-#endif
 
 }  // namespace art
diff --git a/src/thread.cc b/src/thread.cc
index 5fdff78..b48f600 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -61,7 +61,8 @@
   pLdivmod = __aeabi_ldivmod;
   pLmul = __aeabi_lmul;
 #endif
-  pArtAllocArrayByClass = Array::Alloc;
+  pAllocFromCode = Array::AllocFromCode;
+  pNewInstanceFromCode = Class::NewInstanceFromCode;
   pMemcpy = memcpy;
   pArtHandleFillArrayDataNoThrow = artHandleFillArrayDataNoThrow;
 #if 0
diff --git a/src/thread.h b/src/thread.h
index 215da71..6e145fd 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -198,13 +198,14 @@
   int (*pIdiv)(int, int);
   long long (*pLmul)(long long, long long);
   long long (*pLdivmod)(long long, long long);
+  Array* (*pAllocFromCode)(uint32_t, Method*, int32_t);
+  Object* (*pNewInstanceFromCode)(uint32_t, Method*);
   bool (*pArtUnlockObject)(struct Thread*, struct Object*);
   bool (*pArtCanPutArrayElementNoThrow)(const struct ClassObject*,
                  const struct ClassObject*);
   int (*pArtInstanceofNonTrivialNoThrow) (const struct ClassObject*,
                 const struct ClassObject*);
   int (*pArtInstanceofNonTrivial) (const struct ClassObject*, const struct ClassObject*);
-  Array* (*pArtAllocArrayByClass)(Class*, int32_t);
   struct Method* (*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t,
                            const struct Method*, struct DvmDex*);
   bool (*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*);
diff --git a/src/utils.h b/src/utils.h
index b5210ec..6bc27a8 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -144,7 +144,7 @@
 
 // Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
 // "a.b.C.m(II)V" (depending on the value of 'with_signature').
-std::string PrettyMethod(const Method* m, bool with_signature);
+std::string PrettyMethod(const Method* m, bool with_signature = true);
 
 // Returns a human-readable form of the name of the *class* of the given object.
 // So given an instance of java.lang.String, the output would