Add a new index type table for instruction decoding.

This is in prep for -- recurring theme here -- adding the new extended
opcode formats. It turns out that we can avoid a lot of duplicated code
if we determine the type of thing referred to in index-bearing instructions
inside the general instruction decoder. To do so straightforwardly, this
means adding a new opcode info table and then passing it into the decoder.
Rather than add another argument to the decoder, I defined a struct to
contain all the info tables together, and a pointer to that can get passed
in.

I simplified the setting up of the info tables, too, so all the
allocation is handled within InstrUtils, rather than being (partially)
duplicated in a couple places. The only downside is that dexdump will
construct one more table than it actually needs, but given that
construction is quick and the table is only 256 bytes (though will
soon be growing to -- gasp! -- 294 bytes), I figure it's not such a
big deal.

Most of the files that changed only had edits for how to refer to these
info tables.

Change-Id: Ia6f1cb25da6e558ac90c6dd3af6bce36b82a6b4d
diff --git a/vm/Globals.h b/vm/Globals.h
index eaa9000..fb60120 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -495,12 +495,11 @@
      */
     AtomicCache* instanceofCache;
 
-    /* instruction width table, used for optimization and verification */
-    InstructionWidth*   instrWidth;
-    /* instruction flags table, used for verification */
-    InstructionFlags*   instrFlags;
-    /* instruction format table, used for verification */
-    InstructionFormat*  instrFormat;
+    /*
+     * instruction info tables, used for optimization, verification, and
+     * compilation. This is a struct that contains several pointers.
+     */
+    InstructionInfoTables instrInfo;
 
     /* inline substitution table, used during optimization */
     InlineSub*          inlineSubs;
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 49c1a3e..3986aee 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -3513,9 +3513,9 @@
 #ifndef NDEBUG
     memset(&decInsn, 0x81, sizeof(decInsn));
 #endif
-    dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
+    dexDecodeInstruction(&gDvm.instrInfo, insns, &decInsn);
 
