Run time illegal access checks on static and direct methods

Fixes test 075.

Change-Id: I28b20451dcae8000dc0e2cb9068dfa5166659d43
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index cbf5867..a1793e0 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -469,29 +469,14 @@
     return state + 1;
 }
 
-STATIC int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir,
-                                  bool accessCheck, bool isInterface,
-                                  bool isSuper, int state, uint32_t dexIdx,
-                                  uint32_t methodIdx)
+STATIC int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir, int trampoline,
+                            int state, uint32_t dexIdx, uint32_t methodIdx)
 {
     /*
      * This handles the case in which the base method is not fully
      * resolved at compile time, we bail to a runtime helper.
      */
     if (state == 0) {
-        int trampoline;
-        if (!accessCheck) {
-          DCHECK(isInterface);
-          trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline);
-        } else {
-          if (isInterface) {
-            trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck);
-          } else if (isSuper) {
-            trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck);
-          } else {
-            trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck);
-          }
-        }
         // Load trampoline target
         loadWordDisp(cUnit, rSELF, trampoline, rLR);
         // Load r0 with method index
@@ -501,18 +486,32 @@
     return -1;
 }
 
+STATIC int nextStaticCallInsnSP(CompilationUnit* cUnit, MIR* mir,
+                                int state, uint32_t dexIdx, uint32_t methodIdx)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeStaticTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
+STATIC int nextDirectCallInsnSP(CompilationUnit* cUnit, MIR* mir,
+                                int state, uint32_t dexIdx, uint32_t methodIdx)
+{
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeDirectTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+}
+
 STATIC int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir,
                                int state, uint32_t dexIdx, uint32_t methodIdx)
 {
-  return nextInvokeInsnSP(cUnit, mir, true, false, true, state, dexIdx,
-                          methodIdx);
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
 STATIC int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir,
                            int state, uint32_t dexIdx, uint32_t methodIdx)
 {
-  return nextInvokeInsnSP(cUnit, mir, true, false, false, state, dexIdx,
-                          methodIdx);
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
 /*
@@ -522,7 +521,8 @@
 STATIC int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir,
                                  int state, uint32_t dexIdx, uint32_t unused)
 {
-  return nextInvokeInsnSP(cUnit, mir, false, true, false, state, dexIdx, 0);
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
 STATIC int nextInterfaceCallInsnWithAccessCheck(CompilationUnit* cUnit,
@@ -530,7 +530,8 @@
                                                 uint32_t dexIdx,
                                                 uint32_t unused)
 {
-  return nextInvokeInsnSP(cUnit, mir, true, true, false, state, dexIdx, 0);
+  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck);
+  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
 STATIC int loadArgRegs(CompilationUnit* cUnit, MIR* mir,
@@ -569,9 +570,9 @@
  */
 STATIC int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir,
                                 DecodedInstruction* dInsn, int callState,
-                                ArmLIR** pcrLabel, bool isRange,
-                                NextCallInsn nextCallInsn, uint32_t dexIdx,
-                                uint32_t methodIdx, bool skipThis)
+                                ArmLIR** pcrLabel, NextCallInsn nextCallInsn,
+                                uint32_t dexIdx, uint32_t methodIdx,
+                                bool skipThis)
 {
     RegLocation rlArg;
 
@@ -676,7 +677,7 @@
     // If we can treat it as non-range (Jumbo ops will use range form)
     if (numArgs <= 5)
         return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
-                                    true, nextCallInsn, dexIdx, methodIdx,
+                                    nextCallInsn, dexIdx, methodIdx,
                                     skipThis);
     /*
      * Make sure range list doesn't span the break between in normal
@@ -766,45 +767,13 @@
     branchOver->generic.target = (LIR*)target;
 }
 
-STATIC void genInvokeStaticDirect(CompilationUnit* cUnit, MIR* mir,
-                                  bool direct, bool range)
+STATIC void genInvoke(CompilationUnit* cUnit, MIR* mir,
+                      InvokeType type, bool isRange)
 {
     DecodedInstruction* dInsn = &mir->dalvikInsn;
     int callState = 0;
     ArmLIR* nullCk;
-    ArmLIR** pNullCk = direct ? &nullCk : NULL;
-    NextCallInsn nextCallInsn = nextSDCallInsn;
-    oatFlushAllRegs(cUnit);    /* Everything to home location */
-
-    // Explicit register usage
-    oatLockCallTemps(cUnit);
-
-    uint32_t dexMethodIdx = mir->dalvikInsn.vB;
-
-    if (range) {
-        callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
-                                       nextCallInsn, dexMethodIdx, 0, false);
-    } else {
-        callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
-                                         false, nextCallInsn, dexMethodIdx,
-                                         0, false);
-    }
-    // Finish up any of the call sequence not interleaved in arg loading
-    while (callState >= 0) {
-        callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx, 0);
-    }
-    if (DISPLAY_MISSING_TARGETS) {
-        genShowTarget(cUnit);
-    }
-    opReg(cUnit, kOpBlx, rLR);
-    oatClobberCalleeSave(cUnit);
-}
-
-STATIC void genInvoke(CompilationUnit* cUnit, MIR* mir, bool isInterface,
-                      bool isSuper, bool isRange)
-{
-    DecodedInstruction* dInsn = &mir->dalvikInsn;
-    int callState = 0;
+    ArmLIR** pNullCk = NULL;
     NextCallInsn nextCallInsn;
     oatFlushAllRegs(cUnit);    /* Everything to home location */
     // Explicit register usage
@@ -812,25 +781,38 @@
 
     uint32_t dexMethodIdx = dInsn->vB;
     int vtableIdx;
+    bool skipThis;
     bool fastPath =
-        cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, cUnit,
-                                           isInterface, isSuper, vtableIdx)
+        cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, cUnit, type,
+                                           vtableIdx)
         && !SLOW_INVOKE_PATH;
