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/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);
         }
     }