Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Unified Diff: src/debug/debug.cc

Issue 2238893002: [debugger] separate break point info from code instrumentation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/debug/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug/debug.cc
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index 733ea9b02dbb0c9c1dd362645abbd20941a0a401..22a8b49016132f07e9786a3f162d2f5b080cdfcc 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -33,17 +33,6 @@
namespace v8 {
namespace internal {
-namespace {
-
-inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
- // Code offset points to the instruction after the call. Subtract 1 to
- // exclude that instruction from the search. For bytecode, the code offset
- // still points to the call.
- return is_interpreted ? code_offset : code_offset - 1;
-}
-
-} // namespace
-
Debug::Debug(Isolate* isolate)
: debug_context_(Handle<Context>()),
event_listener_(Handle<Object>()),
@@ -65,53 +54,135 @@ Debug::Debug(Isolate* isolate)
ThreadInit();
}
+BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
+ JavaScriptFrame* frame) {
+ FrameSummary summary = FrameSummary::GetFirst(frame);
+ int offset = summary.code_offset();
+ Handle<AbstractCode> abstract_code = summary.abstract_code();
+ if (abstract_code->IsCode()) offset = offset - 1;
+ auto it = BreakIterator::GetIterator(debug_info, abstract_code);
+ it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
+ return it->GetBreakLocation();
+}
-static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
- Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
- // Isolate::context() may have been NULL when "script collected" event
- // occured.
- if (context.is_null()) return v8::Local<v8::Context>();
- Handle<Context> native_context(context->native_context());
- return v8::Utils::ToLocal(native_context);
+void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info,
+ JavaScriptFrame* frame,
+ List<BreakLocation>* result_out) {
+ FrameSummary summary = FrameSummary::GetFirst(frame);
+ int offset = summary.code_offset();
+ Handle<AbstractCode> abstract_code = summary.abstract_code();
+ if (abstract_code->IsCode()) offset = offset - 1;
+ int statement_position;
+ {
+ auto it = BreakIterator::GetIterator(debug_info, abstract_code);
+ it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
+ statement_position = it->statement_position();
+ }
+ for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
+ !it->Done(); it->Next()) {
+ if (it->statement_position() == statement_position) {
+ result_out->Add(it->GetBreakLocation());
+ }
+ }
+}
+
+int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
+ Handle<AbstractCode> abstract_code,
+ int offset) {
+ // Run through all break points to locate the one closest to the address.
+ int closest_break = 0;
+ int distance = kMaxInt;
+ DCHECK(0 <= offset && offset < abstract_code->Size());
+ for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
+ !it->Done(); it->Next()) {
+ // Check if this break point is closer that what was previously found.
+ if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
+ closest_break = it->break_index();
+ distance = offset - it->code_offset();
+ // Check whether we can't get any closer.
+ if (distance == 0) break;
+ }
+ }
+ return closest_break;
}
-BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type,
- int code_offset, int position,
- int statement_position)
- : debug_info_(debug_info),
- code_offset_(code_offset),
- type_(type),
- position_(position),
- statement_position_(statement_position) {}
+bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
+ // First check whether there is a break point with the same source position.
+ if (!debug_info->HasBreakPoint(position_)) return false;
+ // Then check whether a break point at that source position would have
+ // the same code offset. Otherwise it's just a break location that we can
+ // step to, but not actually a location where we can put a break point.
+ if (abstract_code_->IsCode()) {
+ DCHECK_EQ(debug_info->DebugCode(), abstract_code_->GetCode());
+ CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
+ return it.code_offset() == code_offset_;
+ } else {
+ DCHECK(abstract_code_->IsBytecodeArray());
+ BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
+ return it.code_offset() == code_offset_;
+ }
+}
-BreakLocation::Iterator* BreakLocation::GetIterator(
- Handle<DebugInfo> debug_info, BreakLocatorType type) {
- if (debug_info->abstract_code()->IsBytecodeArray()) {
- return new BytecodeArrayIterator(debug_info, type);
+std::unique_ptr<BreakIterator> BreakIterator::GetIterator(
+ Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code,
+ BreakLocatorType type) {
+ if (abstract_code->IsBytecodeArray()) {
+ DCHECK(debug_info->HasDebugBytecodeArray());
+ return std::unique_ptr<BreakIterator>(
+ new BytecodeArrayBreakIterator(debug_info, type));
} else {
- return new CodeIterator(debug_info, type);
+ DCHECK(abstract_code->IsCode());
+ DCHECK(debug_info->HasDebugCode());
+ return std::unique_ptr<BreakIterator>(
+ new CodeBreakIterator(debug_info, type));
}
}
-BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info)
- : debug_info_(debug_info), break_index_(-1) {
+BreakIterator::BreakIterator(Handle<DebugInfo> debug_info,
+ BreakLocatorType type)
+ : debug_info_(debug_info), break_index_(-1), break_locator_type_(type) {
position_ = debug_info->shared()->start_position();
statement_position_ = position_;
}
-BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
- BreakLocatorType type)
- : Iterator(debug_info),
- reloc_iterator_(debug_info->abstract_code()->GetCode(),
- GetModeMask(type)),
+int BreakIterator::BreakIndexFromPosition(int source_position,
+ BreakPositionAlignment alignment) {
+ int distance = kMaxInt;
+ int closest_break = break_index();
+ while (!Done()) {
+ int next_position;
+ if (alignment == STATEMENT_ALIGNED) {
+ next_position = statement_position();
+ } else {
+ DCHECK(alignment == BREAK_POSITION_ALIGNED);
+ next_position = position();
+ }
+ if (source_position <= next_position &&
+ next_position - source_position < distance) {
+ closest_break = break_index();
+ distance = next_position - source_position;
+ // Check whether we can't get any closer.
+ if (distance == 0) break;
+ }
+ Next();
+ }
+ return closest_break;
+}
+
+CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info,
+ BreakLocatorType type)
+ : BreakIterator(debug_info, type),
+ reloc_iterator_(debug_info->DebugCode(), GetModeMask(type)),
source_position_iterator_(
- debug_info->abstract_code()->GetCode()->source_position_table()) {
+ debug_info->DebugCode()->source_position_table()) {
// There is at least one break location.
DCHECK(!Done());
Next();
}
-int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
+int CodeBreakIterator::GetModeMask(BreakLocatorType type) {
int mask = 0;
mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
@@ -125,7 +196,7 @@ int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
return mask;
}
-void BreakLocation::CodeIterator::Next() {
+void CodeBreakIterator::Next() {
DisallowHeapAllocation no_gc;
DCHECK(!Done());
@@ -151,40 +222,71 @@ void BreakLocation::CodeIterator::Next() {
break_index_++;
}
-BreakLocation BreakLocation::CodeIterator::GetBreakLocation() {
- DebugBreakType type;
+DebugBreakType CodeBreakIterator::GetDebugBreakType() {
if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
- type = DEBUG_BREAK_SLOT_AT_RETURN;
+ return DEBUG_BREAK_SLOT_AT_RETURN;
} else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
- type = DEBUG_BREAK_SLOT_AT_CALL;
+ return DEBUG_BREAK_SLOT_AT_CALL;
} else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) {
- type = isolate()->is_tail_call_elimination_enabled()
+ return isolate()->is_tail_call_elimination_enabled()
? DEBUG_BREAK_SLOT_AT_TAIL_CALL
: DEBUG_BREAK_SLOT_AT_CALL;
} else if (RelocInfo::IsDebuggerStatement(rmode())) {
- type = DEBUGGER_STATEMENT;
+ return DEBUGGER_STATEMENT;
} else if (RelocInfo::IsDebugBreakSlot(rmode())) {
- type = DEBUG_BREAK_SLOT;
+ return DEBUG_BREAK_SLOT;
} else {
- type = NOT_DEBUG_BREAK;
+ return NOT_DEBUG_BREAK;
}
- return BreakLocation(debug_info_, type, code_offset(), position(),
- statement_position());
}
-BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
+void CodeBreakIterator::SkipToPosition(int position,
+ BreakPositionAlignment alignment) {
+ CodeBreakIterator it(debug_info_, break_locator_type_);
+ SkipTo(it.BreakIndexFromPosition(position, alignment));
+}
+
+void CodeBreakIterator::SetDebugBreak() {
+ DebugBreakType debug_break_type = GetDebugBreakType();
+ if (debug_break_type == DEBUGGER_STATEMENT) return;
+ DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
+ Builtins* builtins = isolate()->builtins();
+ Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN
+ ? builtins->Return_DebugBreak()
+ : builtins->Slot_DebugBreak();
+ DebugCodegen::PatchDebugBreakSlot(isolate(), rinfo()->pc(), target);
+}
+
+void CodeBreakIterator::ClearDebugBreak() {
+ DebugBreakType debug_break_type = GetDebugBreakType();
+ if (debug_break_type == DEBUGGER_STATEMENT) return;
+ DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
+ DebugCodegen::ClearDebugBreakSlot(isolate(), rinfo()->pc());
+}
+
+bool CodeBreakIterator::IsDebugBreak() {
+ DebugBreakType debug_break_type = GetDebugBreakType();
+ if (debug_break_type == DEBUGGER_STATEMENT) return false;
+ DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
+ return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc());
+}
+
+BreakLocation CodeBreakIterator::GetBreakLocation() {
+ Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode()));
+ return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
+}
+
+BytecodeArrayBreakIterator::BytecodeArrayBreakIterator(
Handle<DebugInfo> debug_info, BreakLocatorType type)
- : Iterator(debug_info),
- source_position_iterator_(debug_info->abstract_code()
- ->GetBytecodeArray()
- ->source_position_table()),
- break_locator_type_(type) {
+ : BreakIterator(debug_info, type),
+ source_position_iterator_(
+ debug_info->DebugBytecodeArray()->source_position_table()) {
// There is at least one break location.
DCHECK(!Done());
Next();
}
-void BreakLocation::BytecodeArrayIterator::Next() {
+void BytecodeArrayBreakIterator::Next() {
DisallowHeapAllocation no_gc;
DCHECK(!Done());
bool first = break_index_ == -1;
@@ -199,7 +301,7 @@ void BreakLocation::BytecodeArrayIterator::Next() {
DCHECK(position_ >= 0);
DCHECK(statement_position_ >= 0);
- enum DebugBreakType type = GetDebugBreakType();
+ DebugBreakType type = GetDebugBreakType();
if (type == NOT_DEBUG_BREAK) continue;
if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
@@ -211,9 +313,8 @@ void BreakLocation::BytecodeArrayIterator::Next() {
break_index_++;
}
-BreakLocation::DebugBreakType
-BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
- BytecodeArray* bytecode_array = debug_info_->original_bytecode_array();
+DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() {
+ BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray();
interpreter::Bytecode bytecode =
interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
@@ -234,215 +335,51 @@ BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
}
}
-BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
- return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(),
- position(), statement_position());
-}
-
-// Find the break point at the supplied address, or the closest one before
-// the address.
-BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
- int offset) {
- std::unique_ptr<Iterator> it(GetIterator(debug_info));
- it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset));
- return it->GetBreakLocation();
-}
-
-BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
- JavaScriptFrame* frame) {
- int code_offset = FrameSummary::GetFirst(frame).code_offset();
- int call_offset =
- CallOffsetFromCodeOffset(code_offset, frame->is_interpreted());
- return FromCodeOffset(debug_info, call_offset);
-}
-
-void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info,
- int statement_position,
- List<BreakLocation>* result_out) {
- for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done();
- it->Next()) {
- if (it->statement_position() == statement_position) {
- result_out->Add(it->GetBreakLocation());
- }
- }
-}
-
-int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
- int offset) {
- // Run through all break points to locate the one closest to the address.
- int closest_break = 0;
- int distance = kMaxInt;
- DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
- for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done();
- it->Next()) {
- // Check if this break point is closer that what was previously found.
- if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
- closest_break = it->break_index();
- distance = offset - it->code_offset();
- // Check whether we can't get any closer.
- if (distance == 0) break;
- }
- }
- return closest_break;
-}
-
-
-BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
- int position,
- BreakPositionAlignment alignment) {
- // Run through all break points to locate the one closest to the source
- // position.
- int distance = kMaxInt;
- std::unique_ptr<Iterator> it(GetIterator(debug_info));
- BreakLocation closest_break = it->GetBreakLocation();
- while (!it->Done()) {
- int next_position;
- if (alignment == STATEMENT_ALIGNED) {
- next_position = it->statement_position();
- } else {
- DCHECK(alignment == BREAK_POSITION_ALIGNED);
- next_position = it->position();
- }
- if (position <= next_position && next_position - position < distance) {
- closest_break = it->GetBreakLocation();
- distance = next_position - position;
- // Check whether we can't get any closer.
- if (distance == 0) break;
- }
- it->Next();
- }
- return closest_break;
-}
-
-
-void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
- // If there is not already a real break point here patch code with debug
- // break.
- if (!HasBreakPoint()) SetDebugBreak();
- DCHECK(IsDebugBreak() || IsDebuggerStatement());
- // Set the break point information.
- DebugInfo::SetBreakPoint(debug_info_, position_, statement_position_,
- break_point_object);
-}
-
-
-void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
- // Clear the break point information.
- DebugInfo::ClearBreakPoint(debug_info_, position_, break_point_object);
- // If there are no more break points here remove the debug break.
- if (!HasBreakPoint()) {
- ClearDebugBreak();
- DCHECK(!IsDebugBreak());
- }
-}
-
-
-void BreakLocation::SetOneShot() {
- // Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) return;
-
- // Patch code with debug break.
- SetDebugBreak();
-}
-
-
-void BreakLocation::ClearOneShot() {
- // Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) return;
-
- // If there is a real break point here no more to do.
- if (HasBreakPoint()) {
- DCHECK(IsDebugBreak());
- return;
- }
-
- // Patch code removing debug break.
- ClearDebugBreak();
- DCHECK(!IsDebugBreak());
-}
-
-
-void BreakLocation::SetDebugBreak() {
- // Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) return;
-
- // If there is already a break point here just return. This might happen if
- // the same code is flooded with break points twice. Flooding the same
- // function twice might happen when stepping in a function with an exception
- // handler as the handler and the function is the same.
- if (IsDebugBreak()) return;
-
- DCHECK(IsDebugBreakSlot());
- if (abstract_code()->IsCode()) {
- Code* code = abstract_code()->GetCode();
- DCHECK(code->kind() == Code::FUNCTION);
- Builtins* builtins = isolate()->builtins();
- Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
- : builtins->Slot_DebugBreak();
- Address pc = code->instruction_start() + code_offset();
- DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
- } else {
- BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
- interpreter::Bytecode bytecode =
- interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
- interpreter::Bytecode debugbreak =
- interpreter::Bytecodes::GetDebugBreak(bytecode);
- bytecode_array->set(code_offset(),
- interpreter::Bytecodes::ToByte(debugbreak));
- }
- DCHECK(IsDebugBreak());
-}
-
-
-void BreakLocation::ClearDebugBreak() {
- // Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) return;
-
- DCHECK(IsDebugBreakSlot());
- if (abstract_code()->IsCode()) {
- Code* code = abstract_code()->GetCode();
- DCHECK(code->kind() == Code::FUNCTION);
- Address pc = code->instruction_start() + code_offset();
- DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
- } else {
- BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
- BytecodeArray* original = debug_info_->original_bytecode_array();
- bytecode_array->set(code_offset(), original->get(code_offset()));
- }
- DCHECK(!IsDebugBreak());
+void BytecodeArrayBreakIterator::SkipToPosition(
+ int position, BreakPositionAlignment alignment) {
+ BytecodeArrayBreakIterator it(debug_info_, break_locator_type_);
+ SkipTo(it.BreakIndexFromPosition(position, alignment));
}
-
-bool BreakLocation::IsDebugBreak() const {
- if (IsDebuggerStatement()) return false;
- DCHECK(IsDebugBreakSlot());
- if (abstract_code()->IsCode()) {
- Code* code = abstract_code()->GetCode();
- DCHECK(code->kind() == Code::FUNCTION);
- Address pc = code->instruction_start() + code_offset();
- return DebugCodegen::DebugBreakSlotIsPatched(pc);
- } else {
- BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
- interpreter::Bytecode bytecode =
- interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
- return interpreter::Bytecodes::IsDebugBreak(bytecode);
- }
+void BytecodeArrayBreakIterator::SetDebugBreak() {
+ DebugBreakType debug_break_type = GetDebugBreakType();
+ if (debug_break_type == DEBUGGER_STATEMENT) return;
+ DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
+ BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
+ interpreter::Bytecode bytecode =
+ interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
+ if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return;
+ interpreter::Bytecode debugbreak =
+ interpreter::Bytecodes::GetDebugBreak(bytecode);
+ bytecode_array->set(code_offset(),
+ interpreter::Bytecodes::ToByte(debugbreak));
+}
+
+void BytecodeArrayBreakIterator::ClearDebugBreak() {
+ DebugBreakType debug_break_type = GetDebugBreakType();
+ if (debug_break_type == DEBUGGER_STATEMENT) return;
+ DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
+ BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
+ BytecodeArray* original = debug_info_->OriginalBytecodeArray();
+ bytecode_array->set(code_offset(), original->get(code_offset()));
+}
+
+bool BytecodeArrayBreakIterator::IsDebugBreak() {
+ DebugBreakType debug_break_type = GetDebugBreakType();
+ if (debug_break_type == DEBUGGER_STATEMENT) return false;
+ DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
+ BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
+ interpreter::Bytecode bytecode =
+ interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
+ return interpreter::Bytecodes::IsDebugBreak(bytecode);
}
-Handle<Object> BreakLocation::BreakPointObjects() const {
- return debug_info_->GetBreakPointObjects(position_);
+BreakLocation BytecodeArrayBreakIterator::GetBreakLocation() {
+ Handle<AbstractCode> code(
+ AbstractCode::cast(debug_info_->DebugBytecodeArray()));
+ return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
}
-bool BreakLocation::HasBreakPoint() const {
- // First check whether there is a break point with the same source position.
- if (!debug_info_->HasBreakPoint(position_)) return false;
- // Then check whether a break point at that source position would have
- // the same code offset. Otherwise it's just a break location that we can
- // step to, but not actually a location where we can put a break point.
- BreakLocation break_point_location = BreakLocation::FromPosition(
- debug_info_, position_, BREAK_POSITION_ALIGNED);
- return break_point_location.code_offset() == code_offset_;
-}
void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
uint32_t mask = 1 << feature;
@@ -582,7 +519,7 @@ void Debug::Break(JavaScriptFrame* frame) {
BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
// Find actual break points, if any, and trigger debug break event.
- Handle<Object> break_points_hit = CheckBreakPoints(&location);
+ Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location);
if (!break_points_hit->IsUndefined(isolate_)) {
// Clear all current stepping setup.
ClearStepping();
@@ -618,7 +555,7 @@ void Debug::Break(JavaScriptFrame* frame) {
step_break = step_break || location.IsReturn() ||
(current_fp != last_fp) ||
(thread_local_.last_statement_position_ !=
- location.abstract_code()->SourceStatementPosition(offset));
+ summary.abstract_code()->SourceStatementPosition(offset));
break;
}
case StepFrame:
@@ -641,15 +578,17 @@ void Debug::Break(JavaScriptFrame* frame) {
// Find break point objects for this location, if any, and evaluate them.
// Return an array of break point objects that evaluated true.
-Handle<Object> Debug::CheckBreakPoints(BreakLocation* location,
+Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
+ BreakLocation* location,
bool* has_break_points) {
Factory* factory = isolate_->factory();
bool has_break_points_to_check =
- break_points_active_ && location->HasBreakPoint();
+ break_points_active_ && location->HasBreakPoint(debug_info);
if (has_break_points) *has_break_points = has_break_points_to_check;
if (!has_break_points_to_check) return factory->undefined_value();
- Handle<Object> break_point_objects = location->BreakPointObjects();
+ Handle<Object> break_point_objects =
+ debug_info->GetBreakPointObjects(location->position());
// Count the number of break points hit. If there are multiple break points
// they are in a FixedArray.
Handle<FixedArray> break_points_hit;
@@ -692,15 +631,13 @@ bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
// Enter the debugger.
DebugScope debug_scope(this);
if (debug_scope.failed()) return false;
- BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame);
List<BreakLocation> break_locations;
- BreakLocation::AllForStatementPosition(
- debug_info, current_position.statement_position(), &break_locations);
+ BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
bool has_break_points_at_all = false;
for (int i = 0; i < break_locations.length(); i++) {
bool has_break_points;
Handle<Object> check_result =
- CheckBreakPoints(&break_locations[i], &has_break_points);
+ CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
has_break_points_at_all |= has_break_points;
if (has_break_points && !check_result->IsUndefined(isolate_)) return false;
}
@@ -762,15 +699,17 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
DCHECK(*source_position >= 0);
// Find the break point and change it.
- BreakLocation location = BreakLocation::FromPosition(
- debug_info, *source_position, STATEMENT_ALIGNED);
- *source_position = location.statement_position();
- location.SetBreakPoint(break_point_object);
+ *source_position =
+ FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED);
+ DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
+ // At least one active break point now.
+ DCHECK(debug_info->GetBreakPointCount() > 0);
- feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
+ ClearBreakPoints(debug_info);
+ ApplyBreakPoints(debug_info);
- // At least one active break point now.
- return debug_info->GetBreakPointCount() > 0;
+ feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
+ return true;
}
@@ -805,64 +744,104 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
// Find the break point and change it.
- BreakLocation location =
- BreakLocation::FromPosition(debug_info, *source_position, alignment);
- location.SetBreakPoint(break_point_object);
+ *source_position =
+ FindBreakablePosition(debug_info, *source_position, alignment);
+ DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
+ // At least one active break point now.
+ DCHECK(debug_info->GetBreakPointCount() > 0);
+
+ ClearBreakPoints(debug_info);
+ ApplyBreakPoints(debug_info);
feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
+ return true;
+}
- *source_position = (alignment == STATEMENT_ALIGNED)
- ? location.statement_position()
- : location.position();
+int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
+ int source_position,
+ BreakPositionAlignment alignment) {
+ int statement_position;
+ int position;
+ if (debug_info->HasDebugCode()) {
+ CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(source_position, alignment);
+ statement_position = it.statement_position();
+ position = it.position();
+ } else {
+ DCHECK(debug_info->HasDebugBytecodeArray());
+ BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(source_position, alignment);
+ statement_position = it.statement_position();
+ position = it.position();
+ }
+ return alignment == STATEMENT_ALIGNED ? statement_position : position;
+}
- // At least one active break point now.
- DCHECK(debug_info->GetBreakPointCount() > 0);
- return true;
+void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
+ DisallowHeapAllocation no_gc;
+ if (debug_info->break_points()->IsUndefined(isolate_)) return;
+ FixedArray* break_points = debug_info->break_points();
+ for (int i = 0; i < break_points->length(); i++) {
+ if (break_points->get(i)->IsUndefined(isolate_)) continue;
+ BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
+ if (info->GetBreakPointCount() == 0) continue;
+ if (debug_info->HasDebugCode()) {
+ CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
+ it.SetDebugBreak();
+ }
+ if (debug_info->HasDebugBytecodeArray()) {
+ BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
+ it.SetDebugBreak();
+ }
+ }
}
+void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
+ DisallowHeapAllocation no_gc;
+ if (debug_info->HasDebugCode()) {
+ for (CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done();
+ it.Next()) {
+ it.ClearDebugBreak();
+ }
+ }
+ if (debug_info->HasDebugBytecodeArray()) {
+ for (BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ !it.Done(); it.Next()) {
+ it.ClearDebugBreak();
+ }
+ }
+}
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
HandleScope scope(isolate_);
- DebugInfoListNode* node = debug_info_list_;
- while (node != NULL) {
+ for (DebugInfoListNode* node = debug_info_list_; node != NULL;
+ node = node->next()) {
Handle<Object> result =
DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
- if (!result->IsUndefined(isolate_)) {
- // Get information in the break point.
- Handle<BreakPointInfo> break_point_info =
- Handle<BreakPointInfo>::cast(result);
- Handle<DebugInfo> debug_info = node->debug_info();
-
- BreakLocation location = BreakLocation::FromPosition(
- debug_info, break_point_info->source_position(),
- BREAK_POSITION_ALIGNED);
- location.ClearBreakPoint(break_point_object);
-
- // If there are no more break points left remove the debug info for this
- // function.
+ if (result->IsUndefined(isolate_)) continue;
+ Handle<DebugInfo> debug_info = node->debug_info();
+ if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) {
+ ClearBreakPoints(debug_info);
if (debug_info->GetBreakPointCount() == 0) {
RemoveDebugInfoAndClearFromShared(debug_info);
+ } else {
+ ApplyBreakPoints(debug_info);
}
-
return;
}
- node = node->next();
}
}
-
// Clear out all the debug break code. This is ONLY supposed to be used when
// shutting down the debugger as it will leave the break point information in
// DebugInfo even though the code is patched back to the non break point state.
void Debug::ClearAllBreakPoints() {
for (DebugInfoListNode* node = debug_info_list_; node != NULL;
node = node->next()) {
- for (std::unique_ptr<BreakLocation::Iterator> it(
- BreakLocation::GetIterator(node->debug_info()));
- !it->Done(); it->Next()) {
- it->GetBreakLocation().ClearDebugBreak();
- }
+ ClearBreakPoints(node->debug_info());
}
// Remove all debug info.
while (debug_info_list_ != NULL) {
@@ -870,7 +849,6 @@ void Debug::ClearAllBreakPoints() {
}
}
-
void Debug::FloodWithOneShot(Handle<JSFunction> function,
BreakLocatorType type) {
// Debug utility functions are not subject to debugging.
@@ -892,14 +870,19 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function,
// Flood the function with break points.
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
- for (std::unique_ptr<BreakLocation::Iterator> it(
- BreakLocation::GetIterator(debug_info, type));
- !it->Done(); it->Next()) {
- it->GetBreakLocation().SetOneShot();
+ if (debug_info->HasDebugCode()) {
+ for (CodeBreakIterator it(debug_info, type); !it.Done(); it.Next()) {
+ it.SetDebugBreak();
+ }
+ }
+ if (debug_info->HasDebugBytecodeArray()) {
+ for (BytecodeArrayBreakIterator it(debug_info, type); !it.Done();
+ it.Next()) {
+ it.SetDebugBreak();
+ }
}
}
-
void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
if (type == BreakUncaughtException) {
break_on_uncaught_exception_ = enable;
@@ -1014,15 +997,7 @@ void Debug::PrepareStep(StepAction step_action) {
}
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
- // Refresh frame summary if the code has been recompiled for debugging.
- if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
- summary = FrameSummary::GetFirst(frame);
- }
-
- int call_offset =
- CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
- BreakLocation location =
- BreakLocation::FromCodeOffset(debug_info, call_offset);
+ BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
// Any step at a return is a step-out.
if (location.IsReturn()) step_action = StepOut;
@@ -1030,8 +1005,7 @@ void Debug::PrepareStep(StepAction step_action) {
if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
thread_local_.last_statement_position_ =
- debug_info->abstract_code()->SourceStatementPosition(
- summary.code_offset());
+ summary.abstract_code()->SourceStatementPosition(summary.code_offset());
thread_local_.last_fp_ = frame->UnpaddedFP();
// No longer perform the current async step.
clear_suspended_generator();
@@ -1076,7 +1050,6 @@ void Debug::PrepareStep(StepAction step_action) {
}
}
-
// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
Handle<SharedFunctionInfo> shared,
@@ -1100,10 +1073,18 @@ Handle<Object> Debug::GetSourceBreakLocations(
if (break_points == 0) continue;
Smi* position = NULL;
if (position_alignment == STATEMENT_ALIGNED) {
- BreakLocation break_point_location = BreakLocation::FromPosition(
- debug_info, break_point_info->source_position(),
- BREAK_POSITION_ALIGNED);
- position = Smi::FromInt(break_point_location.statement_position());
+ if (debug_info->HasDebugCode()) {
+ CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(break_point_info->source_position(),
+ BREAK_POSITION_ALIGNED);
+ position = Smi::FromInt(it.statement_position());
+ } else {
+ DCHECK(debug_info->HasDebugBytecodeArray());
+ BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
+ it.SkipToPosition(break_point_info->source_position(),
+ BREAK_POSITION_ALIGNED);
+ position = Smi::FromInt(it.statement_position());
+ }
} else {
DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment);
position = Smi::FromInt(break_point_info->source_position());
@@ -1114,7 +1095,6 @@ Handle<Object> Debug::GetSourceBreakLocations(
return locations;
}
-
void Debug::ClearStepping() {
// Clear the various stepping setup.
ClearOneShot();
@@ -1135,11 +1115,9 @@ void Debug::ClearOneShot() {
// removed from the list.
for (DebugInfoListNode* node = debug_info_list_; node != NULL;
node = node->next()) {
- for (std::unique_ptr<BreakLocation::Iterator> it(
- BreakLocation::GetIterator(node->debug_info()));
- !it->Done(); it->Next()) {
- it->GetBreakLocation().ClearOneShot();
- }
+ Handle<DebugInfo> debug_info = node->debug_info();
+ ClearBreakPoints(debug_info);
+ ApplyBreakPoints(debug_info);
}
}
@@ -1243,7 +1221,7 @@ class RedirectActiveFunctions : public ThreadVisitor {
InterpretedFrame* interpreted_frame =
reinterpret_cast<InterpretedFrame*>(frame);
BytecodeArray* debug_copy =
- shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray();
+ shared_->GetDebugInfo()->DebugBytecodeArray();
interpreted_frame->PatchBytecodeArray(debug_copy);
continue;
}
@@ -1596,10 +1574,8 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
if (!shared->HasDebugInfo()) return false;
DCHECK(!frame->is_optimized());
- int code_offset = FrameSummary::GetFirst(frame).code_offset();
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
- BreakLocation location =
- BreakLocation::FromCodeOffset(debug_info, code_offset);
+ BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
return location.IsReturn() || location.IsTailCall();
}
@@ -2430,6 +2406,16 @@ v8::Local<v8::String> MessageImpl::GetJSON() const {
}
}
+namespace {
+v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
+ Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
+ // Isolate::context() may have been NULL when "script collected" event
+ // occured.
+ if (context.is_null()) return v8::Local<v8::Context>();
+ Handle<Context> native_context(context->native_context());
+ return v8::Utils::ToLocal(native_context);
+}
+} // anonymous namespace
v8::Local<v8::Context> MessageImpl::GetEventContext() const {
Isolate* isolate = event_data_->GetIsolate();
« no previous file with comments | « src/debug/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698