diff options
Diffstat (limited to 'compiler/optimizing/builder.cc')
-rw-r--r-- | compiler/optimizing/builder.cc | 143 |
1 files changed, 47 insertions, 96 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 5acc5fda71..ed193c7b61 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -159,9 +159,13 @@ void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { int locals_index = locals_.size() - number_of_parameters; int parameter_index = 0; + const DexFile::MethodId& referrer_method_id = + dex_file_->GetMethodId(dex_compilation_unit_->GetDexMethodIndex()); if (!dex_compilation_unit_->IsStatic()) { // Add the implicit 'this' argument, not expressed in the signature. - HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++, + HParameterValue* parameter = new (arena_) HParameterValue(*dex_file_, + referrer_method_id.class_idx_, + parameter_index++, Primitive::kPrimNot, true); entry_block_->AddInstruction(parameter); @@ -170,11 +174,16 @@ void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { number_of_parameters--; } - uint32_t pos = 1; - for (int i = 0; i < number_of_parameters; i++) { - HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++, - Primitive::GetType(shorty[pos++]), - false); + const DexFile::ProtoId& proto = dex_file_->GetMethodPrototype(referrer_method_id); + const DexFile::TypeList* arg_types = dex_file_->GetProtoParameters(proto); + for (int i = 0, shorty_pos = 1; i < number_of_parameters; i++) { + HParameterValue* parameter = new (arena_) HParameterValue( + *dex_file_, + arg_types->GetTypeItem(shorty_pos - 1).type_idx_, + parameter_index++, + Primitive::GetType(shorty[shorty_pos]), + false); + ++shorty_pos; entry_block_->AddInstruction(parameter); HLocal* local = GetLocalAt(locals_index++); // Store the parameter value in the local that the dex code will use @@ -375,7 +384,7 @@ void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) // We do not split each edge separately, but rather create one boundary block // that all predecessors are relinked to. This preserves loop headers (b/23895756). for (auto entry : try_block_info) { - HBasicBlock* try_block = graph_->GetBlock(entry.first); + HBasicBlock* try_block = graph_->GetBlocks()[entry.first]; for (HBasicBlock* predecessor : try_block->GetPredecessors()) { if (GetTryItem(predecessor, try_block_info) != entry.second) { // Found a predecessor not covered by the same TryItem. Insert entering @@ -392,10 +401,10 @@ void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) // Do a second pass over the try blocks and insert exit TryBoundaries where // the successor is not in the same TryItem. for (auto entry : try_block_info) { - HBasicBlock* try_block = graph_->GetBlock(entry.first); + HBasicBlock* try_block = graph_->GetBlocks()[entry.first]; // NOTE: Do not use iterators because SplitEdge would invalidate them. for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) { - HBasicBlock* successor = try_block->GetSuccessor(i); + HBasicBlock* successor = try_block->GetSuccessors()[i]; // If the successor is a try block, all of its predecessors must be // covered by the same TryItem. Otherwise the previous pass would have @@ -581,7 +590,6 @@ bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const { DCHECK_GE(dex_pc, 0); - DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.size()); return branch_targets_[dex_pc]; } @@ -766,11 +774,12 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, &string_init_offset); // Replace calls to String.<init> with StringFactory. if (is_string_init) { - HInvokeStaticOrDirect::DispatchInfo dispatch_info = ComputeDispatchInfo(is_string_init, - string_init_offset, - target_method, - direct_method, - direct_code); + HInvokeStaticOrDirect::DispatchInfo dispatch_info = { + HInvokeStaticOrDirect::MethodLoadKind::kStringInit, + HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod, + dchecked_integral_cast<uint64_t>(string_init_offset), + 0U + }; HInvoke* invoke = new (arena_) HInvokeStaticOrDirect( arena_, number_of_arguments - 1, @@ -833,11 +842,12 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, clinit_check = ProcessClinitCheckForInvoke(dex_pc, method_idx, &clinit_check_requirement); } - HInvokeStaticOrDirect::DispatchInfo dispatch_info = ComputeDispatchInfo(is_string_init, - string_init_offset, - target_method, - direct_method, - direct_code); + HInvokeStaticOrDirect::DispatchInfo dispatch_info = { + HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod, + HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod, + 0u, + 0U + }; invoke = new (arena_) HInvokeStaticOrDirect(arena_, number_of_arguments, return_type, @@ -950,77 +960,6 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke( return clinit_check; } -HInvokeStaticOrDirect::DispatchInfo HGraphBuilder::ComputeDispatchInfo( - bool is_string_init, - int32_t string_init_offset, - MethodReference target_method, - uintptr_t direct_method, - uintptr_t direct_code) { - HInvokeStaticOrDirect::MethodLoadKind method_load_kind; - HInvokeStaticOrDirect::CodePtrLocation code_ptr_location; - uint64_t method_load_data = 0u; - uint64_t direct_code_ptr = 0u; - - if (is_string_init) { - // TODO: Use direct_method and direct_code for the appropriate StringFactory method. - method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kStringInit; - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod; - method_load_data = string_init_offset; - } else if (target_method.dex_file == outer_compilation_unit_->GetDexFile() && - target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex()) { - method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRecursive; - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallSelf; - } else { - if (direct_method != 0u) { // Should we use a direct pointer to the method? - if (direct_method != static_cast<uintptr_t>(-1)) { // Is the method pointer known now? - method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress; - method_load_data = direct_method; - } else { // The direct pointer will be known at link time. - method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup; - } - } else { // Use dex cache. - DCHECK(target_method.dex_file == dex_compilation_unit_->GetDexFile()); - DexCacheArraysLayout layout = - compiler_driver_->GetDexCacheArraysLayout(target_method.dex_file); - if (layout.Valid()) { // Can we use PC-relative access to the dex cache arrays? - method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative; - method_load_data = layout.MethodOffset(target_method.dex_method_index); - } else { // We must go through the ArtMethod's pointer to resolved methods. - method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod; - } - } - if (direct_code != 0u) { // Should we use a direct pointer to the code? - if (direct_code != static_cast<uintptr_t>(-1)) { // Is the code pointer known now? - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirect; - direct_code_ptr = direct_code; - } else if (compiler_driver_->IsImage() || - target_method.dex_file == dex_compilation_unit_->GetDexFile()) { - // Use PC-relative calls for invokes within a multi-dex oat file. - // TODO: Recognize when the target dex file is within the current oat file for - // app compilation. At the moment we recognize only the boot image as multi-dex. - // NOTE: This will require changing the ARM backend which currently falls - // through from kCallPCRelative to kDirectCodeFixup for different dex files. - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative; - } else { // The direct pointer will be known at link time. - // NOTE: This is used for app->boot calls when compiling an app against - // a relocatable but not yet relocated image. - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup; - } - } else { // We must use the code pointer from the ArtMethod. - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod; - } - } - - if (graph_->IsDebuggable()) { - // For debuggable apps always use the code pointer from ArtMethod - // so that we don't circumvent instrumentation stubs if installed. - code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod; - } - - return HInvokeStaticOrDirect::DispatchInfo { - method_load_kind, code_ptr_location, method_load_data, direct_code_ptr }; -} - bool HGraphBuilder::SetupInvokeArguments(HInvoke* invoke, uint32_t number_of_vreg_arguments, uint32_t* args, @@ -1176,10 +1115,9 @@ void HGraphBuilder::PotentiallySimplifyFakeString(uint16_t original_dex_register verified_method->GetStringInitPcRegMap(); auto map_it = string_init_map.find(dex_pc); if (map_it != string_init_map.end()) { - std::set<uint32_t> reg_set = map_it->second; - for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) { + for (uint32_t reg : map_it->second) { HInstruction* load_local = LoadLocal(original_dex_register, Primitive::kPrimNot, dex_pc); - UpdateLocal(*set_it, load_local, dex_pc); + UpdateLocal(reg, load_local, dex_pc); } } } else { @@ -1234,12 +1172,14 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, field_index, dex_pc); } else { + uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex(); field_set = new (arena_) HInstanceFieldSet(null_check, value, field_type, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, + class_def_index, *dex_file_, dex_compilation_unit_->GetDexCache(), dex_pc); @@ -1254,11 +1194,13 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, field_index, dex_pc); } else { + uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex(); field_get = new (arena_) HInstanceFieldGet(null_check, field_type, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, + class_def_index, *dex_file_, dex_compilation_unit_->GetDexCache(), dex_pc); @@ -1303,7 +1245,13 @@ bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const { soa, dex_cache, class_loader, type_index, dex_compilation_unit_))); Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); - return outer_class.Get() == cls.Get(); + // GetOutermostCompilingClass returns null when the class is unresolved + // (e.g. if it derives from an unresolved class). This is bogus knowing that + // we are compiling it. + // When this happens we cannot establish a direct relation between the current + // class and the outer class, so we return false. + // (Note that this is only used for optimizing invokes and field accesses) + return (cls.Get() != nullptr) && (outer_class.Get() == cls.Get()); } void HGraphBuilder::BuildUnresolvedStaticFieldAccess(const Instruction& instruction, @@ -1394,6 +1342,8 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, cls = new (arena_) HClinitCheck(constant, dex_pc); current_block_->AddInstruction(cls); } + + uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex(); if (is_put) { // We need to keep the class alive before loading the value. Temporaries temps(graph_); @@ -1406,6 +1356,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, + class_def_index, *dex_file_, dex_cache_, dex_pc)); @@ -1415,6 +1366,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, + class_def_index, *dex_file_, dex_cache_, dex_pc)); @@ -2877,7 +2829,6 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 } // NOLINT(readability/fn_size) HLocal* HGraphBuilder::GetLocalAt(uint32_t register_index) const { - DCHECK_LT(register_index, locals_.size()); return locals_[register_index]; } |