Using gcmap instead of shadow frame.
Fix misuse of TBAAJRuntime & TBAARuntimeInfo. Now, the TBAAJRuntime is
only for runtime support function.
Update DexPC before lock object and suspend.
Change-Id: I40fa37f4863fe6e127328a8413285ee3c62e8505
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 1c04dc8..32f9b51 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -21,11 +21,10 @@
%JavaObject = type opaque
-%ShadowFrame = type { %ShadowFrame* ; Previous frame
+%ShadowFrame = type { i32 ; Number of VRegs
+ , %ShadowFrame* ; Previous frame
, %JavaObject* ; Method object pointer
, i32 ; Line number for stack backtrace
- , i32 ; Number of references
- ; [0 x %JavaObject*] ; References
; [0 x i32] ; VRegs
}
@@ -45,7 +44,7 @@
declare void @art_test_suspend_from_code(%JavaObject*)
declare %ShadowFrame* @art_push_shadow_frame_from_code(%JavaObject*, %ShadowFrame*,
- %JavaObject*, i16, i16)
+ %JavaObject*, i32)
declare void @art_pop_shadow_frame_from_code(%ShadowFrame*)
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index a27ea6e..3524cdd 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -78,75 +78,6 @@
#include <string>
-namespace {
-
-// TODO: We may need something to manage these passes.
-// TODO: We need high-level IR to analysis and do this at the IRBuilder level.
-class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
- public:
- static char ID;
-
- AddSuspendCheckToLoopLatchPass() : llvm::LoopPass(ID), irb_(NULL) {
- LOG(FATAL) << "Unexpected instantiation of AddSuspendCheckToLoopLatchPass";
- // NOTE: We have to declare this constructor for llvm::RegisterPass, but
- // this constructor won't work because we have no information on
- // IRBuilder. Thus, we should place a LOG(FATAL) here.
- }
-
- AddSuspendCheckToLoopLatchPass(art::compiler_llvm::IRBuilder* irb)
- : llvm::LoopPass(ID), irb_(irb) {
- }
-
- virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
- AU.addRequired<llvm::LoopInfo>();
- AU.addRequiredID(llvm::LoopSimplifyID);
-
- AU.addPreserved<llvm::DominatorTree>();
- AU.addPreserved<llvm::LoopInfo>();
- AU.addPreservedID(llvm::LoopSimplifyID);
- AU.addPreserved<llvm::ScalarEvolution>();
- AU.addPreservedID(llvm::BreakCriticalEdgesID);
- }
-
- virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) {
- llvm::LoopInfo* loop_info = &getAnalysis<llvm::LoopInfo>();
-
- CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!";
- llvm::BasicBlock* bb = loop->getLoopLatch();
- CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist.";
-
- llvm::BasicBlock* tb = bb->splitBasicBlock(bb->getTerminator(), "suspend_exit");
- // Remove unconditional branch which is added by splitBasicBlock.
- bb->getTerminator()->eraseFromParent();
-
- irb_->SetInsertPoint(bb);
- irb_->Runtime().EmitTestSuspend();
- irb_->CreateBr(tb);
-
- loop->addBasicBlockToLoop(tb, loop_info->getBase());
- // EmitTestSuspend() creates some basic blocks. We should add them to using
- // addBasicBlockToLoop(...) as above.
- for (llvm::succ_iterator succ_iter = llvm::succ_begin(bb), succ_end = llvm::succ_end(bb);
- succ_iter != succ_end;
- succ_iter++) {
- loop->addBasicBlockToLoop(*succ_iter, loop_info->getBase());
- }
-
- return true;
- }
-
- private:
- art::compiler_llvm::IRBuilder* irb_;
-};
-
-char AddSuspendCheckToLoopLatchPass::ID = 0;
-
-llvm::RegisterPass<AddSuspendCheckToLoopLatchPass> reg_add_suspend_check_to_loop_latch_pass_(
- "add-suspend-check-to-loop-latch", "Add suspend check to loop latch pass", false, false);
-
-
-} // end anonymous namespace
-
namespace art {
namespace compiler_llvm {
@@ -328,30 +259,22 @@
if (bitcode_filename_.empty()) {
// If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
// regular FunctionPass.
-#if defined(ART_USE_DEXLANG_FRONTEND)
- fpm.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
-#elif defined(ART_USE_PORTABLE_COMPILER)
+#if defined(ART_USE_PORTABLE_COMPILER)
fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
compiler_, oat_compilation_unit_));
#endif
- fpm.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
} else {
- // Run AddSuspendCheckToLoopLatchPass before we write the bitcode to file.
+#if defined(ART_USE_PORTABLE_COMPILER)
llvm::FunctionPassManager fpm2(module_);
-#if defined(ART_USE_DEXLANG_FRONTEND)
- fpm2.add(CreateGBCExpanderPass(dex_lang_ctx_->GetIntrinsicHelper(), *irb_.get()));
-#elif defined(ART_USE_PORTABLE_COMPILER)
fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
compiler_, oat_compilation_unit_));
-#endif
- fpm2.add(new ::AddSuspendCheckToLoopLatchPass(irb_.get()));
fpm2.doInitialization();
for (llvm::Module::iterator F = module_->begin(), E = module_->end();
F != E; ++F) {
fpm2.run(*F);
}
fpm2.doFinalization();
-
+#endif
// Write bitcode to file
std::string errmsg;
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 3ec5e68..7843407 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -31,6 +31,7 @@
#include "stl_util.h"
#include "stub_compiler.h"
#include "utils_llvm.h"
+#include "verifier/method_verifier.h"
#include <llvm/LinkAllPasses.h>
#include <llvm/LinkAllVMCore.h>
@@ -180,8 +181,10 @@
cunit->Materialize();
- return new CompiledMethod(cunit->GetInstructionSet(),
- cunit->GetCompiledCode());
+ Compiler::MethodReference mref(dex_file_, method_idx_);
+ return new CompiledMethod(cunit_->GetInstructionSet(),
+ cunit_->GetCompiledCode(),
+ *verifier::MethodVerifier::GetDexGcMap(mref));
}
#else
UniquePtr<MethodCompiler> method_compiler(
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 57a13d5..93d7d48 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -217,9 +217,7 @@
llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
- void Expand_AllocaShadowFrame(llvm::Value* num_entry_value, llvm::Value* num_vregs_value);
-
- void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
+ void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
@@ -710,7 +708,7 @@
llvm::Value* callee_method_object_field_addr =
EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
- return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
+ return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
}
llvm::Value* GBCExpanderPass::
@@ -765,7 +763,27 @@
}
void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
+ uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+
+ llvm::Value* suspend_count =
+ irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
+ irb_.getInt16Ty(),
+ kTBAARuntimeInfo);
+ llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
+
+ llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
+ llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
+
+ irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
+
+ irb_.SetInsertPoint(basic_block_suspend);
+ if (dex_pc != art::DexFile::kDexNoIndex) {
+ EmitUpdateDexPC(dex_pc);
+ }
irb_.Runtime().EmitTestSuspend();
+ irb_.CreateBr(basic_block_cont);
+
+ irb_.SetInsertPoint(basic_block_cont);
return;
}
@@ -781,7 +799,7 @@
llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
- return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+ return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
}
llvm::Value*
@@ -792,7 +810,7 @@
llvm::Value* type_field_addr =
EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
- return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+ return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
}
void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
@@ -980,7 +998,7 @@
llvm::Value* storage_field_addr =
EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
- return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+ return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
}
llvm::Value*
@@ -1021,7 +1039,7 @@
irb_.LoadFromObjectOffset(callee_method_object_addr,
art::AbstractMethod::GetCodeOffset().Int32Value(),
callee_method_type->getPointerTo(),
- kTBAAJRuntime);
+ kTBAARuntimeInfo);
// Invoke callee
llvm::Value* retval = irb_.CreateCall(code_addr, args);
@@ -1093,17 +1111,14 @@
return result;
}
-void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value,
- llvm::Value* num_vregs_value) {
+void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
// Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
// MethodCompiler::EmitPushShadowFrame
- uint16_t num_shadow_frame_refs =
- llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
uint16_t num_vregs =
llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
llvm::StructType* shadow_frame_type =
- irb_.getShadowFrameTy(num_shadow_frame_refs, num_vregs);
+ irb_.getShadowFrameTy(num_vregs);
shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
@@ -1111,26 +1126,14 @@
old_shadow_frame_ =
irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
- // Zero-initialization of the shadow frame table
- llvm::Value* shadow_frame_table =
- irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
- llvm::Type* table_type = shadow_frame_type->getElementType(1);
-
- llvm::ConstantAggregateZero* zero_initializer =
- llvm::ConstantAggregateZero::get(table_type);
-
- irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
-
// Push the shadow frame
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 = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
method_object_addr,
- num_shadow_frame_refs,
num_vregs);
irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
@@ -1138,34 +1141,13 @@
return;
}
-// TODO: We will remove ShadowFrameEntry later, so I just copy/paste from ShadowFrameEntry.
-void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
- llvm::Value* entry_idx) {
- DCHECK(shadow_frame_ != NULL);
-
- llvm::Value* gep_index[] = {
- irb_.getInt32(0), // No pointer displacement
- irb_.getInt32(1), // SIRT
- entry_idx // Pointer field
- };
-
- llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
-#if defined(ART_USE_PORTABLE_COMPILER)
- if (obj->getType() != irb_.getJObjectTy()) {
- obj = irb_.getJNull();
- }
-#endif
- irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
- return;
-}
-
void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
llvm::Value* value) {
DCHECK(shadow_frame_ != NULL);
llvm::Value* gep_index[] = {
irb_.getInt32(0), // No pointer displacement
- irb_.getInt32(2), // VRegs
+ irb_.getInt32(1), // VRegs
entry_idx // Pointer field
};
@@ -1560,7 +1542,7 @@
llvm::Value* type_field_addr =
EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
- llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+ llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
return type_object_addr;
@@ -1625,7 +1607,7 @@
llvm::Value* storage_field_addr =
EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
- llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+ llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
llvm::BasicBlock* block_original = irb_.GetInsertBlock();
@@ -1832,7 +1814,7 @@
llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
- llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+ llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
llvm::BasicBlock* block_str_exist =
@@ -1905,6 +1887,8 @@
EmitGuard_NullPointerException(dex_pc, object_addr);
}
+ EmitUpdateDexPC(dex_pc);
+
irb_.Runtime().EmitLockObject(object_addr);
return;
@@ -2177,7 +2161,7 @@
irb_.LoadFromObjectOffset(callee_method_object_addr,
art::AbstractMethod::GetCodeOffset().Int32Value(),
GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
- kTBAAJRuntime);
+ kTBAARuntimeInfo);
}
// Invoke callee
@@ -2700,7 +2684,7 @@
return irb_.Runtime().EmitGetCurrentThread();
}
case IntrinsicHelper::CheckSuspend: {
- // We will add suspend by ourselves.
+ Expand_TestSuspend(call_inst);
return NULL;
}
case IntrinsicHelper::TestSuspend: {
@@ -3478,13 +3462,7 @@
//==- Shadow Frame -----------------------------------------------------==//
case IntrinsicHelper::AllocaShadowFrame: {
- Expand_AllocaShadowFrame(call_inst.getArgOperand(0),
- call_inst.getArgOperand(1));
- return NULL;
- }
- case IntrinsicHelper::SetShadowFrameEntry: {
- Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
- call_inst.getArgOperand(1));
+ Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
return NULL;
}
case IntrinsicHelper::SetVReg: {
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index e118646..ef8d6da 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -44,12 +44,12 @@
StructTy_ShadowFrame = StructType::create(mod->getContext(), "ShadowFrame");
}
std::vector<Type*>StructTy_ShadowFrame_fields;
+StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
PointerType* PointerTy_2 = PointerType::get(StructTy_ShadowFrame, 0);
StructTy_ShadowFrame_fields.push_back(PointerTy_2);
StructTy_ShadowFrame_fields.push_back(PointerTy_1);
StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
-StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
if (StructTy_ShadowFrame->isOpaque()) {
StructTy_ShadowFrame->setBody(StructTy_ShadowFrame_fields, /*isPacked=*/false);
}
@@ -93,8 +93,7 @@
FuncTy_7_args.push_back(PointerTy_1);
FuncTy_7_args.push_back(PointerTy_2);
FuncTy_7_args.push_back(PointerTy_1);
-FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
-FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 16));
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 32));
FunctionType* FuncTy_7 = FunctionType::get(
/*Result=*/PointerTy_2,
/*Params=*/FuncTy_7_args,
diff --git a/src/compiler_llvm/ir_builder.cc b/src/compiler_llvm/ir_builder.cc
index b271002..e8e73e3 100644
--- a/src/compiler_llvm/ir_builder.cc
+++ b/src/compiler_llvm/ir_builder.cc
@@ -151,8 +151,8 @@
}
-llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_size) {
- std::string name(StringPrintf("ShadowFrame%u_vreg%u", sirt_size, vreg_size));
+llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t vreg_size) {
+ std::string name(StringPrintf("ShadowFrame%u", vreg_size));
// Try to find the existing struct type definition
if (llvm::Type* type = module_->getTypeByName(name)) {
@@ -163,7 +163,6 @@
// Create new struct type definition
llvm::Type* elem_types[] = {
art_frame_type_,
- llvm::ArrayType::get(jobject_type_, sirt_size),
llvm::ArrayType::get(getInt32Ty(), vreg_size),
};
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index cc0bc8e..4a58515 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -315,7 +315,7 @@
return getJLongTy();
}
- llvm::StructType* getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_size);
+ llvm::StructType* getShadowFrameTy(uint32_t vreg_size);
//--------------------------------------------------------------------------
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index d5a7869..2a17320 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -101,7 +101,7 @@
}
// Shadow stack
- llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size, 0);
+ llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
// Store the dex pc
@@ -113,20 +113,20 @@
// Push the shadow frame
llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
llvm::Value* old_shadow_frame =
- irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr, sirt_size, 0);
+ irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr, sirt_size);
// Get JNIEnv
llvm::Value* jni_env_object_addr =
irb_.Runtime().EmitLoadFromThreadOffset(Thread::JniEnvOffset().Int32Value(),
irb_.getJObjectTy(),
- kTBAAJRuntime);
+ kTBAARuntimeInfo);
// Get callee code_addr
llvm::Value* code_addr =
irb_.LoadFromObjectOffset(method_object_addr,
AbstractMethod::NativeMethodOffset().Int32Value(),
GetFunctionType(method_idx_, is_static, true)->getPointerTo(),
- kTBAAJRuntime);
+ kTBAARuntimeInfo);
// Load actual parameters
std::vector<llvm::Value*> args;
@@ -145,7 +145,8 @@
// Store the "this object or class object" to SIRT
gep_index[2] = irb_.getInt32(sirt_member_index++);
- llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+ llvm::Value* sirt_field_addr = irb_.CreateBitCast(irb_.CreateGEP(shadow_frame_, gep_index),
+ irb_.getJObjectTy()->getPointerTo());
irb_.CreateStore(this_object_or_class_object, sirt_field_addr, kTBAAShadowFrame);
// Push the "this object or class object" to out args
this_object_or_class_object = irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy());
@@ -155,7 +156,8 @@
if (arg_iter->getType() == irb_.getJObjectTy()) {
// Store the reference type arguments to SIRT
gep_index[2] = irb_.getInt32(sirt_member_index++);
- llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+ llvm::Value* sirt_field_addr = irb_.CreateBitCast(irb_.CreateGEP(shadow_frame_, gep_index),
+ irb_.getJObjectTy()->getPointerTo());
irb_.CreateStore(arg_iter, sirt_field_addr, kTBAAShadowFrame);
// Note null is placed in the SIRT but the jobject passed to the native code must be null
// (not a pointer into the SIRT as with regular references).
diff --git a/src/compiler_llvm/md_builder.cc b/src/compiler_llvm/md_builder.cc
index f5232aa..038e133 100644
--- a/src/compiler_llvm/md_builder.cc
+++ b/src/compiler_llvm/md_builder.cc
@@ -39,8 +39,10 @@
case kTBAAHeapInstance: spec_ty = createTBAANode("HeapInstance", tbaa_root_); break;
case kTBAAHeapStatic: spec_ty = createTBAANode("HeapStatic", tbaa_root_); break;
case kTBAAJRuntime: spec_ty = createTBAANode("JRuntime", tbaa_root_); break;
- case kTBAARuntimeInfo: spec_ty = createTBAANode("RuntimeInfo", tbaa_root_); break;
- case kTBAAShadowFrame: spec_ty = createTBAANode("ShadowFrame", tbaa_root_); break;
+ case kTBAARuntimeInfo: spec_ty = createTBAANode("RuntimeInfo",
+ GetTBAASpecialType(kTBAAJRuntime)); break;
+ case kTBAAShadowFrame: spec_ty = createTBAANode("ShadowFrame",
+ GetTBAASpecialType(kTBAAJRuntime)); break;
case kTBAAConstJObject: spec_ty = createTBAANode("ConstJObject", tbaa_root_, true); break;
default:
LOG(FATAL) << "Unknown TBAA special type: " << sty_id;
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index f09553c..68121de 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -60,8 +60,6 @@
irb_(*cunit->GetIRBuilder()),
func_(NULL),
regs_(code_item_->registers_size_),
- shadow_frame_entries_(code_item_->registers_size_),
- reg_to_shadow_frame_index_(code_item_->registers_size_, -1),
retval_reg_(NULL),
basic_block_alloca_(NULL), basic_block_shadow_frame_(NULL),
basic_block_reg_arg_init_(NULL),
@@ -69,7 +67,7 @@
basic_block_landing_pads_(code_item_->tries_size_, NULL),
basic_block_unwind_(NULL),
shadow_frame_(NULL), old_shadow_frame_(NULL),
- already_pushed_shadow_frame_(NULL), num_shadow_frame_refs_(0) {
+ already_pushed_shadow_frame_(NULL) {
}
@@ -176,9 +174,6 @@
name = StringPrintf("%u", r);
#endif
regs_[r] = new DalvikReg(*this, name, GetVRegEntry(r));
-
- // Cache shadow frame entry address
- shadow_frame_entries_[r] = GetShadowFrameEntry(r);
}
std::string name;
@@ -256,7 +251,9 @@
EmitStackOverflowCheck();
}
// Garbage collection safe-point
- EmitGuard_GarbageCollectionSuspend();
+ if (method_info_.has_invoke) {
+ EmitGuard_GarbageCollectionSuspend(DexFile::kDexNoIndex);
+ }
irb_.CreateBr(basic_block_shadow_frame_);
irb_.SetInsertPoint(basic_block_shadow_frame_);
@@ -268,24 +265,7 @@
irb_.SetInsertPoint(basic_block_alloca_);
// Allocate the shadow frame now!
- num_shadow_frame_refs_ = 0;
- uint16_t arg_reg_start = code_item_->registers_size_ - code_item_->ins_size_;
- 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 (i >= arg_reg_start && !method_info_.set_to_another_object[i]) {
- // If we don't set argument registers to another object, we don't need the shadow frame
- // entry for it. Because the arguments must have been in the caller's shadow frame.
- continue;
- }
-
- if (IsRegCanBeObject(i)) {
- reg_to_shadow_frame_index_[i] = num_shadow_frame_refs_++;
- }
- }
- }
-
- llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(num_shadow_frame_refs_,
- code_item_->registers_size_);
+ llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(code_item_->registers_size_);
shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
// Alloca a pointer to old shadow frame
@@ -293,15 +273,6 @@
irb_.SetInsertPoint(basic_block_shadow_frame_);
- // Zero-initialization of the shadow frame table
- llvm::Value* shadow_frame_table = irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
- llvm::Type* table_type = shadow_frame_type->getElementType(1);
-
- llvm::ConstantAggregateZero* zero_initializer =
- llvm::ConstantAggregateZero::get(table_type);
-
- irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
-
// Lazy pushing shadow frame
if (method_info_.lazy_push_shadow_frame) {
irb_.SetInsertPoint(basic_block_alloca_);
@@ -1375,7 +1346,7 @@
llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
- llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
+ llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
llvm::BasicBlock* block_str_exist =
@@ -1444,7 +1415,7 @@
llvm::Value* type_field_addr =
EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
- llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
+ llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
return type_object_addr;
@@ -1523,6 +1494,8 @@
EmitGuard_NullPointerException(dex_pc, object_addr);
}
+ EmitUpdateDexPC(dex_pc);
+
irb_.Runtime().EmitLockObject(object_addr);
irb_.CreateBr(GetNextBasicBlock(dex_pc));
@@ -1914,6 +1887,11 @@
int32_t branch_offset = dec_insn.vA;
+ if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
+ // Garbage collection safe-point on backward branch
+ EmitGuard_GarbageCollectionSuspend(dex_pc);
+ }
+
irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
}
@@ -2044,6 +2022,11 @@
int32_t branch_offset = dec_insn.vC;
+ if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
+ // Garbage collection safe-point on backward branch
+ EmitGuard_GarbageCollectionSuspend(dex_pc);
+ }
+
llvm::Value* src1_value;
llvm::Value* src2_value;
@@ -2105,6 +2088,11 @@
int32_t branch_offset = dec_insn.vB;
+ if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
+ // Garbage collection safe-point on backward branch
+ EmitGuard_GarbageCollectionSuspend(dex_pc);
+ }
+
llvm::Value* src1_value;
llvm::Value* src2_value;
@@ -2145,12 +2133,6 @@
return map->GetRegCategory(dex_pc, reg_idx);
}
-bool MethodCompiler::IsRegCanBeObject(uint16_t reg_idx) {
- const greenland::InferredRegCategoryMap* map = GetInferredRegCategoryMap();
-
- return map->IsRegCanBeObject(reg_idx);
-}
-
llvm::Value* MethodCompiler::EmitConditionResult(llvm::Value* lhs,
llvm::Value* rhs,
@@ -2442,7 +2424,7 @@
llvm::Value* storage_field_addr =
EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
- llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
+ llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
llvm::BasicBlock* block_original = irb_.GetInsertBlock();
@@ -2809,7 +2791,7 @@
irb_.LoadFromObjectOffset(callee_method_object_addr,
AbstractMethod::GetCodeOffset().Int32Value(),
GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
- kTBAAJRuntime);
+ kTBAARuntimeInfo);
}
// Invoke callee
@@ -2835,7 +2817,7 @@
llvm::Value* callee_method_object_field_addr =
EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
- return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
+ return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
}
@@ -3529,8 +3511,10 @@
cunit_->Materialize();
+ Compiler::MethodReference mref(dex_file_, method_idx_);
return new CompiledMethod(cunit_->GetInstructionSet(),
- cunit_->GetCompiledCode());
+ cunit_->GetCompiledCode(),
+ *verifier::MethodVerifier::GetDexGcMap(mref));
}
@@ -3570,13 +3554,26 @@
}
-void MethodCompiler::EmitGuard_GarbageCollectionSuspend() {
- // Loop suspend will be added by our llvm pass.
- if (!method_info_.has_invoke) {
- return;
- }
+void MethodCompiler::EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc) {
+ llvm::Value* suspend_count =
+ irb_.Runtime().EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
+ irb_.getInt16Ty(),
+ kTBAARuntimeInfo);
+ llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
+ llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
+ llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
+
+ irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
+
+ irb_.SetInsertPoint(basic_block_suspend);
+ if (dex_pc != DexFile::kDexNoIndex) {
+ EmitUpdateDexPC(dex_pc);
+ }
irb_.Runtime().EmitTestSuspend();
+ irb_.CreateBr(basic_block_cont);
+
+ irb_.SetInsertPoint(basic_block_cont);
}
@@ -3766,49 +3763,7 @@
}
-llvm::Value* MethodCompiler::GetShadowFrameEntry(uint32_t reg_idx) {
- if (reg_to_shadow_frame_index_[reg_idx] == -1) {
- // This register dosen't need ShadowFrame entry
- return NULL;
- }
-
- if (!method_info_.need_shadow_frame_entry) {
- return NULL;
- }
-
- std::string reg_name;
-
-#if !defined(NDEBUG)
- StringAppendF(®_name, "s%u", reg_idx);
-#endif
-
- // Save current IR builder insert point
- llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
-
- irb_.SetInsertPoint(basic_block_shadow_frame_);
-
- llvm::Value* gep_index[] = {
- irb_.getInt32(0), // No pointer displacement
- irb_.getInt32(1), // SIRT
- irb_.getInt32(reg_to_shadow_frame_index_[reg_idx]) // Pointer field
- };
-
- llvm::Value* reg_addr = irb_.CreateGEP(shadow_frame_, gep_index, reg_name);
-
- // Restore IRBuilder insert point
- irb_.restoreIP(irb_ip_original);
-
- DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
- return reg_addr;
-}
-
-
-// TODO: We will remove ShadowFrameEntry later, so I just copy/paste from ShadowFrameEntry.
llvm::Value* MethodCompiler::GetVRegEntry(uint32_t reg_idx) {
- if (!compiler_->IsDebuggingSupported()) {
- return NULL;
- }
-
if (!method_info_.need_shadow_frame_entry) {
return NULL;
}
@@ -3826,7 +3781,7 @@
llvm::Value* gep_index[] = {
irb_.getInt32(0), // No pointer displacement
- irb_.getInt32(2), // VRegs
+ irb_.getInt32(1), // VRegs
irb_.getInt32(reg_idx) // Pointer field
};
@@ -3857,12 +3812,9 @@
llvm::Value* result;
if (is_inline) {
result = irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr,
- num_shadow_frame_refs_,
code_item_->registers_size_);
} else {
- DCHECK(num_shadow_frame_refs_ == 0);
result = irb_.Runtime().EmitPushShadowFrameNoInline(shadow_frame_upcast, method_object_addr,
- num_shadow_frame_refs_,
code_item_->registers_size_);
}
irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
@@ -3932,9 +3884,6 @@
void MethodCompiler::EmitStoreDalvikReg(uint32_t reg_idx, JType jty,
JTypeSpace space, llvm::Value* new_value) {
regs_[reg_idx]->SetValue(jty, space, new_value);
- if (jty == kObject && shadow_frame_entries_[reg_idx] != NULL) {
- irb_.CreateStore(new_value, shadow_frame_entries_[reg_idx], kTBAAShadowFrame);
- }
}
void MethodCompiler::EmitStoreDalvikReg(uint32_t reg_idx, char shorty,
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 02c3d6a..f67866a 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -289,7 +289,7 @@
void EmitBranchExceptionLandingPad(uint32_t dex_pc);
- void EmitGuard_GarbageCollectionSuspend();
+ void EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc);
llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
llvm::Value* cmp_lt);
@@ -461,9 +461,7 @@
llvm::Function* func_;
std::vector<DalvikReg*> regs_;
- std::vector<llvm::Value*> shadow_frame_entries_;
std::vector<llvm::Value*> vregs_;
- std::vector<int32_t> reg_to_shadow_frame_index_;
UniquePtr<DalvikReg> retval_reg_;
llvm::BasicBlock* basic_block_alloca_;
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index dbcbe89..169f8e8 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -86,8 +86,8 @@
/* ShadowFrame */
llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
- llvm::Value* method, uint16_t num_refs,
- uint16_t num_vregs) {
+ llvm::Value* method,
+ uint32_t num_vregs) {
Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
irb_.getArtFrameTy()->getPointerTo(),
kTBAARuntimeInfo);
@@ -101,16 +101,10 @@
method,
kTBAAShadowFrame);
- // Store the number of the reference slots
- irb_.StoreToObjectOffset(new_shadow_frame,
- ShadowFrame::NumberOfReferencesOffset(),
- irb_.getInt16(num_refs),
- kTBAAShadowFrame);
-
// Store the number of vregs
irb_.StoreToObjectOffset(new_shadow_frame,
ShadowFrame::NumberOfVRegsOffset(),
- irb_.getInt16(num_vregs),
+ irb_.getInt32(num_vregs),
kTBAAShadowFrame);
// Store the link to previous shadow frame
@@ -124,16 +118,15 @@
llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
- llvm::Value* method, uint16_t num_refs,
- uint16_t num_vregs) {
+ llvm::Value* method,
+ uint32_t num_vregs) {
Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
llvm::CallInst* call_inst =
- irb_.CreateCall5(func,
+ irb_.CreateCall4(func,
EmitGetCurrentThread(),
new_shadow_frame,
method,
- irb_.getInt16(num_refs),
- irb_.getInt16(num_vregs));
+ irb_.getInt32(num_vregs));
irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
return call_inst;
}
@@ -156,7 +149,7 @@
llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
irb_.getJObjectTy(),
- kTBAAJRuntime);
+ kTBAARuntimeInfo);
// If exception not null
return irb_.CreateIsNotNull(exception);
}
@@ -166,22 +159,8 @@
void RuntimeSupportBuilder::EmitTestSuspend() {
Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
- Value* suspend_count = EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
- irb_.getInt16Ty(),
- kTBAARuntimeInfo);
- Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
-
- Function* parent_func = irb_.GetInsertBlock()->getParent();
- BasicBlock* basic_block_suspend = BasicBlock::Create(context_, "suspend", parent_func);
- BasicBlock* basic_block_cont = BasicBlock::Create(context_, "suspend_cont", parent_func);
- irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
-
- irb_.SetInsertPoint(basic_block_suspend);
CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
- irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
- irb_.CreateBr(basic_block_cont);
-
- irb_.SetInsertPoint(basic_block_cont);
+ irb_.SetTBAA(call_inst, kTBAAJRuntime);
}
diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h
index ba512af..58f01f6 100644
--- a/src/compiler_llvm/runtime_support_builder.h
+++ b/src/compiler_llvm/runtime_support_builder.h
@@ -51,9 +51,9 @@
/* ShadowFrame */
virtual llvm::Value* EmitPushShadowFrame(llvm::Value* new_shadow_frame,
- llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
+ llvm::Value* method, uint32_t num_vregs);
virtual llvm::Value* EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
- llvm::Value* method, uint16_t num_refs, uint16_t num_vregs);
+ llvm::Value* method, uint32_t num_vregs);
virtual void EmitPopShadowFrame(llvm::Value* old_shadow_frame);
/* Exception */
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 3cdd532..7d73249 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -90,11 +90,9 @@
}
ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
- AbstractMethod* method, uint16_t num_refs,
- uint16_t num_vregs) {
+ AbstractMethod* method, uint32_t num_vregs) {
ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
new_shadow_frame->SetMethod(method);
- new_shadow_frame->SetNumberOfReferences(num_refs);
new_shadow_frame->SetNumberOfVRegs(num_vregs);
return old_frame;
}
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index c52b7f9..6c133c9 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -26,8 +26,7 @@
//----------------------------------------------------------------------------
ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
- AbstractMethod* method, uint16_t num_refs,
- uint16_t num_vregs);
+ AbstractMethod* method, uint32_t num_vregs);
void art_pop_shadow_frame_from_code(void*);
diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc
index 4854c9f..4571f58 100644
--- a/src/compiler_llvm/stub_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -148,7 +148,7 @@
irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
accurate_func_type->getPointerTo()->getPointerTo());
- llvm::Value* code_addr = irb_.CreateLoad(code_field_addr, kTBAAJRuntime);
+ llvm::Value* code_addr = irb_.CreateLoad(code_field_addr, kTBAARuntimeInfo);
llvm::CallInst* retval = irb_.CreateCall(code_addr, args);
#if defined(ART_USE_PORTABLE_COMPILER)