summaryrefslogtreecommitdiffstats
path: root/src/compiler_llvm/method_compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler_llvm/method_compiler.cc')
-rw-r--r--src/compiler_llvm/method_compiler.cc97
1 files changed, 74 insertions, 23 deletions
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 0612855..bdad82b 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -73,6 +73,7 @@ MethodCompiler::MethodCompiler(CompilationUnit* cunit,
basic_block_landing_pads_(code_item_->tries_size_, NULL),
basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
shadow_frame_(NULL), jvalue_temp_(NULL), old_shadow_frame_(NULL),
+ already_pushed_shadow_frame_(NULL), shadow_frame_size_(0),
elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
}
@@ -277,18 +278,21 @@ void MethodCompiler::EmitPrologueAllocShadowFrame() {
irb_.SetInsertPoint(basic_block_alloca_);
// Allocate the shadow frame now!
- uint32_t sirt_size = 0;
+ shadow_frame_size_ = 0;
if (method_info_.need_shadow_frame_entry) {
for (uint32_t i = 0, num_of_regs = code_item_->registers_size_; i < num_of_regs; ++i) {
if (IsRegCanBeObject(i)) {
- reg_to_shadow_frame_index_[i] = sirt_size++;
+ reg_to_shadow_frame_index_[i] = shadow_frame_size_++;
}
}
}
- llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
+ llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(shadow_frame_size_);
shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
+ // Alloca a pointer to old shadow frame
+ old_shadow_frame_ = irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
+
irb_.SetInsertPoint(basic_block_shadow_frame_);
// Zero-initialization of the shadow frame table
@@ -300,26 +304,16 @@ void MethodCompiler::EmitPrologueAllocShadowFrame() {
irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
- // Get method object
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- // Store the method pointer
- irb_.StoreToObjectOffset(shadow_frame_,
- ShadowFrame::MethodOffset(),
- method_object_addr,
- kTBAAShadowFrame);
-
- // Store the number of the pointer slots
- irb_.StoreToObjectOffset(shadow_frame_,
- ShadowFrame::NumberOfReferencesOffset(),
- irb_.getJInt(sirt_size),
- kTBAAShadowFrame);
-
- // Push the shadow frame
- llvm::Value* shadow_frame_upcast =
- irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
+ // Lazy pushing shadow frame
+ if (method_info_.lazy_push_shadow_frame) {
+ irb_.SetInsertPoint(basic_block_alloca_);
+ already_pushed_shadow_frame_ = irb_.CreateAlloca(irb_.getInt1Ty());
+ irb_.SetInsertPoint(basic_block_shadow_frame_);
+ irb_.CreateStore(irb_.getFalse(), already_pushed_shadow_frame_, kTBAARegister);
+ return;
+ }
- old_shadow_frame_ = irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);
+ EmitPushShadowFrame(true);
}
@@ -3952,12 +3946,50 @@ llvm::Value* MethodCompiler::GetShadowFrameEntry(uint32_t reg_idx) {
}
+void MethodCompiler::EmitPushShadowFrame(bool is_inline) {
+ if (!method_info_.need_shadow_frame) {
+ return;
+ }
+ DCHECK(shadow_frame_ != NULL);
+ DCHECK(old_shadow_frame_ != NULL);
+
+ // Get method object
+ llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+ // Push the shadow frame
+ llvm::Value* shadow_frame_upcast =
+ irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
+
+ llvm::Value* result =
+ irb_.CreateCall3(irb_.GetRuntime(is_inline ? PushShadowFrame : PushShadowFrameNoInline),
+ shadow_frame_upcast, method_object_addr, irb_.getJInt(shadow_frame_size_));
+ irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
+}
+
+
void MethodCompiler::EmitPopShadowFrame() {
if (!method_info_.need_shadow_frame) {
return;
}
DCHECK(old_shadow_frame_ != NULL);
- irb_.CreateCall(irb_.GetRuntime(PopShadowFrame), old_shadow_frame_);
+
+ if (method_info_.lazy_push_shadow_frame) {
+ llvm::BasicBlock* bb_pop = llvm::BasicBlock::Create(*context_, "pop", func_);
+ llvm::BasicBlock* bb_cont = llvm::BasicBlock::Create(*context_, "cont", func_);
+
+ llvm::Value* need_pop = irb_.CreateLoad(already_pushed_shadow_frame_, kTBAARegister);
+ irb_.CreateCondBr(need_pop, bb_pop, bb_cont, kUnlikely);
+
+ irb_.SetInsertPoint(bb_pop);
+ irb_.CreateCall(irb_.GetRuntime(PopShadowFrame),
+ irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
+ irb_.CreateBr(bb_cont);
+
+ irb_.SetInsertPoint(bb_cont);
+ } else {
+ irb_.CreateCall(irb_.GetRuntime(PopShadowFrame),
+ irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
+ }
}
@@ -3969,6 +4001,21 @@ void MethodCompiler::EmitUpdateDexPC(uint32_t dex_pc) {
ShadowFrame::DexPCOffset(),
irb_.getInt32(dex_pc),
kTBAAShadowFrame);
+ // Lazy pushing shadow frame
+ if (method_info_.lazy_push_shadow_frame) {
+ llvm::BasicBlock* bb_push = CreateBasicBlockWithDexPC(dex_pc, "push");
+ llvm::BasicBlock* bb_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+ llvm::Value* no_need_push = irb_.CreateLoad(already_pushed_shadow_frame_, kTBAARegister);
+ irb_.CreateCondBr(no_need_push, bb_cont, bb_push, kLikely);
+
+ irb_.SetInsertPoint(bb_push);
+ EmitPushShadowFrame(false);
+ irb_.CreateStore(irb_.getTrue(), already_pushed_shadow_frame_, kTBAARegister);
+ irb_.CreateBr(bb_cont);
+
+ irb_.SetInsertPoint(bb_cont);
+ }
}
@@ -4611,6 +4658,10 @@ void MethodCompiler::ComputeMethodInfo() {
method_info_.need_shadow_frame_entry = has_invoke || may_have_loop;
// If this method may throw an exception, we need a shadow frame for stack trace (dexpc).
method_info_.need_shadow_frame = method_info_.need_shadow_frame_entry || may_throw_exception;
+ // If can only throw exception, but can't suspend check (no loop, no invoke),
+ // then there is no shadow frame entry. Only Shadow frame is needed.
+ method_info_.lazy_push_shadow_frame =
+ method_info_.need_shadow_frame && !method_info_.need_shadow_frame_entry;
}