diff options
| author | 2011-09-09 09:59:52 -0700 | |
|---|---|---|
| committer | 2011-09-09 12:30:27 -0700 | |
| commit | cefd1878e09fb0fb519a175545a99eb8c4a375b2 (patch) | |
| tree | 6a1624e0cc03a93efdaf575a24bbc0214fa0e243 | |
| parent | 449b4bdf90b527ef7a42faaf087494538e62363c (diff) | |
Add stack overflow check
Change-Id: I67fcb5ad4bda304879ce05561b03aa7cd46e9990
| -rw-r--r-- | src/compiler/CompilerIR.h | 1 | ||||
| -rw-r--r-- | src/compiler/Dataflow.cc | 10 | ||||
| -rw-r--r-- | src/compiler/Frontend.cc | 3 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/MethodCodegenDriver.cc | 30 | ||||
| -rw-r--r-- | src/thread.cc | 10 | ||||
| -rw-r--r-- | src/thread.h | 2 |
6 files changed, 53 insertions, 3 deletions
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h index 4ce31776fd..9c9bcb0bff 100644 --- a/src/compiler/CompilerIR.h +++ b/src/compiler/CompilerIR.h @@ -263,6 +263,7 @@ typedef struct CompilationUnit { int frameSize; unsigned int coreSpillMask; unsigned int fpSpillMask; + unsigned int attrs; /* * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in * mechanism to propogate the original Dalvik opcode address to the diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc index 4e3c9c4398..cb208a574c 100644 --- a/src/compiler/Dataflow.cc +++ b/src/compiler/Dataflow.cc @@ -1989,6 +1989,16 @@ bool oatDoSSAConversion(CompilationUnit* cUnit, BasicBlock* bb) int dfAttributes = oatDataFlowAttributes[mir->dalvikInsn.opcode]; + int flags = dexGetFlagsFromOpcode(mir->dalvikInsn.opcode); + + if (flags & kInstrCanThrow) { + cUnit->attrs &= ~METHOD_IS_THROW_FREE; + } + + if (flags & kInstrInvoke) { + cUnit->attrs &= ~METHOD_IS_LEAF; + } + int numUses = 0; if (dfAttributes & DF_FORMAT_35C) { diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index 702611de2c..2f86c48f6d 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -707,6 +707,9 @@ bool oatCompileMethod(Method* method, art::InstructionSet insnSet) 0; #endif + /* Assume non-throwing leaf */ + cUnit.attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE); + /* Initialize the block list */ oatInitGrowableList(&cUnit.blockList, 40); diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc index cf1ad0473e..2319a712e9 100644 --- a/src/compiler/codegen/arm/MethodCodegenDriver.cc +++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc @@ -1809,14 +1809,42 @@ static bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) oatLockTemp(cUnit, r1); oatLockTemp(cUnit, r2); oatLockTemp(cUnit, r3); + + /* + * We can safely skip the stack overflow check if we're + * a leaf *and* our frame size < fudge factor. + */ + bool skipOverflowCheck = ((cUnit->attrs & METHOD_IS_LEAF) && + ((size_t)cUnit->frameSize < + art::Thread::kStackOverflowReservedBytes)); newLIR0(cUnit, kArmPseudoMethodEntry); + if (!skipOverflowCheck) { + /* Load stack limit */ + loadWordDisp(cUnit, rSELF, + art::Thread::StackEndOffset().Int32Value(), r12); + } /* Spill core callee saves */ newLIR1(cUnit, kThumb2Push, cUnit->coreSpillMask); /* Need to spill any FP regs? */ if (cUnit->numFPSpills) { newLIR1(cUnit, kThumb2VPushCS, cUnit->numFPSpills); } - opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (cUnit->numSpills * 4)); + if (!skipOverflowCheck) { + opRegRegImm(cUnit, kOpSub, rLR, rSP, + cUnit->frameSize - (cUnit->numSpills * 4)); + opRegReg(cUnit, kOpCmp, rLR, r12); // Stack overflow? + /* Begin conditional skip */ + genIT(cUnit, kArmCondCc, "TT"); // Carry clear; unsigned < + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pStackOverflowFromCode), rLR); + newLIR2(cUnit, kThumbAddRI8, rSP, cUnit->numSpills * 4); + opReg(cUnit, kOpBlx, rLR); + /* End conditional skip */ + genRegCopy(cUnit, rSP, rLR); // Establish stack + } else { + opRegImm(cUnit, kOpSub, rSP, + cUnit->frameSize - (cUnit->numSpills * 4)); + } storeBaseDisp(cUnit, rSP, 0, r0, kWord); flushIns(cUnit); oatFreeTemp(cUnit, r0); diff --git a/src/thread.cc b/src/thread.cc index e1de92d0d0..45ff6dd73e 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -136,6 +136,12 @@ static void CheckSuspendFromCode(Thread* thread) { */ } +// TODO: placeholder +static void StackOverflowFromCode(Method* method) { + //NOTE: to save code space, this handler needs to look up its own Thread* + UNIMPLEMENTED(FATAL) << "Stack overflow: " << PrettyMethod(method); +} + void Thread::InitFunctionPointers() { #if defined(__arm__) pShlLong = art_shl_long; @@ -188,6 +194,7 @@ void Thread::InitFunctionPointers() { pUnlockObjectFromCode = UnlockObjectFromCode; pFindFieldFromCode = Field::FindFieldFromCode; pCheckSuspendFromCode = CheckSuspendFromCode; + pStackOverflowFromCode = StackOverflowFromCode; pDebugMe = DebugMe; } @@ -380,7 +387,6 @@ void Thread::InitStackHwm() { PLOG(FATAL) << "pthread_attr_getstack failed"; } - const size_t kStackOverflowReservedBytes = 1024; // Space to throw a StackOverflowError in. if (stack_size <= kStackOverflowReservedBytes) { LOG(FATAL) << "attempt to attach a thread with a too-small stack (" << stack_size << " bytes)"; } @@ -388,7 +394,7 @@ void Thread::InitStackHwm() { // stack_base is the "lowest addressable byte" of the stack. // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room // to throw a StackOverflowError. - stack_end_ = reinterpret_cast<byte*>(stack_base) - kStackOverflowReservedBytes; + stack_end_ = reinterpret_cast<byte*>(stack_base) + kStackOverflowReservedBytes; // Sanity check. int stack_variable; diff --git a/src/thread.h b/src/thread.h index 6095407b48..957345816d 100644 --- a/src/thread.h +++ b/src/thread.h @@ -166,6 +166,7 @@ class Thread { kTerminated, }; + static const size_t kStackOverflowReservedBytes = 1024; // Space to throw a StackOverflowError in. static const size_t kDefaultStackSize = 64 * KB; @@ -222,6 +223,7 @@ class Thread { StaticStorageBase* (*pInitializeStaticStorage)(uint32_t, const Method*); Field* (*pFindFieldFromCode)(uint32_t, const Method*); void (*pCheckSuspendFromCode)(Thread*); + void (*pStackOverflowFromCode)(Method*); class StackVisitor { public: |