diff options
author | 2017-01-12 13:25:19 +0000 | |
---|---|---|
committer | 2017-01-16 22:56:56 +0000 | |
commit | 5d37c152f21a0807459c6f53bc25e2d84f56d259 (patch) | |
tree | 7d8cbce0a55f258150a047def70244f79afc866d | |
parent | aa89a4c6fca095904521842c018399f1e3501a45 (diff) |
Put inlined ArtMethod pointer in stack maps.
Currently done for JIT. Can be extended for AOT and inlined boot
image methods.
Also refactor the lookup of a inlined method at runtime to not
rely on the dex cache, but look at the class loader tables.
bug: 30933338
test: test-art-host, test-art-target
Change-Id: I58bd4d763b82ab8ca3023742835ac388671d1794
26 files changed, 222 insertions, 199 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index f00648f570..8ee0a6bbdb 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -927,10 +927,10 @@ void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slo if (environment->GetParent() != nullptr) { // We emit the parent environment first. EmitEnvironment(environment->GetParent(), slow_path); - stack_map_stream_.BeginInlineInfoEntry(environment->GetMethodIdx(), + stack_map_stream_.BeginInlineInfoEntry(environment->GetMethod(), environment->GetDexPc(), - environment->GetInvokeType(), - environment->Size()); + environment->Size(), + &graph_->GetDexFile()); } // Walk over the environment, and record the location of dex registers. diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 4b6a9bed61..494c281590 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -3994,7 +3994,7 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invok break; case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: { // Add ADRP with its PC-relative DexCache access patch. - const DexFile& dex_file = invoke->GetDexFile(); + const DexFile& dex_file = invoke->GetDexFileForPcRelativeDexCache(); uint32_t element_offset = invoke->GetDexCacheArrayOffset(); vixl::aarch64::Label* adrp_label = NewPcRelativeDexCacheArrayPatch(dex_file, element_offset); EmitAdrpPlaceholder(adrp_label, XRegisterFrom(temp)); diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 046d59cee7..318d45528e 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -3366,7 +3366,7 @@ void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative: { uint32_t offset = invoke->GetDexCacheArrayOffset(); CodeGeneratorMIPS64::PcRelativePatchInfo* info = - NewPcRelativeDexCacheArrayPatch(invoke->GetDexFile(), offset); + NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset); EmitPcRelativeAddressPlaceholderHigh(info, AT); __ Ld(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678); break; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index f13b60aebf..8b4f060ef0 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -4505,7 +4505,7 @@ Location CodeGeneratorX86::GenerateCalleeMethodStaticOrDirectCall(HInvokeStaticO __ movl(temp.AsRegister<Register>(), Address(base_reg, kDummy32BitOffset)); // Bind a new fixup label at the end of the "movl" insn. uint32_t offset = invoke->GetDexCacheArrayOffset(); - __ Bind(NewPcRelativeDexCacheArrayPatch(invoke->GetDexFile(), offset)); + __ Bind(NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset)); break; } case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: { diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 89f4ae04d7..d4bf18d176 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -986,7 +986,7 @@ Location CodeGeneratorX86_64::GenerateCalleeMethodStaticOrDirectCall(HInvokeStat Address::Absolute(kDummy32BitOffset, /* no_rip */ false)); // Bind a new fixup label at the end of the "movl" insn. uint32_t offset = invoke->GetDexCacheArrayOffset(); - __ Bind(NewPcRelativeDexCacheArrayPatch(invoke->GetDexFile(), offset)); + __ Bind(NewPcRelativeDexCacheArrayPatch(invoke->GetDexFileForPcRelativeDexCache(), offset)); break; } case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod: { diff --git a/compiler/optimizing/dex_cache_array_fixups_arm.cc b/compiler/optimizing/dex_cache_array_fixups_arm.cc index 10a36c6ff4..ae9e0febfb 100644 --- a/compiler/optimizing/dex_cache_array_fixups_arm.cc +++ b/compiler/optimizing/dex_cache_array_fixups_arm.cc @@ -79,9 +79,10 @@ class DexCacheArrayFixupsVisitor : public HGraphVisitor { // we need to add the dex cache arrays base as the special input. if (invoke->HasPcRelativeDexCache() && !IsCallFreeIntrinsic<IntrinsicLocationsBuilderARMType>(invoke, codegen_)) { - HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(invoke->GetDexFile()); + HArmDexCacheArraysBase* base = + GetOrCreateDexCacheArrayBase(invoke->GetDexFileForPcRelativeDexCache()); // Update the element offset in base. - DexCacheArraysLayout layout(kArmPointerSize, &invoke->GetDexFile()); + DexCacheArraysLayout layout(kArmPointerSize, &invoke->GetDexFileForPcRelativeDexCache()); base->UpdateElementOffset(layout.MethodOffset(invoke->GetDexMethodIndex())); // Add the special argument base to the method. DCHECK(!invoke->HasCurrentMethodInput()); diff --git a/compiler/optimizing/dex_cache_array_fixups_mips.cc b/compiler/optimizing/dex_cache_array_fixups_mips.cc index 31fff26dd5..798193e6e6 100644 --- a/compiler/optimizing/dex_cache_array_fixups_mips.cc +++ b/compiler/optimizing/dex_cache_array_fixups_mips.cc @@ -74,9 +74,10 @@ class DexCacheArrayFixupsVisitor : public HGraphVisitor { if (invoke->HasPcRelativeDexCache() && !IsCallFreeIntrinsic<IntrinsicLocationsBuilderMIPS>(invoke, codegen_)) { // Initialize base for target method dex file if needed. - HMipsDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(invoke->GetDexFile()); + HMipsDexCacheArraysBase* base = + GetOrCreateDexCacheArrayBase(invoke->GetDexFileForPcRelativeDexCache()); // Update the element offset in base. - DexCacheArraysLayout layout(kMipsPointerSize, &invoke->GetDexFile()); + DexCacheArraysLayout layout(kMipsPointerSize, &invoke->GetDexFileForPcRelativeDexCache()); base->UpdateElementOffset(layout.MethodOffset(invoke->GetDexMethodIndex())); // Add the special argument base to the method. DCHECK(!invoke->HasCurrentMethodInput()); diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 768b1d80a1..5a75a01867 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -207,10 +207,8 @@ void HInstructionBuilder::InitializeInstruction(HInstruction* instruction) { HEnvironment* environment = new (arena_) HEnvironment( arena_, current_locals_->size(), - graph_->GetDexFile(), - graph_->GetMethodIdx(), + graph_->GetArtMethod(), instruction->GetDexPc(), - graph_->GetInvokeType(), instruction); environment->CopyFrom(*current_locals_); instruction->SetRawEnvironment(environment); diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index fc6ff7b197..17d683f357 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -145,7 +145,7 @@ void IntrinsicsRecognizer::Run() { if (!CheckInvokeType(intrinsic, invoke)) { LOG(WARNING) << "Found an intrinsic with unexpected invoke type: " << intrinsic << " for " - << invoke->GetDexFile().PrettyMethod(invoke->GetDexMethodIndex()) + << art_method->PrettyMethod() << invoke->DebugName(); } else { invoke->SetIntrinsic(intrinsic, diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index d45fa11534..f7c2f9735c 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -2387,6 +2387,14 @@ bool HInvoke::NeedsEnvironment() const { return !opt.GetDoesNotNeedEnvironment(); } +const DexFile& HInvokeStaticOrDirect::GetDexFileForPcRelativeDexCache() const { + ArtMethod* caller = GetEnvironment()->GetMethod(); + ScopedObjectAccess soa(Thread::Current()); + // `caller` is null for a top-level graph representing a method whose declaring + // class was not resolved. + return caller == nullptr ? GetBlock()->GetGraph()->GetDexFile() : *caller->GetDexFile(); +} + bool HInvokeStaticOrDirect::NeedsDexCacheOfDeclaringClass() const { if (GetMethodLoadKind() != MethodLoadKind::kDexCacheViaMethod) { return false; diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 7d6f6164ec..e32c661176 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1720,28 +1720,22 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> { public: HEnvironment(ArenaAllocator* arena, size_t number_of_vregs, - const DexFile& dex_file, - uint32_t method_idx, + ArtMethod* method, uint32_t dex_pc, - InvokeType invoke_type, HInstruction* holder) : vregs_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentVRegs)), locations_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentLocations)), parent_(nullptr), - dex_file_(dex_file), - method_idx_(method_idx), + method_(method), dex_pc_(dex_pc), - invoke_type_(invoke_type), holder_(holder) { } HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder) : HEnvironment(arena, to_copy.Size(), - to_copy.GetDexFile(), - to_copy.GetMethodIdx(), + to_copy.GetMethod(), to_copy.GetDexPc(), - to_copy.GetInvokeType(), holder) {} void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) { @@ -1790,16 +1784,8 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> { return dex_pc_; } - uint32_t GetMethodIdx() const { - return method_idx_; - } - - InvokeType GetInvokeType() const { - return invoke_type_; - } - - const DexFile& GetDexFile() const { - return dex_file_; + ArtMethod* GetMethod() const { + return method_; } HInstruction* GetHolder() const { @@ -1815,10 +1801,8 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> { ArenaVector<HUserRecord<HEnvironment*>> vregs_; ArenaVector<Location> locations_; HEnvironment* parent_; - const DexFile& dex_file_; - const uint32_t method_idx_; + ArtMethod* method_; const uint32_t dex_pc_; - const InvokeType invoke_type_; // The instruction that holds this environment. HInstruction* const holder_; @@ -3868,7 +3852,6 @@ class HInvoke : public HVariableInputSizeInstruction { Primitive::Type GetType() const OVERRIDE { return GetPackedField<ReturnTypeField>(); } uint32_t GetDexMethodIndex() const { return dex_method_index_; } - const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); } InvokeType GetInvokeType() const { return GetPackedField<InvokeTypeField>(); @@ -4166,6 +4149,8 @@ class HInvokeStaticOrDirect FINAL : public HInvoke { return dispatch_info_.method_load_data; } + const DexFile& GetDexFileForPcRelativeDexCache() const; + ClinitCheckRequirement GetClinitCheckRequirement() const { return GetPackedField<ClinitCheckRequirementField>(); } @@ -5425,10 +5410,10 @@ class HBoundsCheck FINAL : public HExpression<2> { HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc, - uint32_t string_char_at_method_index = DexFile::kDexNoIndex) - : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc), - string_char_at_method_index_(string_char_at_method_index) { + bool string_char_at = false) + : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc) { DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(index->GetType())); + SetPackedFlag<kFlagIsStringCharAt>(string_char_at); SetRawInputAt(0, index); SetRawInputAt(1, length); } @@ -5442,22 +5427,14 @@ class HBoundsCheck FINAL : public HExpression<2> { bool CanThrow() const OVERRIDE { return true; } - bool IsStringCharAt() const { return GetStringCharAtMethodIndex() != DexFile::kDexNoIndex; } - uint32_t GetStringCharAtMethodIndex() const { return string_char_at_method_index_; } + bool IsStringCharAt() const { return GetPackedFlag<kFlagIsStringCharAt>(); } HInstruction* GetIndex() const { return InputAt(0); } DECLARE_INSTRUCTION(BoundsCheck); private: - // We treat a String as an array, creating the HBoundsCheck from String.charAt() - // intrinsic in the instruction simplifier. We want to include the String.charAt() - // in the stack trace if we actually throw the StringIndexOutOfBoundsException, - // so we need to create an HEnvironment which will be translated to an InlineInfo - // indicating the extra stack frame. Since we add this HEnvironment quite late, - // in the PrepareForRegisterAllocation pass, we need to remember the method index - // from the invoke as we don't want to look again at the dex bytecode. - uint32_t string_char_at_method_index_; // DexFile::kDexNoIndex if regular array. + static constexpr size_t kFlagIsStringCharAt = kNumberOfExpressionPackedBits; DISALLOW_COPY_AND_ASSIGN(HBoundsCheck); }; diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc index 5d9a6528ca..7686ba851b 100644 --- a/compiler/optimizing/nodes_test.cc +++ b/compiler/optimizing/nodes_test.cc @@ -52,7 +52,7 @@ TEST(Node, RemoveInstruction) { exit_block->AddInstruction(new (&allocator) HExit()); HEnvironment* environment = new (&allocator) HEnvironment( - &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, null_check); + &allocator, 1, graph->GetArtMethod(), 0, null_check); null_check->SetRawEnvironment(environment); environment->SetRawEnvAt(0, parameter); parameter->AddEnvUseAt(null_check->GetEnvironment(), 0); @@ -137,7 +137,7 @@ TEST(Node, ParentEnvironment) { ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement()); HEnvironment* environment = new (&allocator) HEnvironment( - &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, with_environment); + &allocator, 1, graph->GetArtMethod(), 0, with_environment); ArenaVector<HInstruction*> array(allocator.Adapter()); array.push_back(parameter1); @@ -148,13 +148,13 @@ TEST(Node, ParentEnvironment) { ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement()); HEnvironment* parent1 = new (&allocator) HEnvironment( - &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr); + &allocator, 1, graph->GetArtMethod(), 0, nullptr); parent1->CopyFrom(array); ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u); HEnvironment* parent2 = new (&allocator) HEnvironment( - &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr); + &allocator, 1, graph->GetArtMethod(), 0, nullptr); parent2->CopyFrom(array); parent1->SetAndCopyParentChain(&allocator, parent2); diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc index f9ac3a0f72..d6a6efe604 100644 --- a/compiler/optimizing/prepare_for_register_allocation.cc +++ b/compiler/optimizing/prepare_for_register_allocation.cc @@ -16,6 +16,9 @@ #include "prepare_for_register_allocation.h" +#include "jni_internal.h" +#include "well_known_classes.h" + namespace art { void PrepareForRegisterAllocation::Run() { @@ -42,16 +45,12 @@ void PrepareForRegisterAllocation::VisitBoundsCheck(HBoundsCheck* check) { if (check->IsStringCharAt()) { // Add a fake environment for String.charAt() inline info as we want // the exception to appear as being thrown from there. - const DexFile& dex_file = check->GetEnvironment()->GetDexFile(); - DCHECK_STREQ(dex_file.PrettyMethod(check->GetStringCharAtMethodIndex()).c_str(), - "char java.lang.String.charAt(int)"); + ArtMethod* char_at_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt); ArenaAllocator* arena = GetGraph()->GetArena(); HEnvironment* environment = new (arena) HEnvironment(arena, /* number_of_vregs */ 0u, - dex_file, - check->GetStringCharAtMethodIndex(), + char_at_method, /* dex_pc */ DexFile::kDexNoIndex, - kVirtual, check); check->InsertRawEnvironment(environment); } @@ -232,8 +231,7 @@ bool PrepareForRegisterAllocation::CanMoveClinitCheck(HInstruction* input, return false; } if (user_environment->GetDexPc() != input_environment->GetDexPc() || - user_environment->GetMethodIdx() != input_environment->GetMethodIdx() || - !IsSameDexFile(user_environment->GetDexFile(), input_environment->GetDexFile())) { + user_environment->GetMethod() != input_environment->GetMethod()) { return false; } user_environment = user_environment->GetParent(); diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index f8a4469712..213a5acba6 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -499,18 +499,19 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst if (instr->IsInvokeStaticOrDirect() && instr->AsInvokeStaticOrDirect()->IsStringInit()) { // Calls to String.<init> are replaced with a StringFactory. if (kIsDebugBuild) { - HInvoke* invoke = instr->AsInvoke(); + HInvokeStaticOrDirect* invoke = instr->AsInvokeStaticOrDirect(); ClassLinker* cl = Runtime::Current()->GetClassLinker(); Thread* self = Thread::Current(); StackHandleScope<2> hs(self); + const DexFile& dex_file = *invoke->GetTargetMethod().dex_file; Handle<mirror::DexCache> dex_cache( - hs.NewHandle(FindDexCacheWithHint(self, invoke->GetDexFile(), hint_dex_cache_))); + hs.NewHandle(FindDexCacheWithHint(self, dex_file, hint_dex_cache_))); // Use a null loader. We should probably use the compiling method's class loader, // but then we would need to pass it to RTPVisitor just for this debug check. Since // the method is from the String class, the null loader is good enough. Handle<mirror::ClassLoader> loader; ArtMethod* method = cl->ResolveMethod<ClassLinker::kNoICCECheckForCache>( - invoke->GetDexFile(), invoke->GetDexMethodIndex(), dex_cache, loader, nullptr, kDirect); + dex_file, invoke->GetDexMethodIndex(), dex_cache, loader, nullptr, kDirect); DCHECK(method != nullptr); mirror::Class* declaring_class = method->GetDeclaringClass(); DCHECK(declaring_class != nullptr); @@ -844,10 +845,8 @@ void ReferenceTypePropagation::RTPVisitor::VisitInvoke(HInvoke* instr) { ScopedObjectAccess soa(Thread::Current()); ClassLinker* cl = Runtime::Current()->GetClassLinker(); - mirror::DexCache* dex_cache = - FindDexCacheWithHint(soa.Self(), instr->GetDexFile(), hint_dex_cache_); PointerSize pointer_size = cl->GetImagePointerSize(); - ArtMethod* method = dex_cache->GetResolvedMethod(instr->GetDexMethodIndex(), pointer_size); + ArtMethod* method = instr->GetResolvedMethod(); mirror::Class* klass = (method == nullptr) ? nullptr : method->GetReturnType(false, pointer_size); SetClassAsTypeInfo(instr, klass, /* is_exact */ false); } diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index fc8af6462a..6087e36507 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -13,8 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "stack_map_stream.h" +#include "art_method.h" +#include "runtime.h" +#include "scoped_thread_state_change-inl.h" + namespace art { void StackMapStream::BeginStackMapEntry(uint32_t dex_pc, @@ -98,15 +103,27 @@ void StackMapStream::AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t current_dex_register_++; } -void StackMapStream::BeginInlineInfoEntry(uint32_t method_index, +static bool EncodeArtMethodInInlineInfo(ArtMethod* method ATTRIBUTE_UNUSED) { + // Note: the runtime is null only for unit testing. + return Runtime::Current() == nullptr || !Runtime::Current()->IsAotCompiler(); +} + +void StackMapStream::BeginInlineInfoEntry(ArtMethod* method, uint32_t dex_pc, - InvokeType invoke_type, - uint32_t num_dex_registers) { + uint32_t num_dex_registers, + const DexFile* outer_dex_file) { DCHECK(!in_inline_frame_); in_inline_frame_ = true; - current_inline_info_.method_index = method_index; + if (EncodeArtMethodInInlineInfo(method)) { + current_inline_info_.method = method; + } else { + if (dex_pc != static_cast<uint32_t>(-1) && kIsDebugBuild) { + ScopedObjectAccess soa(Thread::Current()); + DCHECK(IsSameDexFile(*outer_dex_file, *method->GetDexFile())); + } + current_inline_info_.method_index = method->GetDexMethodIndexUnchecked(); + } current_inline_info_.dex_pc = dex_pc; - current_inline_info_.invoke_type = invoke_type; current_inline_info_.num_dex_registers = num_dex_registers; current_inline_info_.dex_register_locations_start_index = dex_register_locations_.size(); if (num_dex_registers != 0) { @@ -229,25 +246,32 @@ size_t StackMapStream::ComputeDexRegisterMapsSize() const { void StackMapStream::ComputeInlineInfoEncoding() { uint32_t method_index_max = 0; uint32_t dex_pc_max = DexFile::kDexNoIndex; - uint32_t invoke_type_max = 0; + uint32_t extra_data_max = 0; uint32_t inline_info_index = 0; for (const StackMapEntry& entry : stack_maps_) { for (size_t j = 0; j < entry.inlining_depth; ++j) { InlineInfoEntry inline_entry = inline_infos_[inline_info_index++]; - method_index_max = std::max(method_index_max, inline_entry.method_index); + if (inline_entry.method == nullptr) { + method_index_max = std::max(method_index_max, inline_entry.method_index); + extra_data_max = std::max(extra_data_max, 1u); + } else { + method_index_max = std::max( + method_index_max, High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method))); + extra_data_max = std::max( + extra_data_max, Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method))); + } if (inline_entry.dex_pc != DexFile::kDexNoIndex && (dex_pc_max == DexFile::kDexNoIndex || dex_pc_max < inline_entry.dex_pc)) { dex_pc_max = inline_entry.dex_pc; } - invoke_type_max = std::max(invoke_type_max, static_cast<uint32_t>(inline_entry.invoke_type)); } } DCHECK_EQ(inline_info_index, inline_infos_.size()); inline_info_encoding_.SetFromSizes(method_index_max, dex_pc_max, - invoke_type_max, + extra_data_max, dex_register_maps_size_); } @@ -354,9 +378,20 @@ void StackMapStream::FillIn(MemoryRegion region) { DCHECK_LE(entry.inline_infos_start_index + entry.inlining_depth, inline_infos_.size()); for (size_t depth = 0; depth < entry.inlining_depth; ++depth) { InlineInfoEntry inline_entry = inline_infos_[depth + entry.inline_infos_start_index]; - inline_info.SetMethodIndexAtDepth(inline_info_encoding_, depth, inline_entry.method_index); + if (inline_entry.method != nullptr) { + inline_info.SetMethodIndexAtDepth( + inline_info_encoding_, + depth, + High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method))); + inline_info.SetExtraDataAtDepth( + inline_info_encoding_, + depth, + Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method))); + } else { + inline_info.SetMethodIndexAtDepth(inline_info_encoding_, depth, inline_entry.method_index); + inline_info.SetExtraDataAtDepth(inline_info_encoding_, depth, 1); + } inline_info.SetDexPcAtDepth(inline_info_encoding_, depth, inline_entry.dex_pc); - inline_info.SetInvokeTypeAtDepth(inline_info_encoding_, depth, inline_entry.invoke_type); if (inline_entry.num_dex_registers == 0) { // No dex map available. inline_info.SetDexRegisterMapOffsetAtDepth(inline_info_encoding_, @@ -544,10 +579,13 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { InlineInfoEntry inline_entry = inline_infos_[inline_info_index]; DCHECK_EQ(inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, d), inline_entry.dex_pc); - DCHECK_EQ(inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, d), - inline_entry.method_index); - DCHECK_EQ(inline_info.GetInvokeTypeAtDepth(encoding.inline_info_encoding, d), - inline_entry.invoke_type); + if (inline_info.EncodesArtMethodAtDepth(encoding.inline_info_encoding, d)) { + DCHECK_EQ(inline_info.GetArtMethodAtDepth(encoding.inline_info_encoding, d), + inline_entry.method); + } else { + DCHECK_EQ(inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, d), + inline_entry.method_index); + } CheckDexRegisterMap(code_info, code_info.GetDexRegisterMapAtDepth( diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h index 53a9795d52..d6f42b373c 100644 --- a/compiler/optimizing/stack_map_stream.h +++ b/compiler/optimizing/stack_map_stream.h @@ -109,8 +109,8 @@ class StackMapStream : public ValueObject { struct InlineInfoEntry { uint32_t dex_pc; // DexFile::kDexNoIndex for intrinsified native methods. + ArtMethod* method; uint32_t method_index; - InvokeType invoke_type; uint32_t num_dex_registers; BitVector* live_dex_registers_mask; size_t dex_register_locations_start_index; @@ -126,10 +126,10 @@ class StackMapStream : public ValueObject { void AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value); - void BeginInlineInfoEntry(uint32_t method_index, + void BeginInlineInfoEntry(ArtMethod* method, uint32_t dex_pc, - InvokeType invoke_type, - uint32_t num_dex_registers); + uint32_t num_dex_registers, + const DexFile* outer_dex_file = nullptr); void EndInlineInfoEntry(); size_t GetNumberOfStackMaps() const { diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index 967fd96561..22810ea4f7 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -16,6 +16,7 @@ #include "stack_map.h" +#include "art_method.h" #include "base/arena_bit_vector.h" #include "stack_map_stream.h" @@ -128,6 +129,7 @@ TEST(StackMapTest, Test2) { ArenaPool pool; ArenaAllocator arena(&pool); StackMapStream stream(&arena); + ArtMethod art_method; ArenaBitVector sp_mask1(&arena, 0, true); sp_mask1.SetBit(2); @@ -137,9 +139,9 @@ TEST(StackMapTest, Test2) { stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2); stream.AddDexRegisterEntry(Kind::kInStack, 0); // Short location. stream.AddDexRegisterEntry(Kind::kConstant, -2); // Large location. - stream.BeginInlineInfoEntry(82, 3, kDirect, number_of_dex_registers_in_inline_info); + stream.BeginInlineInfoEntry(&art_method, 3, number_of_dex_registers_in_inline_info); stream.EndInlineInfoEntry(); - stream.BeginInlineInfoEntry(42, 2, kStatic, number_of_dex_registers_in_inline_info); + stream.BeginInlineInfoEntry(&art_method, 2, number_of_dex_registers_in_inline_info); stream.EndInlineInfoEntry(); stream.EndStackMapEntry(); @@ -238,12 +240,10 @@ TEST(StackMapTest, Test2) { ASSERT_TRUE(stack_map.HasInlineInfo(encoding.stack_map_encoding)); InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding); ASSERT_EQ(2u, inline_info.GetDepth(encoding.inline_info_encoding)); - ASSERT_EQ(82u, inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(42u, inline_info.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1)); ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 0)); ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(kDirect, inline_info.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(kStatic, inline_info.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1)); + ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0)); + ASSERT_TRUE(inline_info.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1)); } // Second stack map. @@ -662,6 +662,7 @@ TEST(StackMapTest, InlineTest) { ArenaPool pool; ArenaAllocator arena(&pool); StackMapStream stream(&arena); + ArtMethod art_method; ArenaBitVector sp_mask1(&arena, 0, true); sp_mask1.SetBit(2); @@ -672,10 +673,10 @@ TEST(StackMapTest, InlineTest) { stream.AddDexRegisterEntry(Kind::kInStack, 0); stream.AddDexRegisterEntry(Kind::kConstant, 4); - stream.BeginInlineInfoEntry(42, 2, kStatic, 1); + stream.BeginInlineInfoEntry(&art_method, 2, 1); stream.AddDexRegisterEntry(Kind::kInStack, 8); stream.EndInlineInfoEntry(); - stream.BeginInlineInfoEntry(82, 3, kStatic, 3); + stream.BeginInlineInfoEntry(&art_method, 3, 3); stream.AddDexRegisterEntry(Kind::kInStack, 16); stream.AddDexRegisterEntry(Kind::kConstant, 20); stream.AddDexRegisterEntry(Kind::kInRegister, 15); @@ -688,15 +689,15 @@ TEST(StackMapTest, InlineTest) { stream.AddDexRegisterEntry(Kind::kInStack, 56); stream.AddDexRegisterEntry(Kind::kConstant, 0); - stream.BeginInlineInfoEntry(42, 2, kDirect, 1); + stream.BeginInlineInfoEntry(&art_method, 2, 1); stream.AddDexRegisterEntry(Kind::kInStack, 12); stream.EndInlineInfoEntry(); - stream.BeginInlineInfoEntry(82, 3, kStatic, 3); + stream.BeginInlineInfoEntry(&art_method, 3, 3); stream.AddDexRegisterEntry(Kind::kInStack, 80); stream.AddDexRegisterEntry(Kind::kConstant, 10); stream.AddDexRegisterEntry(Kind::kInRegister, 5); stream.EndInlineInfoEntry(); - stream.BeginInlineInfoEntry(52, 5, kVirtual, 0); + stream.BeginInlineInfoEntry(&art_method, 5, 0); stream.EndInlineInfoEntry(); stream.EndStackMapEntry(); @@ -712,12 +713,12 @@ TEST(StackMapTest, InlineTest) { stream.AddDexRegisterEntry(Kind::kInStack, 56); stream.AddDexRegisterEntry(Kind::kConstant, 0); - stream.BeginInlineInfoEntry(42, 2, kVirtual, 0); + stream.BeginInlineInfoEntry(&art_method, 2, 0); stream.EndInlineInfoEntry(); - stream.BeginInlineInfoEntry(52, 5, kInterface, 1); + stream.BeginInlineInfoEntry(&art_method, 5, 1); stream.AddDexRegisterEntry(Kind::kInRegister, 2); stream.EndInlineInfoEntry(); - stream.BeginInlineInfoEntry(52, 10, kStatic, 2); + stream.BeginInlineInfoEntry(&art_method, 10, 2); stream.AddDexRegisterEntry(Kind::kNone, 0); stream.AddDexRegisterEntry(Kind::kInRegister, 3); stream.EndInlineInfoEntry(); @@ -743,11 +744,9 @@ TEST(StackMapTest, InlineTest) { InlineInfo if0 = ci.GetInlineInfoOf(sm0, encoding); ASSERT_EQ(2u, if0.GetDepth(encoding.inline_info_encoding)); ASSERT_EQ(2u, if0.GetDexPcAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(42u, if0.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0)); + ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0)); ASSERT_EQ(3u, if0.GetDexPcAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(82u, if0.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1)); + ASSERT_TRUE(if0.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1)); DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, encoding, 1); ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding)); @@ -769,14 +768,11 @@ TEST(StackMapTest, InlineTest) { InlineInfo if1 = ci.GetInlineInfoOf(sm1, encoding); ASSERT_EQ(3u, if1.GetDepth(encoding.inline_info_encoding)); ASSERT_EQ(2u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(42u, if1.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(kDirect, if1.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0)); + ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0)); ASSERT_EQ(3u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(82u, if1.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(kStatic, if1.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1)); + ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1)); ASSERT_EQ(5u, if1.GetDexPcAtDepth(encoding.inline_info_encoding, 2)); - ASSERT_EQ(52u, if1.GetMethodIndexAtDepth(encoding.inline_info_encoding, 2)); - ASSERT_EQ(kVirtual, if1.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 2)); + ASSERT_TRUE(if1.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 2)); DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, encoding, 1); ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci, encoding)); @@ -810,14 +806,11 @@ TEST(StackMapTest, InlineTest) { InlineInfo if2 = ci.GetInlineInfoOf(sm3, encoding); ASSERT_EQ(3u, if2.GetDepth(encoding.inline_info_encoding)); ASSERT_EQ(2u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(42u, if2.GetMethodIndexAtDepth(encoding.inline_info_encoding, 0)); - ASSERT_EQ(kVirtual, if2.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 0)); + ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 0)); ASSERT_EQ(5u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(encoding.inline_info_encoding, 1)); - ASSERT_EQ(kInterface, if2.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 1)); + ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 1)); ASSERT_EQ(10u, if2.GetDexPcAtDepth(encoding.inline_info_encoding, 2)); - ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(encoding.inline_info_encoding, 2)); - ASSERT_EQ(kStatic, if2.GetInvokeTypeAtDepth(encoding.inline_info_encoding, 2)); + ASSERT_TRUE(if2.EncodesArtMethodAtDepth(encoding.inline_info_encoding, 2)); ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, 0)); diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index 96976d9bce..9c207400a2 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -121,7 +121,7 @@ inline uint16_t ArtMethod::GetMethodIndexDuringLinking() { inline uint32_t ArtMethod::GetDexMethodIndex() { DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous()); - return dex_method_index_; + return GetDexMethodIndexUnchecked(); } inline ArtMethod** ArtMethod::GetDexCacheResolvedMethods(PointerSize pointer_size) { diff --git a/runtime/art_method.h b/runtime/art_method.h index 11dcc35df5..2c31f6c95e 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -322,6 +322,9 @@ class ArtMethod FINAL { // Number of 32bit registers that would be required to hold all the arguments static size_t NumArgRegisters(const StringPiece& shorty); + ALWAYS_INLINE uint32_t GetDexMethodIndexUnchecked() { + return dex_method_index_; + } ALWAYS_INLINE uint32_t GetDexMethodIndex() REQUIRES_SHARED(Locks::mutator_lock_); void SetDexMethodIndex(uint32_t new_idx) { diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index c9b2cc8b68..8220ba4910 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2700,10 +2700,6 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, CHECK(h_new_class.Get() != nullptr) << descriptor; CHECK(h_new_class->IsResolved()) << descriptor; - // Update the dex cache of where the class is defined. Inlining depends on having - // this filled. - h_new_class->GetDexCache()->SetResolvedType(h_new_class->GetDexTypeIndex(), h_new_class.Get()); - // Instrumentation may have updated entrypoints for all methods of all // classes. However it could not update methods of this class while we // were loading it. Now the class is resolved, we can update entrypoints diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 42108d8621..8518b08b55 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -899,7 +899,6 @@ TEST_F(ClassLinkerTest, LookupResolvedType) { dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache(); const DexFile& dex_file = klass->GetDexFile(); - EXPECT_OBJ_PTR_EQ(dex_cache->GetResolvedType(type_idx), klass); EXPECT_OBJ_PTR_EQ( class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader.Get()), klass); diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 14c9c21356..72dad0cb32 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -52,21 +52,19 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, // suspended while executing it. ScopedAssertNoThreadSuspension sants(__FUNCTION__); + if (inline_info.EncodesArtMethodAtDepth(encoding, inlining_depth)) { + return inline_info.GetArtMethodAtDepth(encoding, inlining_depth); + } + uint32_t method_index = inline_info.GetMethodIndexAtDepth(encoding, inlining_depth); - InvokeType invoke_type = static_cast<InvokeType>( - inline_info.GetInvokeTypeAtDepth(encoding, inlining_depth)); - ArtMethod* inlined_method = outer_method->GetDexCacheResolvedMethod(method_index, - kRuntimePointerSize); - if (!inlined_method->IsRuntimeMethod()) { + if (inline_info.GetDexPcAtDepth(encoding, inlining_depth) == static_cast<uint32_t>(-1)) { + // "charAt" special case. It is the only non-leaf method we inline across dex files. + ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt); + DCHECK_EQ(inlined_method->GetDexMethodIndex(), method_index); return inlined_method; } - // The method in the dex cache is the runtime method responsible for invoking - // the stub that will then update the dex cache. Therefore, we need to do the - // resolution ourselves. - - // We first find the dex cache of our caller. If it is the outer method, we can directly - // use its dex cache. Otherwise, we also need to resolve our caller. + // Find which method did the call in the inlining hierarchy. ArtMethod* caller = outer_method; if (inlining_depth != 0) { caller = GetResolvedMethod(outer_method, @@ -74,51 +72,38 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, encoding, inlining_depth - 1); } - DCHECK_EQ(caller->GetDexCache(), outer_method->GetDexCache()) - << "Compiler only supports inlining calls within the same dex cache"; - const DexFile* dex_file = outer_method->GetDexFile(); - const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index); - if (inline_info.GetDexPcAtDepth(encoding, inlining_depth) == static_cast<uint32_t>(-1)) { - // "charAt" special case. It is the only non-leaf method we inline across dex files. - if (kIsDebugBuild) { - const char* name = dex_file->StringDataByIdx(method_id.name_idx_); - DCHECK_EQ(std::string(name), "charAt"); - DCHECK_EQ(std::string(dex_file->GetMethodShorty(method_id)), "CI") - << std::string(dex_file->GetMethodShorty(method_id)); - DCHECK_EQ(std::string(dex_file->StringByTypeIdx(method_id.class_idx_)), "Ljava/lang/String;") - << std::string(dex_file->StringByTypeIdx(method_id.class_idx_)); - } - mirror::Class* cls = - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangString); - // Update the dex cache for future lookups. - caller->GetDexCache()->SetResolvedType(method_id.class_idx_, cls); - inlined_method = cls->FindVirtualMethod("charAt", "(I)C", kRuntimePointerSize); - } else { - mirror::Class* klass = caller->GetDexCache()->GetResolvedType(method_id.class_idx_); - DCHECK_EQ(klass->GetDexCache(), caller->GetDexCache()) - << "Compiler only supports inlining calls within the same dex cache"; - switch (invoke_type) { - case kDirect: - case kStatic: - inlined_method = - klass->FindDirectMethod(klass->GetDexCache(), method_index, kRuntimePointerSize); - break; - case kSuper: - case kVirtual: - inlined_method = - klass->FindVirtualMethod(klass->GetDexCache(), method_index, kRuntimePointerSize); - break; - default: - LOG(FATAL) << "Unimplemented inlined invocation type: " << invoke_type; - UNREACHABLE(); + // Lookup the declaring class of the inlined method. + const DexFile* dex_file = caller->GetDexFile(); + const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index); + const char* descriptor = dex_file->StringByTypeIdx(method_id.class_idx_); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Thread* self = Thread::Current(); + mirror::ClassLoader* class_loader = caller->GetDeclaringClass()->GetClassLoader(); + mirror::Class* klass = class_linker->LookupClass(self, descriptor, class_loader); + if (klass == nullptr) { + LOG(FATAL) << "Could not find an inlined method from an .oat file: " + << "the class " << descriptor << " was not found in the class loader of " + << caller->PrettyMethod() << ". " + << "This must be due to playing wrongly with class loaders"; + } + + // Lookup the method. + const char* method_name = dex_file->GetMethodName(method_id); + const Signature signature = dex_file->GetMethodSignature(method_id); + + ArtMethod* inlined_method = + klass->FindDeclaredDirectMethod(method_name, signature, kRuntimePointerSize); + if (inlined_method == nullptr) { + inlined_method = klass->FindDeclaredVirtualMethod(method_name, signature, kRuntimePointerSize); + if (inlined_method == nullptr) { + LOG(FATAL) << "Could not find an inlined method from an .oat file: " + << "the class " << descriptor << " does not have " + << method_name << signature << " declared. " + << "This must be due to duplicate classes or playing wrongly with class loaders"; } } - // Update the dex cache for future lookups. Note that for static methods, this is safe - // when the class is being initialized, as the entrypoint for the ArtMethod is at - // this point still the resolution trampoline. - outer_method->SetDexCacheResolvedMethod(method_index, inlined_method, kRuntimePointerSize); return inlined_method; } diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc index a7e7c21a42..9ebf9a7bdd 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -18,8 +18,9 @@ #include <stdint.h> +#include "art_method.h" #include "indenter.h" -#include "invoke_type.h" +#include "scoped_thread_state_change-inl.h" namespace art { @@ -106,7 +107,7 @@ void InlineInfoEncoding::Dump(VariableIndentationOutputStream* vios) const { << "InlineInfoEncoding" << " (method_index_bit_offset=" << static_cast<uint32_t>(kMethodIndexBitOffset) << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_) - << ", invoke_type_bit_offset=" << static_cast<uint32_t>(invoke_type_bit_offset_) + << ", extra_data_bit_offset=" << static_cast<uint32_t>(extra_data_bit_offset_) << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_) << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_) << ")\n"; @@ -230,12 +231,16 @@ void InlineInfo::Dump(VariableIndentationOutputStream* vios, vios->Stream() << " At depth " << i << std::hex - << " (dex_pc=0x" << GetDexPcAtDepth(inline_info_encoding, i) - << std::dec - << ", method_index=" << GetMethodIndexAtDepth(inline_info_encoding, i) - << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(inline_info_encoding, - i)) - << ")\n"; + << " (dex_pc=0x" << GetDexPcAtDepth(inline_info_encoding, i); + if (EncodesArtMethodAtDepth(inline_info_encoding, i)) { + ScopedObjectAccess soa(Thread::Current()); + vios->Stream() << ", method=" << GetArtMethodAtDepth(inline_info_encoding, i)->PrettyMethod(); + } else { + vios->Stream() + << std::dec + << ", method_index=" << GetMethodIndexAtDepth(inline_info_encoding, i); + } + vios->Stream() << ")\n"; if (HasDexRegisterMapAtDepth(inline_info_encoding, i) && (number_of_dex_registers != nullptr)) { CodeInfoEncoding encoding = code_info.ExtractEncoding(); DexRegisterMap dex_register_map = diff --git a/runtime/stack_map.h b/runtime/stack_map.h index 5e556be286..15d7816031 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -35,6 +35,7 @@ static constexpr ssize_t kFrameSlotSize = 4; // Size of Dex virtual registers. static constexpr size_t kVRegSize = 4; +class ArtMethod; class CodeInfo; class StackMapEncoding; struct CodeInfoEncoding; @@ -887,7 +888,7 @@ class InlineInfoEncoding { public: void SetFromSizes(size_t method_index_max, size_t dex_pc_max, - size_t invoke_type_max, + size_t extra_data_max, size_t dex_register_map_size) { total_bit_size_ = kMethodIndexBitOffset; total_bit_size_ += MinimumBitsToStore(method_index_max); @@ -899,8 +900,8 @@ class InlineInfoEncoding { total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max); } - invoke_type_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_); - total_bit_size_ += MinimumBitsToStore(invoke_type_max); + extra_data_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_); + total_bit_size_ += MinimumBitsToStore(extra_data_max); // We also need +1 for kNoDexRegisterMap, but since the size is strictly // greater than any offset we might try to encode, we already implicitly have it. @@ -912,10 +913,10 @@ class InlineInfoEncoding { return FieldEncoding(kMethodIndexBitOffset, dex_pc_bit_offset_); } ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const { - return FieldEncoding(dex_pc_bit_offset_, invoke_type_bit_offset_, -1 /* min_value */); + return FieldEncoding(dex_pc_bit_offset_, extra_data_bit_offset_, -1 /* min_value */); } - ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const { - return FieldEncoding(invoke_type_bit_offset_, dex_register_map_bit_offset_); + ALWAYS_INLINE FieldEncoding GetExtraDataEncoding() const { + return FieldEncoding(extra_data_bit_offset_, dex_register_map_bit_offset_); } ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const { return FieldEncoding(dex_register_map_bit_offset_, total_bit_size_, -1 /* min_value */); @@ -930,7 +931,7 @@ class InlineInfoEncoding { static constexpr uint8_t kIsLastBitOffset = 0; static constexpr uint8_t kMethodIndexBitOffset = 1; uint8_t dex_pc_bit_offset_; - uint8_t invoke_type_bit_offset_; + uint8_t extra_data_bit_offset_; uint8_t dex_register_map_bit_offset_; uint8_t total_bit_size_; }; @@ -938,7 +939,11 @@ class InlineInfoEncoding { /** * Inline information for a specific PC. The information is of the form: * - * [is_last, method_index, dex_pc, invoke_type, dex_register_map_offset]+. + * [is_last, + * method_index (or ArtMethod high bits), + * dex_pc, + * extra_data (ArtMethod low bits or 1), + * dex_register_map_offset]+. */ class InlineInfo { public: @@ -960,6 +965,7 @@ class InlineInfo { ALWAYS_INLINE uint32_t GetMethodIndexAtDepth(const InlineInfoEncoding& encoding, uint32_t depth) const { + DCHECK(!EncodesArtMethodAtDepth(encoding, depth)); return encoding.GetMethodIndexEncoding().Load(GetRegionAtDepth(encoding, depth)); } @@ -980,15 +986,28 @@ class InlineInfo { encoding.GetDexPcEncoding().Store(GetRegionAtDepth(encoding, depth), dex_pc); } - ALWAYS_INLINE uint32_t GetInvokeTypeAtDepth(const InlineInfoEncoding& encoding, - uint32_t depth) const { - return encoding.GetInvokeTypeEncoding().Load(GetRegionAtDepth(encoding, depth)); + ALWAYS_INLINE bool EncodesArtMethodAtDepth(const InlineInfoEncoding& encoding, + uint32_t depth) const { + return (encoding.GetExtraDataEncoding().Load(GetRegionAtDepth(encoding, depth)) & 1) == 0; + } + + ALWAYS_INLINE void SetExtraDataAtDepth(const InlineInfoEncoding& encoding, + uint32_t depth, + uint32_t extra_data) { + encoding.GetExtraDataEncoding().Store(GetRegionAtDepth(encoding, depth), extra_data); } - ALWAYS_INLINE void SetInvokeTypeAtDepth(const InlineInfoEncoding& encoding, - uint32_t depth, - uint32_t invoke_type) { - encoding.GetInvokeTypeEncoding().Store(GetRegionAtDepth(encoding, depth), invoke_type); + ALWAYS_INLINE ArtMethod* GetArtMethodAtDepth(const InlineInfoEncoding& encoding, + uint32_t depth) const { + uint32_t low_bits = encoding.GetExtraDataEncoding().Load(GetRegionAtDepth(encoding, depth)); + uint32_t high_bits = encoding.GetMethodIndexEncoding().Load(GetRegionAtDepth(encoding, depth)); + if (high_bits == 0) { + return reinterpret_cast<ArtMethod*>(low_bits); + } else { + uint64_t address = high_bits; + address = address << 32; + return reinterpret_cast<ArtMethod*>(address | low_bits); + } } ALWAYS_INLINE uint32_t GetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding, diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index a5b275cc3b..507ea165e5 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -103,6 +103,7 @@ jmethodID WellKnownClasses::java_lang_reflect_Parameter_init; jmethodID WellKnownClasses::java_lang_reflect_Proxy_invoke; jmethodID WellKnownClasses::java_lang_Runtime_nativeLoad; jmethodID WellKnownClasses::java_lang_Short_valueOf; +jmethodID WellKnownClasses::java_lang_String_charAt; jmethodID WellKnownClasses::java_lang_System_runFinalization = nullptr; jmethodID WellKnownClasses::java_lang_Thread_dispatchUncaughtException; jmethodID WellKnownClasses::java_lang_Thread_init; @@ -337,6 +338,7 @@ void WellKnownClasses::Init(JNIEnv* env) { java_lang_ref_ReferenceQueue_add = CacheMethod(env, java_lang_ref_ReferenceQueue.get(), true, "add", "(Ljava/lang/ref/Reference;)V"); java_lang_reflect_Parameter_init = CacheMethod(env, java_lang_reflect_Parameter, false, "<init>", "(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V"); + java_lang_String_charAt = CacheMethod(env, java_lang_String, false, "charAt", "(I)C"); java_lang_Thread_dispatchUncaughtException = CacheMethod(env, java_lang_Thread, false, "dispatchUncaughtException", "(Ljava/lang/Throwable;)V"); java_lang_Thread_init = CacheMethod(env, java_lang_Thread, false, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V"); java_lang_Thread_run = CacheMethod(env, java_lang_Thread, false, "run", "()V"); diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 371be61f43..b3ce3d1597 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -113,6 +113,7 @@ struct WellKnownClasses { static jmethodID java_lang_reflect_Proxy_invoke; static jmethodID java_lang_Runtime_nativeLoad; static jmethodID java_lang_Short_valueOf; + static jmethodID java_lang_String_charAt; static jmethodID java_lang_System_runFinalization; static jmethodID java_lang_Thread_dispatchUncaughtException; static jmethodID java_lang_Thread_init; |