diff options
| -rw-r--r-- | src/asm_support.h | 9 | ||||
| -rw-r--r-- | src/compiler/CompilerIR.h | 3 | ||||
| -rw-r--r-- | src/compiler/Dataflow.cc | 4 | ||||
| -rw-r--r-- | src/compiler/Frontend.cc | 3 | ||||
| -rw-r--r-- | src/compiler/SSATransformation.cc | 8 | ||||
| -rw-r--r-- | src/compiler/Utility.cc | 10 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArchUtility.cc | 3 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArmLIR.h | 7 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/MethodCodegenDriver.cc | 40 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Factory.cc | 6 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 22 | ||||
| -rw-r--r-- | src/jni_internal_arm.cc | 18 | ||||
| -rw-r--r-- | src/runtime_support.S | 17 | ||||
| -rw-r--r-- | src/runtime_support.h | 1 | ||||
| -rw-r--r-- | src/thread.cc | 5 | ||||
| -rw-r--r-- | src/thread.h | 1 |
16 files changed, 125 insertions, 32 deletions
diff --git a/src/asm_support.h b/src/asm_support.h index 6eda4bf8a4..097ab7a2ee 100644 --- a/src/asm_support.h +++ b/src/asm_support.h @@ -3,9 +3,16 @@ #ifndef ART_SRC_ASM_SUPPORT_H_ #define ART_SRC_ASM_SUPPORT_H_ +#if defined(__arm__) +#define rSUSPEND r4 +#define rSELF r9 +#define rLR r14 +#define SUSPEND_CHECK_INTERVAL (1000) +#endif + #if defined(__i386__) // Offset of field Thread::self_ verified in InitCpu -#define THREAD_SELF_OFFSET 0x161 +#define THREAD_SELF_OFFSET 0x165 #endif #endif // ART_SRC_ASM_SUPPORT_H_ diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h index b6972920d3..0965c14218 100644 --- a/src/compiler/CompilerIR.h +++ b/src/compiler/CompilerIR.h @@ -87,6 +87,7 @@ typedef enum { kMIRInlined, // Invoke is inlined (ie dead) kMIRInlinedPred, // Invoke is inlined via prediction kMIRCallee, // Instruction is inlined from callee + kMIRIgnoreSuspendCheck, } MIROptimizationFlagPositons; #define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck) @@ -96,6 +97,7 @@ typedef enum { #define MIR_INLINED (1 << kMIRInlined) #define MIR_INLINED_PRED (1 << kMIRInlinedPred) #define MIR_CALLEE (1 << kMIRCallee) +#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck) typedef struct CallsiteInfo { const char* classDescriptor; @@ -239,6 +241,7 @@ typedef struct CompilationUnit { GrowableList dfsOrder; GrowableList domPostOrderTraversal; GrowableList throwLaunchpads; + GrowableList suspendLaunchpads; ArenaBitVector* tryBlockAddr; ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks ArenaBitVector* tempBlockV; diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc index 827470e2e4..d4b5339e0b 100644 --- a/src/compiler/Dataflow.cc +++ b/src/compiler/Dataflow.cc @@ -2405,6 +2405,10 @@ static bool eliminateNullChecks( struct CompilationUnit* cUnit, if (predBBIdx == -1) break; predBB = (BasicBlock*)oatGrowableListGetElement( blockList, predBBIdx); + if ((predBB->dataFlowInfo == NULL) || + (predBB->dataFlowInfo->endingNullCheckV == NULL)) { + continue; + } oatIntersectBitVectors(cUnit->tempSSARegisterV, cUnit->tempSSARegisterV, predBB->dataFlowInfo->endingNullCheckV); diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index fdcce9cd46..6a01e36481 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -725,6 +725,9 @@ bool oatCompileMethod(const Compiler& compiler, Method* method, art::Instruction /* Intialize the throwLaunchpads list */ oatInitGrowableList(&cUnit.throwLaunchpads, 4); + /* Intialize the suspendLaunchpads list */ + oatInitGrowableList(&cUnit.suspendLaunchpads, 4); + /* Allocate the bit-vector to track the beginning of basic blocks */ ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.insnsSize, true /* expandable */); diff --git a/src/compiler/SSATransformation.cc b/src/compiler/SSATransformation.cc index dea197112a..1a488bb1fd 100644 --- a/src/compiler/SSATransformation.cc +++ b/src/compiler/SSATransformation.cc @@ -247,7 +247,9 @@ static bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb) BasicBlock* predBB = (BasicBlock* ) oatGrowableListGetElement( blockList, predIdx); /* tempBlockV = tempBlockV ^ dominators */ - oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators); + if (predBB->dominators != NULL) { + oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators); + } } oatSetBit(tempBlockV, bb->id); if (oatCompareBitVectors(tempBlockV, bb->dominators)) { @@ -452,7 +454,9 @@ static void insertPhiNodes(CompilationUnit* cUnit) (BasicBlock* ) oatGrowableListGetElement(blockList, idx); /* Merge the dominance frontier to tmpBlocks */ - oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier); + if (defBB->domFrontier != NULL) { + oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier); + } } if (oatCompareBitVectors(phiBlocks, tmpBlocks)) { change = true; diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc index 7d3a887d98..7b99966759 100644 --- a/src/compiler/Utility.cc +++ b/src/compiler/Utility.cc @@ -373,8 +373,9 @@ void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src) bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1, const ArenaBitVector* src2) { - if (src2 == NULL || - dest->storageSize != src1->storageSize || + DCHECK(src1 != NULL); + DCHECK(src2 != NULL); + if (dest->storageSize != src1->storageSize || dest->storageSize != src2->storageSize || dest->expandable != src1->expandable || dest->expandable != src2->expandable) @@ -393,8 +394,9 @@ bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1, bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1, const ArenaBitVector* src2) { - if (src2 == NULL || - dest->storageSize != src1->storageSize || + DCHECK(src1 != NULL); + DCHECK(src2 != NULL); + if (dest->storageSize != src1->storageSize || dest->storageSize != src2->storageSize || dest->expandable != src1->expandable || dest->expandable != src2->expandable) diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc index 1d6bb41b8a..45e1b19ee7 100644 --- a/src/compiler/codegen/arm/ArchUtility.cc +++ b/src/compiler/codegen/arm/ArchUtility.cc @@ -354,6 +354,9 @@ void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) case kArmPseudoThrowTarget: LOG(INFO) << "LT" << (intptr_t)lir << ":"; break; + case kArmPseudoSuspendTarget: + LOG(INFO) << "LS" << (intptr_t)lir << ":"; + break; case kArmPseudoCaseLabel: LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" << std::hex << lir->operands[0] << "|" << std::dec << diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h index 07e2e97661..e436eea6ed 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -28,7 +28,7 @@ * pointer in r0 as a hidden arg0. Otherwise used as codegen scratch * registers. * r0-r1: As in C/C++ r0 is 32-bit return register and r0/r1 is 64-bit - * r4 : Callee save (promotion target) + * r4 : (rSUSPEND) is reserved (suspend check assist) * r5 : Callee save (promotion target) * r6 : Callee save (promotion target) * r7 : Callee save (promotion target) @@ -243,7 +243,7 @@ typedef enum OpKind { /* * Annotate special-purpose core registers: - * - VM: r4PC, r5FP, and r6SELF + * - VM: r6SELF * - ARM architecture: r13sp, r14lr, and r15pc * * rPC, rFP, and rSELF are for architecture-independent code to use. @@ -253,7 +253,7 @@ typedef enum NativeRegisterPool { r1 = 1, r2 = 2, r3 = 3, - r4 = 4, + rSUSPEND = 4, r5 = 5, r6 = 6, r7 = 7, @@ -366,6 +366,7 @@ typedef enum ArmThrowKind { * Assemble.c. */ typedef enum ArmOpcode { + kArmPseudoSuspendTarget = -15, kArmPseudoThrowTarget = -14, kArmPseudoCaseLabel = -13, kArmPseudoMethodEntry = -12, diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc index 8dc388c7e3..41053a2def 100644 --- a/src/compiler/codegen/arm/MethodCodegenDriver.cc +++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc @@ -849,6 +849,8 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pMemcpy), rLR); loadConstant(cUnit, r2, (numArgs - 3) * 4); callNoUnwindHelper(cUnit, rLR); + // Restore Method* + loadCurrMethodDirect(cUnit, r0); } else { // Use vldm/vstm pair using r3 as a temp int regsLeft = std::min(numArgs - 3, 16); @@ -1111,10 +1113,12 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, case OP_RETURN: case OP_RETURN_OBJECT: + genSuspendPoll(cUnit, mir); storeValue(cUnit, retLoc, rlSrc[0]); break; case OP_RETURN_WIDE: + genSuspendPoll(cUnit, mir); rlDest = retLocWide; rlDest.fp = rlSrc[0].fp; storeValueWide(cUnit, rlDest, rlSrc[0]); @@ -1275,11 +1279,8 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, case OP_GOTO: case OP_GOTO_16: case OP_GOTO_32: - // TUNING: add MIR flag to disable when unnecessary - bool backwardBranch; - backwardBranch = (bb->taken->startOffset <= mir->offset); - if (backwardBranch) { - genSuspendPoll(cUnit, mir); + if (bb->taken->startOffset <= mir->offset) { + genSuspendTest(cUnit, mir); } genUnconditionalBranch(cUnit, &labelList[bb->taken->id]); break; @@ -1313,7 +1314,7 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, ArmConditionCode cond; backwardBranch = (bb->taken->startOffset <= mir->offset); if (backwardBranch) { - genSuspendPoll(cUnit, mir); + genSuspendTest(cUnit, mir); } rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg); rlSrc[1] = loadValue(cUnit, rlSrc[1], kCoreReg); @@ -1356,7 +1357,7 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, ArmConditionCode cond; backwardBranch = (bb->taken->startOffset <= mir->offset); if (backwardBranch) { - genSuspendPoll(cUnit, mir); + genSuspendTest(cUnit, mir); } rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg); opRegImm(cUnit, kOpCmp, rlSrc[0].lowReg, 0); @@ -1997,6 +1998,27 @@ void removeRedundantBranches(CompilationUnit* cUnit) } } +static void handleSuspendLaunchpads(CompilationUnit *cUnit) +{ + ArmLIR** suspendLabel = + (ArmLIR **) cUnit->suspendLaunchpads.elemList; + int numElems = cUnit->suspendLaunchpads.numUsed; + + for (int i = 0; i < numElems; i++) { + /* TUNING: move suspend count load into helper */ + ArmLIR* lab = suspendLabel[i]; + ArmLIR* resumeLab = (ArmLIR*)lab->operands[0]; + cUnit->currentDalvikOffset = lab->operands[1]; + oatAppendLIR(cUnit, (LIR *)lab); + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pTestSuspendFromCode), rLR); + loadWordDisp(cUnit, rSELF, + art::Thread::SuspendCountOffset().Int32Value(), rSUSPEND); + opReg(cUnit, kOpBlx, rLR); + genUnconditionalBranch(cUnit, resumeLab); + } +} + static void handleThrowLaunchpads(CompilationUnit *cUnit) { ArmLIR** throwLabel = @@ -2082,9 +2104,11 @@ void oatMethodMIR2LIR(CompilationUnit* cUnit) oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen, kPreOrderDFSTraversal, false /* Iterative */); - removeRedundantBranches(cUnit); + handleSuspendLaunchpads(cUnit); handleThrowLaunchpads(cUnit); + + removeRedundantBranches(cUnit); } /* Common initialization routine for an architecture family */ diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc index 254802d032..9321753da7 100644 --- a/src/compiler/codegen/arm/Thumb2/Factory.cc +++ b/src/compiler/codegen/arm/Thumb2/Factory.cc @@ -22,9 +22,9 @@ * */ -static int coreRegs[] = {r0, r1, r2, r3, r4, r5, r6, r7, rSELF, r8, r10, r11, - r12, rSP, rLR, rPC}; -static int reservedRegs[] = {rSELF, rSP, rLR, rPC}; +static int coreRegs[] = {r0, r1, r2, r3, rSUSPEND, r5, r6, r7, rSELF, r8, r10, + r11, r12, rSP, rLR, rPC}; +static int reservedRegs[] = {rSUSPEND, rSELF, rSP, rLR, rPC}; static int fpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15, fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23, diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index 2404ca7524..76d8b45b3f 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -1683,9 +1683,31 @@ static bool genArithOpInt(CompilationUnit* cUnit, MIR* mir, return false; } +/* Check if we need to check for pending suspend request */ +static void genSuspendTest(CompilationUnit* cUnit, MIR* mir) +{ + if (mir->optimizationFlags & MIR_IGNORE_SUSPEND_CHECK) { + return; + } + newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1); + ArmLIR* branch = opCondBranch(cUnit, kArmCondEq); + ArmLIR* retLab = newLIR0(cUnit, kArmPseudoTargetLabel); + retLab->defMask = ENCODE_ALL; + ArmLIR* target = (ArmLIR*)oatNew(sizeof(ArmLIR), true); + target->generic.dalvikOffset = cUnit->currentDalvikOffset; + target->opcode = kArmPseudoSuspendTarget; + target->operands[0] = (intptr_t)retLab; + target->operands[1] = mir->offset; + branch->generic.target = (LIR*)target; + oatInsertGrowableList(&cUnit->suspendLaunchpads, (intptr_t)target); +} + /* Check for pending suspend request. */ static void genSuspendPoll(CompilationUnit* cUnit, MIR* mir) { + if (mir->optimizationFlags & MIR_IGNORE_SUSPEND_CHECK) { + return; + } oatLockCallTemps(cUnit); // Explicit register usage int rSuspendCount = r1; ArmLIR* ld; diff --git a/src/jni_internal_arm.cc b/src/jni_internal_arm.cc index 65dc3806b6..8ba5717580 100644 --- a/src/jni_internal_arm.cc +++ b/src/jni_internal_arm.cc @@ -31,21 +31,21 @@ void ArmCreateInvokeStub(Method* method) { UniquePtr<ArmAssembler> assembler( down_cast<ArmAssembler*>(Assembler::Create(kArm))); #define __ assembler-> - // Size of frame - spill of R9/LR + Method* + possible receiver + arg array - size_t unpadded_frame_size = (3 * kPointerSize) + + // Size of frame - spill of R4,R9/LR + Method* + possible receiver + arg array + size_t unpadded_frame_size = (4 * kPointerSize) + (method->IsStatic() ? 0 : kPointerSize) + method->NumArgArrayBytes(); size_t frame_size = RoundUp(unpadded_frame_size, kStackAlignment); - // Spill R9 and LR - RegList save = (1 << R9); + // Spill R4,R9 and LR + RegList save = (1 << R9) | (1 << R4); __ PushList(save | (1 << LR)); // Move the managed thread pointer into R9. __ mov(R9, ShifterOperand(R2)); - // Move frame down for arguments less 2 pushed values above - __ AddConstant(SP, -frame_size + (2 * kPointerSize)); + // Move frame down for arguments less 3 pushed values above + __ AddConstant(SP, -frame_size + (3 * kPointerSize)); // Can either get 3 or 2 arguments into registers size_t reg_bytes = (method->IsStatic() ? 3 : 2) * kPointerSize; @@ -112,10 +112,10 @@ void ArmCreateInvokeStub(Method* method) { } } - // Remove the frame less the spilled R9 and LR - __ AddConstant(SP, frame_size - (2 * kPointerSize)); + // Remove the frame less the spilled R4, R9 and LR + __ AddConstant(SP, frame_size - (3 * kPointerSize)); - // Pop R9 and the LR into PC + // Pop R4, R9 and the LR into PC __ PopList(save | (1 << PC)); // TODO: store native_entry in the stub table ByteArray* code = ByteArray::Alloc(assembler->CodeSize()); diff --git a/src/runtime_support.S b/src/runtime_support.S index 24883fc7b0..652224368f 100644 --- a/src/runtime_support.S +++ b/src/runtime_support.S @@ -159,6 +159,23 @@ art_ushr_long: mov r1, r1, lsr r2 @ r1<- r1 >>> r2 bx lr + .balign 4 + .global art_test_suspend + .extern artCheckSuspendFromCode +art_test_suspend: + /* + * Check to see if there's a pending suspend request on our thread. + * reset rSUSPEND to SUSPEND_CHECK_INTERVAL. + * On entry, rSUSPEND holds the suspend request value + * [TUNING: move load of suspend check value into this stub. + */ + cmp rSUSPEND, #0 + mov rSUSPEND, #SUSPEND_CHECK_INTERVAL + bxeq rLR + mov r0, rSELF + b artCheckSuspendFromCode + + #endif #if defined(__i386__) diff --git a/src/runtime_support.h b/src/runtime_support.h index d421fccb87..ed047c934f 100644 --- a/src/runtime_support.h +++ b/src/runtime_support.h @@ -15,6 +15,7 @@ extern "C" void art_deliver_exception(void*); extern "C" void art_throw_div_zero_from_code(); extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit); extern "C" void art_invoke_interface_trampoline(void*, void*, void*, void*); + extern "C" void art_test_suspend(); /* Conversions */ extern "C" float __aeabi_i2f(int op1); // OP_INT_TO_FLOAT diff --git a/src/thread.cc b/src/thread.cc index d86a0c5674..8ab10aff3c 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -178,7 +178,7 @@ void LockObjectFromCode(Thread* thread, Object* obj) { // TODO: throw and unwind on failure. } -void CheckSuspendFromCode(Thread* thread) { +extern "C" void artCheckSuspendFromCode(Thread* thread) { Runtime::Current()->GetThreadList()->FullSuspendCheck(thread); } @@ -367,6 +367,7 @@ void Thread::InitFunctionPointers() { pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code; pThrowDivZeroFromCode = art_throw_div_zero_from_code; pInvokeInterfaceTrampoline = art_invoke_interface_trampoline; + pTestSuspendFromCode = art_test_suspend; #endif pDeliverException = art_deliver_exception; pF2l = F2L; @@ -391,7 +392,7 @@ void Thread::InitFunctionPointers() { pLockObjectFromCode = LockObjectFromCode; pUnlockObjectFromCode = UnlockObjectFromCode; pFindInstanceFieldFromCode = Field::FindInstanceFieldFromCode; - pCheckSuspendFromCode = CheckSuspendFromCode; + pCheckSuspendFromCode = artCheckSuspendFromCode; pStackOverflowFromCode = StackOverflowFromCode; pThrowVerificationErrorFromCode = ThrowVerificationErrorFromCode; pThrowNegArraySizeFromCode = ThrowNegArraySizeFromCode; diff --git a/src/thread.h b/src/thread.h index 03f3ef69e2..212abdcab6 100644 --- a/src/thread.h +++ b/src/thread.h @@ -224,6 +224,7 @@ class PACKED Thread { StaticStorageBase* (*pInitializeStaticStorage)(uint32_t, const Method*); Field* (*pFindInstanceFieldFromCode)(uint32_t, const Method*); void (*pCheckSuspendFromCode)(Thread*); + void (*pTestSuspendFromCode)(); void (*pStackOverflowFromCode)(Method*); void (*pThrowNullPointerFromCode)(); void (*pThrowArrayBoundsFromCode)(int32_t, int32_t); |