diff options
Diffstat (limited to 'runtime/stack.cc')
| -rw-r--r-- | runtime/stack.cc | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc index 50a96d0ddf..5ee20e5fd3 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -129,7 +129,7 @@ uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const { GetCurrentQuickFrame(), cur_quick_frame_pc_, abort_on_failure); } else if (cur_oat_quick_method_header_->IsOptimized()) { StackMap* stack_map = GetCurrentStackMap(); - DCHECK(stack_map->IsValid()); + CHECK(stack_map->IsValid()) << "StackMap not found for " << std::hex << cur_quick_frame_pc_; return stack_map->GetDexPc(); } else { DCHECK(cur_oat_quick_method_header_->IsNterpMethodHeader()); @@ -780,7 +780,6 @@ void StackVisitor::WalkStack(bool include_transitions) { DCHECK(thread_ == Thread::Current() || thread_->IsSuspended()); } CHECK_EQ(cur_depth_, 0U); - size_t inlined_frames_count = 0; for (const ManagedStack* current_fragment = thread_->GetManagedStack(); current_fragment != nullptr; current_fragment = current_fragment->GetLink()) { @@ -788,6 +787,12 @@ void StackVisitor::WalkStack(bool include_transitions) { cur_quick_frame_ = current_fragment->GetTopQuickFrame(); cur_quick_frame_pc_ = 0; DCHECK(cur_oat_quick_method_header_ == nullptr); + + if (kDebugStackWalk) { + LOG(INFO) << "Tid=" << thread_-> GetThreadId() + << ", ManagedStack fragement: " << current_fragment; + } + if (cur_quick_frame_ != nullptr) { // Handle quick stack frames. // Can't be both a shadow and a quick fragment. DCHECK(current_fragment->GetTopShadowFrame() == nullptr); @@ -800,10 +805,20 @@ void StackVisitor::WalkStack(bool include_transitions) { // between GenericJNI frame and JIT-compiled JNI stub; the entrypoint may have // changed since the frame was entered. The top quick frame tag indicates // GenericJNI here, otherwise it's either AOT-compiled or JNI-compiled JNI stub. - if (UNLIKELY(current_fragment->GetTopQuickFrameTag())) { + if (UNLIKELY(current_fragment->GetTopQuickFrameGenericJniTag())) { // The generic JNI does not have any method header. cur_oat_quick_method_header_ = nullptr; + } else if (UNLIKELY(current_fragment->GetTopQuickFrameJitJniTag())) { + // Should be JITed code. + Runtime* runtime = Runtime::Current(); + const void* code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method); + CHECK(code != nullptr) << method->PrettyMethod(); + cur_oat_quick_method_header_ = OatQuickMethodHeader::FromCodePointer(code); } else { + // We are sure we are not running GenericJni here. Though the entry point could still be + // GenericJnistub. The entry point is usually JITed, AOT or instrumentation stub when + // instrumentation is enabled. It could be lso a resolution stub if the class isn't + // visibly initialized yet. const void* existing_entry_point = method->GetEntryPointFromQuickCompiledCode(); CHECK(existing_entry_point != nullptr); Runtime* runtime = Runtime::Current(); @@ -819,7 +834,11 @@ void StackVisitor::WalkStack(bool include_transitions) { if (code != nullptr) { cur_oat_quick_method_header_ = OatQuickMethodHeader::FromEntryPoint(code); } else { - // This must be a JITted JNI stub frame. + // This must be a JITted JNI stub frame. For non-debuggable runtimes we only generate + // JIT stubs if there are no AOT stubs for native methods. Since we checked for AOT + // code earlier, we must be running JITed code. For debuggable runtimes we might have + // JIT code even when AOT code is present but we tag SP in JITed JNI stubs + // in debuggable runtimes. This case is handled earlier. CHECK(runtime->GetJit() != nullptr); code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method); CHECK(code != nullptr) << method->PrettyMethod(); @@ -834,8 +853,12 @@ void StackVisitor::WalkStack(bool include_transitions) { cur_oat_quick_method_header_ = method->GetOatQuickMethodHeader(cur_quick_frame_pc_); } header_retrieved = false; // Force header retrieval in next iteration. - ValidateFrame(); + if (kDebugStackWalk) { + LOG(INFO) << "Early print: Tid=" << thread_-> GetThreadId() << ", method: " + << ArtMethod::PrettyMethod(method) << "@" << method; + } + ValidateFrame(); if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames) && (cur_oat_quick_method_header_ != nullptr) && cur_oat_quick_method_header_->IsOptimized() @@ -854,7 +877,6 @@ void StackVisitor::WalkStack(bool include_transitions) { return; } cur_depth_++; - inlined_frames_count++; } } } @@ -908,7 +930,8 @@ void StackVisitor::WalkStack(bool include_transitions) { cur_quick_frame_ = reinterpret_cast<ArtMethod**>(next_frame); if (kDebugStackWalk) { - LOG(INFO) << ArtMethod::PrettyMethod(method) << "@" << method << " size=" << frame_size + LOG(INFO) << "Tid=" << thread_-> GetThreadId() << ", method: " + << ArtMethod::PrettyMethod(method) << "@" << method << " size=" << frame_size << std::boolalpha << " optimized=" << (cur_oat_quick_method_header_ != nullptr && cur_oat_quick_method_header_->IsOptimized()) @@ -928,6 +951,12 @@ void StackVisitor::WalkStack(bool include_transitions) { cur_oat_quick_method_header_ = nullptr; } else if (cur_shadow_frame_ != nullptr) { do { + if (kDebugStackWalk) { + ArtMethod* method = cur_shadow_frame_->GetMethod(); + LOG(INFO) << "Tid=" << thread_-> GetThreadId() << ", method: " + << ArtMethod::PrettyMethod(method) << "@" << method + << ", ShadowFrame"; + } ValidateFrame(); bool should_continue = VisitFrame(); if (UNLIKELY(!should_continue)) { |