-    int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
+    int nextFlags = dexGetInstrFlags(gDvm.instrInfo.flags, decInsn.opCode);
 
     /*
      * Make a copy of the previous register state.  If the instruction
diff --git a/vm/analysis/DexVerify.c b/vm/analysis/DexVerify.c
index 213b674..dd09859 100644
--- a/vm/analysis/DexVerify.c
+++ b/vm/analysis/DexVerify.c
@@ -33,12 +33,7 @@
  */
 bool dvmVerificationStartup(void)
 {
-    gDvm.instrWidth = dexCreateInstrWidthTable();
-    gDvm.instrFormat = dexCreateInstrFormatTable();
-    gDvm.instrFlags = dexCreateInstrFlagsTable();
-    if (gDvm.instrWidth == NULL || gDvm.instrFormat == NULL ||
-        gDvm.instrFlags == NULL)
-    {
+    if (dexCreateInstructionInfoTables(&gDvm.instrInfo)) {
         LOGE("Unable to create instruction tables\n");
         return false;
     }
@@ -51,12 +46,9 @@
  */
 void dvmVerificationShutdown(void)
 {
-    free(gDvm.instrWidth);
-    free(gDvm.instrFormat);
-    free(gDvm.instrFlags);
+    dexFreeInstructionInfoTables(&gDvm.instrInfo);
 }
 
-
 /*
  * Verify a class.
  *
@@ -120,7 +112,8 @@
 
 
     for (i = 0; i < (int) insnCount; /**/) {
-        size_t width = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, insns);
+        size_t width =
+            dexGetInstrOrTableWidthAbs(gDvm.instrInfo.widths, insns);
         if (width == 0) {
             LOG_VFY_METH(meth,
                 "VFY: invalid post-opt instruction (0x%04x)\n", *insns);
@@ -825,8 +818,8 @@
     const Method* meth = vdata->method;
     const DvmDex* pDvmDex = meth->clazz->pDvmDex;
     InsnFlags* insnFlags = vdata->insnFlags;
-    const InstructionFormat* formatTable = gDvm.instrFormat;
-    const InstructionFlags* flagTable = gDvm.instrFlags;
+    const InstructionInfoTables* infoTables = &gDvm.instrInfo;
+    const InstructionFlags* flagTable = gDvm.instrInfo.flags;
     const u2* insns = meth->insns;
     unsigned int codeOffset;
 
@@ -841,7 +834,7 @@
         DecodedInstruction decInsn;
         bool okay = true;
 
-        dexDecodeInstruction(formatTable, meth->insns + codeOffset, &decInsn);
+        dexDecodeInstruction(infoTables, meth->insns + codeOffset, &decInsn);
 
         /*
          * Check register, type, class, field, method, and string indices
diff --git a/vm/analysis/Optimize.c b/vm/analysis/Optimize.c
index 5a1deca..3e43f71 100644
--- a/vm/analysis/Optimize.c
+++ b/vm/analysis/Optimize.c
@@ -299,7 +299,7 @@
             }
         }
 
-        width = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, insns);
+        width = dexGetInstrOrTableWidthAbs(gDvm.instrInfo.widths, insns);
         assert(width > 0);
 
         insns += width;
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 7f02ea1..7d28b36 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -34,13 +34,13 @@
     if (opcode == OP_NOP && instr != 0) {
         return 0;
     } else {
-        insnWidth = gDvm.instrWidth[opcode];
+        insnWidth = gDvm.instrInfo.widths[opcode];
         if (insnWidth < 0) {
             insnWidth = -insnWidth;
         }
     }
 
-    dexDecodeInstruction(gDvm.instrFormat, codePtr, decInsn);
+    dexDecodeInstruction(&gDvm.instrInfo, codePtr, decInsn);
     if (printMe) {
         char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn, NULL);
         LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
@@ -205,7 +205,7 @@
 static int analyzeInlineTarget(DecodedInstruction *dalvikInsn, int attributes,
                                int offset)
 {
-    int flags = dexGetInstrFlags(gDvm.instrFlags, dalvikInsn->opCode);
+    int flags = dexGetInstrFlags(gDvm.instrInfo.flags, dalvikInsn->opCode);
     int dalvikOpCode = dalvikInsn->opCode;
 
     if ((flags & kInstrInvoke) &&
@@ -570,7 +570,8 @@
         dvmCompilerAppendMIR(curBB, insn);
         cUnit.numInsts++;
 
-        int flags = dexGetInstrFlags(gDvm.instrFlags, insn->dalvikInsn.opCode);
+        int flags =
+            dexGetInstrFlags(gDvm.instrInfo.flags, insn->dalvikInsn.opCode);
 
         if ((flags & kInstrInvoke) &&
             (insn->dalvikInsn.opCode != OP_INVOKE_DIRECT_EMPTY)) {
@@ -643,7 +644,7 @@
         /* Link the taken and fallthrough blocks */
         BasicBlock *searchBB;
 
-        int flags = dexGetInstrFlags(gDvm.instrFlags,
+        int flags = dexGetInstrFlags(gDvm.instrInfo.flags,
                                      lastInsn->dalvikInsn.opCode);
 
         if (flags & kInstrInvoke) {
@@ -1207,7 +1208,7 @@
                      * aligned to 4-byte boundary (alignment instruction to be
                      * inserted later.
                      */
-                    if (dexGetInstrFlags(gDvm.instrFlags,
+                    if (dexGetInstrFlags(gDvm.instrInfo.flags,
                            curBB->lastMIRInsn->dalvikInsn.opCode) &
                         kInstrInvoke) {
                         newBB->isFallThroughFromInvoke = true;
diff --git a/vm/compiler/InlineTransformation.c b/vm/compiler/InlineTransformation.c
index ce45b8b..951da61 100644
--- a/vm/compiler/InlineTransformation.c
+++ b/vm/compiler/InlineTransformation.c
@@ -46,7 +46,7 @@
     MIR *newGetterMIR = dvmCompilerNew(sizeof(MIR), true);
     DecodedInstruction getterInsn;
 
-    dexDecodeInstruction(gDvm.instrFormat, calleeMethod->insns, &getterInsn);
+    dexDecodeInstruction(&gDvm.instrInfo, calleeMethod->insns, &getterInsn);
 
     if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &getterInsn))
         return;
@@ -85,7 +85,7 @@
     /* Now setup the Dalvik instruction with converted src/dst registers */
     newGetterMIR->dalvikInsn = getterInsn;
 
-    newGetterMIR->width = gDvm.instrWidth[getterInsn.opCode];
+    newGetterMIR->width = gDvm.instrInfo.widths[getterInsn.opCode];
 
     newGetterMIR->OptimizationFlags |= MIR_CALLEE;
 
@@ -137,7 +137,7 @@
     MIR *newSetterMIR = dvmCompilerNew(sizeof(MIR), true);
     DecodedInstruction setterInsn;
 
-    dexDecodeInstruction(gDvm.instrFormat, calleeMethod->insns, &setterInsn);
+    dexDecodeInstruction(&gDvm.instrInfo, calleeMethod->insns, &setterInsn);
 
     if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &setterInsn))
         return;
@@ -164,7 +164,7 @@
     /* Now setup the Dalvik instruction with converted src/dst registers */
     newSetterMIR->dalvikInsn = setterInsn;
 
-    newSetterMIR->width = gDvm.instrWidth[setterInsn.opCode];
+    newSetterMIR->width = gDvm.instrInfo.widths[setterInsn.opCode];
 
     newSetterMIR->OptimizationFlags |= MIR_CALLEE;
 
@@ -296,7 +296,7 @@
             continue;
         MIR *lastMIRInsn = bb->lastMIRInsn;
         int opCode = lastMIRInsn->dalvikInsn.opCode;
-        int flags = dexGetInstrFlags(gDvm.instrFlags, opCode);
+        int flags = dexGetInstrFlags(gDvm.instrInfo.flags, opCode);
 
         /* No invoke - continue */
         if ((flags & kInstrInvoke) == 0)
diff --git a/vm/compiler/Loop.c b/vm/compiler/Loop.c
index 918d955..de05644 100644
--- a/vm/compiler/Loop.c
+++ b/vm/compiler/Loop.c
@@ -311,7 +311,7 @@
         /* Skip extended MIR instructions */
         if (dInsn->opCode > 255) continue;
 
-        int instrFlags = dexGetInstrFlags(gDvm.instrFlags, dInsn->opCode);
+        int instrFlags = dexGetInstrFlags(gDvm.instrInfo.flags, dInsn->opCode);
 
         /* Instruction is clean */
         if ((instrFlags & kInstrCanThrow) == 0) continue;
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 5cd901e..de0d6e6 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1233,7 +1233,7 @@
  */
 static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
 {
-    int flags = dexGetInstrFlags(gDvm.instrFlags, mir->dalvikInsn.opCode);
+    int flags = dexGetInstrFlags(gDvm.instrInfo.flags, mir->dalvikInsn.opCode);
     int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
                        kInstrCanThrow;
 
@@ -1283,7 +1283,8 @@
     if (isEnter) {
         /* Get dPC of next insn */
         loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
-                 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
+                 dexGetInstrWidthAbs(gDvm.instrInfo.widths,
+                         OP_MONITOR_ENTER)));
 #if defined(WITH_DEADLOCK_PREDICTION)
         genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG);
 #else
@@ -1297,7 +1298,8 @@
         ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
         loadConstant(cUnit, r0,
                      (int) (cUnit->method->insns + mir->offset +
-                     dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
+                     dexGetInstrWidthAbs(gDvm.instrInfo.widths,
+                             OP_MONITOR_EXIT)));
         genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
         ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
         target->defMask = ENCODE_ALL;
@@ -4098,7 +4100,7 @@
 
             OpCode dalvikOpCode = mir->dalvikInsn.opCode;
             InstructionFormat dalvikFormat =
-                dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
+                dexGetInstrFormat(gDvm.instrInfo.formats, dalvikOpCode);
             char *note;
             if (mir->OptimizationFlags & MIR_INLINED) {
                 note = " (I)";
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index 33c77f6..6dab426 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -288,7 +288,7 @@
     SelfVerificationState state = shadowSpace->selfVerificationState;
 
     DecodedInstruction decInsn;
-    dexDecodeInstruction(gDvm.instrFormat, pc, &decInsn);
+    dexDecodeInstruction(&gDvm.instrInfo, pc, &decInsn);
 
     //LOGD("### DbgIntp(%d): PC: 0x%x endPC: 0x%x state: %d len: %d %s",
     //    self->threadId, (int)pc, (int)shadowSpace->endPC, state,
@@ -669,7 +669,7 @@
     DecodedInstruction nextDecInsn;
     const u2 *moveResultPC = lastPC + len;
 
-    dexDecodeInstruction(gDvm.instrFormat, moveResultPC, &nextDecInsn);
+    dexDecodeInstruction(&gDvm.instrInfo, moveResultPC, &nextDecInsn);
     if ((nextDecInsn.opCode != OP_MOVE_RESULT) &&
         (nextDecInsn.opCode != OP_MOVE_RESULT_WIDE) &&
         (nextDecInsn.opCode != OP_MOVE_RESULT_OBJECT))
@@ -685,8 +685,8 @@
     interpState->trace[currTraceRun].frag.isCode = true;
     interpState->totalTraceLen++;
 
-    interpState->currRunLen = dexGetInstrOrTableWidthAbs(gDvm.instrWidth,
-                                                         moveResultPC);
+    interpState->currRunLen =
+        dexGetInstrOrTableWidthAbs(gDvm.instrInfo.widths, moveResultPC);
 }
 
 /*
@@ -733,7 +733,7 @@
             /* First instruction - just remember the PC and exit */
             if (lastPC == NULL) break;
             /* Grow the trace around the last PC if jitState is kJitTSelect */
-            dexDecodeInstruction(gDvm.instrFormat, lastPC, &decInsn);
+            dexDecodeInstruction(&gDvm.instrInfo, lastPC, &decInsn);
 
             /*
              * Treat {PACKED,SPARSE}_SWITCH as trace-ending instructions due
@@ -751,8 +751,8 @@
 #if defined(SHOW_TRACE)
             LOGD("TraceGen: adding %s", dexGetOpcodeName(decInsn.opCode));
 #endif
-            flags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
-            len = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, lastPC);
+            flags = dexGetInstrFlags(gDvm.instrInfo.flags, decInsn.opCode);
+            len = dexGetInstrOrTableWidthAbs(gDvm.instrInfo.widths, lastPC);
             offset = lastPC - interpState->method->insns;
             assert((unsigned) offset <
                    dvmGetMethodInsnsSize(interpState->method));