diff options
Diffstat (limited to 'vm/compiler/codegen/arm')
| -rw-r--r-- | vm/compiler/codegen/arm/ArmLIR.h | 2 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 516 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/Codegen.h | 4 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/CodegenDriver.c | 629 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/Thumb/Factory.c | 21 | ||||
| -rw-r--r-- | vm/compiler/codegen/arm/Thumb2/Factory.c | 44 |
6 files changed, 671 insertions, 545 deletions
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h index 21e2a3273..b329aedb7 100644 --- a/vm/compiler/codegen/arm/ArmLIR.h +++ b/vm/compiler/codegen/arm/ArmLIR.h @@ -723,6 +723,8 @@ typedef struct ArmLIR { 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 c3ad957ac..5cb8ff697 100644 --- a/vm/compiler/codegen/arm/Assemble.c +++ b/vm/compiler/codegen/arm/Assemble.c @@ -1841,3 +1841,519 @@ done: 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 b148bda9b..0674b8b98 100644 --- a/vm/compiler/codegen/arm/Codegen.h +++ b/vm/compiler/codegen/arm/Codegen.h @@ -45,6 +45,10 @@ static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir); 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 b0e16b82f..1bf80cb8f 100644 --- a/vm/compiler/codegen/arm/CodegenDriver.c +++ b/vm/compiler/codegen/arm/CodegenDriver.c @@ -208,411 +208,37 @@ static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir) } #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) -{ - 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)]; - } -} - -/* Decode contents of heapArgSpace to determine reg to load into */ -static void selfVerificationLoadDecodeData(HeapArgSpace* heapArgSpace, - int data, int reg) -{ - if (!FPREG(reg)) { - assert(reg < 16); - heapArgSpace->coreRegs[reg] = data; - } else { - assert(!DOUBLEREG(reg)); - heapArgSpace->fpRegs[(reg & FP_REG_MASK)] = data; - } -} - -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); - - 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) +static void selfVerificationBranchInsert(LIR *currentLIR, ArmOpCode opCode, + int dest, int src1) { - 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); + ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + insn->opCode = opCode; + insn->operands[0] = dest; + insn->operands[1] = src1; + setupResourceMasks(insn); + dvmCompilerInsertLIRBefore(currentLIR, (LIR *) insn); } -static void selfVerificationStoreHalfword(InterpState* interpState) +static void selfVerificationBranchInsertPass(CompilationUnit *cUnit) { - 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); -} + ArmLIR *thisLIR; + ArmLIR *branchLIR = dvmCompilerNew(sizeof(ArmLIR), true); + TemplateOpCode opCode = TEMPLATE_MEM_OP_DECODE; -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; + 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 (!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 @@ static void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset) 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 @@ static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset) 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 @@ static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size, 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 @@ static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size, 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 @@ static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size, /* 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 @@ static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size, 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 @@ static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size, 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 @@ static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size, 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 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) 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 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) 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 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) 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 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) 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 @@ gen_fallthrough: } 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 2348b3a84..586e64039 100644 --- a/vm/compiler/codegen/arm/Thumb/Factory.c +++ b/vm/compiler/codegen/arm/Thumb/Factory.c @@ -457,6 +457,10 @@ static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase, 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 @@ static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, 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 @@ static ArmLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase, 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 @@ static ArmLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase, } 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 ea93bbf0b..433953ea2 100644 --- a/vm/compiler/codegen/arm/Thumb2/Factory.c +++ b/vm/compiler/codegen/arm/Thumb2/Factory.c @@ -660,6 +660,7 @@ static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase, 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 @@ static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase, } 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 @@ static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase, 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 @@ static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, } 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 @@ static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, 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 @@ static ArmLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase, 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 @@ static ArmLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase, if (rBase == rFP) { annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */); } +#if defined(WITH_SELF_VERIFICATION) + if (cUnit->heapMemOp) + store->branchInsertSV = true; +#endif return res; } |
