Implement StackOverflow check.
Change-Id: I981afe85ace84749f2e194e6df902c8ede947828
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 0ab8871..bcd40de 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -139,6 +139,9 @@
void MethodCompiler::EmitPrologue() {
// Create basic blocks for prologue
+ basic_block_stack_overflow_ =
+ llvm::BasicBlock::Create(*context_, "prologue.stack_overflow_check", func_);
+
basic_block_reg_alloca_ =
llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
@@ -151,6 +154,9 @@
basic_block_reg_arg_init_ =
llvm::BasicBlock::Create(*context_, "prologue.arginit", func_);
+ // Before alloca, check stack overflow.
+ EmitStackOverflowCheck();
+
// Create register array
for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
@@ -170,7 +176,61 @@
}
+void MethodCompiler::EmitStackOverflowCheck() {
+ irb_.SetInsertPoint(basic_block_stack_overflow_);
+
+ // Call llvm intrinsic function to get frame address.
+ llvm::Function* frameaddress =
+ llvm::Intrinsic::getDeclaration(module_, llvm::Intrinsic::frameaddress);
+
+ // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
+ llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
+
+ // Cast i8* to int
+ frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
+
+ // Get thread.stack_end_
+ llvm::Value* thread_object_addr =
+ irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
+
+ llvm::Value* stack_end_addr =
+ irb_.CreatePtrDisp(thread_object_addr,
+ irb_.getPtrEquivInt(Thread::StackEndOffset().Int32Value()),
+ irb_.getPtrEquivIntTy()->getPointerTo());
+
+ llvm::Value* stack_end = irb_.CreateLoad(stack_end_addr);
+
+ // Check the frame address < thread.stack_end_ ?
+ llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
+
+ llvm::BasicBlock* block_exception =
+ llvm::BasicBlock::Create(*context_, "stack_overflow", func_);
+
+ llvm::BasicBlock* block_continue =
+ llvm::BasicBlock::Create(*context_, "stack_overflow_cont", func_);
+
+ irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue);
+
+ // If stack overflow, throw exception.
+ irb_.SetInsertPoint(block_exception);
+ irb_.CreateCall(irb_.GetRuntime(ThrowStackOverflowException));
+
+ // Unwind.
+ char ret_shorty = method_helper_.GetShorty()[0];
+ if (ret_shorty == 'V') {
+ irb_.CreateRetVoid();
+ } else {
+ irb_.CreateRet(irb_.getJZero(ret_shorty));
+ }
+
+ basic_block_stack_overflow_ = block_continue;
+}
+
+
void MethodCompiler::EmitPrologueLastBranch() {
+ irb_.SetInsertPoint(basic_block_stack_overflow_);
+ irb_.CreateBr(basic_block_reg_alloca_);
+
irb_.SetInsertPoint(basic_block_reg_alloca_);
irb_.CreateBr(basic_block_shadow_frame_alloca_);