diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator.cc | 17 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 6 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 34 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_stream.cc | 72 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_stream.h | 13 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_test.cc | 37 |
6 files changed, 138 insertions, 41 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 424b8507fb..b7c80756b0 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -654,8 +654,12 @@ std::unique_ptr<CodeGenerator> CodeGenerator::Create(HGraph* graph, } } -size_t CodeGenerator::ComputeStackMapsSize() { - return stack_map_stream_.PrepareForFillIn(); +void CodeGenerator::ComputeStackMapAndMethodInfoSize(size_t* stack_map_size, + size_t* method_info_size) { + DCHECK(stack_map_size != nullptr); + DCHECK(method_info_size != nullptr); + *stack_map_size = stack_map_stream_.PrepareForFillIn(); + *method_info_size = stack_map_stream_.ComputeMethodInfoSize(); } static void CheckCovers(uint32_t dex_pc, @@ -723,10 +727,13 @@ static void CheckLoopEntriesCanBeUsedForOsr(const HGraph& graph, } } -void CodeGenerator::BuildStackMaps(MemoryRegion region, const DexFile::CodeItem& code_item) { - stack_map_stream_.FillIn(region); +void CodeGenerator::BuildStackMaps(MemoryRegion stack_map_region, + MemoryRegion method_info_region, + const DexFile::CodeItem& code_item) { + stack_map_stream_.FillInCodeInfo(stack_map_region); + stack_map_stream_.FillInMethodInfo(method_info_region); if (kIsDebugBuild) { - CheckLoopEntriesCanBeUsedForOsr(*graph_, CodeInfo(region), code_item); + CheckLoopEntriesCanBeUsedForOsr(*graph_, CodeInfo(stack_map_region), code_item); } } diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index b912672792..ea463eeb62 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -341,8 +341,10 @@ class CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { slow_paths_.push_back(std::unique_ptr<SlowPathCode>(slow_path)); } - void BuildStackMaps(MemoryRegion region, const DexFile::CodeItem& code_item); - size_t ComputeStackMapsSize(); + void BuildStackMaps(MemoryRegion stack_map_region, + MemoryRegion method_info_region, + const DexFile::CodeItem& code_item); + void ComputeStackMapAndMethodInfoSize(size_t* stack_map_size, size_t* method_info_size); size_t GetNumberOfJitRoots() const { return jit_string_roots_.size() + jit_class_roots_.size(); } diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index d6153b091c..8b1b04b462 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -1,3 +1,4 @@ + /* * Copyright (C) 2014 The Android Open Source Project * @@ -856,8 +857,15 @@ CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* arena, const DexFile::CodeItem* code_item) const { ArenaVector<LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen); ArenaVector<uint8_t> stack_map(arena->Adapter(kArenaAllocStackMaps)); - stack_map.resize(codegen->ComputeStackMapsSize()); - codegen->BuildStackMaps(MemoryRegion(stack_map.data(), stack_map.size()), *code_item); + ArenaVector<uint8_t> method_info(arena->Adapter(kArenaAllocStackMaps)); + size_t stack_map_size = 0; + size_t method_info_size = 0; + codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size); + stack_map.resize(stack_map_size); + method_info.resize(method_info_size); + codegen->BuildStackMaps(MemoryRegion(stack_map.data(), stack_map.size()), + MemoryRegion(method_info.data(), method_info.size()), + *code_item); CompiledMethod* compiled_method = CompiledMethod::SwapAllocCompiledMethod( compiler_driver, @@ -869,7 +877,7 @@ CompiledMethod* OptimizingCompiler::Emit(ArenaAllocator* arena, codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(), codegen->GetCoreSpillMask(), codegen->GetFpuSpillMask(), - ArrayRef<const SrcMapElem>(), + ArrayRef<const uint8_t>(method_info), ArrayRef<const uint8_t>(stack_map), ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()), ArrayRef<const LinkerPatch>(linker_patches)); @@ -1200,7 +1208,9 @@ bool OptimizingCompiler::JitCompile(Thread* self, } } - size_t stack_map_size = codegen->ComputeStackMapsSize(); + size_t stack_map_size = 0; + size_t method_info_size = 0; + codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size); size_t number_of_roots = codegen->GetNumberOfJitRoots(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); // We allocate an object array to ensure the JIT roots that we will collect in EmitJitRoots @@ -1216,20 +1226,30 @@ bool OptimizingCompiler::JitCompile(Thread* self, return false; } uint8_t* stack_map_data = nullptr; + uint8_t* method_info_data = nullptr; uint8_t* roots_data = nullptr; - uint32_t data_size = code_cache->ReserveData( - self, stack_map_size, number_of_roots, method, &stack_map_data, &roots_data); + uint32_t data_size = code_cache->ReserveData(self, + stack_map_size, + method_info_size, + number_of_roots, + method, + &stack_map_data, + &method_info_data, + &roots_data); if (stack_map_data == nullptr || roots_data == nullptr) { return false; } MaybeRecordStat(MethodCompilationStat::kCompiled); - codegen->BuildStackMaps(MemoryRegion(stack_map_data, stack_map_size), *code_item); + codegen->BuildStackMaps(MemoryRegion(stack_map_data, stack_map_size), + MemoryRegion(method_info_data, method_info_size), + *code_item); codegen->EmitJitRoots(code_allocator.GetData(), roots, roots_data); const void* code = code_cache->CommitCode( self, method, stack_map_data, + method_info_data, roots_data, codegen->HasEmptyFrame() ? 0 : codegen->GetFrameSize(), codegen->GetCoreSpillMask(), diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index 4d12ad6eb6..b7840d73db 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -152,6 +152,9 @@ size_t StackMapStream::PrepareForFillIn() { encoding.location_catalog.num_entries = location_catalog_entries_.size(); encoding.location_catalog.num_bytes = ComputeDexRegisterLocationCatalogSize(); encoding.inline_info.num_entries = inline_infos_.size(); + // Must be done before calling ComputeInlineInfoEncoding since ComputeInlineInfoEncoding requires + // dex_method_index_idx to be filled in. + PrepareMethodIndices(); ComputeInlineInfoEncoding(&encoding.inline_info.encoding, encoding.dex_register_map.num_bytes); CodeOffset max_native_pc_offset = ComputeMaxNativePcCodeOffset(); @@ -245,7 +248,7 @@ void StackMapStream::ComputeInlineInfoEncoding(InlineInfoEncoding* encoding, for (size_t j = 0; j < entry.inlining_depth; ++j) { InlineInfoEntry inline_entry = inline_infos_[inline_info_index++]; if (inline_entry.method == nullptr) { - method_index_max = std::max(method_index_max, inline_entry.method_index); + method_index_max = std::max(method_index_max, inline_entry.dex_method_index_idx); extra_data_max = std::max(extra_data_max, 1u); } else { method_index_max = std::max( @@ -288,7 +291,25 @@ size_t StackMapStream::MaybeCopyDexRegisterMap(DexRegisterMapEntry& entry, return entry.offset; } -void StackMapStream::FillIn(MemoryRegion region) { +void StackMapStream::FillInMethodInfo(MemoryRegion region) { + { + MethodInfo info(region.begin(), method_indices_.size()); + for (size_t i = 0; i < method_indices_.size(); ++i) { + info.SetMethodIndex(i, method_indices_[i]); + } + } + if (kIsDebugBuild) { + // Check the data matches. + MethodInfo info(region.begin()); + const size_t count = info.NumMethodIndices(); + DCHECK_EQ(count, method_indices_.size()); + for (size_t i = 0; i < count; ++i) { + DCHECK_EQ(info.GetMethodIndex(i), method_indices_[i]); + } + } +} + +void StackMapStream::FillInCodeInfo(MemoryRegion region) { DCHECK_EQ(0u, current_entry_.dex_pc) << "EndStackMapEntry not called after BeginStackMapEntry"; DCHECK_NE(0u, needed_size_) << "PrepareForFillIn not called before FillIn"; @@ -345,7 +366,7 @@ void StackMapStream::FillIn(MemoryRegion region) { 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.SetMethodIndexIdx(encoding.invoke_info.encoding, entry.dex_method_index_idx); ++invoke_info_idx; } @@ -364,7 +385,7 @@ void StackMapStream::FillIn(MemoryRegion region) { for (size_t depth = 0; depth < entry.inlining_depth; ++depth) { InlineInfoEntry inline_entry = inline_infos_[depth + entry.inline_infos_start_index]; if (inline_entry.method != nullptr) { - inline_info.SetMethodIndexAtDepth( + inline_info.SetMethodIndexIdxAtDepth( encoding.inline_info.encoding, depth, High32Bits(reinterpret_cast<uintptr_t>(inline_entry.method))); @@ -373,9 +394,9 @@ void StackMapStream::FillIn(MemoryRegion region) { depth, Low32Bits(reinterpret_cast<uintptr_t>(inline_entry.method))); } else { - inline_info.SetMethodIndexAtDepth(encoding.inline_info.encoding, - depth, - inline_entry.method_index); + inline_info.SetMethodIndexIdxAtDepth(encoding.inline_info.encoding, + depth, + inline_entry.dex_method_index_idx); inline_info.SetExtraDataAtDepth(encoding.inline_info.encoding, depth, 1); } inline_info.SetDexPcAtDepth(encoding.inline_info.encoding, depth, inline_entry.dex_pc); @@ -533,6 +554,29 @@ size_t StackMapStream::PrepareRegisterMasks() { return dedupe.size(); } +void StackMapStream::PrepareMethodIndices() { + CHECK(method_indices_.empty()); + method_indices_.resize(stack_maps_.size() + inline_infos_.size()); + ArenaUnorderedMap<uint32_t, size_t> dedupe(allocator_->Adapter(kArenaAllocStackMapStream)); + for (StackMapEntry& stack_map : stack_maps_) { + const size_t index = dedupe.size(); + const uint32_t method_index = stack_map.dex_method_index; + if (method_index != DexFile::kDexNoIndex) { + stack_map.dex_method_index_idx = dedupe.emplace(method_index, index).first->second; + method_indices_[index] = method_index; + } + } + for (InlineInfoEntry& inline_info : inline_infos_) { + const size_t index = dedupe.size(); + const uint32_t method_index = inline_info.method_index; + CHECK_NE(method_index, DexFile::kDexNoIndex); + inline_info.dex_method_index_idx = dedupe.emplace(method_index, index).first->second; + method_indices_[index] = method_index; + } + method_indices_.resize(dedupe.size()); +} + + size_t StackMapStream::PrepareStackMasks(size_t entry_size_in_bits) { // Preallocate memory since we do not want it to move (the dedup map will point into it). const size_t byte_entry_size = RoundUp(entry_size_in_bits, kBitsPerByte) / kBitsPerByte; @@ -590,7 +634,8 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { 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); + DCHECK_EQ(invoke_info.GetMethodIndexIdx(encoding.invoke_info.encoding), + entry.dex_method_index_idx); invoke_info_index++; } CheckDexRegisterMap(code_info, @@ -615,8 +660,10 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { 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); + const size_t method_index_idx = + inline_info.GetMethodIndexIdxAtDepth(encoding.inline_info.encoding, d); + DCHECK_EQ(method_index_idx, inline_entry.dex_method_index_idx); + DCHECK_EQ(method_indices_[method_index_idx], inline_entry.method_index); } CheckDexRegisterMap(code_info, @@ -633,4 +680,9 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { } } +size_t StackMapStream::ComputeMethodInfoSize() const { + DCHECK_NE(0u, needed_size_) << "PrepareForFillIn not called before " << __FUNCTION__; + return MethodInfo::ComputeSize(method_indices_.size()); +} + } // namespace art diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h index 4225a875b9..e6471e1bc5 100644 --- a/compiler/optimizing/stack_map_stream.h +++ b/compiler/optimizing/stack_map_stream.h @@ -22,6 +22,7 @@ #include "base/hash_map.h" #include "base/value_object.h" #include "memory_region.h" +#include "method_info.h" #include "nodes.h" #include "stack_map.h" @@ -70,6 +71,7 @@ class StackMapStream : public ValueObject { inline_infos_(allocator->Adapter(kArenaAllocStackMapStream)), stack_masks_(allocator->Adapter(kArenaAllocStackMapStream)), register_masks_(allocator->Adapter(kArenaAllocStackMapStream)), + method_indices_(allocator->Adapter(kArenaAllocStackMapStream)), dex_register_entries_(allocator->Adapter(kArenaAllocStackMapStream)), stack_mask_max_(-1), dex_pc_max_(0), @@ -120,6 +122,7 @@ class StackMapStream : public ValueObject { size_t dex_register_map_index; InvokeType invoke_type; uint32_t dex_method_index; + uint32_t dex_method_index_idx; // Index into dex method index table. }; struct InlineInfoEntry { @@ -128,6 +131,7 @@ class StackMapStream : public ValueObject { uint32_t method_index; DexRegisterMapEntry dex_register_entry; size_t dex_register_map_index; + uint32_t dex_method_index_idx; // Index into the dex method index table. }; void BeginStackMapEntry(uint32_t dex_pc, @@ -164,7 +168,10 @@ class StackMapStream : public ValueObject { // Prepares the stream to fill in a memory region. Must be called before FillIn. // Returns the size (in bytes) needed to store this stream. size_t PrepareForFillIn(); - void FillIn(MemoryRegion region); + void FillInCodeInfo(MemoryRegion region); + void FillInMethodInfo(MemoryRegion region); + + size_t ComputeMethodInfoSize() const; private: size_t ComputeDexRegisterLocationCatalogSize() const; @@ -180,6 +187,9 @@ class StackMapStream : public ValueObject { // Returns the number of unique register masks. size_t PrepareRegisterMasks(); + // Prepare and deduplicate method indices. + void PrepareMethodIndices(); + // Deduplicate entry if possible and return the corresponding index into dex_register_entries_ // array. If entry is not a duplicate, a new entry is added to dex_register_entries_. size_t AddDexRegisterMapEntry(const DexRegisterMapEntry& entry); @@ -232,6 +242,7 @@ class StackMapStream : public ValueObject { ArenaVector<InlineInfoEntry> inline_infos_; ArenaVector<uint8_t> stack_masks_; ArenaVector<uint32_t> register_masks_; + ArenaVector<uint32_t> method_indices_; ArenaVector<DexRegisterMapEntry> dex_register_entries_; int stack_mask_max_; uint32_t dex_pc_max_; diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index 330f7f28b6..a842c6e452 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -60,7 +60,7 @@ TEST(StackMapTest, Test1) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -173,7 +173,7 @@ TEST(StackMapTest, Test2) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -433,7 +433,7 @@ TEST(StackMapTest, TestDeduplicateInlineInfoDexRegisterMap) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -519,7 +519,7 @@ TEST(StackMapTest, TestNonLiveDexRegisters) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -611,7 +611,7 @@ TEST(StackMapTest, DexRegisterMapOffsetOverflow) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -672,7 +672,7 @@ TEST(StackMapTest, TestShareDexRegisterMap) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo ci(region); CodeInfoEncoding encoding = ci.ExtractEncoding(); @@ -721,7 +721,7 @@ TEST(StackMapTest, TestNoDexRegisterMap) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -823,7 +823,7 @@ TEST(StackMapTest, InlineTest) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo ci(region); CodeInfoEncoding encoding = ci.ExtractEncoding(); @@ -950,7 +950,7 @@ TEST(StackMapTest, TestDeduplicateStackMask) { size_t size = stream.PrepareForFillIn(); void* memory = arena.Alloc(size, kArenaAllocMisc); MemoryRegion region(memory, size); - stream.FillIn(region); + stream.FillInCodeInfo(region); CodeInfo code_info(region); CodeInfoEncoding encoding = code_info.ExtractEncoding(); @@ -979,11 +979,16 @@ TEST(StackMapTest, TestInvokeInfo) { stream.AddInvoke(kDirect, 65535); stream.EndStackMapEntry(); - const size_t size = stream.PrepareForFillIn(); - MemoryRegion region(arena.Alloc(size, kArenaAllocMisc), size); - stream.FillIn(region); + const size_t code_info_size = stream.PrepareForFillIn(); + MemoryRegion code_info_region(arena.Alloc(code_info_size, kArenaAllocMisc), code_info_size); + stream.FillInCodeInfo(code_info_region); - CodeInfo code_info(region); + const size_t method_info_size = stream.ComputeMethodInfoSize(); + MemoryRegion method_info_region(arena.Alloc(method_info_size, kArenaAllocMisc), method_info_size); + stream.FillInMethodInfo(method_info_region); + + CodeInfo code_info(code_info_region); + MethodInfo method_info(method_info_region.begin()); CodeInfoEncoding encoding = code_info.ExtractEncoding(); ASSERT_EQ(3u, code_info.GetNumberOfStackMaps(encoding)); @@ -996,13 +1001,13 @@ TEST(StackMapTest, TestInvokeInfo) { EXPECT_TRUE(invoke2.IsValid()); EXPECT_TRUE(invoke3.IsValid()); EXPECT_EQ(invoke1.GetInvokeType(encoding.invoke_info.encoding), kSuper); - EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding), 1u); + EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding, method_info), 1u); EXPECT_EQ(invoke1.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 4u); EXPECT_EQ(invoke2.GetInvokeType(encoding.invoke_info.encoding), kStatic); - EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding), 3u); + EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding, method_info), 3u); EXPECT_EQ(invoke2.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 8u); EXPECT_EQ(invoke3.GetInvokeType(encoding.invoke_info.encoding), kDirect); - EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding), 65535u); + EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding, method_info), 65535u); EXPECT_EQ(invoke3.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 16u); } |