-    if (isInterface) {
+    if (type == kInterface) {
       nextCallInsn = fastPath ? nextInterfaceCallInsn
                               : nextInterfaceCallInsnWithAccessCheck;
-    } else if (isSuper) {
+      skipThis = false;
+    } else if (type == kDirect) {
+      if (fastPath) {
+        pNullCk = &nullCk;
+      }
+      nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
+      skipThis = false;
+    } else if (type == kStatic) {
+      nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
+      skipThis = false;
+    } else if (type == kSuper) {
       nextCallInsn = fastPath ? nextSuperCallInsn : nextSuperCallInsnSP;
+      skipThis = fastPath;
     } else {
+      DCHECK_EQ(type, kVirtual);
       nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
+      skipThis = fastPath;
     }
-    bool skipThis = fastPath && !isInterface;
     if (!isRange) {
-        callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, NULL,
-                                         false, nextCallInsn, dexMethodIdx,
+        callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
+                                         nextCallInsn, dexMethodIdx,
                                          vtableIdx, skipThis);
     } else {
-        callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, NULL,
+        callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
                                        nextCallInsn, dexMethodIdx, vtableIdx,
                                        skipThis);
     }
@@ -1296,48 +1278,38 @@
             break;
 
         case OP_INVOKE_STATIC_RANGE:
-            genInvokeStaticDirect(cUnit, mir, false /*direct*/,
-                                  true /*range*/);
+            genInvoke(cUnit, mir, kStatic, true /*range*/);
             break;
         case OP_INVOKE_STATIC:
-            genInvokeStaticDirect(cUnit, mir, false /*direct*/,
-                                  false /*range*/);
+            genInvoke(cUnit, mir, kStatic, false /*range*/);
             break;
 
         case OP_INVOKE_DIRECT:
-            genInvokeStaticDirect(cUnit, mir, true /*direct*/,
-                                  false /*range*/);
+            genInvoke(cUnit, mir, kDirect, false /*range*/);
             break;
         case OP_INVOKE_DIRECT_RANGE:
-            genInvokeStaticDirect(cUnit, mir, true /*direct*/,
-                                  true /*range*/);
+            genInvoke(cUnit, mir, kDirect, true /*range*/);
             break;
 
         case OP_INVOKE_VIRTUAL:
-            genInvoke(cUnit, mir, false /*interface*/, false /*super*/,
-                      false /*range*/);
+            genInvoke(cUnit, mir, kVirtual, false /*range*/);
             break;
         case OP_INVOKE_VIRTUAL_RANGE:
-            genInvoke(cUnit, mir, false /*interface*/, false /*super*/,
-                      true /*range*/);
+            genInvoke(cUnit, mir, kVirtual, true /*range*/);
             break;
 
         case OP_INVOKE_SUPER:
-            genInvoke(cUnit, mir, false /*interface*/, true /*super*/,
-                      false /*range*/);
+            genInvoke(cUnit, mir, kSuper, false /*range*/);
             break;
         case OP_INVOKE_SUPER_RANGE:
-            genInvoke(cUnit, mir, false /*interface*/, true /*super*/,
-                      true /*range*/);
+            genInvoke(cUnit, mir, kSuper, true /*range*/);
             break;
 
         case OP_INVOKE_INTERFACE:
-            genInvoke(cUnit, mir, true /*interface*/, false /*super*/,
-                      false /*range*/);
+            genInvoke(cUnit, mir, kInterface, false /*range*/);
             break;
         case OP_INVOKE_INTERFACE_RANGE:
-            genInvoke(cUnit, mir, true /*interface*/, false /*super*/,
-                      true /*range*/);
+            genInvoke(cUnit, mir, kInterface, true /*range*/);
             break;
 
         case OP_NEG_INT: