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);
 }
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index cc5c6bc..acfd5e5 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -292,9 +292,8 @@
   CompileVirtualMethod(NULL, "java.lang.StringBuilder", "append", "(C)Ljava/lang/StringBuilder;");
   CompileVirtualMethod(NULL, "java.lang.StringBuilder", "toString", "()Ljava/lang/String;");
 
-  // TODO: we can't compile these yet.
-  //  CompileDirectMethod(NULL, "java.lang.Long", "toString", "(JI)Ljava/lang/String;");
-  //  CompileDirectMethod(NULL, "java.lang.IntegralToString", "longToString", "(JI)Ljava/lang/String;");
+  CompileDirectMethod(NULL, "java.lang.Long", "toString", "(JI)Ljava/lang/String;");
+  CompileDirectMethod(NULL, "java.lang.IntegralToString", "longToString", "(JI)Ljava/lang/String;");
 
   CompileDirectMethod(NULL, "java.lang.System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
   CompileDirectMethod(NULL, "java.lang.System", "log", "(CLjava/lang/String;Ljava/lang/Throwable;)V");
@@ -303,6 +302,8 @@
   CompileDirectMethod(NULL, "java.lang.System", "currentTimeMillis", "()J");
 
   const ClassLoader* class_loader = LoadDex("SystemMethods");
+  AssertStaticIntMethod(class_loader, "SystemMethods", "test0", "()I", 123);
+  AssertStaticIntMethod(class_loader, "SystemMethods", "test1", "()I", 123);
   AssertStaticIntMethod(class_loader, "SystemMethods", "test2", "()I", 123);
 }