Index: runtime/vm/debugger.cc |
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc |
index 4253eca091d89ff9a06aa966decee5ef35bafe84..f94fbe598e24c344e1abb82a84f0371aa35c933a 100644 |
--- a/runtime/vm/debugger.cc |
+++ b/runtime/vm/debugger.cc |
@@ -12,6 +12,7 @@ |
#include "vm/compiler.h" |
#include "vm/dart_entry.h" |
#include "vm/deopt_instructions.h" |
+#include "vm/disassembler.h" |
#include "vm/flags.h" |
#include "vm/globals.h" |
#include "vm/json_stream.h" |
@@ -264,6 +265,7 @@ ActivationFrame::ActivationFrame(uword pc, |
token_pos_initialized_(false), |
token_pos_(TokenPosition::kNoSource), |
try_index_(-1), |
+ deopt_id_(Thread::kNoDeoptId), |
line_number_(-1), |
column_number_(-1), |
context_level_(-1), |
@@ -611,6 +613,7 @@ TokenPosition ActivationFrame::TokenPos() { |
if (iter.PcOffset() == pc_offset) { |
try_index_ = iter.TryIndex(); |
token_pos_ = iter.TokenPos(); |
+ deopt_id_ = iter.DeoptId(); |
break; |
} |
} |
@@ -627,6 +630,14 @@ intptr_t ActivationFrame::TryIndex() { |
} |
+intptr_t ActivationFrame::DeoptId() { |
+ if (!token_pos_initialized_) { |
+ TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. |
+ } |
+ return deopt_id_; |
+} |
+ |
+ |
intptr_t ActivationFrame::LineNumber() { |
// Compute line number lazily since it causes scanning of the script. |
if ((line_number_ < 0) && TokenPos().IsSourcePosition()) { |
@@ -678,42 +689,55 @@ bool ActivationFrame::IsDebuggable() const { |
} |
+void ActivationFrame::PrintDescriptorsError(const char* message) { |
+ OS::PrintErr("Bad descriptors: %s\n", message); |
+ OS::PrintErr("function %s\n", function().ToQualifiedCString()); |
+ OS::PrintErr("pc_ %" Px "\n", pc_); |
+ OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_); |
+ OS::PrintErr("context_level_ %" Px "\n", context_level_); |
+ DisassembleToStdout formatter; |
+ code().Disassemble(&formatter); |
+ PcDescriptors::Handle(code().pc_descriptors()).Print(); |
+ StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, |
+ Thread::Current(), |
+ StackFrameIterator::kNoCrossThreadIteration); |
+ StackFrame* frame = frames.NextFrame(); |
+ while (frame != NULL) { |
+ OS::PrintErr("%s\n", frame->ToCString()); |
+ frame = frames.NextFrame(); |
+ } |
+ OS::Abort(); |
+} |
+ |
+ |
// Calculate the context level at the current token index of the frame. |
intptr_t ActivationFrame::ContextLevel() { |
const Context& ctx = GetSavedCurrentContext(); |
if (context_level_ < 0 && !ctx.IsNull()) { |
ASSERT(!code_.is_optimized()); |
- context_level_ = 0; |
- // TODO(hausner): What to do if there is no descriptor entry |
- // for the code position of the frame? For now say we are at context |
- // level 0. |
- TokenPos(); |
- if (token_pos_ == TokenPosition::kNoSource) { |
- // No PcDescriptor. |
- return context_level_; |
- } |
- ASSERT(!pc_desc_.IsNull()); |
- TokenPosition innermost_begin_pos = TokenPosition::kMinSource; |
- TokenPosition activation_token_pos = TokenPos().FromSynthetic(); |
- ASSERT(activation_token_pos.IsReal()); |
+ |
GetVarDescriptors(); |
+ intptr_t deopt_id = DeoptId(); |
+ if (deopt_id == Thread::kNoDeoptId) { |
+ PrintDescriptorsError("Missing deopt id"); |
+ } |
intptr_t var_desc_len = var_descriptors_.Length(); |
+ bool found = false; |
for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
RawLocalVarDescriptors::VarInfo var_info; |
var_descriptors_.GetInfo(cur_idx, &var_info); |
const int8_t kind = var_info.kind(); |
if ((kind == RawLocalVarDescriptors::kContextLevel) && |
- (var_info.begin_pos <= activation_token_pos) && |
- (activation_token_pos < var_info.end_pos)) { |
- // This var_descriptors_ entry is a context scope which is in scope |
- // of the current token position. Now check whether it is shadowing |
- // the previous context scope. |
- if (innermost_begin_pos < var_info.begin_pos) { |
- innermost_begin_pos = var_info.begin_pos; |
- context_level_ = var_info.index(); |
- } |
+ (deopt_id >= var_info.begin_pos.value()) && |
+ (deopt_id <= var_info.end_pos.value())) { |
+ context_level_ = var_info.index(); |
+ found = true; |
+ break; |
} |
} |
+ if (!found) { |
+ PrintDescriptorsError("Missing context level"); |
+ } |
ASSERT(context_level_ >= 0); |
} |
return context_level_; |