From d776ff08e07494327716f0d2ea1a774b2ebfbca9 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Tue, 17 Jan 2017 09:32:18 -0800 Subject: Add invoke infos to stack maps Invoke info records the invoke type and dex method index for invokes that may reach artQuickResolutionTrampoline. Having this information recorded allows the runtime to avoid reading the dex code and pulling in extra pages. Code size increase for a large app: 93886360 -> 95811480 (2.05% increase) 1/2 of the code size increase is from making less stack maps deduped. I suspect there is less deduping because of the invoke info method index. Merged disabled until we measure the RAM savings. Test: test-art-host, N6P boots Bug: 34109702 Change-Id: I6c5e4a60675a1d7c76dee0561a12909e4ab6d5d9 --- compiler/optimizing/stack_map_stream.cc | 45 +++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'compiler/optimizing/stack_map_stream.cc') diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index 1bcc8e1ace..eeae96e6c2 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -41,12 +41,12 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc, current_entry_.inlining_depth = inlining_depth; current_entry_.inline_infos_start_index = inline_infos_.size(); current_entry_.stack_mask_index = 0; + current_entry_.dex_method_index = DexFile::kDexNoIndex; current_entry_.dex_register_entry.num_dex_registers = num_dex_registers; current_entry_.dex_register_entry.locations_start_index = dex_register_locations_.size(); current_entry_.dex_register_entry.live_dex_registers_mask = (num_dex_registers != 0) ? ArenaBitVector::Create(allocator_, num_dex_registers, true, kArenaAllocStackMapStream) : nullptr; - if (sp_mask != nullptr) { stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet()); } @@ -99,6 +99,11 @@ void StackMapStream::AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t current_dex_register_++; } +void StackMapStream::AddInvoke(InvokeType invoke_type, uint32_t dex_method_index) { + current_entry_.invoke_type = invoke_type; + current_entry_.dex_method_index = dex_method_index; +} + void StackMapStream::BeginInlineInfoEntry(ArtMethod* method, uint32_t dex_pc, uint32_t num_dex_registers, @@ -166,6 +171,7 @@ size_t StackMapStream::PrepareForFillIn() { encoding.inline_info.num_entries, encoding.register_mask.num_entries, encoding.stack_mask.num_entries); + ComputeInvokeInfoEncoding(&encoding); DCHECK_EQ(code_info_encoding_.size(), 0u); encoding.Compress(&code_info_encoding_); encoding.ComputeTableOffsets(); @@ -212,6 +218,24 @@ size_t StackMapStream::ComputeDexRegisterMapsSize() const { return size; } +void StackMapStream::ComputeInvokeInfoEncoding(CodeInfoEncoding* encoding) { + DCHECK(encoding != nullptr); + uint32_t native_pc_max = 0; + uint16_t method_index_max = 0; + size_t invoke_infos_count = 0; + size_t invoke_type_max = 0; + for (const StackMapEntry& entry : stack_maps_) { + if (entry.dex_method_index != DexFile::kDexNoIndex) { + native_pc_max = std::max(native_pc_max, entry.native_pc_code_offset.CompressedValue()); + method_index_max = std::max(method_index_max, static_cast(entry.dex_method_index)); + invoke_type_max = std::max(invoke_type_max, static_cast(entry.invoke_type)); + ++invoke_infos_count; + } + } + encoding->invoke_info.num_entries = invoke_infos_count; + encoding->invoke_info.encoding.SetFromSizes(native_pc_max, invoke_type_max, method_index_max); +} + void StackMapStream::ComputeInlineInfoEncoding(InlineInfoEncoding* encoding, size_t dex_register_maps_bytes) { uint32_t method_index_max = 0; @@ -304,6 +328,7 @@ void StackMapStream::FillIn(MemoryRegion region) { ArenaBitVector empty_bitmask(allocator_, 0, /* expandable */ false, kArenaAllocStackMapStream); uintptr_t next_dex_register_map_offset = 0; uintptr_t next_inline_info_index = 0; + size_t invoke_info_idx = 0; for (size_t i = 0, e = stack_maps_.size(); i < e; ++i) { StackMap stack_map = code_info.GetStackMapAt(i, encoding); StackMapEntry entry = stack_maps_[i]; @@ -318,6 +343,14 @@ void StackMapStream::FillIn(MemoryRegion region) { dex_register_locations_region); stack_map.SetDexRegisterMapOffset(encoding.stack_map.encoding, offset); + if (entry.dex_method_index != DexFile::kDexNoIndex) { + InvokeInfo invoke_info(code_info.GetInvokeInfo(encoding, invoke_info_idx)); + invoke_info.SetNativePcCodeOffset(encoding.invoke_info.encoding, entry.native_pc_code_offset); + invoke_info.SetInvokeType(encoding.invoke_info.encoding, entry.invoke_type); + invoke_info.SetMethodIndex(encoding.invoke_info.encoding, entry.dex_method_index); + ++invoke_info_idx; + } + // Set the inlining info. if (entry.inlining_depth != 0) { InlineInfo inline_info = code_info.GetInlineInfo(next_inline_info_index, encoding); @@ -528,6 +561,7 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); DCHECK_EQ(code_info.GetNumberOfStackMaps(encoding), stack_maps_.size()); + size_t invoke_info_index = 0; for (size_t s = 0; s < stack_maps_.size(); ++s) { const StackMap stack_map = code_info.GetStackMapAt(s, encoding); const StackMapEncoding& stack_map_encoding = encoding.stack_map.encoding; @@ -552,7 +586,14 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { DCHECK_EQ(stack_mask.LoadBit(b), 0u); } } - + if (entry.dex_method_index != DexFile::kDexNoIndex) { + InvokeInfo invoke_info = code_info.GetInvokeInfo(encoding, invoke_info_index); + DCHECK_EQ(invoke_info.GetNativePcOffset(encoding.invoke_info.encoding, instruction_set_), + entry.native_pc_code_offset.Uint32Value(instruction_set_)); + DCHECK_EQ(invoke_info.GetInvokeType(encoding.invoke_info.encoding), entry.invoke_type); + DCHECK_EQ(invoke_info.GetMethodIndex(encoding.invoke_info.encoding), entry.dex_method_index); + invoke_info_index++; + } CheckDexRegisterMap(code_info, code_info.GetDexRegisterMapOf( stack_map, encoding, entry.dex_register_entry.num_dex_registers), -- cgit v1.2.3-59-g8ed1b