diff options
author | Sebastien Hertz <shertz@google.com> | 2013-03-20 08:32:34 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-03-20 08:32:34 +0000 |
commit | 2da15eda3ff7c4d7f5f35606cb8e5e596a1e0e74 (patch) | |
tree | 32bcd37f37ff00185e8356e1b4240bf66f275a8c /src/compiler | |
parent | 71fe267165765bee6ff1b2e6c35de17910a14f80 (diff) | |
parent | f11afa079d5899b9ff74d2cad507cfa8c7324690 (diff) | |
download | android_art-2da15eda3ff7c4d7f5f35606cb8e5e596a1e0e74.tar.gz android_art-2da15eda3ff7c4d7f5f35606cb8e5e596a1e0e74.tar.bz2 android_art-2da15eda3ff7c4d7f5f35606cb8e5e596a1e0e74.zip |
Merge "Make shadow frame addresses unique." into dalvik-dev
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/llvm/gbc_expander.cc | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/compiler/llvm/gbc_expander.cc b/src/compiler/llvm/gbc_expander.cc index c61667377f..2ae77a127e 100644 --- a/src/compiler/llvm/gbc_expander.cc +++ b/src/compiler/llvm/gbc_expander.cc @@ -80,6 +80,9 @@ class GBCExpanderPass : public llvm::FunctionPass { landing_pad_phi_mapping_; llvm::BasicBlock* basic_block_unwind_; + // Maps each vreg to its shadow frame address. + std::vector<llvm::Value*> shadow_frame_vreg_addresses_; + bool changed_; private: @@ -376,6 +379,7 @@ bool GBCExpanderPass::runOnFunction(llvm::Function& func) { func_ = &func; changed_ = false; // Assume unchanged + shadow_frame_vreg_addresses_.resize(dex_compilation_unit_->GetCodeItem()->registers_size_, NULL); basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_); basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL); basic_block_unwind_ = NULL; @@ -1305,15 +1309,32 @@ void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) { void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* value) { - DCHECK(shadow_frame_ != NULL); + unsigned vreg_idx = LV2UInt(entry_idx); + DCHECK_LT(vreg_idx, dex_compilation_unit_->GetCodeItem()->registers_size_); - llvm::Value* gep_index[] = { - irb_.getInt32(0), // No pointer displacement - irb_.getInt32(1), // VRegs - entry_idx // Pointer field - }; + llvm::Value* vreg_addr = shadow_frame_vreg_addresses_[vreg_idx]; + if (UNLIKELY(vreg_addr == NULL)) { + DCHECK(shadow_frame_ != NULL); + + llvm::Value* gep_index[] = { + irb_.getInt32(0), // No pointer displacement + irb_.getInt32(1), // VRegs + entry_idx // Pointer field + }; - llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index); + // A shadow frame address must dominate every use in the function so we + // place it in the entry block right after the allocas. + llvm::BasicBlock::iterator first_non_alloca = func_->getEntryBlock().begin(); + while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) { + ++first_non_alloca; + } + + llvm::IRBuilderBase::InsertPoint ip = irb_.saveIP(); + irb_.SetInsertPoint(static_cast<llvm::Instruction*>(first_non_alloca)); + vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index); + shadow_frame_vreg_addresses_[vreg_idx] = vreg_addr; + irb_.restoreIP(ip); + } irb_.CreateStore(value, irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()), |