diff options
-rw-r--r-- | compiler/debug/elf_debug_info_writer.h | 3 | ||||
-rw-r--r-- | compiler/debug/elf_debug_line_writer.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_stream.cc | 10 | ||||
-rw-r--r-- | compiler/optimizing/stack_map_test.cc | 78 | ||||
-rw-r--r-- | libartbase/base/bit_table.h | 44 | ||||
-rw-r--r-- | libartbase/base/iteration_range.h | 6 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 32 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.cc | 6 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 61 | ||||
-rw-r--r-- | runtime/quick_exception_handler.cc | 2 | ||||
-rw-r--r-- | runtime/stack.cc | 37 | ||||
-rw-r--r-- | runtime/stack.h | 13 | ||||
-rw-r--r-- | runtime/stack_map.cc | 9 | ||||
-rw-r--r-- | runtime/stack_map.h | 50 |
14 files changed, 177 insertions, 178 deletions
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h index f2a942f34a..bda7108c74 100644 --- a/compiler/debug/elf_debug_info_writer.h +++ b/compiler/debug/elf_debug_info_writer.h @@ -208,8 +208,7 @@ class ElfCompilationUnitWriter { std::vector<DexRegisterMap> dex_reg_maps; if (accessor.HasCodeItem() && mi->code_info != nullptr) { code_info.reset(new CodeInfo(mi->code_info)); - for (size_t s = 0; s < code_info->GetNumberOfStackMaps(); ++s) { - const StackMap stack_map = code_info->GetStackMapAt(s); + for (StackMap stack_map : code_info->GetStackMaps()) { dex_reg_maps.push_back(code_info->GetDexRegisterMapOf(stack_map)); } } diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h index a7adab5506..3d78943cd0 100644 --- a/compiler/debug/elf_debug_line_writer.h +++ b/compiler/debug/elf_debug_line_writer.h @@ -101,9 +101,7 @@ class ElfDebugLineWriter { // Use stack maps to create mapping table from pc to dex. const CodeInfo code_info(mi->code_info); pc2dex_map.reserve(code_info.GetNumberOfStackMaps()); - for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) { - StackMap stack_map = code_info.GetStackMapAt(s); - DCHECK(stack_map.IsValid()); + for (StackMap stack_map : code_info.GetStackMaps()) { const uint32_t pc = stack_map.GetNativePcOffset(isa); const int32_t dex = stack_map.GetDexPc(); pc2dex_map.push_back({pc, dex}); diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index 5d361953ba..3e1a36dc9b 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -151,7 +151,7 @@ void StackMapStream::EndStackMapEntry() { StackMap stack_map = code_info.GetStackMapAt(stack_map_index); CHECK_EQ(stack_map.HasDexRegisterMap(), (num_dex_registers != 0)); CHECK_EQ(stack_map.HasInlineInfo(), (inlining_depth != 0)); - CHECK_EQ(code_info.GetInlineDepthOf(stack_map), inlining_depth); + CHECK_EQ(code_info.GetInlineInfosOf(stack_map).size(), inlining_depth); }); } } @@ -209,7 +209,7 @@ void StackMapStream::BeginInlineInfoEntry(ArtMethod* method, size_t depth = current_inline_infos_.size() - 1; dchecks_.emplace_back([=](const CodeInfo& code_info) { StackMap stack_map = code_info.GetStackMapAt(stack_map_index); - InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth); + InlineInfo inline_info = code_info.GetInlineInfosOf(stack_map)[depth]; CHECK_EQ(inline_info.GetDexPc(), dex_pc); bool encode_art_method = EncodeArtMethodInInlineInfo(method); CHECK_EQ(inline_info.EncodesArtMethod(), encode_art_method); @@ -275,7 +275,6 @@ void StackMapStream::CreateDexRegisterMap() { if (kVerifyStackMaps) { size_t stack_map_index = stack_maps_.size(); - uint32_t depth = current_inline_infos_.size(); // We need to make copy of the current registers for later (when the check is run). auto expected_dex_registers = std::make_shared<dchecked_vector<DexRegisterLocation>>( current_dex_registers_.begin(), current_dex_registers_.end()); @@ -285,8 +284,9 @@ void StackMapStream::CreateDexRegisterMap() { for (DexRegisterLocation reg : code_info.GetDexRegisterMapOf(stack_map)) { CHECK_EQ((*expected_dex_registers)[expected_reg++], reg); } - for (uint32_t d = 0; d < depth; d++) { - for (DexRegisterLocation reg : code_info.GetDexRegisterMapAtDepth(d, stack_map)) { + for (InlineInfo inline_info : code_info.GetInlineInfosOf(stack_map)) { + DexRegisterMap map = code_info.GetInlineDexRegisterMapOf(stack_map, inline_info); + for (DexRegisterLocation reg : map) { CHECK_EQ((*expected_dex_registers)[expected_reg++], reg); } } diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index 6241e0c25a..9ed90a4839 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -193,13 +193,12 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(-2, location1.GetValue()); ASSERT_TRUE(stack_map.HasInlineInfo()); - InlineInfo inline_info0 = code_info.GetInlineInfoAtDepth(stack_map, 0); - InlineInfo inline_info1 = code_info.GetInlineInfoAtDepth(stack_map, 1); - ASSERT_EQ(2u, code_info.GetInlineDepthOf(stack_map)); - ASSERT_EQ(3u, inline_info0.GetDexPc()); - ASSERT_EQ(2u, inline_info1.GetDexPc()); - ASSERT_TRUE(inline_info0.EncodesArtMethod()); - ASSERT_TRUE(inline_info1.EncodesArtMethod()); + auto inline_infos = code_info.GetInlineInfosOf(stack_map); + ASSERT_EQ(2u, inline_infos.size()); + ASSERT_EQ(3u, inline_infos[0].GetDexPc()); + ASSERT_EQ(2u, inline_infos[1].GetDexPc()); + ASSERT_TRUE(inline_infos[0].EncodesArtMethod()); + ASSERT_TRUE(inline_infos[1].EncodesArtMethod()); } // Second stack map. @@ -614,19 +613,18 @@ TEST(StackMapTest, InlineTest) { ASSERT_EQ(0, dex_registers0[0].GetStackOffsetInBytes()); ASSERT_EQ(4, dex_registers0[1].GetConstant()); - InlineInfo if0_0 = ci.GetInlineInfoAtDepth(sm0, 0); - InlineInfo if0_1 = ci.GetInlineInfoAtDepth(sm0, 1); - ASSERT_EQ(2u, ci.GetInlineDepthOf(sm0)); - ASSERT_EQ(2u, if0_0.GetDexPc()); - ASSERT_TRUE(if0_0.EncodesArtMethod()); - ASSERT_EQ(3u, if0_1.GetDexPc()); - ASSERT_TRUE(if0_1.EncodesArtMethod()); + auto inline_infos = ci.GetInlineInfosOf(sm0); + ASSERT_EQ(2u, inline_infos.size()); + ASSERT_EQ(2u, inline_infos[0].GetDexPc()); + ASSERT_TRUE(inline_infos[0].EncodesArtMethod()); + ASSERT_EQ(3u, inline_infos[1].GetDexPc()); + ASSERT_TRUE(inline_infos[1].EncodesArtMethod()); - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, sm0); + DexRegisterMap dex_registers1 = ci.GetInlineDexRegisterMapOf(sm0, inline_infos[0]); ASSERT_EQ(1u, dex_registers1.size()); ASSERT_EQ(8, dex_registers1[0].GetStackOffsetInBytes()); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, sm0); + DexRegisterMap dex_registers2 = ci.GetInlineDexRegisterMapOf(sm0, inline_infos[1]); ASSERT_EQ(3u, dex_registers2.size()); ASSERT_EQ(16, dex_registers2[0].GetStackOffsetInBytes()); ASSERT_EQ(20, dex_registers2[1].GetConstant()); @@ -642,22 +640,20 @@ TEST(StackMapTest, InlineTest) { ASSERT_EQ(56, dex_registers0[0].GetStackOffsetInBytes()); ASSERT_EQ(0, dex_registers0[1].GetConstant()); - InlineInfo if1_0 = ci.GetInlineInfoAtDepth(sm1, 0); - InlineInfo if1_1 = ci.GetInlineInfoAtDepth(sm1, 1); - InlineInfo if1_2 = ci.GetInlineInfoAtDepth(sm1, 2); - ASSERT_EQ(3u, ci.GetInlineDepthOf(sm1)); - ASSERT_EQ(2u, if1_0.GetDexPc()); - ASSERT_TRUE(if1_0.EncodesArtMethod()); - ASSERT_EQ(3u, if1_1.GetDexPc()); - ASSERT_TRUE(if1_1.EncodesArtMethod()); - ASSERT_EQ(5u, if1_2.GetDexPc()); - ASSERT_TRUE(if1_2.EncodesArtMethod()); - - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, sm1); + auto inline_infos = ci.GetInlineInfosOf(sm1); + ASSERT_EQ(3u, inline_infos.size()); + ASSERT_EQ(2u, inline_infos[0].GetDexPc()); + ASSERT_TRUE(inline_infos[0].EncodesArtMethod()); + ASSERT_EQ(3u, inline_infos[1].GetDexPc()); + ASSERT_TRUE(inline_infos[1].EncodesArtMethod()); + ASSERT_EQ(5u, inline_infos[2].GetDexPc()); + ASSERT_TRUE(inline_infos[2].EncodesArtMethod()); + + DexRegisterMap dex_registers1 = ci.GetInlineDexRegisterMapOf(sm1, inline_infos[0]); ASSERT_EQ(1u, dex_registers1.size()); ASSERT_EQ(12, dex_registers1[0].GetStackOffsetInBytes()); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, sm1); + DexRegisterMap dex_registers2 = ci.GetInlineDexRegisterMapOf(sm1, inline_infos[1]); ASSERT_EQ(3u, dex_registers2.size()); ASSERT_EQ(80, dex_registers2[0].GetStackOffsetInBytes()); ASSERT_EQ(10, dex_registers2[1].GetConstant()); @@ -684,22 +680,20 @@ TEST(StackMapTest, InlineTest) { ASSERT_EQ(56, dex_registers0[0].GetStackOffsetInBytes()); ASSERT_EQ(0, dex_registers0[1].GetConstant()); - InlineInfo if2_0 = ci.GetInlineInfoAtDepth(sm3, 0); - InlineInfo if2_1 = ci.GetInlineInfoAtDepth(sm3, 1); - InlineInfo if2_2 = ci.GetInlineInfoAtDepth(sm3, 2); - ASSERT_EQ(3u, ci.GetInlineDepthOf(sm3)); - ASSERT_EQ(2u, if2_0.GetDexPc()); - ASSERT_TRUE(if2_0.EncodesArtMethod()); - ASSERT_EQ(5u, if2_1.GetDexPc()); - ASSERT_TRUE(if2_1.EncodesArtMethod()); - ASSERT_EQ(10u, if2_2.GetDexPc()); - ASSERT_TRUE(if2_2.EncodesArtMethod()); - - DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, sm3); + auto inline_infos = ci.GetInlineInfosOf(sm3); + ASSERT_EQ(3u, inline_infos.size()); + ASSERT_EQ(2u, inline_infos[0].GetDexPc()); + ASSERT_TRUE(inline_infos[0].EncodesArtMethod()); + ASSERT_EQ(5u, inline_infos[1].GetDexPc()); + ASSERT_TRUE(inline_infos[1].EncodesArtMethod()); + ASSERT_EQ(10u, inline_infos[2].GetDexPc()); + ASSERT_TRUE(inline_infos[2].EncodesArtMethod()); + + DexRegisterMap dex_registers1 = ci.GetInlineDexRegisterMapOf(sm3, inline_infos[1]); ASSERT_EQ(1u, dex_registers1.size()); ASSERT_EQ(2, dex_registers1[0].GetMachineRegister()); - DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, sm3); + DexRegisterMap dex_registers2 = ci.GetInlineDexRegisterMapOf(sm3, inline_infos[2]); ASSERT_EQ(2u, dex_registers2.size()); ASSERT_FALSE(dex_registers2[0].IsLive()); ASSERT_EQ(3, dex_registers2[1].GetMachineRegister()); diff --git a/libartbase/base/bit_table.h b/libartbase/base/bit_table.h index b0fc4d1d1b..218203f9e0 100644 --- a/libartbase/base/bit_table.h +++ b/libartbase/base/bit_table.h @@ -26,6 +26,7 @@ #include "base/bit_memory_region.h" #include "base/casts.h" +#include "base/iteration_range.h" #include "base/memory_region.h" #include "base/scoped_arena_containers.h" #include "base/stl_util.h" @@ -207,9 +208,18 @@ class BitTable : public BitTableBase<Accessor::kNumColumns> { bool operator>=(const_iterator i) const { DCHECK(table_ == i.table_); return row_ >= i.row_; } bool operator<(const_iterator i) const { DCHECK(table_ == i.table_); return row_ < i.row_; } bool operator>(const_iterator i) const { DCHECK(table_ == i.table_); return row_ > i.row_; } - Accessor operator*() { return Accessor(table_, row_); } - Accessor operator->() { return Accessor(table_, row_); } - Accessor operator[](size_t index) { return Accessor(table_, row_ + index); } + Accessor operator*() { + DCHECK_LT(row_, table_->NumRows()); + return Accessor(table_, row_); + } + Accessor operator->() { + DCHECK_LT(row_, table_->NumRows()); + return Accessor(table_, row_); + } + Accessor operator[](size_t index) { + DCHECK_LT(row_ + index, table_->NumRows()); + return Accessor(table_, row_ + index); + } private: const BitTable* table_ = nullptr; uint32_t row_ = 0; @@ -236,6 +246,34 @@ typename BitTable<Accessor>::const_iterator operator+( return a + n; } +template<typename Accessor> +class BitTableRange : public IterationRange<typename BitTable<Accessor>::const_iterator> { + public: + typedef typename BitTable<Accessor>::const_iterator const_iterator; + + using IterationRange<const_iterator>::IterationRange; + BitTableRange() : IterationRange<const_iterator>(const_iterator(), const_iterator()) { } + + bool empty() const { return this->begin() == this->end(); } + size_t size() const { return this->end() - this->begin(); } + + Accessor operator[](size_t index) const { + const_iterator it = this->begin() + index; + DCHECK(it < this->end()); + return *it; + } + + Accessor back() const { + DCHECK(!empty()); + return *(this->end() - 1); + } + + void pop_back() { + DCHECK(!empty()); + --this->last_; + } +}; + // Helper class for encoding BitTable. It can optionally de-duplicate the inputs. template<uint32_t kNumColumns> class BitTableBuilderBase { diff --git a/libartbase/base/iteration_range.h b/libartbase/base/iteration_range.h index 76049a7e4d..cd87d85f68 100644 --- a/libartbase/base/iteration_range.h +++ b/libartbase/base/iteration_range.h @@ -39,9 +39,9 @@ class IterationRange { iterator cbegin() const { return first_; } iterator cend() const { return last_; } - private: - const iterator first_; - const iterator last_; + protected: + iterator first_; + iterator last_; }; template <typename Iter> diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 4a3d3b0da6..40ef10f904 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -46,38 +46,38 @@ namespace art { inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, const MethodInfo& method_info, - const CodeInfo& code_info, - const StackMap& stack_map, - uint8_t inlining_depth) + const BitTableRange<InlineInfo>& inline_infos) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(!outer_method->IsObsolete()); - InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, inlining_depth); // This method is being used by artQuickResolutionTrampoline, before it sets up // the passed parameters in a GC friendly way. Therefore we must never be // suspended while executing it. ScopedAssertNoThreadSuspension sants(__FUNCTION__); - if (inline_info.EncodesArtMethod()) { - return inline_info.GetArtMethod(); - } + { + InlineInfo inline_info = inline_infos.back(); + + if (inline_info.EncodesArtMethod()) { + return inline_info.GetArtMethod(); + } - uint32_t method_index = inline_info.GetMethodIndex(method_info); - if (inline_info.GetDexPc() == 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; + uint32_t method_index = inline_info.GetMethodIndex(method_info); + if (inline_info.GetDexPc() == 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; + } } // Find which method did the call in the inlining hierarchy. ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ArtMethod* method = outer_method; - for (uint32_t depth = 0, end = inlining_depth + 1u; depth != end; ++depth) { - inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth); + for (InlineInfo inline_info : inline_infos) { DCHECK(!inline_info.EncodesArtMethod()); DCHECK_NE(inline_info.GetDexPc(), static_cast<uint32_t>(-1)); - method_index = inline_info.GetMethodIndex(method_info); + uint32_t method_index = inline_info.GetMethodIndex(method_info); ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index, method->GetDexCache(), method->GetClassLoader()); diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index e71d1fa38a..9e6c642f14 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -205,9 +205,9 @@ static inline ArtMethod* DoGetCalleeSaveMethodCaller(ArtMethod* outer_method, MethodInfo method_info = current_code->GetOptimizedMethodInfo(); StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); DCHECK(stack_map.IsValid()); - uint32_t depth = code_info.GetInlineDepthOf(stack_map); - if (depth != 0) { - caller = GetResolvedMethod(outer_method, method_info, code_info, stack_map, depth - 1); + BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map); + if (!inline_infos.empty()) { + caller = GetResolvedMethod(outer_method, method_info, inline_infos); } } if (kIsDebugBuild && do_caller_check) { diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 3ccfa556f1..c894406e98 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -345,10 +345,9 @@ class QuickArgumentVisitor { CodeInfo code_info(current_code); StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset); DCHECK(stack_map.IsValid()); - uint32_t depth = code_info.GetInlineDepthOf(stack_map); - if (depth != 0) { - InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth - 1); - return inline_info.GetDexPc(); + BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map); + if (!inline_infos.empty()) { + return inline_infos.back().GetDexPc(); } else { return stack_map.GetDexPc(); } @@ -1236,37 +1235,35 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(outer_method, dex_pc); ArtMethod* caller = outer_method; - uint32_t depth = code_info.GetInlineDepthOf(stack_map); - if (depth != 0) { - for (size_t d = 0; d < depth; ++d) { - InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, d); - const char* tag = ""; - dex_pc = inline_info.GetDexPc(); - if (inline_info.EncodesArtMethod()) { - tag = "encoded "; - caller = inline_info.GetArtMethod(); + BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map); + for (InlineInfo inline_info : inline_infos) { + const char* tag = ""; + dex_pc = inline_info.GetDexPc(); + if (inline_info.EncodesArtMethod()) { + tag = "encoded "; + caller = inline_info.GetArtMethod(); + } else { + uint32_t method_index = inline_info.GetMethodIndex(method_info); + if (dex_pc == static_cast<uint32_t>(-1)) { + tag = "special "; + CHECK(inline_info.Equals(inline_infos.back())); + caller = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt); + CHECK_EQ(caller->GetDexMethodIndex(), method_index); } else { - uint32_t method_index = inline_info.GetMethodIndex(method_info); - if (dex_pc == static_cast<uint32_t>(-1)) { - tag = "special "; - CHECK_EQ(d + 1u, depth); - caller = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt); - CHECK_EQ(caller->GetDexMethodIndex(), method_index); - } else { - ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache(); - ObjPtr<mirror::ClassLoader> class_loader = caller->GetClassLoader(); - caller = class_linker->LookupResolvedMethod(method_index, dex_cache, class_loader); - CHECK(caller != nullptr); - } + ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache(); + ObjPtr<mirror::ClassLoader> class_loader = caller->GetClassLoader(); + caller = class_linker->LookupResolvedMethod(method_index, dex_cache, class_loader); + CHECK(caller != nullptr); } - LOG(FATAL_WITHOUT_ABORT) << "Inlined method #" << d << ": " << tag << caller->PrettyMethod() - << " dex pc: " << dex_pc - << " dex file: " << caller->GetDexFile()->GetLocation() - << " class table: " - << class_linker->ClassTableForClassLoader(caller->GetClassLoader()); - DumpB74410240ClassData(caller->GetDeclaringClass()); - LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(caller, dex_pc); } + LOG(FATAL_WITHOUT_ABORT) << "InlineInfo #" << inline_info.Row() + << ": " << tag << caller->PrettyMethod() + << " dex pc: " << dex_pc + << " dex file: " << caller->GetDexFile()->GetLocation() + << " class table: " + << class_linker->ClassTableForClassLoader(caller->GetClassLoader()); + DumpB74410240ClassData(caller->GetDeclaringClass()); + LOG(FATAL_WITHOUT_ABORT) << " instruction: " << DumpInstruction(caller, dex_pc); } } diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 8b99b9f9c8..28fcd871be 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -404,7 +404,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { uint32_t register_mask = code_info.GetRegisterMaskOf(stack_map); BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map); DexRegisterMap vreg_map = IsInInlinedFrame() - ? code_info.GetDexRegisterMapAtDepth(GetCurrentInliningDepth() - 1, stack_map) + ? code_info.GetInlineDexRegisterMapOf(stack_map, GetCurrentInlinedFrame()) : code_info.GetDexRegisterMapOf(stack_map); if (vreg_map.empty()) { return; diff --git a/runtime/stack.cc b/runtime/stack.cc index a181bfe091..97d077f860 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -68,7 +68,6 @@ StackVisitor::StackVisitor(Thread* thread, cur_oat_quick_method_header_(nullptr), num_frames_(num_frames), cur_depth_(0), - current_inlining_depth_(0), context_(context), check_suspended_(check_suspended) { if (check_suspended_) { @@ -76,32 +75,15 @@ StackVisitor::StackVisitor(Thread* thread, } } -static StackMap GetCurrentStackMap(CodeInfo& code_info, - const OatQuickMethodHeader* method_header, - uintptr_t cur_quick_frame_pc) - REQUIRES_SHARED(Locks::mutator_lock_) { - uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc); - StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); - DCHECK(stack_map.IsValid()); - return stack_map; -} - ArtMethod* StackVisitor::GetMethod() const { if (cur_shadow_frame_ != nullptr) { return cur_shadow_frame_->GetMethod(); } else if (cur_quick_frame_ != nullptr) { if (IsInInlinedFrame()) { - size_t depth_in_stack_map = current_inlining_depth_ - 1; const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader(); - CodeInfo code_info(method_header); - StackMap stack_map = GetCurrentStackMap(code_info, method_header, cur_quick_frame_pc_); MethodInfo method_info = method_header->GetOptimizedMethodInfo(); DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames); - return GetResolvedMethod(*GetCurrentQuickFrame(), - method_info, - code_info, - stack_map, - depth_in_stack_map); + return GetResolvedMethod(*GetCurrentQuickFrame(), method_info, current_inline_frames_); } else { return *cur_quick_frame_; } @@ -114,11 +96,7 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const { return cur_shadow_frame_->GetDexPC(); } else if (cur_quick_frame_ != nullptr) { if (IsInInlinedFrame()) { - const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader(); - CodeInfo code_info(method_header); - size_t depth_in_stack_map = current_inlining_depth_ - 1; - StackMap stack_map = GetCurrentStackMap(code_info, method_header, cur_quick_frame_pc_); - return code_info.GetInlineInfoAtDepth(stack_map, depth_in_stack_map).GetDexPc(); + return current_inline_frames_.back().GetDexPc(); } else if (cur_oat_quick_method_header_ == nullptr) { return dex::kDexNoIndex; } else { @@ -233,10 +211,9 @@ bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKin uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc_); StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); DCHECK(stack_map.IsValid()); - size_t depth_in_stack_map = current_inlining_depth_ - 1; DexRegisterMap dex_register_map = IsInInlinedFrame() - ? code_info.GetDexRegisterMapAtDepth(depth_in_stack_map, stack_map) + ? code_info.GetInlineDexRegisterMapOf(stack_map, current_inline_frames_.back()) : code_info.GetDexRegisterMapOf(stack_map); if (dex_register_map.empty()) { return false; @@ -820,10 +797,10 @@ void StackVisitor::WalkStack(bool include_transitions) { cur_oat_quick_method_header_->NativeQuickPcOffset(cur_quick_frame_pc_); StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset); if (stack_map.IsValid() && stack_map.HasInlineInfo()) { - DCHECK_EQ(current_inlining_depth_, 0u); - for (current_inlining_depth_ = code_info.GetInlineDepthOf(stack_map); - current_inlining_depth_ != 0; - --current_inlining_depth_) { + DCHECK_EQ(current_inline_frames_.size(), 0u); + for (current_inline_frames_ = code_info.GetInlineInfosOf(stack_map); + !current_inline_frames_.empty(); + current_inline_frames_.pop_back()) { bool should_continue = VisitFrame(); if (UNLIKELY(!should_continue)) { return; diff --git a/runtime/stack.h b/runtime/stack.h index a16930bba0..02578d25b7 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -23,6 +23,7 @@ #include "base/macros.h" #include "base/mutex.h" #include "quick/quick_method_frame_info.h" +#include "stack_map.h" namespace art { @@ -219,11 +220,11 @@ class StackVisitor { void SetReturnPc(uintptr_t new_ret_pc) REQUIRES_SHARED(Locks::mutator_lock_); bool IsInInlinedFrame() const { - return current_inlining_depth_ != 0; + return !current_inline_frames_.empty(); } - size_t GetCurrentInliningDepth() const { - return current_inlining_depth_; + InlineInfo GetCurrentInlinedFrame() const { + return current_inline_frames_.back(); } uintptr_t GetCurrentQuickFramePc() const { @@ -309,9 +310,9 @@ class StackVisitor { size_t num_frames_; // Depth of the frame we're currently at. size_t cur_depth_; - // Current inlining depth of the method we are currently at. - // 0 if there is no inlined frame. - size_t current_inlining_depth_; + // Current inlined frames of the method we are currently at. + // We keep poping frames from the end as we visit the frames. + BitTableRange<InlineInfo> current_inline_frames_; protected: Context* const context_; diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc index a3c6e05045..7e46eb7e47 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -232,8 +232,7 @@ void CodeInfo::Dump(VariableIndentationOutputStream* vios, // Display stack maps along with (live) Dex register maps. if (verbose) { - for (size_t i = 0; i < GetNumberOfStackMaps(); ++i) { - StackMap stack_map = GetStackMapAt(i); + for (StackMap stack_map : stack_maps_) { stack_map.Dump(vios, *this, method_info, code_offset, instruction_set); } } @@ -259,9 +258,7 @@ void StackMap::Dump(VariableIndentationOutputStream* vios, } vios->Stream() << ")\n"; code_info.GetDexRegisterMapOf(*this).Dump(vios); - uint32_t depth = code_info.GetInlineDepthOf(*this); - for (size_t d = 0; d < depth; d++) { - InlineInfo inline_info = code_info.GetInlineInfoAtDepth(*this, d); + for (InlineInfo inline_info : code_info.GetInlineInfosOf(*this)) { inline_info.Dump(vios, code_info, *this, method_info); } } @@ -285,7 +282,7 @@ void InlineInfo::Dump(VariableIndentationOutputStream* vios, << ", method_index=" << GetMethodIndex(method_info); } vios->Stream() << ")\n"; - code_info.GetDexRegisterMapAtDepth(depth, stack_map).Dump(vios); + code_info.GetInlineDexRegisterMapOf(stack_map, *this).Dump(vios); } } // namespace art diff --git a/runtime/stack_map.h b/runtime/stack_map.h index ad52f377cf..2f2053a52a 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -298,8 +298,8 @@ class CodeInfo { return BitsToBytesRoundUp(size_in_bits_); } - bool HasInlineInfo() const { - return inline_infos_.NumRows() > 0; + ALWAYS_INLINE const BitTable<StackMap>& GetStackMaps() const { + return stack_maps_; } ALWAYS_INLINE StackMap GetStackMapAt(size_t index) const { @@ -330,6 +330,10 @@ class CodeInfo { : dex_register_catalog_.GetRow(index).GetLocation(); } + bool HasInlineInfo() const { + return inline_infos_.NumRows() > 0; + } + uint32_t GetNumberOfStackMaps() const { return stack_maps_.NumRows(); } @@ -347,14 +351,18 @@ class CodeInfo { return DexRegisterMap(0, DexRegisterLocation::None()); } - ALWAYS_INLINE DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth, StackMap stack_map) const { + ALWAYS_INLINE DexRegisterMap GetInlineDexRegisterMapOf(StackMap stack_map, + InlineInfo inline_info) const { if (stack_map.HasDexRegisterMap()) { + DCHECK(stack_map.HasInlineInfoIndex()); + uint32_t depth = inline_info.Row() - stack_map.GetInlineInfoIndex(); // The register counts are commutative and include all outer levels. // This allows us to determine the range [first, last) in just two lookups. // If we are at depth 0 (the first inlinee), the count from the main method is used. - uint32_t first = (depth == 0) ? number_of_dex_registers_ - : GetInlineInfoAtDepth(stack_map, depth - 1).GetNumberOfDexRegisters(); - uint32_t last = GetInlineInfoAtDepth(stack_map, depth).GetNumberOfDexRegisters(); + uint32_t first = (depth == 0) + ? number_of_dex_registers_ + : inline_infos_.GetRow(inline_info.Row() - 1).GetNumberOfDexRegisters(); + uint32_t last = inline_info.GetNumberOfDexRegisters(); DexRegisterMap map(last - first, DexRegisterLocation::Invalid()); DecodeDexRegisterMap(stack_map.Row(), first, &map); return map; @@ -362,28 +370,20 @@ class CodeInfo { return DexRegisterMap(0, DexRegisterLocation::None()); } - InlineInfo GetInlineInfo(size_t index) const { - return inline_infos_.GetRow(index); - } - - uint32_t GetInlineDepthOf(StackMap stack_map) const { - uint32_t depth = 0; + BitTableRange<InlineInfo> GetInlineInfosOf(StackMap stack_map) const { uint32_t index = stack_map.GetInlineInfoIndex(); if (index != StackMap::kNoValue) { - while (GetInlineInfo(index + depth++).GetIsLast() == InlineInfo::kMore) { } + auto begin = inline_infos_.begin() + index; + auto end = begin; + while ((*end++).GetIsLast() == InlineInfo::kMore) { } + return BitTableRange<InlineInfo>(begin, end); + } else { + return BitTableRange<InlineInfo>(); } - return depth; - } - - InlineInfo GetInlineInfoAtDepth(StackMap stack_map, uint32_t depth) const { - DCHECK(stack_map.HasInlineInfo()); - DCHECK_LT(depth, GetInlineDepthOf(stack_map)); - return GetInlineInfo(stack_map.GetInlineInfoIndex() + depth); } StackMap GetStackMapForDexPc(uint32_t dex_pc) const { - for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { - StackMap stack_map = GetStackMapAt(i); + for (StackMap stack_map : stack_maps_) { if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() != StackMap::Kind::Debug) { return stack_map; } @@ -403,8 +403,7 @@ class CodeInfo { } StackMap GetOsrStackMapForDexPc(uint32_t dex_pc) const { - for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { - StackMap stack_map = GetStackMapAt(i); + for (StackMap stack_map : stack_maps_) { if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() == StackMap::Kind::OSR) { return stack_map; } @@ -415,8 +414,7 @@ class CodeInfo { StackMap GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa = kRuntimeISA) const; InvokeInfo GetInvokeInfoForNativePcOffset(uint32_t native_pc_offset) { - for (size_t index = 0; index < invoke_infos_.NumRows(); index++) { - InvokeInfo item = GetInvokeInfo(index); + for (InvokeInfo item : invoke_infos_) { if (item.GetNativePcOffset(kRuntimeISA) == native_pc_offset) { return item; } |