Fix bug in invoke-super slow path

Also re-enabled some SystemMethods tests, now that we can compile
them.

Change-Id: Ie91aabd0eb015656d4dc546b4698c967b73c6ba8
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 13e5497..78a9767 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -667,14 +667,13 @@
             // Load curMethod->declaring_class_ [uses r0, sets r0]
             loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(),
                          r0);
-        case 4: // Get method->declaring_class_->super_class [usr r0, set r0]
+            // Null this?
+            genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir->offset, NULL);
+            // Get method->declaring_class_->super_class [usr r0, set r0]
             loadWordDisp(cUnit, r0, Class::SuperClassOffset().Int32Value(), r0);
             break;
-        case 5: // Get ...->super_class_->vtable [u/s r0]
+        case 4: // Get ...->super_class_->vtable [u/s r0]
             loadWordDisp(cUnit, r0, Class::VTableOffset().Int32Value(), r0);
-            // In load shadow fold vtable_ object header size into method_index_
-            opRegImm(cUnit, kOpAdd, rLR,
-                     art::Array::DataOffset().Int32Value() / 4);
             if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
                 // Range check, throw NSM on failure
                 tReg = oatAllocTemp(cUnit);
@@ -683,10 +682,12 @@
                 genBoundsCheck(cUnit, tReg, rLR, mir->offset, NULL);
                 oatFreeTemp(cUnit, tReg);
             }
+            // Adjust vtable_ base past object header
+            opRegImm(cUnit, kOpAdd, r0, art::Array::DataOffset().Int32Value());
             // Get target Method*
-            loadBaseIndexed(cUnit, r0, r0, rLR, 2, kWord);
+            loadBaseIndexed(cUnit, r0, rLR, r0, 2, kWord);
             break;
-        case 6: // Get the target compiled code address [uses r0, sets rLR]
+        case 5: // Get the target compiled code address [uses r0, sets rLR]
             loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
             break;
         default:
@@ -711,8 +712,6 @@
     RegLocation rlArg;
     int registerArgs[3];
 
-skipThis = false;
-
     /* If no arguments, just return */
     if (dInsn->vA == 0)
         return callState;
@@ -751,6 +750,7 @@
     callState = loadArgRegs(cUnit, mir, dInsn, callState, registerArgs,
                             nextCallInsn, rollback);
 
+    //TODO: better to move this into CallInsn lists
     // Load direct & need a "this" null check?
     if (pcrLabel) {
         *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1,
@@ -783,8 +783,6 @@
     int numArgs = dInsn->vA;
     int registerArgs[3];
 
-skipThis = false;
-
     // If we can treat it as non-range (Jumbo ops will use range form)
     if (numArgs <= 5)
         return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
@@ -927,7 +925,7 @@
         Get(dInsn->vB);
     NextCallInsn nextCallInsn;
     bool fastPath = true;
-    if (baseMethod == NULL) {
+    if (FORCE_SLOW || baseMethod == NULL) {
         fastPath = false;
     } else {
         Class* superClass = cUnit->method->GetDeclaringClass()->GetSuperClass();
@@ -958,7 +956,7 @@
                                        nextCallInsn, rollback, true);
     // Finish up any of the call sequence not interleaved in arg loading
     while (callState >= 0) {
-        callState = nextSuperCallInsn(cUnit, mir, dInsn, callState, NULL);
+        callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
     }
     newLIR1(cUnit, kThumbBlxR, rLR);
 }