Made Self Verification mode's memory interface less intrusive.
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index f5178d8..00892fa 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -151,6 +151,7 @@
bool halveInstCount;
bool executionCount; // Add code to count trace executions
bool hasLoop;
+ bool heapMemOp; // Mark mem ops for self verification
int numChainingCells[kChainingCellGap];
LIR *firstChainingLIR[kChainingCellGap];
LIR *chainingCellBottom;
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 347bc50..c8e8e52 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -300,7 +300,7 @@
CompilerMethodStats *methodStats;
/* If we've already compiled this trace, just return success */
- if (dvmJitGetCodeAddr(startCodePtr)) {
+ if (dvmJitGetCodeAddr(startCodePtr) && !info->discardResult) {
return true;
}
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index 21e2a32..b329aed 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -723,6 +723,8 @@
ArmOpCode opCode;
int operands[4]; // [0..3] = [dest, src1, src2, extra]
bool isNop; // LIR is optimized away
+ bool branchInsertSV;// mark for insertion of branch before this instruction,
+ // used to identify mem ops for self verification mode
int age; // default is 0, set lazily by the optimizer
int size; // 16-bit unit size (1 for thumb, 1 or 2 for thumb2)
int aliasInfo; // For Dalvik register access disambiguation
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index c3ad957..5cb8ff6 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1841,3 +1841,519 @@
dvmUnlockMutex(&gDvmJit.tableLock);
return;
}
+
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * 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.
+ */
+
+/* Used to specify sizes of memory operations */
+enum {
+ kSVByte,
+ kSVSignedByte,
+ kSVHalfword,
+ kSVSignedHalfword,
+ kSVWord,
+ kSVDoubleword,
+};
+
+/* Load the value of a decoded register from the stack */
+static int selfVerificationMemRegLoad(int* sp, int reg)
+{
+ return *(sp + reg);
+}
+
+/* Load the value of a decoded doubleword register from the stack */
+static s8 selfVerificationMemRegLoadDouble(int* sp, int reg)
+{
+ return *((s8*)(sp + reg));
+}
+
+/* Store the value of a decoded register out to the stack */
+static void selfVerificationMemRegStore(int* sp, int data, int reg)
+{
+ *(sp + reg) = data;
+}
+
+/* Store the value of a decoded doubleword register out to the stack */
+static void selfVerificationMemRegStoreDouble(int* sp, s8 data, int reg)
+{
+ *((s8*)(sp + reg)) = data;
+}
+
+/*
+ * Load the specified size of data from the specified address, checking
+ * heapSpace first if Self Verification mode wrote to it previously, and
+ * falling back to actual memory otherwise.
+ */
+static int selfVerificationLoad(int addr, int size)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ ShadowHeap *heapSpacePtr;
+
+ int data;
+ 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;
+ break;
+ }
+ }
+
+ switch (size) {
+ case kSVByte:
+ data = *((u1*) addr);
+ break;
+ case kSVSignedByte:
+ data = *((s1*) addr);
+ break;
+ case kSVHalfword:
+ data = *((u2*) addr);
+ break;
+ case kSVSignedHalfword:
+ data = *((s2*) addr);
+ break;
+ case kSVWord:
+ data = *((u4*) addr);
+ }
+
+ //LOGD("*** HEAP LOAD: Addr: 0x%x Data: 0x%x Size: %d", addr, data, size);
+ return data;
+}
+
+/* Like selfVerificationLoad, but specifically for doublewords */
+static s8 selfVerificationLoadDoubleword(int addr)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ ShadowHeap* heapSpacePtr;
+
+ 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);
+ return (((s8) data2) << 32) | data;
+}
+
+/*
+ * Handles a store of a specified size of data to a specified address.
+ * This gets logged as an addr/data pair in heapSpace instead of modifying
+ * memory. Addresses in heapSpace are unique, and accesses smaller than a
+ * word pull the entire word from memory first before updating.
+ */
+static void selfVerificationStore(int addr, int data, int size)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ ShadowHeap *heapSpacePtr;
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ //LOGD("*** HEAP STORE: Addr: 0x%x Data: 0x%x Size: %d", addr, data, size);
+
+ 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;
+ switch (size) {
+ case kSVByte:
+ *((u1*) addr) = data;
+ break;
+ case kSVSignedByte:
+ *((s1*) addr) = data;
+ break;
+ case kSVHalfword:
+ *((u2*) addr) = data;
+ break;
+ case kSVSignedHalfword:
+ *((s2*) addr) = data;
+ break;
+ case kSVWord:
+ *((u4*) addr) = data;
+ }
+}
+
+/* Like selfVerificationStore, but specifically for doublewords */
+static void selfVerificationStoreDoubleword(int addr, s8 double_data)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ ShadowHeap *heapSpacePtr;
+
+ int addr2 = addr+4;
+ int data = double_data;
+ int data2 = double_data >> 32;
+ 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++;
+ }
+}
+
+/*
+ * Decodes the memory instruction at the address specified in the link
+ * register. All registers (r0-r12,lr) and fp registers (d0-d15) are stored
+ * consecutively on the stack beginning at the specified stack pointer.
+ * Calls the proper Self Verification handler for the memory instruction and
+ * updates the link register to point past the decoded memory instruction.
+ */
+void dvmSelfVerificationMemOpDecode(int lr, int* sp)
+{
+ enum {
+ kMemOpLdrPcRel = 0x09, // ldr(3) [01001] rd[10..8] imm_8[7..0]
+ kMemOpRRR = 0x0A, // Full opcode is 7 bits
+ kMemOp2Single = 0x0A, // Used for Vstrs and Vldrs
+ kMemOpRRR2 = 0x0B, // Full opcode is 7 bits
+ kMemOp2Double = 0x0B, // Used for Vstrd and Vldrd
+ kMemOpStrRRI5 = 0x0C, // str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0]
+ kMemOpLdrRRI5 = 0x0D, // ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0]
+ kMemOpStrbRRI5 = 0x0E, // strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0]
+ kMemOpLdrbRRI5 = 0x0F, // ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0]
+ kMemOpStrhRRI5 = 0x10, // strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0]
+ kMemOpLdrhRRI5 = 0x11, // ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0]
+ kMemOpLdrSpRel = 0x13, // ldr(4) [10011] rd[10..8] imm_8[7..0]
+ kMemOpStrRRR = 0x28, // str(2) [0101000] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpStrhRRR = 0x29, // strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpStrbRRR = 0x2A, // strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpLdrsbRRR = 0x2B, // ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpLdrRRR = 0x2C, // ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpLdrhRRR = 0x2D, // ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpLdrbRRR = 0x2E, // ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0]
+ kMemOpLdrshRRR = 0x2F, // ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0]
+ kMemOp2Vstr = 0xED8, // Used for Vstrs and Vstrd
+ kMemOp2Vldr = 0xED9, // Used for Vldrs and Vldrd
+ kMemOp2Vstr2 = 0xEDC, // Used for Vstrs and Vstrd
+ kMemOp2Vldr2 = 0xEDD, // Used for Vstrs and Vstrd
+ kMemOp2StrbRRR = 0xF80, /* str rt,[rn,rm,LSL #imm] [111110000000]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2LdrbRRR = 0xF81, /* ldrb rt,[rn,rm,LSL #imm] [111110000001]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2StrhRRR = 0xF82, /* str rt,[rn,rm,LSL #imm] [111110000010]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2LdrhRRR = 0xF83, /* ldrh rt,[rn,rm,LSL #imm] [111110000011]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2StrRRR = 0xF84, /* str rt,[rn,rm,LSL #imm] [111110000100]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2LdrRRR = 0xF85, /* ldr rt,[rn,rm,LSL #imm] [111110000101]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2StrbRRI12 = 0xF88, /* strb rt,[rn,#imm12] [111110001000]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kMemOp2LdrbRRI12 = 0xF89, /* ldrb rt,[rn,#imm12] [111110001001]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kMemOp2StrhRRI12 = 0xF8A, /* strh rt,[rn,#imm12] [111110001010]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kMemOp2LdrhRRI12 = 0xF8B, /* ldrh rt,[rn,#imm12] [111110001011]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kMemOp2StrRRI12 = 0xF8C, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
+ rn[19..16] rt[15..12] imm12[11..0] */
+ kMemOp2LdrRRI12 = 0xF8D, /* ldr(Imm,T3) rd,[rn,#imm12] [111110001101]
+ rn[19..16] rt[15..12] imm12[11..0] */
+ kMemOp2LdrsbRRR = 0xF91, /* ldrsb rt,[rn,rm,LSL #imm] [111110010001]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2LdrshRRR = 0xF93, /* ldrsh rt,[rn,rm,LSL #imm] [111110010011]
+ rn[19-16] rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kMemOp2LdrsbRRI12 = 0xF99, /* ldrsb rt,[rn,#imm12] [111110011001]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kMemOp2LdrshRRI12 = 0xF9B, /* ldrsh rt,[rn,#imm12] [111110011011]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kMemOp2 = 0xE000, // top 3 bits set indicates Thumb2
+ };
+
+ int addr, offset, data;
+ long long double_data;
+ int size = kSVWord;
+ bool store = false;
+ unsigned int *lr_masked = (unsigned int *) (lr & 0xFFFFFFFE);
+ unsigned int insn = *lr_masked;
+
+ int old_lr;
+ old_lr = selfVerificationMemRegLoad(sp, 13);
+
+ if ((insn & kMemOp2) == kMemOp2) {
+ insn = (insn << 16) | (insn >> 16);
+ //LOGD("*** THUMB2 - Addr: 0x%x Insn: 0x%x", lr, insn);
+
+ int opcode12 = (insn >> 20) & 0xFFF;
+ int opcode6 = (insn >> 6) & 0x3F;
+ int opcode4 = (insn >> 8) & 0xF;
+ int imm2 = (insn >> 4) & 0x3;
+ int imm8 = insn & 0xFF;
+ int imm12 = insn & 0xFFF;
+ int rd = (insn >> 12) & 0xF;
+ int rm = insn & 0xF;
+ int rn = (insn >> 16) & 0xF;
+ int rt = (insn >> 12) & 0xF;
+
+ // Update the link register
+ selfVerificationMemRegStore(sp, old_lr+4, 13);
+
+ // Determine whether the mem op is a store or load
+ switch (opcode12) {
+ case kMemOp2Vstr:
+ case kMemOp2Vstr2:
+ case kMemOp2StrbRRR:
+ case kMemOp2StrhRRR:
+ case kMemOp2StrRRR:
+ case kMemOp2StrbRRI12:
+ case kMemOp2StrhRRI12:
+ case kMemOp2StrRRI12:
+ store = true;
+ }
+
+ // Determine the size of the mem access
+ switch (opcode12) {
+ case kMemOp2StrbRRR:
+ case kMemOp2LdrbRRR:
+ case kMemOp2StrbRRI12:
+ case kMemOp2LdrbRRI12:
+ size = kSVByte;
+ break;
+ case kMemOp2LdrsbRRR:
+ case kMemOp2LdrsbRRI12:
+ size = kSVSignedByte;
+ break;
+ case kMemOp2StrhRRR:
+ case kMemOp2LdrhRRR:
+ case kMemOp2StrhRRI12:
+ case kMemOp2LdrhRRI12:
+ size = kSVHalfword;
+ break;
+ case kMemOp2LdrshRRR:
+ case kMemOp2LdrshRRI12:
+ size = kSVSignedHalfword;
+ break;
+ case kMemOp2Vstr:
+ case kMemOp2Vstr2:
+ case kMemOp2Vldr:
+ case kMemOp2Vldr2:
+ if (opcode4 == kMemOp2Double) size = kSVDoubleword;
+ break;
+ }
+
+ // Load the value of the address
+ addr = selfVerificationMemRegLoad(sp, rn);
+
+ // Figure out the offset
+ switch (opcode12) {
+ case kMemOp2Vstr:
+ case kMemOp2Vstr2:
+ case kMemOp2Vldr:
+ case kMemOp2Vldr2:
+ offset = imm8 << 2;
+ if (opcode4 == kMemOp2Single) {
+ rt = rd << 1;
+ if (insn & 0x400000) rt |= 0x1;
+ } else if (opcode4 == kMemOp2Double) {
+ if (insn & 0x400000) rt |= 0x10;
+ rt = rt << 1;
+ } else {
+ LOGD("*** ERROR: UNRECOGNIZED VECTOR MEM OP");
+ assert(0);
+ dvmAbort();
+ }
+ rt += 14;
+ break;
+ case kMemOp2StrbRRR:
+ case kMemOp2LdrbRRR:
+ case kMemOp2StrhRRR:
+ case kMemOp2LdrhRRR:
+ case kMemOp2StrRRR:
+ case kMemOp2LdrRRR:
+ case kMemOp2LdrsbRRR:
+ case kMemOp2LdrshRRR:
+ offset = selfVerificationMemRegLoad(sp, rm) << imm2;
+ break;
+ case kMemOp2StrbRRI12:
+ case kMemOp2LdrbRRI12:
+ case kMemOp2StrhRRI12:
+ case kMemOp2LdrhRRI12:
+ case kMemOp2StrRRI12:
+ case kMemOp2LdrRRI12:
+ case kMemOp2LdrsbRRI12:
+ case kMemOp2LdrshRRI12:
+ offset = imm12;
+ break;
+ default:
+ LOGD("*** ERROR: UNRECOGNIZED MEM OP");
+ assert(0);
+ dvmAbort();
+ }
+
+ // Handle the decoded mem op accordingly
+ if (store) {
+ if (size == kSVDoubleword) {
+ double_data = selfVerificationMemRegLoadDouble(sp, rt);
+ selfVerificationStoreDoubleword(addr+offset, double_data);
+ } else {
+ data = selfVerificationMemRegLoad(sp, rt);
+ selfVerificationStore(addr+offset, data, size);
+ }
+ } else {
+ if (size == kSVDoubleword) {
+ double_data = selfVerificationLoadDoubleword(addr+offset);
+ selfVerificationMemRegStoreDouble(sp, double_data, rt);
+ } else {
+ data = selfVerificationLoad(addr+offset, size);
+ selfVerificationMemRegStore(sp, data, rt);
+ }
+ }
+ } else {
+ //LOGD("*** THUMB - Addr: 0x%x Insn: 0x%x", lr, insn);
+
+ // Update the link register
+ selfVerificationMemRegStore(sp, old_lr+2, 13);
+
+ int opcode5 = (insn >> 11) & 0x1F;
+ int opcode7 = (insn >> 9) & 0x7F;
+ int imm = (insn >> 6) & 0x1F;
+ int rd = (insn >> 8) & 0x7;
+ int rm = (insn >> 6) & 0x7;
+ int rn = (insn >> 3) & 0x7;
+ int rt = insn & 0x7;
+
+ // Determine whether the mem op is a store or load
+ switch (opcode5) {
+ case kMemOpRRR:
+ switch (opcode7) {
+ case kMemOpStrRRR:
+ case kMemOpStrhRRR:
+ case kMemOpStrbRRR:
+ store = true;
+ }
+ break;
+ case kMemOpStrRRI5:
+ case kMemOpStrbRRI5:
+ case kMemOpStrhRRI5:
+ store = true;
+ }
+
+ // Determine the size of the mem access
+ switch (opcode5) {
+ case kMemOpRRR:
+ case kMemOpRRR2:
+ switch (opcode7) {
+ case kMemOpStrbRRR:
+ case kMemOpLdrbRRR:
+ size = kSVByte;
+ break;
+ case kMemOpLdrsbRRR:
+ size = kSVSignedByte;
+ break;
+ case kMemOpStrhRRR:
+ case kMemOpLdrhRRR:
+ size = kSVHalfword;
+ break;
+ case kMemOpLdrshRRR:
+ size = kSVSignedHalfword;
+ break;
+ }
+ break;
+ case kMemOpStrbRRI5:
+ case kMemOpLdrbRRI5:
+ size = kSVByte;
+ break;
+ case kMemOpStrhRRI5:
+ case kMemOpLdrhRRI5:
+ size = kSVHalfword;
+ break;
+ }
+
+ // Load the value of the address
+ if (opcode5 == kMemOpLdrPcRel)
+ addr = selfVerificationMemRegLoad(sp, 4);
+ else
+ addr = selfVerificationMemRegLoad(sp, rn);
+
+ // Figure out the offset
+ switch (opcode5) {
+ case kMemOpLdrPcRel:
+ offset = (insn & 0xFF) << 2;
+ rt = rd;
+ break;
+ case kMemOpRRR:
+ case kMemOpRRR2:
+ offset = selfVerificationMemRegLoad(sp, rm);
+ break;
+ case kMemOpStrRRI5:
+ case kMemOpLdrRRI5:
+ offset = imm << 2;
+ break;
+ case kMemOpStrhRRI5:
+ case kMemOpLdrhRRI5:
+ offset = imm << 1;
+ break;
+ case kMemOpStrbRRI5:
+ case kMemOpLdrbRRI5:
+ offset = imm;
+ break;
+ default:
+ LOGD("*** ERROR: UNRECOGNIZED MEM OP");
+ assert(0);
+ dvmAbort();
+ }
+
+ // Handle the decoded mem op accordingly
+ if (store) {
+ data = selfVerificationMemRegLoad(sp, rt);
+ selfVerificationStore(addr+offset, data, size);
+ } else {
+ data = selfVerificationLoad(addr+offset, size);
+ selfVerificationMemRegStore(sp, data, rt);
+ }
+ }
+}
+#endif
diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h
index b148bda..0674b8b 100644
--- a/vm/compiler/codegen/arm/Codegen.h
+++ b/vm/compiler/codegen/arm/Codegen.h
@@ -45,6 +45,10 @@
static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir);
+#if defined(WITH_SELF_VERIFICATION)
+/* Self Verification memory instruction decoder */
+void dvmSelfVerificationMemOpDecode(int lr, int* sp);
+#endif
/*
* Architecture-dependent register allocation routines implemented in
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index b0e16b8..1bf80cb 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -208,411 +208,37 @@
}
#if defined(WITH_SELF_VERIFICATION)
-/*
- * 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)
+static void selfVerificationBranchInsert(LIR *currentLIR, ArmOpCode opCode,
+ int dest, int src1)
{
- int reg = heapArgSpace->regMap & 0xFF;
- if (!FPREG(reg)) {
- assert(reg < 16);
- *addr = heapArgSpace->coreRegs[reg];
- } else {
- assert(!DOUBLEREG(reg));
- *addr = heapArgSpace->fpRegs[(reg & FP_REG_MASK)];
- }
+ ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+ insn->opCode = opCode;
+ insn->operands[0] = dest;
+ insn->operands[1] = src1;
+ setupResourceMasks(insn);
+ dvmCompilerInsertLIRBefore(currentLIR, (LIR *) insn);
}
-/* Decode contents of heapArgSpace to determine reg to load into */
-static void selfVerificationLoadDecodeData(HeapArgSpace* heapArgSpace,
- int data, int reg)
+static void selfVerificationBranchInsertPass(CompilationUnit *cUnit)
{
- if (!FPREG(reg)) {
- assert(reg < 16);
- heapArgSpace->coreRegs[reg] = data;
- } else {
- assert(!DOUBLEREG(reg));
- heapArgSpace->fpRegs[(reg & FP_REG_MASK)] = data;
- }
-}
+ ArmLIR *thisLIR;
+ ArmLIR *branchLIR = dvmCompilerNew(sizeof(ArmLIR), true);
+ TemplateOpCode opCode = TEMPLATE_MEM_OP_DECODE;
-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;
+ for (thisLIR = (ArmLIR *) cUnit->firstLIRInsn;
+ thisLIR != (ArmLIR *) cUnit->lastLIRInsn;
+ thisLIR = NEXT_LIR(thisLIR)) {
+ if (thisLIR->branchInsertSV) {
+ /* Branch to mem op decode template */
+ selfVerificationBranchInsert((LIR *) thisLIR, kThumbBlx1,
+ (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+ (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+ selfVerificationBranchInsert((LIR *) thisLIR, kThumbBlx2,
+ (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+ (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
}
}
-
- if (heapSpacePtr == shadowSpace->heapSpaceTail)
- data = *((unsigned int*) addr);
-
- int reg = (heapArgSpace->regMap >> 8) & 0xFF;
-
- // LOGD("*** HEAP LOAD: Reg:%d Addr: 0x%x Data: 0x%x", reg, addr, data);
-
- 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 >> 8) & 0xFF;
- 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 kHalfWord: Addr: 0x%x Data: 0x%x", addr, data);
-
- int reg = (heapArgSpace->regMap >> 8) & 0xFF;
- 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 >> 8) & 0xFF;
- 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 kHalfWord: Addr: 0x%x Data: 0x%x", addr, data);
-
- int reg = (heapArgSpace->regMap >> 8) & 0xFF;
- 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 >> 8) & 0xFF;
- int reg2 = (heapArgSpace->regMap >> 16) & 0xFF;
- 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)
-{
- if (!FPREG(reg)) {
- assert(reg < 16);
- *value = heapArgSpace->coreRegs[reg];
- } else {
- assert(!DOUBLEREG(reg));
- *value = heapArgSpace->fpRegs[(reg & FP_REG_MASK)];
- }
-}
-
-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 & 0xFF;
- int reg1 = (heapArgSpace->regMap >> 8) & 0xFF;
- 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 & 0xFF;
- int reg1 = (heapArgSpace->regMap >> 8) & 0xFF;
- 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 & 0xFF;
- int reg1 = (heapArgSpace->regMap >> 8) & 0xFF;
- selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
- selfVerificationStoreDecode(heapArgSpace, &data, reg1);
-
- int maskedAddr = addr & 0xFFFFFFFC;
- int alignment = addr & 0x2;
-
- //LOGD("*** HEAP STORE kHalfWord: 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 kHalfWord: 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 & 0xFF;
- int reg1 = (heapArgSpace->regMap >> 8) & 0xFF;
- int reg2 = (heapArgSpace->regMap >> 16) & 0xFF;
- 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)
-{
- /* push r0 and r7 to give us a foothold */
- newLIR1(cUnit, kThumbPush, (1 << r0) | (1 << r7));
-
- /* Let the save handler know where the save record is */
- loadConstant(cUnit, r0, offsetof(InterpState, heapArgSpace));
-
- /* Load the regMap and call the save handler [note: handler pops r0/r7] */
- loadConstant(cUnit, r7, regMap);
- genDispatchToHandler(cUnit, TEMPLATE_SAVE_STATE);
-
- /* Set function pointer, pass rGLUE and branch */
- loadConstant(cUnit, r1, (int) funct);
- newLIR2(cUnit, kThumbMovRR, r0, rGLUE);
- newLIR1(cUnit, kThumbBlxR, r1);
-
- /* Let the recover handler know where coreRegs[0] and restore regs */
- loadConstant(cUnit, r0, offsetof(InterpState, heapArgSpace) +
- offsetof(HeapArgSpace, coreRegs));
- genDispatchToHandler(cUnit, TEMPLATE_RESTORE_STATE);
-}
-
#endif
/* Generate a unconditional branch to go to the interpreter */
@@ -639,12 +265,12 @@
NULL);/* null object? */
opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
-#else
- int regMap = rlResult.highReg << 16 | rlResult.lowReg << 8 | regPtr;
- selfVerificationMemOpWrapper(cUnit, regMap,
- &selfVerificationLoadDoubleword);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
freeTemp(cUnit, regPtr);
storeValueWide(cUnit, rlDest, rlResult);
@@ -663,12 +289,12 @@
NULL);/* null object? */
regPtr = allocTemp(cUnit);
opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
-#else
- int regMap = rlSrc.highReg << 16 | rlSrc.lowReg << 8 | regPtr;
- selfVerificationMemOpWrapper(cUnit, regMap,
- &selfVerificationStoreDoubleword);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
freeTemp(cUnit, regPtr);
}
@@ -689,17 +315,13 @@
rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
size, rlObj.sRegLow);
-#else
- /* Combine address and offset */
- regPtr = allocTemp(cUnit);
- opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-
- int regMap = rlResult.lowReg << 8 | regPtr;
- selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
- freeTemp(cUnit, regPtr);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
storeValue(cUnit, rlDest, rlResult);
}
@@ -719,15 +341,12 @@
int regPtr;
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
-#else
- /* Combine address and offset */
- regPtr = allocTemp(cUnit);
- opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-
- int regMap = rlSrc.lowReg << 8 | regPtr;
- selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
}
@@ -769,7 +388,6 @@
/* regPtr -> array data */
opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
}
-#if !defined(WITH_SELF_VERIFICATION)
if ((size == kLong) || (size == kDouble)) {
if (scale) {
int rNewIndex = allocTemp(cUnit);
@@ -780,63 +398,28 @@
opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
}
rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
+#endif
freeTemp(cUnit, regPtr);
storeValueWide(cUnit, rlDest, rlResult);
} else {
rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
scale, size);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
+#endif
freeTemp(cUnit, regPtr);
storeValue(cUnit, rlDest, rlResult);
}
-#else
- //TODO: probably want to move this into loadBaseIndexed
- void *funct = NULL;
- switch(size) {
- case kLong:
- case kDouble:
- funct = (void*) &selfVerificationLoadDoubleword;
- break;
- case kWord:
- funct = (void*) &selfVerificationLoad;
- break;
- case kUnsignedHalf:
- funct = (void*) &selfVerificationLoadHalfword;
- break;
- case kSignedHalf:
- funct = (void*) &selfVerificationLoadSignedHalfword;
- break;
- case kUnsignedByte:
- funct = (void*) &selfVerificationLoadByte;
- break;
- case kSignedByte:
- funct = (void*) &selfVerificationLoadSignedByte;
- break;
- default:
- assert(0);
- dvmAbort();
- }
- /* Combine address and index */
- if (scale) {
- int regTmp = allocTemp(cUnit);
- opRegRegImm(cUnit, kOpLsl, regTmp, rlIndex.lowReg, scale);
- opRegReg(cUnit, kOpAdd, regPtr, regTmp);
- freeTemp(cUnit, regTmp);
- } else {
- opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
- }
-
- rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
- int regMap = rlResult.highReg << 16 | rlResult.lowReg << 8 | regPtr;
- selfVerificationMemOpWrapper(cUnit, regMap, funct);
-
- freeTemp(cUnit, regPtr);
- if ((size == kLong) || (size == kDouble))
- storeValueWide(cUnit, rlDest, rlResult);
- else
- storeValue(cUnit, rlDest, rlResult);
-#endif
}
/*
@@ -885,7 +468,6 @@
opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
}
/* at this point, regPtr points to array, 2 live temps */
-#if !defined(WITH_SELF_VERIFICATION)
if ((size == kLong) || (size == kDouble)) {
//TODO: need specific wide routine that can handle fp regs
if (scale) {
@@ -897,57 +479,25 @@
opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
}
rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
+#endif
freeTemp(cUnit, regPtr);
} else {
rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
scale, size);
- }
-#else
- //TODO: probably want to move this into storeBaseIndexed
- void *funct = NULL;
- switch(size) {
- case kLong:
- case kDouble:
- funct = (void*) &selfVerificationStoreDoubleword;
- break;
- case kWord:
- funct = (void*) &selfVerificationStore;
- break;
- case kSignedHalf:
- case kUnsignedHalf:
- funct = (void*) &selfVerificationStoreHalfword;
- break;
- case kSignedByte:
- case kUnsignedByte:
- funct = (void*) &selfVerificationStoreByte;
- break;
- default:
- assert(0);
- dvmAbort();
- }
-
- if (scale) {
- int regTmpIndex = allocTemp(cUnit);
- // 3 live temps
- opRegRegImm(cUnit, kOpLsl, regTmpIndex, rlIndex.lowReg, scale);
- opRegReg(cUnit, kOpAdd, regPtr, regTmpIndex);
- freeTemp(cUnit, regTmpIndex);
- } else {
- opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
- }
- /* Combine address and index */
- if ((size == kLong) || (size == kDouble)) {
- rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
- } else {
- rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
- }
-
- int regMap = rlSrc.highReg << 16 | rlSrc.lowReg << 8 | regPtr;
- selfVerificationMemOpWrapper(cUnit, regMap, funct);
-
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
+ }
}
static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
@@ -1881,12 +1431,12 @@
rlDest = getDestLoc(cUnit, mir, 0);
rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
-#else
- int regMap = rlResult.lowReg << 8 | tReg;
- selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
-
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
storeValue(cUnit, rlDest, rlResult);
break;
@@ -1900,14 +1450,12 @@
rlDest = getDestLocWide(cUnit, mir, 0, 1);
rlResult = evalLoc(cUnit, rlDest, kAnyReg, true);
loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
-#else
- int regMap = rlResult.highReg << 16 |
- rlResult.lowReg << 8 | tReg;
- selfVerificationMemOpWrapper(cUnit, regMap,
- &selfVerificationLoadDoubleword);
-
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
storeValueWide(cUnit, rlDest, rlResult);
break;
@@ -1927,11 +1475,12 @@
rlSrc = getSrcLoc(cUnit, mir, 0);
rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
-#else
- int regMap = rlSrc.lowReg << 8 | tReg;
- selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
break;
}
@@ -1945,12 +1494,12 @@
rlSrc = getSrcLocWide(cUnit, mir, 0, 1);
rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
-#if !defined(WITH_SELF_VERIFICATION)
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = true;
+#endif
storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
-#else
- int regMap = rlSrc.highReg << 16 | rlSrc.lowReg << 8 | tReg;
- selfVerificationMemOpWrapper(cUnit, regMap,
- &selfVerificationStoreDoubleword);
+#if defined(WITH_SELF_VERIFICATION)
+ cUnit->heapMemOp = false;
#endif
break;
}
@@ -4114,6 +3663,10 @@
}
dvmCompilerApplyGlobalOptimizations(cUnit);
+
+#if defined(WITH_SELF_VERIFICATION)
+ selfVerificationBranchInsertPass(cUnit);
+#endif
}
/* Accept the work and start compiling */
diff --git a/vm/compiler/codegen/arm/Thumb/Factory.c b/vm/compiler/codegen/arm/Thumb/Factory.c
index 2348b3a..586e640 100644
--- a/vm/compiler/codegen/arm/Thumb/Factory.c
+++ b/vm/compiler/codegen/arm/Thumb/Factory.c
@@ -457,6 +457,10 @@
assert(0);
}
res = newLIR3(cUnit, opCode, rDest, rBase, rNewIndex);
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ res->branchInsertSV = true;
+#endif
if (scale)
freeTemp(cUnit, rNewIndex);
return (first) ? first : res;
@@ -490,6 +494,10 @@
assert(0);
}
res = newLIR3(cUnit, opCode, rSrc, rBase, rNewIndex);
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ res->branchInsertSV = true;
+#endif
if (scale)
freeTemp(cUnit, rNewIndex);
return (first) ? first : res;
@@ -625,7 +633,12 @@
freeTemp(cUnit, rTmp);
}
}
-
+#if defined(WITH_SELF_VERIFICATION)
+ if (load != NULL && cUnit->heapMemOp)
+ load->branchInsertSV = true;
+ if (load2 != NULL && cUnit->heapMemOp)
+ load2->branchInsertSV = true;
+#endif
return res;
}
@@ -726,6 +739,12 @@
}
freeTemp(cUnit, rScratch);
}
+#if defined(WITH_SELF_VERIFICATION)
+ if (store != NULL && cUnit->heapMemOp)
+ store->branchInsertSV = true;
+ if (store2 != NULL && cUnit->heapMemOp)
+ store2->branchInsertSV = true;
+#endif
return res;
}
diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.c b/vm/compiler/codegen/arm/Thumb2/Factory.c
index ea93bbf..433953e 100644
--- a/vm/compiler/codegen/arm/Thumb2/Factory.c
+++ b/vm/compiler/codegen/arm/Thumb2/Factory.c
@@ -660,6 +660,7 @@
int rIndex, int rDest, int scale, OpSize size)
{
bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
+ ArmLIR *load;
ArmOpCode opCode = kThumbBkpt;
bool thumbForm = (allLowRegs && (scale == 0));
int regPtr;
@@ -683,7 +684,12 @@
} else {
opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
}
- return newLIR3(cUnit, opCode, rDest, regPtr, 0);
+ load = newLIR3(cUnit, opCode, rDest, regPtr, 0);
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ load->branchInsertSV = true;
+#endif
+ return load;
case kWord:
opCode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
break;
@@ -703,15 +709,22 @@
assert(0);
}
if (thumbForm)
- return newLIR3(cUnit, opCode, rDest, rBase, rIndex);
+ load = newLIR3(cUnit, opCode, rDest, rBase, rIndex);
else
- return newLIR4(cUnit, opCode, rDest, rBase, rIndex, scale);
+ load = newLIR4(cUnit, opCode, rDest, rBase, rIndex, scale);
+
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ load->branchInsertSV = true;
+#endif
+ return load;
}
static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
int rIndex, int rSrc, int scale, OpSize size)
{
bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
+ ArmLIR *store;
ArmOpCode opCode = kThumbBkpt;
bool thumbForm = (allLowRegs && (scale == 0));
int regPtr;
@@ -735,7 +748,12 @@
} else {
opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
}
- return newLIR3(cUnit, opCode, rSrc, regPtr, 0);
+ store = newLIR3(cUnit, opCode, rSrc, regPtr, 0);
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ store->branchInsertSV = true;
+#endif
+ return store;
case kWord:
opCode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
break;
@@ -751,9 +769,15 @@
assert(0);
}
if (thumbForm)
- return newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
+ store = newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
else
- return newLIR4(cUnit, opCode, rSrc, rBase, rIndex, scale);
+ store = newLIR4(cUnit, opCode, rSrc, rBase, rIndex, scale);
+
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ store->branchInsertSV = true;
+#endif
+ return store;
}
/*
@@ -872,6 +896,10 @@
if (rBase == rFP) {
annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
}
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ load->branchInsertSV = true;
+#endif
return res;
}
@@ -982,6 +1010,10 @@
if (rBase == rFP) {
annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
}
+#if defined(WITH_SELF_VERIFICATION)
+ if (cUnit->heapMemOp)
+ store->branchInsertSV = true;
+#endif
return res;
}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S
new file mode 100644
index 0000000..21e23a9
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S
@@ -0,0 +1,19 @@
+#if defined(WITH_SELF_VERIFICATION)
+ /*
+ * This handler encapsulates heap memory ops for selfVerification mode.
+ *
+ * The call to the handler is inserted prior to a heap memory operation.
+ * This handler then calls a function to decode the memory op, and process
+ * it accordingly. Afterwards, the handler changes the return address to
+ * skip the memory op so it never gets executed.
+ */
+ vpush {d0-d15} @ save out all fp registers
+ push {r0-r12,lr} @ save out all registers
+ mov r0, lr @ arg0 <- link register
+ mov r1, sp @ arg1 <- stack pointer
+ ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
+ blx r2 @ decode and handle the mem op
+ pop {r0-r12,lr} @ restore all registers
+ vpop {d0-d15} @ restore all fp registers
+ bx lr @ return to compiled code
+#endif
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index 8855d46..d991bed 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -51,8 +51,7 @@
JIT_TEMPLATE(CMPL_FLOAT_VFP)
JIT_TEMPLATE(SQRT_DOUBLE_VFP)
JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
-JIT_TEMPLATE(SAVE_STATE)
-JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(MEM_OP_DECODE)
JIT_TEMPLATE(STRING_COMPARETO)
JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_MEM_OP_DECODE.S b/vm/compiler/template/armv5te/TEMPLATE_MEM_OP_DECODE.S
new file mode 100644
index 0000000..ecd4eaa
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_MEM_OP_DECODE.S
@@ -0,0 +1,17 @@
+#if defined(WITH_SELF_VERIFICATION)
+ /*
+ * This handler encapsulates heap memory ops for selfVerification mode.
+ *
+ * The call to the handler is inserted prior to a heap memory operation.
+ * This handler then calls a function to decode the memory op, and process
+ * it accordingly. Afterwards, the handler changes the return address to
+ * skip the memory op so it never gets executed.
+ */
+ push {r0-r12,lr} @ save out all registers
+ mov r0, lr @ arg0 <- link register
+ mov r1, sp @ arg1 <- stack pointer
+ ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
+ blx r2 @ decode and handle the mem op
+ pop {r0-r12,lr} @ restore all registers
+ bx lr @ return to compiled code
+#endif
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index c7ae80a..e81383c 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -36,8 +36,7 @@
JIT_TEMPLATE(SHR_LONG)
JIT_TEMPLATE(USHR_LONG)
JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
-JIT_TEMPLATE(SAVE_STATE)
-JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(MEM_OP_DECODE)
JIT_TEMPLATE(STRING_COMPARETO)
JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 0e817a6..1709bf3 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -79,6 +79,10 @@
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+#if defined(WITH_SELF_VERIFICATION)
+.LdvmSelfVerificationMemOpDecode:
+ .word dvmSelfVerificationMemOpDecode
+#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index 8855d46..d991bed 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -51,8 +51,7 @@
JIT_TEMPLATE(CMPL_FLOAT_VFP)
JIT_TEMPLATE(SQRT_DOUBLE_VFP)
JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
-JIT_TEMPLATE(SAVE_STATE)
-JIT_TEMPLATE(RESTORE_STATE)
+JIT_TEMPLATE(MEM_OP_DECODE)
JIT_TEMPLATE(STRING_COMPARETO)
JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 3090a17..7ecad39 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -1056,49 +1056,28 @@
/* ------------------------------ */
.balign 4
- .global dvmCompiler_TEMPLATE_SAVE_STATE
-dvmCompiler_TEMPLATE_SAVE_STATE:
-/* File: armv5te-vfp/TEMPLATE_SAVE_STATE.S */
+ .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
+dvmCompiler_TEMPLATE_MEM_OP_DECODE:
+/* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */
+#if defined(WITH_SELF_VERIFICATION)
/*
- * This handler performs a register save for selfVerification mode.
- * On entry:
- * Top of stack + 4: r7 value to save
- * Top of stack + 0: r0 value to save
- * r0 - offset from rGLUE to the beginning of the heapArgSpace record
- * r7 - the value of regMap
+ * This handler encapsulates heap memory ops for selfVerification mode.
*
- * The handler must save regMap, r0-r12 and then return with r0-r12
- * with their original values (note that this means r0 and r7 must take
- * the values on the stack - not the ones in those registers on entry.
- * Finally, the two registers previously pushed must be popped.
+ * The call to the handler is inserted prior to a heap memory operation.
+ * This handler then calls a function to decode the memory op, and process
+ * it accordingly. Afterwards, the handler changes the return address to
+ * skip the memory op so it never gets executed.
*/
- add r0, r0, rGLUE @ pointer to heapArgSpace
- stmia r0!, {r7} @ save regMap
- ldr r7, [r13, #0] @ recover r0 value
- stmia r0!, {r7} @ save r0
- ldr r7, [r13, #4] @ recover r7 value
- stmia r0!, {r1-r12}
- add r0, #12 @ move to start of FP save regio
- vstmia r0, {d0-d15}
- pop {r0, r7} @ recover r0, r7
- bx lr
-
-/* ------------------------------ */
- .balign 4
- .global dvmCompiler_TEMPLATE_RESTORE_STATE
-dvmCompiler_TEMPLATE_RESTORE_STATE:
-/* File: armv5te-vfp/TEMPLATE_RESTORE_STATE.S */
- /*
- * This handler restores state following a selfVerification memory access.
- * On entry:
- * r0 - offset from rGLUE to the 1st element of the coreRegs save array.
- */
- add r0, r0, rGLUE @ pointer to heapArgSpace.coreRegs[0]
- add r0, #64 @ pointer to heapArgSpace.fpRegs[0]
- vldmia r0, {d0-d15}
- sub r0, #64 @ pointer to heapArgSpace.coreRegs[0]
- ldmia r0, {r0-r12}
- bx lr
+ vpush {d0-d15} @ save out all fp registers
+ push {r0-r12,lr} @ save out all registers
+ mov r0, lr @ arg0 <- link register
+ mov r1, sp @ arg1 <- stack pointer
+ ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
+ blx r2 @ decode and handle the mem op
+ pop {r0-r12,lr} @ restore all registers
+ vpop {d0-d15} @ restore all fp registers
+ bx lr @ return to compiled code
+#endif
/* ------------------------------ */
.balign 4
@@ -1535,6 +1514,10 @@
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+#if defined(WITH_SELF_VERIFICATION)
+.LdvmSelfVerificationMemOpDecode:
+ .word dvmSelfVerificationMemOpDecode
+#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index ffb9786..173cec0 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -786,44 +786,26 @@
/* ------------------------------ */
.balign 4
- .global dvmCompiler_TEMPLATE_SAVE_STATE
-dvmCompiler_TEMPLATE_SAVE_STATE:
-/* File: armv5te/TEMPLATE_SAVE_STATE.S */
+ .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
+dvmCompiler_TEMPLATE_MEM_OP_DECODE:
+/* File: armv5te/TEMPLATE_MEM_OP_DECODE.S */
+#if defined(WITH_SELF_VERIFICATION)
/*
- * This handler performs a register save for selfVerification mode.
- * On entry:
- * Top of stack + 4: r7 value to save
- * Top of stack + 0: r0 value to save
- * r0 - offset from rGLUE to the beginning of the heapArgSpace record
- * r7 - the value of regMap
+ * This handler encapsulates heap memory ops for selfVerification mode.
*
- * The handler must save regMap, r0-r12 and then return with r0-r12
- * with their original values (note that this means r0 and r7 must take
- * the values on the stack - not the ones in those registers on entry.
- * Finally, the two registers previously pushed must be popped.
+ * The call to the handler is inserted prior to a heap memory operation.
+ * This handler then calls a function to decode the memory op, and process
+ * it accordingly. Afterwards, the handler changes the return address to
+ * skip the memory op so it never gets executed.
*/
- add r0, r0, rGLUE @ pointer to heapArgSpace
- stmia r0!, {r7} @ save regMap
- ldr r7, [r13, #0] @ recover r0 value
- stmia r0!, {r7} @ save r0
- ldr r7, [r13, #4] @ recover r7 value
- stmia r0!, {r1-r12}
- pop {r0, r7} @ recover r0, r7
- bx lr
-
-/* ------------------------------ */
- .balign 4
- .global dvmCompiler_TEMPLATE_RESTORE_STATE
-dvmCompiler_TEMPLATE_RESTORE_STATE:
-/* File: armv5te/TEMPLATE_RESTORE_STATE.S */
- /*
- * This handler restores state following a selfVerification memory access.
- * On entry:
- * r0 - offset from rGLUE to the 1st element of the coreRegs save array.
- */
- add r0, r0, rGLUE @ pointer to heapArgSpace.coreRegs[0]
- ldmia r0, {r0-r12}
- bx lr
+ push {r0-r12,lr} @ save out all registers
+ mov r0, lr @ arg0 <- link register
+ mov r1, sp @ arg1 <- stack pointer
+ ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
+ blx r2 @ decode and handle the mem op
+ pop {r0-r12,lr} @ restore all registers
+ bx lr @ return to compiled code
+#endif
/* ------------------------------ */
.balign 4
@@ -1260,6 +1242,10 @@
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+#if defined(WITH_SELF_VERIFICATION)
+.LdvmSelfVerificationMemOpDecode:
+ .word dvmSelfVerificationMemOpDecode
+#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index b157ff3..872a1df 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -1056,49 +1056,28 @@
/* ------------------------------ */
.balign 4
- .global dvmCompiler_TEMPLATE_SAVE_STATE
-dvmCompiler_TEMPLATE_SAVE_STATE:
-/* File: armv5te-vfp/TEMPLATE_SAVE_STATE.S */
+ .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
+dvmCompiler_TEMPLATE_MEM_OP_DECODE:
+/* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */
+#if defined(WITH_SELF_VERIFICATION)
/*
- * This handler performs a register save for selfVerification mode.
- * On entry:
- * Top of stack + 4: r7 value to save
- * Top of stack + 0: r0 value to save
- * r0 - offset from rGLUE to the beginning of the heapArgSpace record
- * r7 - the value of regMap
+ * This handler encapsulates heap memory ops for selfVerification mode.
*
- * The handler must save regMap, r0-r12 and then return with r0-r12
- * with their original values (note that this means r0 and r7 must take
- * the values on the stack - not the ones in those registers on entry.
- * Finally, the two registers previously pushed must be popped.
+ * The call to the handler is inserted prior to a heap memory operation.
+ * This handler then calls a function to decode the memory op, and process
+ * it accordingly. Afterwards, the handler changes the return address to
+ * skip the memory op so it never gets executed.
*/
- add r0, r0, rGLUE @ pointer to heapArgSpace
- stmia r0!, {r7} @ save regMap
- ldr r7, [r13, #0] @ recover r0 value
- stmia r0!, {r7} @ save r0
- ldr r7, [r13, #4] @ recover r7 value
- stmia r0!, {r1-r12}
- add r0, #12 @ move to start of FP save regio
- vstmia r0, {d0-d15}
- pop {r0, r7} @ recover r0, r7
- bx lr
-
-/* ------------------------------ */
- .balign 4
- .global dvmCompiler_TEMPLATE_RESTORE_STATE
-dvmCompiler_TEMPLATE_RESTORE_STATE:
-/* File: armv5te-vfp/TEMPLATE_RESTORE_STATE.S */
- /*
- * This handler restores state following a selfVerification memory access.
- * On entry:
- * r0 - offset from rGLUE to the 1st element of the coreRegs save array.
- */
- add r0, r0, rGLUE @ pointer to heapArgSpace.coreRegs[0]
- add r0, #64 @ pointer to heapArgSpace.fpRegs[0]
- vldmia r0, {d0-d15}
- sub r0, #64 @ pointer to heapArgSpace.coreRegs[0]
- ldmia r0, {r0-r12}
- bx lr
+ vpush {d0-d15} @ save out all fp registers
+ push {r0-r12,lr} @ save out all registers
+ mov r0, lr @ arg0 <- link register
+ mov r1, sp @ arg1 <- stack pointer
+ ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
+ blx r2 @ decode and handle the mem op
+ pop {r0-r12,lr} @ restore all registers
+ vpop {d0-d15} @ restore all fp registers
+ bx lr @ return to compiled code
+#endif
/* ------------------------------ */
.balign 4
@@ -1541,6 +1520,10 @@
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+#if defined(WITH_SELF_VERIFICATION)
+.LdvmSelfVerificationMemOpDecode:
+ .word dvmSelfVerificationMemOpDecode
+#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index 3231968..67d005e 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -38,19 +38,6 @@
} InterpEntry;
#if defined(WITH_JIT)
-#if defined(WITH_SELF_VERIFICATION)
-/*
- * Note: layout is important. This record hold saved state information
- * and is used by both C, generated code in the cache, and assembler handlers.
- */
-typedef struct HeapArgSpace {
-//FIXME: This is arm-specific. Need to be able to redefine this by target
- int regMap;
- int coreRegs[16];
- int fpRegs[32];
-} HeapArgSpace;
-#endif
-
/*
* There are six entry points from the compiled code to the interpreter:
* 1) dvmJitToInterpNormal: find if there is a corresponding compilation for
@@ -186,9 +173,6 @@
int currRunLen; // Length of run in 16-bit words
int lastThreshFilter;
const u2* lastPC; // Stage the PC first for the threaded interpreter
-#if defined(WITH_SELF_VERIFICATION)
- struct HeapArgSpace heapArgSpace;
-#endif
const u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
JitTraceRun trace[MAX_JIT_RUN_LEN];
double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];