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/compiled_method.h b/src/compiled_method.h
index 901ec64..b7a2f9c 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -99,6 +99,15 @@
// Constructs a CompiledMethod for the LLVM compiler.
CompiledMethod(InstructionSet instruction_set,
+ const std::vector<uint8_t>& code,
+ const std::vector<uint8_t>& gc_map)
+ : CompiledCode(instruction_set, code),
+ frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
+ fp_spill_mask_(0), native_gc_map_(gc_map) {
+ }
+
+ // Constructs a CompiledMethod for the LLVM JniCompiler.
+ CompiledMethod(InstructionSet instruction_set,
const std::vector<uint8_t>& code)
: CompiledCode(instruction_set, code),
frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc
index c1d61d4..2c27bb0 100644
--- a/src/compiler/codegen/mir_to_gbc.cc
+++ b/src/compiler/codegen/mir_to_gbc.cc
@@ -544,34 +544,6 @@
DefineValue(cu, res, rl_dest.orig_sreg);
}
-static void SetShadowFrameEntry(CompilationUnit* cu, llvm::Value* new_val)
-{
- int index = -1;
- DCHECK(new_val != NULL);
- int v_reg = SRegToVReg(cu, GetLoc(cu, new_val).orig_sreg);
- for (int i = 0; i < cu->num_shadow_frame_entries; i++) {
- if (cu->shadow_map[i] == v_reg) {
- index = i;
- break;
- }
- }
- if (index == -1) {
- return;
- }
- llvm::Type* ty = new_val->getType();
- greenland::IntrinsicHelper::IntrinsicId id =
- greenland::IntrinsicHelper::SetShadowFrameEntry;
- llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id);
- llvm::Value* table_slot = cu->irb->getInt32(index);
- // If new_val is a Null pointer, we'll see it here as a const int. Replace
- if (!ty->isPointerTy()) {
- // TODO: assert new_val created w/ dex_lang_const_int(0) or dex_lang_const_float(0)
- new_val = cu->irb->GetJNull();
- }
- llvm::Value* args[] = { new_val, table_slot };
- cu->irb->CreateCall(func, args);
-}
-
static void ConvertArithOpLit(CompilationUnit* cu, OpKind op, RegLocation rl_dest,
RegLocation rl_src1, int32_t imm)
{
@@ -633,10 +605,6 @@
llvm::Value* res = cu->irb->CreateCall(intr, args);
if (info->result.location != kLocInvalid) {
DefineValue(cu, res, info->result.orig_sreg);
- if (info->result.ref) {
- SetShadowFrameEntry(cu, reinterpret_cast<llvm::Value*>
- (cu->llvm_values.elem_list[info->result.orig_sreg]));
- }
}
}
@@ -855,8 +823,6 @@
uint32_t vC = mir->dalvikInsn.vC;
int opt_flags = mir->optimization_flags;
- bool object_definition = false;
-
if (cu->verbose) {
if (op_val < kMirOpFirst) {
LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" << std::hex << op_val;
@@ -900,9 +866,6 @@
rl_dest = GetDestWide(cu, mir);
} else {
rl_dest = GetDest(cu, mir);
- if (rl_dest.ref) {
- object_definition = true;
- }
}
}
@@ -935,9 +898,6 @@
case Instruction::CONST:
case Instruction::CONST_4:
case Instruction::CONST_16: {
- if (vB == 0) {
- object_definition = true;
- }
llvm::Constant* imm_value = cu->irb->GetJInt(vB);
llvm::Value* res = EmitConst(cu, imm_value, rl_dest);
DefineValue(cu, res, rl_dest.orig_sreg);
@@ -1662,10 +1622,6 @@
UNIMPLEMENTED(FATAL) << "Unsupported Dex opcode 0x" << std::hex << opcode;
res = true;
}
- if (object_definition) {
- SetShadowFrameEntry(cu, reinterpret_cast<llvm::Value*>
- (cu->llvm_values.elem_list[rl_dest.orig_sreg]));
- }
return res;
}
@@ -3022,7 +2978,6 @@
cu->intrinsic_helper->GetIntrinsicId(callee);
switch (id) {
case greenland::IntrinsicHelper::AllocaShadowFrame:
- case greenland::IntrinsicHelper::SetShadowFrameEntry:
case greenland::IntrinsicHelper::PopShadowFrame:
case greenland::IntrinsicHelper::SetVReg:
// Ignore shadow frame stuff for quick compiler
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)
diff --git a/src/greenland/inferred_reg_category_map.cc b/src/greenland/inferred_reg_category_map.cc
index 86c855c..0c31634 100644
--- a/src/greenland/inferred_reg_category_map.cc
+++ b/src/greenland/inferred_reg_category_map.cc
@@ -27,7 +27,7 @@
InferredRegCategoryMap::InferredRegCategoryMap(uint32_t insns_size,
uint16_t regs_size)
-: registers_size_(regs_size), can_be_object_(regs_size) {
+: registers_size_(regs_size) {
}
InferredRegCategoryMap::~InferredRegCategoryMap() {
@@ -54,14 +54,6 @@
}
}
-bool InferredRegCategoryMap::IsRegCanBeObject(uint16_t reg_idx) const {
- return can_be_object_[reg_idx];
-}
-
-void InferredRegCategoryMap::SetRegCanBeObject(uint16_t reg_idx) {
- can_be_object_[reg_idx] = true;
-}
-
bool InferredRegCategoryMap::
operator==(InferredRegCategoryMap const& rhs) const {
diff --git a/src/greenland/inferred_reg_category_map.h b/src/greenland/inferred_reg_category_map.h
index b48dcee..b354097 100644
--- a/src/greenland/inferred_reg_category_map.h
+++ b/src/greenland/inferred_reg_category_map.h
@@ -63,9 +63,6 @@
RegCategory GetRegCategory(uint32_t dex_pc, uint16_t reg_idx) const;
void SetRegCategory(uint32_t dex_pc, uint16_t reg_idx, RegCategory cat);
- bool IsRegCanBeObject(uint16_t reg_idx) const;
- void SetRegCanBeObject(uint16_t reg_idx);
-
bool operator==(InferredRegCategoryMap const& rhs) const;
bool operator!=(InferredRegCategoryMap const& rhs) const;
@@ -74,8 +71,6 @@
SafeMap<uint32_t, RegCategoryLine*> lines_;
- std::vector<bool> can_be_object_;
-
DISALLOW_COPY_AND_ASSIGN(InferredRegCategoryMap);
};
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index 57faf4c..e6e3ec2 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -1546,14 +1546,7 @@
dex_lang_alloca_shadow_frame,
kAttrNoThrow,
kVoidTy,
- _EXPAND_ARG2(kInt32ConstantTy, kInt32ConstantTy))
-
-// void dex_lang_set_shadow_frame_entry(JavaObject* obj, int entry_idx)
-_EVAL_DEF_INTRINSICS_FUNC(SetShadowFrameEntry,
- dex_lang_set_shadow_frame_entry,
- kAttrNoThrow,
- kVoidTy,
- _EXPAND_ARG2(kJavaObjectTy, kInt32ConstantTy))
+ _EXPAND_ARG1(kInt32ConstantTy))
// void dex_lang_set_vreg(int entry_idx, ...)
_EVAL_DEF_INTRINSICS_FUNC(SetVReg,
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 8c217c7..5aa4c2d 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -377,7 +377,7 @@
if (type == kStatic) {
receiver = NULL;
} else {
- receiver = shadow_frame.GetReference(dec_insn.vC);
+ receiver = shadow_frame.GetVRegReference(dec_insn.vC);
if (UNLIKELY(receiver == NULL)) {
ThrowNullPointerExceptionForMethodAccess(shadow_frame.GetMethod(), dec_insn.vB, type);
result->SetJ(0);
@@ -426,7 +426,7 @@
if (is_static) {
obj = f->GetDeclaringClass();
} else {
- obj = shadow_frame.GetReference(dec_insn.vB);
+ obj = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(f, true);
return;
@@ -452,7 +452,7 @@
shadow_frame.SetVRegLong(dec_insn.vA, f->GetLong(obj));
break;
case Primitive::kPrimNot:
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, f->GetObject(obj));
+ shadow_frame.SetVRegReference(dec_insn.vA, f->GetObject(obj));
break;
default:
LOG(FATAL) << "Unreachable: " << field_type;
@@ -473,7 +473,7 @@
if (is_static) {
obj = f->GetDeclaringClass();
} else {
- obj = shadow_frame.GetReference(dec_insn.vB);
+ obj = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionForFieldAccess(f, false);
return;
@@ -499,7 +499,7 @@
f->SetLong(obj, shadow_frame.GetVRegLong(dec_insn.vA));
break;
case Primitive::kPrimNot:
- f->SetObj(obj, shadow_frame.GetReference(dec_insn.vA));
+ f->SetObj(obj, shadow_frame.GetVRegReference(dec_insn.vA));
break;
default:
LOG(FATAL) << "Unreachable: " << field_type;
@@ -567,8 +567,8 @@
LOG(INFO) << PrettyMethod(shadow_frame.GetMethod())
<< StringPrintf("\n0x%x: %s\nReferences:",
inst->GetDexPc(insns), inst->DumpString(&mh.GetDexFile()).c_str());
- for (size_t i = 0; i < shadow_frame.NumberOfReferences(); ++i) {
- Object* o = shadow_frame.GetReference(i);
+ for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
+ Object* o = shadow_frame.GetVRegReference(i);
if (o != NULL) {
if (o->GetClass()->IsStringClass() && o->AsString()->GetCharArray() != NULL) {
LOG(INFO) << i << ": java.lang.String " << static_cast<void*>(o)
@@ -581,7 +581,7 @@
}
}
LOG(INFO) << "vregs:";
- for (size_t i = 0; i < shadow_frame.NumberOfReferences(); ++i) {
+ for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
LOG(INFO) << StringPrintf("%d: %08x", i, shadow_frame.GetVReg(i));
}
}
@@ -602,8 +602,7 @@
case Instruction::MOVE_OBJECT:
case Instruction::MOVE_OBJECT_FROM16:
case Instruction::MOVE_OBJECT_16:
- shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
- shadow_frame.SetReference(dec_insn.vA, shadow_frame.GetReference(dec_insn.vB));
+ shadow_frame.SetVRegReference(dec_insn.vA, shadow_frame.GetVRegReference(dec_insn.vB));
break;
case Instruction::MOVE_RESULT:
shadow_frame.SetVReg(dec_insn.vA, result_register.GetI());
@@ -612,12 +611,12 @@
shadow_frame.SetVRegLong(dec_insn.vA, result_register.GetJ());
break;
case Instruction::MOVE_RESULT_OBJECT:
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, result_register.GetL());
+ shadow_frame.SetVRegReference(dec_insn.vA, result_register.GetL());
break;
case Instruction::MOVE_EXCEPTION: {
Throwable* exception = self->GetException();
self->ClearException();
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, exception);
+ shadow_frame.SetVRegReference(dec_insn.vA, exception);
break;
}
case Instruction::RETURN_VOID: {
@@ -639,14 +638,14 @@
case Instruction::RETURN_OBJECT: {
JValue result;
result.SetJ(0);
- result.SetL(shadow_frame.GetReference(dec_insn.vA));
+ result.SetL(shadow_frame.GetVRegReference(dec_insn.vA));
return result;
}
case Instruction::CONST_4: {
int32_t val = static_cast<int32_t>(dec_insn.vB << 28) >> 28;
shadow_frame.SetVReg(dec_insn.vA, val);
if (val == 0) {
- shadow_frame.SetReference(dec_insn.vA, NULL);
+ shadow_frame.SetVRegReference(dec_insn.vA, NULL);
}
break;
}
@@ -654,7 +653,7 @@
int32_t val = static_cast<int16_t>(dec_insn.vB);
shadow_frame.SetVReg(dec_insn.vA, val);
if (val == 0) {
- shadow_frame.SetReference(dec_insn.vA, NULL);
+ shadow_frame.SetVRegReference(dec_insn.vA, NULL);
}
break;
}
@@ -662,7 +661,7 @@
int32_t val = dec_insn.vB;
shadow_frame.SetVReg(dec_insn.vA, val);
if (val == 0) {
- shadow_frame.SetReference(dec_insn.vA, NULL);
+ shadow_frame.SetVRegReference(dec_insn.vA, NULL);
}
break;
}
@@ -670,7 +669,7 @@
int32_t val = dec_insn.vB << 16;
shadow_frame.SetVReg(dec_insn.vA, val);
if (val == 0) {
- shadow_frame.SetReference(dec_insn.vA, NULL);
+ shadow_frame.SetVRegReference(dec_insn.vA, NULL);
}
break;
}
@@ -693,16 +692,16 @@
true, true);
}
String* s = mh.ResolveString(dec_insn.vB);
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, s);
+ shadow_frame.SetVRegReference(dec_insn.vA, s);
break;
}
case Instruction::CONST_CLASS: {
Class* c = ResolveVerifyAndClinit(dec_insn.vB, shadow_frame.GetMethod(), self, false, true);
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, c);
+ shadow_frame.SetVRegReference(dec_insn.vA, c);
break;
}
case Instruction::MONITOR_ENTER: {
- Object* obj = shadow_frame.GetReference(dec_insn.vA);
+ Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
} else {
@@ -711,7 +710,7 @@
break;
}
case Instruction::MONITOR_EXIT: {
- Object* obj = shadow_frame.GetReference(dec_insn.vA);
+ Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
if (UNLIKELY(obj == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
} else {
@@ -724,7 +723,7 @@
if (UNLIKELY(c == NULL)) {
CHECK(self->IsExceptionPending());
} else {
- Object* obj = shadow_frame.GetReference(dec_insn.vA);
+ Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
"%s cannot be cast to %s",
@@ -739,13 +738,13 @@
if (UNLIKELY(c == NULL)) {
CHECK(self->IsExceptionPending());
} else {
- Object* obj = shadow_frame.GetReference(dec_insn.vB);
+ Object* obj = shadow_frame.GetVRegReference(dec_insn.vB);
shadow_frame.SetVReg(dec_insn.vA, (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
}
break;
}
case Instruction::ARRAY_LENGTH: {
- Object* array = shadow_frame.GetReference(dec_insn.vB);
+ Object* array = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(array == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -755,13 +754,13 @@
}
case Instruction::NEW_INSTANCE: {
Object* obj = AllocObjectFromCode(dec_insn.vB, shadow_frame.GetMethod(), self, true);
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, obj);
+ shadow_frame.SetVRegReference(dec_insn.vA, obj);
break;
}
case Instruction::NEW_ARRAY: {
int32_t length = shadow_frame.GetVReg(dec_insn.vB);
Object* obj = AllocArrayFromCode(dec_insn.vC, shadow_frame.GetMethod(), length, self, true);
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, obj);
+ shadow_frame.SetVRegReference(dec_insn.vA, obj);
break;
}
case Instruction::FILLED_NEW_ARRAY:
@@ -861,7 +860,7 @@
break;
}
case Instruction::THROW: {
- Throwable* t = shadow_frame.GetReference(dec_insn.vA)->AsThrowable();
+ Throwable* t = shadow_frame.GetVRegReference(dec_insn.vA)->AsThrowable();
self->DeliverException(t);
break;
}
@@ -918,7 +917,7 @@
break;
}
case Instruction::FILL_ARRAY_DATA: {
- Object* obj = shadow_frame.GetReference(dec_insn.vA);
+ Object* obj = shadow_frame.GetVRegReference(dec_insn.vA);
if (UNLIKELY(obj == NULL)) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
"null array in FILL_ARRAY_DATA");
@@ -1024,7 +1023,7 @@
break;
}
case Instruction::AGET_BOOLEAN: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1034,7 +1033,7 @@
break;
}
case Instruction::AGET_BYTE: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1044,7 +1043,7 @@
break;
}
case Instruction::AGET_CHAR: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1054,7 +1053,7 @@
break;
}
case Instruction::AGET_SHORT: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1064,7 +1063,7 @@
break;
}
case Instruction::AGET: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1074,7 +1073,7 @@
break;
}
case Instruction::AGET_WIDE: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1084,18 +1083,18 @@
break;
}
case Instruction::AGET_OBJECT: {
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
}
int32_t index = shadow_frame.GetVReg(dec_insn.vC);
- shadow_frame.SetReferenceAndVReg(dec_insn.vA, a->AsObjectArray<Object>()->Get(index));
+ shadow_frame.SetVRegReference(dec_insn.vA, a->AsObjectArray<Object>()->Get(index));
break;
}
case Instruction::APUT_BOOLEAN: {
uint8_t val = shadow_frame.GetVReg(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1106,7 +1105,7 @@
}
case Instruction::APUT_BYTE: {
int8_t val = shadow_frame.GetVReg(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1117,7 +1116,7 @@
}
case Instruction::APUT_CHAR: {
uint16_t val = shadow_frame.GetVReg(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1128,7 +1127,7 @@
}
case Instruction::APUT_SHORT: {
int16_t val = shadow_frame.GetVReg(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1139,7 +1138,7 @@
}
case Instruction::APUT: {
int32_t val = shadow_frame.GetVReg(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1150,7 +1149,7 @@
}
case Instruction::APUT_WIDE: {
int64_t val = shadow_frame.GetVRegLong(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1160,8 +1159,8 @@
break;
}
case Instruction::APUT_OBJECT: {
- Object* val = shadow_frame.GetReference(dec_insn.vA);
- Object* a = shadow_frame.GetReference(dec_insn.vB);
+ Object* val = shadow_frame.GetVRegReference(dec_insn.vA);
+ Object* a = shadow_frame.GetVRegReference(dec_insn.vB);
if (UNLIKELY(a == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
break;
@@ -1777,14 +1776,14 @@
}
// Set up shadow frame with matching number of reference slots to vregs.
ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
- UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs, num_regs,
+ UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs,
(last_shadow_frame == NULL) ? NULL : last_shadow_frame->GetLink(),
method, 0));
self->PushShadowFrame(shadow_frame.get());
size_t cur_reg = num_regs - num_ins;
if (!method->IsStatic()) {
CHECK(receiver != NULL);
- shadow_frame->SetReferenceAndVReg(cur_reg, receiver);
+ shadow_frame->SetVRegReference(cur_reg, receiver);
++cur_reg;
} else if (!method->GetDeclaringClass()->IsInitializing()) {
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
@@ -1801,7 +1800,7 @@
switch (shorty[arg_pos + 1]) {
case 'L': {
Object* o = args[arg_pos].GetL();
- shadow_frame->SetReferenceAndVReg(cur_reg, o);
+ shadow_frame->SetVRegReference(cur_reg, o);
break;
}
case 'J': case 'D':
diff --git a/src/invoke_arg_array_builder.h b/src/invoke_arg_array_builder.h
index 5d4fa5a..16eedfe 100644
--- a/src/invoke_arg_array_builder.h
+++ b/src/invoke_arg_array_builder.h
@@ -148,7 +148,7 @@
arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(range_start + offset));
break;
case 'L':
- arg_array_[i - 1].SetL(shadow_frame.GetReference(range_start + offset));
+ arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(range_start + offset));
break;
case 'D':
arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(range_start + offset));
@@ -185,7 +185,7 @@
arg_array_[i - 1].SetF(shadow_frame.GetVRegFloat(arg_regs[offset]));
break;
case 'L':
- arg_array_[i - 1].SetL(shadow_frame.GetReference(arg_regs[offset]));
+ arg_array_[i - 1].SetL(shadow_frame.GetVRegReference(arg_regs[offset]));
break;
case 'D':
arg_array_[i - 1].SetD(shadow_frame.GetVRegDouble(arg_regs[offset]));
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 382139e..a15c5cf 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -302,7 +302,7 @@
size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
gc_map_offset = (gc_map_size == 0) ? 0 : offset;
-#if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER)
+#if !defined(NDEBUG)
// We expect GC maps except when the class hasn't been verified or the method is native
Compiler::ClassReference class_ref = Compiler::ClassReference(dex_file, class_def_index);
CompiledClass* compiled_class = compiler_->GetCompiledClass(class_ref);
diff --git a/src/stack.cc b/src/stack.cc
index be737ac..be6fe45 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -24,13 +24,16 @@
namespace art {
-size_t ManagedStack::NumShadowFrameReferences() const {
+size_t ManagedStack::NumJniShadowFrameReferences() const {
size_t count = 0;
for (const ManagedStack* current_fragment = this; current_fragment != NULL;
current_fragment = current_fragment->GetLink()) {
for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != NULL;
current_frame = current_frame->GetLink()) {
- count += current_frame->NumberOfReferences();
+ if (current_frame->GetMethod()->IsNative()) {
+ // The JNI ShadowFrame only contains references. (For indirect reference.)
+ count += current_frame->NumberOfVRegs();
+ }
}
}
return count;
diff --git a/src/stack.h b/src/stack.h
index 1134b25..ce84807 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -51,26 +51,34 @@
kUndefined,
};
+// ShadowFrame has 3 possible layouts: portable (VRegs & references overlap),
+// interpreter (VRegs and separate references array), JNI (just VRegs, but where
+// VRegs really => references).
class ShadowFrame {
public:
- static ShadowFrame* Create(uint16_t num_refs, uint16_t num_vregs, ShadowFrame* link,
+ // Create ShadowFrame for interpreter.
+ static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
AbstractMethod* method, uint32_t dex_pc) {
- size_t sz = sizeof(ShadowFrame) + (sizeof(Object*) * num_refs) + (sizeof(uint32_t) * num_vregs);
+ size_t sz = sizeof(ShadowFrame) +
+ (sizeof(uint32_t) * num_vregs) +
+ (sizeof(Object*) * num_vregs);
uint8_t* memory = new uint8_t[sz];
- return new (memory) ShadowFrame(num_refs, num_vregs, link, method, dex_pc);
+ ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
+ return sf;
}
~ShadowFrame() {}
- uint32_t NumberOfReferences() const {
- return number_of_references_;
+ bool HasReferenceArray() const {
+ return (number_of_vregs_ & kHasReferenceArray) != 0;
}
- void SetNumberOfReferences(uint16_t number_of_references) {
- number_of_references_ = number_of_references;
+ uint32_t NumberOfVRegs() const {
+ return number_of_vregs_ & ~kHasReferenceArray;
}
- void SetNumberOfVRegs(uint16_t number_of_vregs) {
- number_of_vregs_ = number_of_vregs;
+ void SetNumberOfVRegs(uint32_t number_of_vregs) {
+ DCHECK(number_of_vregs < kHasReferenceArray);
+ number_of_vregs_ = number_of_vregs | (number_of_vregs_ & kHasReferenceArray);
}
uint32_t GetDexPC() const {
@@ -90,67 +98,68 @@
link_ = frame;
}
- Object* GetReference(size_t i) const {
- DCHECK_LT(i, number_of_references_);
- return references_[i];
- }
-
- void SetReference(size_t i, Object* object) {
- DCHECK_LT(i, number_of_references_);
- references_[i] = object;
- }
-
int32_t GetVReg(size_t i) const {
- DCHECK_LT(i, number_of_vregs_);
- const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
- return reinterpret_cast<const int32_t*>(vregs)[i];
+ DCHECK_LT(i, NumberOfVRegs());
+ const uint32_t* vreg = &vregs_[i];
+ return *reinterpret_cast<const int32_t*>(vreg);
}
float GetVRegFloat(size_t i) const {
- DCHECK_LT(i, number_of_vregs_);
- const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
- return reinterpret_cast<const float*>(vregs)[i];
+ DCHECK_LT(i, NumberOfVRegs());
+ // NOTE: Strict-aliasing?
+ const uint32_t* vreg = &vregs_[i];
+ return *reinterpret_cast<const float*>(vreg);
}
int64_t GetVRegLong(size_t i) const {
- const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
- const int32_t* low_half = &reinterpret_cast<const int32_t*>(vregs)[i];
- return *reinterpret_cast<const int64_t*>(low_half);
+ const uint32_t* vreg = &vregs_[i];
+ return *reinterpret_cast<const int64_t*>(vreg);
}
double GetVRegDouble(size_t i) const {
- const int8_t* vregs = reinterpret_cast<const int8_t*>(this) + VRegsOffset();
- const int32_t* low_half = &reinterpret_cast<const int32_t*>(vregs)[i];
- return *reinterpret_cast<const double*>(low_half);
+ const uint32_t* vreg = &vregs_[i];
+ return *reinterpret_cast<const double*>(vreg);
+ }
+
+ Object* GetVRegReference(size_t i) const {
+ DCHECK_LT(i, NumberOfVRegs());
+ if (HasReferenceArray()) {
+ return References()[i];
+ } else {
+ const uint32_t* vreg = &vregs_[i];
+ return *reinterpret_cast<Object* const*>(vreg);
+ }
}
void SetVReg(size_t i, int32_t val) {
- DCHECK_LT(i, number_of_vregs_);
- int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
- reinterpret_cast<int32_t*>(vregs)[i] = val;
+ DCHECK_LT(i, NumberOfVRegs());
+ uint32_t* vreg = &vregs_[i];
+ *reinterpret_cast<int32_t*>(vreg) = val;
}
void SetVRegFloat(size_t i, float val) {
- DCHECK_LT(i, number_of_vregs_);
- int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
- reinterpret_cast<float*>(vregs)[i] = val;
+ DCHECK_LT(i, NumberOfVRegs());
+ uint32_t* vreg = &vregs_[i];
+ *reinterpret_cast<float*>(vreg) = val;
}
void SetVRegLong(size_t i, int64_t val) {
- int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
- int32_t* low_half = &reinterpret_cast<int32_t*>(vregs)[i];
- *reinterpret_cast<int64_t*>(low_half) = val;
+ uint32_t* vreg = &vregs_[i];
+ *reinterpret_cast<int64_t*>(vreg) = val;
}
void SetVRegDouble(size_t i, double val) {
- int8_t* vregs = reinterpret_cast<int8_t*>(this) + VRegsOffset();
- int32_t* low_half = &reinterpret_cast<int32_t*>(vregs)[i];
- *reinterpret_cast<double*>(low_half) = val;
+ uint32_t* vreg = &vregs_[i];
+ *reinterpret_cast<double*>(vreg) = val;
}
- void SetReferenceAndVReg(size_t i, Object* val) {
- SetReference(i, val);
- SetVReg(i, reinterpret_cast<int32_t>(val));
+ void SetVRegReference(size_t i, Object* val) {
+ DCHECK_LT(i, NumberOfVRegs());
+ uint32_t* vreg = &vregs_[i];
+ *reinterpret_cast<Object**>(vreg) = val;
+ if (HasReferenceArray()) {
+ References()[i] = val;
+ }
}
AbstractMethod* GetMethod() const {
@@ -163,19 +172,14 @@
method_ = method;
}
- bool Contains(Object** shadow_frame_entry) const {
- return ((&references_[0] <= shadow_frame_entry) &&
- (shadow_frame_entry <= (&references_[number_of_references_ - 1])));
- }
-
- template <typename Visitor>
- void VisitRoots(const Visitor& visitor) {
- size_t num_refs = NumberOfReferences();
- for (size_t j = 0; j < num_refs; j++) {
- Object* object = GetReference(j);
- if (object != NULL) {
- visitor(object, j);
- }
+ bool Contains(Object** shadow_frame_entry_obj) const {
+ if (HasReferenceArray()) {
+ return ((&References()[0] <= shadow_frame_entry_obj) &&
+ (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1])));
+ } else {
+ uint32_t* shadow_frame_entry = reinterpret_cast<uint32_t*>(shadow_frame_entry_obj);
+ return ((&vregs_[0] <= shadow_frame_entry) &&
+ (shadow_frame_entry <= (&vregs_[NumberOfVRegs() - 1])));
}
}
@@ -191,43 +195,48 @@
return OFFSETOF_MEMBER(ShadowFrame, dex_pc_);
}
- static size_t NumberOfReferencesOffset() {
- return OFFSETOF_MEMBER(ShadowFrame, number_of_references_);
- }
-
static size_t NumberOfVRegsOffset() {
return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_);
}
- static size_t ReferencesOffset() {
- return OFFSETOF_MEMBER(ShadowFrame, references_);
- }
-
- size_t VRegsOffset() const {
- return ReferencesOffset() + (sizeof(Object*) * NumberOfReferences());
+ static size_t VRegsOffset() {
+ return OFFSETOF_MEMBER(ShadowFrame, vregs_);
}
private:
- ShadowFrame(uint16_t num_refs, uint16_t num_vregs, ShadowFrame* link, AbstractMethod* method,
- uint32_t dex_pc)
- : number_of_references_ (num_refs), number_of_vregs_(num_vregs), link_(link),
- method_(method), dex_pc_(dex_pc) {
- for (size_t i = 0; i < num_refs; ++i) {
- SetReference(i, NULL);
+ ShadowFrame(uint32_t num_vregs, ShadowFrame* link, AbstractMethod* method, uint32_t dex_pc,
+ bool has_reference_array)
+ : number_of_vregs_(num_vregs), link_(link), method_(method), dex_pc_(dex_pc) {
+ if (has_reference_array) {
+ number_of_vregs_ |= kHasReferenceArray;
+ for (size_t i = 0; i < num_vregs; ++i) {
+ SetVRegReference(i, NULL);
+ }
}
for (size_t i = 0; i < num_vregs; ++i) {
SetVReg(i, 0);
}
}
+ Object* const* References() const {
+ const uint32_t* vreg_end = &vregs_[NumberOfVRegs()];
+ return reinterpret_cast<Object* const*>(vreg_end);
+ }
+
+ Object** References() {
+ return const_cast<Object**>(const_cast<const ShadowFrame*>(this)->References());
+ }
+
+ enum ShadowFrameFlag {
+ kHasReferenceArray = 1ul << 31
+ };
// TODO: make the majority of these fields const.
- uint16_t number_of_references_;
- uint16_t number_of_vregs_;
+ uint32_t number_of_vregs_;
// Link to previous shadow frame or NULL.
ShadowFrame* link_;
AbstractMethod* method_;
uint32_t dex_pc_;
- Object* references_[0];
+ uint32_t vregs_[0];
DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame);
};
@@ -306,7 +315,7 @@
return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
}
- size_t NumShadowFrameReferences() const;
+ size_t NumJniShadowFrameReferences() const;
bool ShadowFramesContain(Object** shadow_frame_entry) const;
diff --git a/src/thread.cc b/src/thread.cc
index 75d0468..7490d2a 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -52,6 +52,7 @@
#include "stack_indirect_reference_table.h"
#include "thread_list.h"
#include "utils.h"
+#include "verifier/dex_gc_map.h"
#include "well_known_classes.h"
namespace art {
@@ -1853,8 +1854,39 @@
}
ShadowFrame* shadow_frame = GetCurrentShadowFrame();
if (shadow_frame != NULL) {
- WrapperVisitor wrapperVisitor(visitor_, this);
- shadow_frame->VisitRoots(wrapperVisitor);
+ AbstractMethod* m = shadow_frame->GetMethod();
+ size_t num_regs = shadow_frame->NumberOfVRegs();
+ if (m->IsNative() || shadow_frame->HasReferenceArray()) {
+ // SIRT for JNI or References for interpreter.
+ for (size_t reg = 0; reg < num_regs; ++reg) {
+ Object* ref = shadow_frame->GetVRegReference(reg);
+ if (ref != NULL) {
+ visitor_(ref, reg, this);
+ }
+ }
+ } else {
+ // Java method.
+ // Portable path use DexGcMap and store in Method.native_gc_map_.
+ const uint8_t* gc_map = m->GetNativeGcMap();
+ CHECK(gc_map != NULL) << PrettyMethod(m);
+ uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
+ (gc_map[1] << 16) |
+ (gc_map[2] << 8) |
+ (gc_map[3] << 0));
+ verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
+ uint32_t dex_pc = GetDexPc();
+ const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
+ DCHECK(reg_bitmap != NULL);
+ num_regs = std::min(dex_gc_map.RegWidth() * 8, num_regs);
+ for (size_t reg = 0; reg < num_regs; ++reg) {
+ if (TestBitmap(reg, reg_bitmap)) {
+ Object* ref = shadow_frame->GetVRegReference(reg);
+ if (ref != NULL) {
+ visitor_(ref, reg, this);
+ }
+ }
+ }
+ }
} else {
AbstractMethod* m = GetMethod();
// Process register map (which native and runtime methods don't have)
@@ -1903,21 +1935,6 @@
}
private:
-
- class WrapperVisitor {
- public:
- WrapperVisitor(const RootVisitor& root_visitor, const StackVisitor* stack_visitor)
- : root_visitor_(root_visitor), stack_visitor_(stack_visitor) {}
-
- void operator()(const Object* obj, size_t offset) const {
- root_visitor_(obj, offset, stack_visitor_);
- }
-
- private:
- const RootVisitor& root_visitor_;
- const StackVisitor* const stack_visitor_;
- };
-
static bool TestBitmap(int reg, const uint8_t* reg_vector) {
return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
}
diff --git a/src/thread.h b/src/thread.h
index 8b9c81d..7bd64c8 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -524,17 +524,17 @@
ManagedStack::TopShadowFrameOffset());
}
- // Number of references allocated in ShadowFrames on this thread
- size_t NumShadowFrameReferences() const {
- return managed_stack_.NumShadowFrameReferences();
+ // Number of references allocated in JNI ShadowFrames on this thread
+ size_t NumJniShadowFrameReferences() const {
+ return managed_stack_.NumJniShadowFrameReferences();
}
// Number of references in SIRTs on this thread
size_t NumSirtReferences();
- // Number of references allocated in SIRTs & shadow frames on this thread
+ // Number of references allocated in SIRTs & JNI shadow frames on this thread
size_t NumStackReferences() {
- return NumSirtReferences() + NumShadowFrameReferences();
+ return NumSirtReferences() + NumJniShadowFrameReferences();
};
// Is the given obj in this thread's stack indirect reference table?
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index d6cd665dd..b96989d 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -979,7 +979,6 @@
return true;
}
-#if !defined(ART_USE_LLVM_COMPILER)
static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(const std::vector<uint8_t>& gc_map) {
std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
@@ -997,7 +996,6 @@
(length_prefixed_gc_map->at(3) << 0)));
return length_prefixed_gc_map;
}
-#endif
bool MethodVerifier::VerifyCodeFlow() {
uint16_t registers_size = code_item_->registers_size_;
@@ -1029,7 +1027,6 @@
Compiler::MethodReference ref(dex_file_, dex_method_idx_);
-#if !defined(ART_USE_LLVM_COMPILER)
/* Generate a register map and add it to the method. */
UniquePtr<const std::vector<uint8_t> > map(GenerateGcMap());
@@ -1043,13 +1040,13 @@
const std::vector<uint8_t>* dex_gc_map = CreateLengthPrefixedDexGcMap(*(map.get()));
verifier::MethodVerifier::SetDexGcMap(ref, *dex_gc_map);
-#else // defined(ART_USE_LLVM_COMPILER)
+#if defined(ART_USE_LLVM_COMPILER)
/* Generate Inferred Register Category for LLVM-based Code Generator */
const InferredRegCategoryMap* table = GenerateInferredRegCategoryMap();
verifier::MethodVerifier::SetInferredRegCategoryMap(ref, *table);
-
#endif
+
return true;
}
@@ -3498,17 +3495,6 @@
for (size_t i = 0; i < insns_size; ++i) {
if (RegisterLine* line = reg_table_.GetLine(i)) {
const Instruction* inst = Instruction::At(code_item_->insns_ + i);
-
- // GC points
- if (inst->IsBranch() || inst->IsInvoke()) {
- for (size_t r = 0; r < regs_size; ++r) {
- const RegType &rt = line->GetRegisterType(r);
- if (rt.IsNonZeroReferenceTypes()) {
- table->SetRegCanBeObject(r);
- }
- }
- }
-
/* We only use InferredRegCategoryMap in one case */
if (inst->IsBranch()) {
for (size_t r = 0; r < regs_size; ++r) {