New changes to enable self verification mode.
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index b6c266d..83b9b24 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -31,6 +31,456 @@
/* Track exercised opcodes */
static int opcodeCoverage[256];
+#if defined(WITH_SELF_VERIFICATION)
+/* Prevent certain opcodes from being jitted */
+static inline bool selfVerificationPuntOps(OpCode op)
+{
+ return (op == OP_MONITOR_ENTER || op == OP_MONITOR_EXIT ||
+ op == OP_NEW_INSTANCE || op == OP_NEW_ARRAY);
+}
+
+/*
+ * The following are used to keep compiled loads and stores from modifying
+ * memory during self verification mode.
+ *
+ * Stores do not modify memory. Instead, the address and value pair are stored
+ * into heapSpace. Addresses within heapSpace are unique. For accesses smaller
+ * than a word, the word containing the address is loaded first before being
+ * updated.
+ *
+ * Loads check heapSpace first and return data from there if an entry exists.
+ * Otherwise, data is loaded from memory as usual.
+ */
+
+/* Decode contents of heapArgSpace to determine addr to load from */
+static void selfVerificationLoadDecode(HeapArgSpace* heapArgSpace, int* addr)
+{
+ int reg = heapArgSpace->regMap & 0xF;
+
+ switch (reg) {
+ case 0:
+ *addr = heapArgSpace->r0;
+ break;
+ case 1:
+ *addr = heapArgSpace->r1;
+ break;
+ case 2:
+ *addr = heapArgSpace->r2;
+ break;
+ case 3:
+ *addr = heapArgSpace->r3;
+ break;
+ default:
+ LOGE("ERROR: bad reg used in selfVerificationLoadDecode: %d", reg);
+ break;
+ }
+}
+
+/* Decode contents of heapArgSpace to determine reg to load into */
+static void selfVerificationLoadDecodeData(HeapArgSpace* heapArgSpace,
+ int data, int reg)
+{
+ switch (reg) {
+ case 0:
+ heapArgSpace->r0 = data;
+ break;
+ case 1:
+ heapArgSpace->r1 = data;
+ break;
+ case 2:
+ heapArgSpace->r2 = data;
+ break;
+ case 3:
+ heapArgSpace->r3 = data;
+ break;
+ default:
+ LOGE("ERROR: bad reg passed to selfVerificationLoadDecodeData: %d",
+ reg);
+ break;
+ }
+}
+
+static void selfVerificationLoad(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) {
+ data = heapSpacePtr->data;
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((unsigned int*) addr);
+
+ //LOGD("*** HEAP LOAD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadByte(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((unsigned char*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((unsigned char*) addr);
+
+ //LOGD("*** HEAP LOAD BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadHalfword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x2;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((unsigned short*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((unsigned short*) addr);
+
+ //LOGD("*** HEAP LOAD HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadSignedByte(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap* heapSpacePtr;
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((signed char*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((signed char*) addr);
+
+ //LOGD("*** HEAP LOAD SIGNED BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadSignedHalfword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap* heapSpacePtr;
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x2;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((signed short*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((signed short*) addr);
+
+ //LOGD("*** HEAP LOAD SIGNED HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadDoubleword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap* heapSpacePtr;
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int addr2 = addr+4;
+ unsigned int data = *((unsigned int*) addr);
+ unsigned int data2 = *((unsigned int*) addr2);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) {
+ data = heapSpacePtr->data;
+ } else if (heapSpacePtr->addr == addr2) {
+ data2 = heapSpacePtr->data;
+ }
+ }
+
+ //LOGD("*** HEAP LOAD DOUBLEWORD: Addr: 0x%x Data: 0x%x Data2: 0x%x",
+ // addr, data, data2);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ int reg2 = (heapArgSpace->regMap >> 8) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+ selfVerificationLoadDecodeData(heapArgSpace, data2, reg2);
+}
+
+/* Decode contents of heapArgSpace to determine arguments to store. */
+static void selfVerificationStoreDecode(HeapArgSpace* heapArgSpace,
+ int* value, int reg)
+{
+ switch (reg) {
+ case 0:
+ *value = heapArgSpace->r0;
+ break;
+ case 1:
+ *value = heapArgSpace->r1;
+ break;
+ case 2:
+ *value = heapArgSpace->r2;
+ break;
+ case 3:
+ *value = heapArgSpace->r3;
+ break;
+ default:
+ LOGE("ERROR: bad reg passed to selfVerificationStoreDecode: %d",
+ reg);
+ break;
+ }
+}
+
+static void selfVerificationStore(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+ //LOGD("*** HEAP STORE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) break;
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+ heapSpacePtr->addr = addr;
+ shadowSpace->heapSpaceTail++;
+ }
+
+ heapSpacePtr->data = data;
+}
+
+static void selfVerificationStoreByte(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ //LOGD("*** HEAP STORE BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) break;
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+ heapSpacePtr->addr = maskedAddr;
+ heapSpacePtr->data = *((unsigned int*) maskedAddr);
+ shadowSpace->heapSpaceTail++;
+ }
+
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ *((unsigned char*) addr) = (char) data;
+
+ //LOGD("*** HEAP STORE BYTE: Addr: 0x%x Final Data: 0x%x",
+ // addr, heapSpacePtr->data);
+}
+
+static void selfVerificationStoreHalfword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x2;
+
+ //LOGD("*** HEAP STORE HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) break;
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+ heapSpacePtr->addr = maskedAddr;
+ heapSpacePtr->data = *((unsigned int*) maskedAddr);
+ shadowSpace->heapSpaceTail++;
+ }
+
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ *((unsigned short*) addr) = (short) data;
+
+ //LOGD("*** HEAP STORE HALFWORD: Addr: 0x%x Final Data: 0x%x",
+ // addr, heapSpacePtr->data);
+}
+
+static void selfVerificationStoreDoubleword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data, data2;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ int reg2 = (heapArgSpace->regMap >> 8) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+ selfVerificationStoreDecode(heapArgSpace, &data2, reg2);
+
+ int addr2 = addr+4;
+ bool store1 = false, store2 = false;
+
+ //LOGD("*** HEAP STORE DOUBLEWORD: Addr: 0x%x Data: 0x%x, Data2: 0x%x",
+ // addr, data, data2);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) {
+ heapSpacePtr->data = data;
+ store1 = true;
+ } else if (heapSpacePtr->addr == addr2) {
+ heapSpacePtr->data = data2;
+ store2 = true;
+ }
+ }
+
+ if (!store1) {
+ shadowSpace->heapSpaceTail->addr = addr;
+ shadowSpace->heapSpaceTail->data = data;
+ shadowSpace->heapSpaceTail++;
+ }
+ if (!store2) {
+ shadowSpace->heapSpaceTail->addr = addr2;
+ shadowSpace->heapSpaceTail->data = data2;
+ shadowSpace->heapSpaceTail++;
+ }
+}
+
+/* Common wrapper function for all memory operations */
+static void selfVerificationMemOpWrapper(CompilationUnit *cUnit, int regMap,
+ void* funct)
+{
+ int regMask = (1 << r4PC) | (1 << r3) | (1 << r2) | (1 << r1) | (1 << r0);
+
+ /* r7 <- InterpState->heapArgSpace */
+ loadConstant(cUnit, r4PC, offsetof(InterpState, heapArgSpace));
+ newLIR3(cUnit, THUMB_ADD_RRR, r7, rGLUE, r4PC);
+
+ /* Save out values to heapArgSpace */
+ loadConstant(cUnit, r4PC, regMap);
+ newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+
+ /* Pass interpState pointer to function */
+ newLIR2(cUnit, THUMB_MOV_RR, r0, rGLUE);
+
+ /* Set function pointer and branch */
+ loadConstant(cUnit, r1, (int) funct);
+ newLIR1(cUnit, THUMB_BLX_R, r1);
+
+ /* r7 <- InterpState->heapArgSpace */
+ loadConstant(cUnit, r4PC, offsetof(InterpState, heapArgSpace));
+ newLIR3(cUnit, THUMB_ADD_RRR, r7, rGLUE, r4PC);
+
+ /* Restore register state */
+ newLIR2(cUnit, THUMB_LDMIA, r7, regMask);
+}
+#endif
+
/*****************************************************************************/
/*
@@ -284,8 +734,16 @@
loadConstant(cUnit, reg3, fieldOffset);
genNullCheck(cUnit, dInsn->vB, reg2, mir->offset, NULL); /* null object? */
newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
+#if !defined(WITH_SELF_VERIFICATION)
newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
storeValuePair(cUnit, reg0, reg1, dInsn->vA, reg3);
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationLoadDoubleword);
+
+ storeValuePair(cUnit, reg0, reg1, dInsn->vA, reg3);
+#endif
}
/* Store a wide field to an object instance */
@@ -313,7 +771,13 @@
loadConstant(cUnit, reg3, fieldOffset);
genNullCheck(cUnit, dInsn->vB, reg2, mir->offset, NULL); /* null object? */
newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
+#if !defined(WITH_SELF_VERIFICATION)
newLIR2(cUnit, THUMB_STMIA, reg2, (1<<reg0 | 1<<reg1));
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationStoreDoubleword);
+#endif
}
/*
@@ -338,8 +802,18 @@
loadValue(cUnit, dInsn->vB, reg0);
loadConstant(cUnit, reg1, fieldOffset);
genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
+#if !defined(WITH_SELF_VERIFICATION)
newLIR3(cUnit, inst, reg0, reg0, reg1);
storeValue(cUnit, reg0, dInsn->vA, reg1);
+#else
+ /* Combine address and offset */
+ newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, reg1);
+
+ int regMap = reg0 << 4 | reg0;
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
+
+ storeValue(cUnit, reg0, dInsn->vA, reg1);
+#endif
}
/*
@@ -366,7 +840,17 @@
loadValue(cUnit, dInsn->vA, reg2);
updateLiveRegister(cUnit, dInsn->vA, reg2);
genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
+#if !defined(WITH_SELF_VERIFICATION)
newLIR3(cUnit, inst, reg2, reg0, reg1);
+#else
+ /* Combine address and offset */
+ newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, reg1);
+
+ int regMap = reg2 << 4 | reg0;
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+
+ newLIR3(cUnit, THUMB_SUB_RRR, reg0, reg0, reg1);
+#endif
}
@@ -406,6 +890,7 @@
if (scale) {
newLIR3(cUnit, THUMB_LSL, reg3, reg3, scale);
}
+#if !defined(WITH_SELF_VERIFICATION)
if (scale==3) {
newLIR3(cUnit, inst, reg0, reg2, reg3);
newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
@@ -415,6 +900,46 @@
newLIR3(cUnit, inst, reg0, reg2, reg3);
storeValue(cUnit, reg0, vDest, reg3);
}
+#else
+ void* funct;
+ switch (scale) {
+ case 0:
+ if (inst == THUMB_LDRSB_RRR)
+ funct = (void*) &selfVerificationLoadSignedByte;
+ else
+ funct = (void*) &selfVerificationLoadByte;
+ break;
+ case 1:
+ if (inst == THUMB_LDRSH_RRR)
+ funct = (void*) &selfVerificationLoadSignedHalfword;
+ else
+ funct = (void*) &selfVerificationLoadHalfword;
+ break;
+ case 2:
+ funct = (void*) &selfVerificationLoad;
+ break;
+ case 3:
+ funct = (void*) &selfVerificationLoadDoubleword;
+ break;
+ default:
+ LOGE("ERROR: bad scale value in genArrayGet: %d", scale);
+ funct = (void*) &selfVerificationLoad;
+ break;
+ }
+
+ /* Combine address and offset */
+ newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
+
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap, funct);
+
+ newLIR3(cUnit, THUMB_SUB_RRR, reg2, reg2, reg3);
+
+ if (scale==3)
+ storeValuePair(cUnit, reg0, reg1, vDest, reg3);
+ else
+ storeValue(cUnit, reg0, vDest, reg3);
+#endif
}
/* TODO: This should probably be done as an out-of-line instruction handler. */
@@ -463,6 +988,7 @@
* at this point, reg2 points to array, reg3 is scaled index, and
* reg0[reg1] is data
*/
+#if !defined(WITH_SELF_VERIFICATION)
if (scale==3) {
newLIR3(cUnit, inst, reg0, reg2, reg3);
newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
@@ -470,6 +996,35 @@
} else {
newLIR3(cUnit, inst, reg0, reg2, reg3);
}
+#else
+ void *funct;
+ switch (scale) {
+ case 0:
+ funct = (void*) &selfVerificationStoreByte;
+ break;
+ case 1:
+ funct = (void*) &selfVerificationStoreHalfword;
+ break;
+ case 2:
+ funct = (void*) &selfVerificationStore;
+ break;
+ case 3:
+ funct = (void*) &selfVerificationStoreDoubleword;
+ break;
+ default:
+ LOGE("ERROR: bad scale value in genArrayPut: %d", scale);
+ funct = (void*) &selfVerificationStore;
+ break;
+ }
+
+ /* Combine address and offset */
+ newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
+
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap, funct);
+
+ newLIR3(cUnit, THUMB_SUB_RRR, reg2, reg2, reg3);
+#endif
}
static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
@@ -1545,8 +2100,15 @@
(cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
assert(fieldPtr != NULL);
loadConstant(cUnit, regvNone, (int) fieldPtr + valOffset);
+#if !defined(WITH_SELF_VERIFICATION)
newLIR3(cUnit, THUMB_LDR_RRI5, regvNone, regvNone, 0);
storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
+#else
+ int regMap = regvNone << 4 | regvNone;
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
+
+ storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
+#endif
break;
}
case OP_SGET_WIDE: {
@@ -1560,8 +2122,16 @@
reg1 = NEXT_REG(reg0);
reg2 = NEXT_REG(reg1);
loadConstant(cUnit, reg2, (int) fieldPtr + valOffset);
+#if !defined(WITH_SELF_VERIFICATION)
newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationLoadDoubleword);
+
+ storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
+#endif
break;
}
case OP_SPUT_OBJECT:
@@ -1578,7 +2148,12 @@
loadValue(cUnit, mir->dalvikInsn.vA, regvA);
updateLiveRegister(cUnit, mir->dalvikInsn.vA, regvA);
loadConstant(cUnit, NEXT_REG(regvA), (int) fieldPtr + valOffset);
+#if !defined(WITH_SELF_VERIFICATION)
newLIR3(cUnit, THUMB_STR_RRI5, regvA, NEXT_REG(regvA), 0);
+#else
+ int regMap = regvA << 4 | NEXT_REG(regvA);
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+#endif
break;
}
case OP_SPUT_WIDE: {
@@ -1594,7 +2169,13 @@
loadValuePair(cUnit, mir->dalvikInsn.vA, reg0, reg1);
updateLiveRegisterPair(cUnit, mir->dalvikInsn.vA, reg0, reg1);
loadConstant(cUnit, reg2, (int) fieldPtr + valOffset);
+#if !defined(WITH_SELF_VERIFICATION)
newLIR2(cUnit, THUMB_STMIA, reg2, (1<<reg0 | 1<<reg1));
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationStoreDoubleword);
+#endif
break;
}
case OP_NEW_INSTANCE: {
@@ -2909,6 +3490,18 @@
addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
}
+#if defined(WITH_SELF_VERIFICATION)
+/* Chaining cell for branches that branch back into the same basic block */
+static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
+ unsigned int offset)
+{
+ newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
+ offsetof(InterpState, jitToInterpEntries.dvmJitToBackwardBranch) >> 2);
+ newLIR1(cUnit, THUMB_BLX_R, r0);
+ addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+}
+
+#endif
/* Chaining cell for monomorphic method invocations. */
static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
const Method *callee)
@@ -3073,6 +3666,16 @@
newLIR1(cUnit, THUMB_BLX_R, r1);
}
break;
+#if defined(WITH_SELF_VERIFICATION)
+ case CHAINING_CELL_BACKWARD_BRANCH:
+ labelList[i].opCode =
+ ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH;
+ /* handle the codegen later */
+ dvmInsertGrowableList(
+ &chainingListByType[CHAINING_CELL_BACKWARD_BRANCH],
+ (void *) i);
+ break;
+#endif
default:
break;
}
@@ -3102,6 +3705,11 @@
((gDvmJit.opList[dalvikOpCode >> 3] &
(1 << (dalvikOpCode & 0x7))) !=
0);
+#if defined(WITH_SELF_VERIFICATION)
+ /* Punt on opcodes we can't replay */
+ if (selfVerificationPuntOps(dalvikOpCode))
+ singleStepMe = true;
+#endif
if (singleStepMe || cUnit->allSingleStep) {
notHandled = false;
genInterpSingleStep(cUnit, mir);
@@ -3252,6 +3860,12 @@
handleHotChainingCell(cUnit,
blockList[blockId]->startOffset);
break;
+#if defined(WITH_SELF_VERIFICATION)
+ case CHAINING_CELL_BACKWARD_BRANCH:
+ handleBackwardBranchChainingCell(cUnit,
+ blockList[blockId]->startOffset);
+ break;
+#endif
default:
dvmAbort();
break;