diff options
author | 2012-11-18 16:59:53 -0800 | |
---|---|---|
committer | 2012-12-04 11:07:34 -0800 | |
commit | ce4cc0d1818e872c1c7f3c3519a82259afd5c288 (patch) | |
tree | 308f2c30e5a842a5e459d96e730ca4432a020f4f | |
parent | 823b8acdf2c8274ff93b685e50a93ab9afc6af8b (diff) |
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
29 files changed, 323 insertions, 537 deletions
diff --git a/src/compiled_method.h b/src/compiled_method.h index 901ec64d79..b7a2f9c629 100644 --- a/src/compiled_method.h +++ b/src/compiled_method.h @@ -99,6 +99,15 @@ class CompiledMethod : public CompiledCode { // 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 c1d61d4279..2c27bb0dc5 100644 --- a/src/compiler/codegen/mir_to_gbc.cc +++ b/src/compiler/codegen/mir_to_gbc.cc @@ -544,34 +544,6 @@ static void ConvertArithOp(CompilationUnit* cu, OpKind op, RegLocation rl_dest, 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 @@ static void ConvertInvoke(CompilationUnit* cu, BasicBlock* bb, MIR* mir, 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 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, 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 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, rl_dest = GetDestWide(cu, mir); } else { rl_dest = GetDest(cu, mir); - if (rl_dest.ref) { - object_definition = true; - } } } @@ -935,9 +898,6 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, 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 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, 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 @@ static bool BitcodeBlockCodeGen(CompilationUnit* cu, llvm::BasicBlock* bb) 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 1c04dc836c..32f9b51866 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_unlock_object_from_code(%JavaObject*, %JavaObject*) 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 a27ea6e41a..3524cddfbf 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 @@ bool CompilationUnit::MaterializeToRawOStream(llvm::raw_ostream& out_stream) { 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 3ec5e68061..78434072ee 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 @@ CompileDexMethod(OatCompilationUnit* oat_compilation_unit, InvokeType invoke_typ 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 57a13d56d3..93d7d48ab3 100644 --- a/src/compiler_llvm/gbc_expander.cc +++ b/src/compiler_llvm/gbc_expander.cc @@ -217,9 +217,7 @@ class GBCExpanderPass : public llvm::FunctionPass { 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 @@ GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) { 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 @@ llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr, } 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 @@ GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) { 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 @@ GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) { 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 @@ GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) { 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 @@ llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) { 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 @@ llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst, 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 @@ void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value, 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 @@ void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value, 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* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc, 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* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc, 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* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) { 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 @@ void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) { EmitGuard_NullPointerException(dex_pc, object_addr); } + EmitUpdateDexPC(dex_pc); + irb_.Runtime().EmitLockObject(object_addr); return; @@ -2177,7 +2161,7 @@ llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) { 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 @@ GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id, 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 @@ GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id, //==- 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 e118646a82..ef8d6da2e5 100644 --- a/src/compiler_llvm/generated/art_module.cc +++ b/src/compiler_llvm/generated/art_module.cc @@ -44,12 +44,12 @@ if (!StructTy_ShadowFrame) { 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 @@ std::vector<Type*>FuncTy_7_args; 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 b271002df4..e8e73e3780 100644 --- a/src/compiler_llvm/ir_builder.cc +++ b/src/compiler_llvm/ir_builder.cc @@ -151,8 +151,8 @@ llvm::Type* IRBuilder::getJTypeInArraySpace(JType jty) { } -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 @@ llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_ // 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 cc0bc8e801..4a5851575c 100644 --- a/src/compiler_llvm/ir_builder.h +++ b/src/compiler_llvm/ir_builder.h @@ -315,7 +315,7 @@ class IRBuilder : public LLVMIRBuilder { 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 d5a7869d00..2a173208ac 100644 --- a/src/compiler_llvm/jni_compiler.cc +++ b/src/compiler_llvm/jni_compiler.cc @@ -101,7 +101,7 @@ CompiledMethod* JniCompiler::Compile() { } // 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 @@ CompiledMethod* JniCompiler::Compile() { // 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 @@ CompiledMethod* JniCompiler::Compile() { // 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 @@ CompiledMethod* JniCompiler::Compile() { 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 f5232aa69c..038e133356 100644 --- a/src/compiler_llvm/md_builder.cc +++ b/src/compiler_llvm/md_builder.cc @@ -39,8 +39,10 @@ llvm::MDNode* MDBuilder::GetTBAASpecialType(TBAASpecialType sty_id) { 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 f09553cf06..68121de4f4 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -60,8 +60,6 @@ MethodCompiler::MethodCompiler(CompilationUnit* cunit, 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 @@ MethodCompiler::MethodCompiler(CompilationUnit* cunit, 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 @@ void MethodCompiler::EmitPrologue() { 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 @@ void MethodCompiler::EmitPrologueLastBranch() { 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 @@ void MethodCompiler::EmitPrologueAllocShadowFrame() { 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 @@ void MethodCompiler::EmitPrologueAllocShadowFrame() { 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 @@ void MethodCompiler::EmitInsn_LoadConstantString(uint32_t dex_pc, 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* MethodCompiler::EmitLoadConstantClass(uint32_t dex_pc, 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 @@ void MethodCompiler::EmitInsn_MonitorEnter(uint32_t dex_pc, EmitGuard_NullPointerException(dex_pc, object_addr); } + EmitUpdateDexPC(dex_pc); + irb_.Runtime().EmitLockObject(object_addr); irb_.CreateBr(GetNextBasicBlock(dex_pc)); @@ -1914,6 +1887,11 @@ void MethodCompiler::EmitInsn_UnconditionalBranch(uint32_t dex_pc, 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 @@ void MethodCompiler::EmitInsn_BinaryConditionalBranch(uint32_t dex_pc, 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 @@ void MethodCompiler::EmitInsn_UnaryConditionalBranch(uint32_t dex_pc, 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 @@ greenland::RegCategory MethodCompiler::GetInferredRegCategory(uint32_t dex_pc, 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* MethodCompiler::EmitLoadStaticStorage(uint32_t dex_pc, 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 @@ void MethodCompiler::EmitInsn_Invoke(uint32_t dex_pc, irb_.LoadFromObjectOffset(callee_method_object_addr, AbstractMethod::GetCodeOffset().Int32Value(), GetFunctionType(callee_method_idx, is_static)->getPointerTo(), - kTBAAJRuntime); + kTBAARuntimeInfo); } // Invoke callee @@ -2835,7 +2817,7 @@ EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) { 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 @@ CompiledMethod *MethodCompiler::Compile() { 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_ExceptionLandingPad(uint32_t dex_pc, bool can_ski } -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::AllocDalvikReg(RegCategory cat, const std::string& } -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* MethodCompiler::GetVRegEntry(uint32_t reg_idx) { 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 @@ void MethodCompiler::EmitPushShadowFrame(bool is_inline) { 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 @@ llvm::Value* MethodCompiler::EmitLoadDalvikReg(uint32_t reg_idx, char shorty, 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 02c3d6a476..f67866affd 100644 --- a/src/compiler_llvm/method_compiler.h +++ b/src/compiler_llvm/method_compiler.h @@ -289,7 +289,7 @@ class MethodCompiler { 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 @@ class MethodCompiler { 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 dbcbe89034..169f8e8b42 100644 --- a/src/compiler_llvm/runtime_support_builder.cc +++ b/src/compiler_llvm/runtime_support_builder.cc @@ -86,8 +86,8 @@ llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(llvm::Value* thread) { /* 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 @@ llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_ 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::EmitPushShadowFrame(llvm::Value* new_shadow_ 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::EmitGetAndClearException() { 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 @@ llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() { 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 ba512af66a..58f01f69e6 100644 --- a/src/compiler_llvm/runtime_support_builder.h +++ b/src/compiler_llvm/runtime_support_builder.h @@ -51,9 +51,9 @@ class RuntimeSupportBuilder { /* 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 3cdd532493..7d732490ca 100644 --- a/src/compiler_llvm/runtime_support_llvm.cc +++ b/src/compiler_llvm/runtime_support_llvm.cc @@ -90,11 +90,9 @@ void art_test_suspend_from_code(Thread* thread) } 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 c52b7f992f..6c133c9902 100644 --- a/src/compiler_llvm/runtime_support_llvm.h +++ b/src/compiler_llvm/runtime_support_llvm.h @@ -26,8 +26,7 @@ namespace art { //---------------------------------------------------------------------------- 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 4854c9fa29..4571f58015 100644 --- a/src/compiler_llvm/stub_compiler.cc +++ b/src/compiler_llvm/stub_compiler.cc @@ -148,7 +148,7 @@ CompiledInvokeStub* StubCompiler::CreateInvokeStub(bool is_static, 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 86c855c89a..0c31634762 100644 --- a/src/greenland/inferred_reg_category_map.cc +++ b/src/greenland/inferred_reg_category_map.cc @@ -27,7 +27,7 @@ namespace greenland { 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 @@ void InferredRegCategoryMap::SetRegCategory(uint32_t dex_pc, } } -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 b48dcee0db..b354097123 100644 --- a/src/greenland/inferred_reg_category_map.h +++ b/src/greenland/inferred_reg_category_map.h @@ -63,9 +63,6 @@ class InferredRegCategoryMap { 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 @@ class InferredRegCategoryMap { 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 57faf4c9fc..e6e3ec2f7c 100644 --- a/src/greenland/intrinsic_func_list.def +++ b/src/greenland/intrinsic_func_list.def @@ -1546,14 +1546,7 @@ _EVAL_DEF_INTRINSICS_FUNC(AllocaShadowFrame, 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 8c217c71e3..5aa4c2d959 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -377,7 +377,7 @@ static void DoInvoke(Thread* self, MethodHelper& mh, ShadowFrame& shadow_frame, 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 @@ static void DoFieldGet(Thread* self, ShadowFrame& shadow_frame, 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 @@ static void DoFieldGet(Thread* self, ShadowFrame& shadow_frame, 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 @@ static void DoFieldPut(Thread* self, ShadowFrame& shadow_frame, 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 @@ static void DoFieldPut(Thread* self, ShadowFrame& shadow_frame, 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } 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 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c 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 @@ void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* re } // 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 @@ void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* re 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 5d4fa5ac12..16eedfe54d 100644 --- a/src/invoke_arg_array_builder.h +++ b/src/invoke_arg_array_builder.h @@ -148,7 +148,7 @@ class ArgArray { 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 @@ class ArgArray { 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 382139ea86..a15c5cfbff 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -302,7 +302,7 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, 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 be737acb4a..be6fe458de 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 1134b25246..ce84807098 100644 --- a/src/stack.h +++ b/src/stack.h @@ -51,26 +51,34 @@ enum VRegKind { 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 @@ class ShadowFrame { 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 @@ class ShadowFrame { 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 @@ class ShadowFrame { 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 @@ class PACKED(4) ManagedStack { 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 75d0468dab..7490d2ae6f 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 @@ class ReferenceMapVisitor : public StackVisitor { } 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 @@ class ReferenceMapVisitor : public StackVisitor { } 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 8b9c81d068..7bd64c825f 100644 --- a/src/thread.h +++ b/src/thread.h @@ -524,17 +524,17 @@ class PACKED(4) Thread { 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 d6cd665dd6..b96989ddec 100644 --- a/src/verifier/method_verifier.cc +++ b/src/verifier/method_verifier.cc @@ -979,7 +979,6 @@ bool MethodVerifier::CheckVarArgRangeRegs(uint32_t vA, uint32_t vC) { 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 @@ static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(const std::vecto (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 @@ bool MethodVerifier::VerifyCodeFlow() { 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 @@ bool MethodVerifier::VerifyCodeFlow() { 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 @@ const greenland::InferredRegCategoryMap* MethodVerifier::GenerateInferredRegCate 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) { |