[debug] remove legacy implementation for break points.

R=herhut@chromium.org, jgruber@chromium.org

Bug: v8:7310, v8:5510
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Icefd10b6cc210e5bb2684d18b091179ead387326
Reviewed-on: https://chromium-review.googlesource.com/934445
Commit-Queue: Yang Guo <yangguo@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51552}
This commit is contained in:
Yang Guo 2018-02-26 10:20:45 +01:00 committed by Commit Bot
parent d504203e93
commit 175fc49c6e
20 changed files with 153 additions and 1988 deletions

View File

@ -180,12 +180,10 @@ class DebugDelegate {
bool is_blackboxed) {}
virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited,
bool has_compile_error) {}
// |break_points_hit| contains installed by JS debug API breakpoint objects.
// |inspector_break_points_hit| contains id of breakpoints installed with
// debug::Script::SetBreakpoint API.
virtual void BreakProgramRequested(
v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> break_points_hit,
const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,

View File

@ -510,9 +510,9 @@ MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
if (has_break_points) *has_break_points = has_break_points_to_check;
if (!has_break_points_to_check) return {};
Handle<Object> break_point_objects =
debug_info->GetBreakPointObjects(location->position());
return Debug::GetHitBreakPointObjects(break_point_objects);
Handle<Object> break_points =
debug_info->GetBreakPoints(location->position());
return Debug::GetHitBreakPoints(break_points);
}
@ -567,15 +567,9 @@ MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
Factory* factory = isolate_->factory();
bool Debug::CheckBreakPoint(Handle<BreakPoint> break_point) {
HandleScope scope(isolate_);
// TODO(kozyatinskiy): replace this if by DCHEK once the JS debug API has been
// removed.
if (break_point_object->IsBreakPoint()) {
Handle<BreakPoint> break_point =
Handle<BreakPoint>::cast(break_point_object);
if (!break_point->condition()->length()) return true;
Handle<String> condition(break_point->condition());
Handle<Object> result;
@ -592,27 +586,8 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
return result->BooleanValue();
}
// Ignore check if break point object is not a JSObject.
if (!break_point_object->IsJSObject()) return true;
// Get the break id as an object.
Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
// Call IsBreakPointTriggered.
Handle<Object> argv[] = { break_id, break_point_object };
Handle<Object> result;
if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
.ToHandle(&result)) {
return false;
}
// Return whether the break point is triggered.
return result->IsTrue(isolate_);
}
bool Debug::SetBreakPoint(Handle<JSFunction> function,
Handle<Object> break_point_object,
Handle<BreakPoint> break_point,
int* source_position) {
HandleScope scope(isolate_);
@ -626,7 +601,7 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
// Find the break point and change it.
*source_position = FindBreakablePosition(debug_info, *source_position);
DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
DebugInfo::SetBreakPoint(debug_info, *source_position, break_point);
// At least one active break point now.
DCHECK_LT(0, debug_info->GetBreakPointCount());
@ -638,13 +613,13 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
}
bool Debug::SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
Handle<BreakPoint> break_point,
int* source_position) {
if (script->type() == Script::TYPE_WASM) {
Handle<WasmCompiledModule> compiled_module(
WasmCompiledModule::cast(script->wasm_compiled_module()), isolate_);
return WasmCompiledModule::SetBreakPoint(compiled_module, source_position,
break_point_object);
break_point);
}
HandleScope scope(isolate_);
@ -674,7 +649,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
if (breakable_position < *source_position) return false;
*source_position = breakable_position;
DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
DebugInfo::SetBreakPoint(debug_info, *source_position, break_point);
// At least one active break point now.
DCHECK_LT(0, debug_info->GetBreakPointCount());
@ -731,16 +706,16 @@ void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
}
}
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
void Debug::ClearBreakPoint(Handle<BreakPoint> break_point) {
HandleScope scope(isolate_);
for (DebugInfoListNode* node = debug_info_list_; node != nullptr;
node = node->next()) {
Handle<Object> result =
DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
DebugInfo::FindBreakPointInfo(node->debug_info(), break_point);
if (result->IsUndefined(isolate_)) continue;
Handle<DebugInfo> debug_info = node->debug_info();
if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) {
if (DebugInfo::ClearBreakPoint(debug_info, break_point)) {
ClearBreakPoints(debug_info);
if (debug_info->GetBreakPointCount() == 0) {
RemoveBreakInfoAndMaybeFree(debug_info);
@ -806,25 +781,24 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) {
}
}
MaybeHandle<FixedArray> Debug::GetHitBreakPointObjects(
Handle<Object> break_point_objects) {
DCHECK(!break_point_objects->IsUndefined(isolate_));
if (!break_point_objects->IsFixedArray()) {
if (!CheckBreakPoint(break_point_objects)) return {};
MaybeHandle<FixedArray> Debug::GetHitBreakPoints(Handle<Object> break_points) {
DCHECK(!break_points->IsUndefined(isolate_));
if (!break_points->IsFixedArray()) {
if (!CheckBreakPoint(Handle<BreakPoint>::cast(break_points))) return {};
Handle<FixedArray> break_points_hit = isolate_->factory()->NewFixedArray(1);
break_points_hit->set(0, *break_point_objects);
break_points_hit->set(0, *break_points);
return break_points_hit;
}
Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
Handle<FixedArray> array(FixedArray::cast(*break_points));
int num_objects = array->length();
Handle<FixedArray> break_points_hit =
isolate_->factory()->NewFixedArray(num_objects);
int break_points_hit_count = 0;
for (int i = 0; i < num_objects; ++i) {
Handle<Object> break_point_object(array->get(i), isolate_);
if (CheckBreakPoint(break_point_object)) {
break_points_hit->set(break_points_hit_count++, *break_point_object);
Handle<Object> break_point(array->get(i), isolate_);
if (CheckBreakPoint(Handle<BreakPoint>::cast(break_point))) {
break_points_hit->set(break_points_hit_count++, *break_point);
}
}
if (break_points_hit_count == 0) return {};
@ -1567,14 +1541,6 @@ MaybeHandle<Object> Debug::MakeExecutionState() {
}
MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
// Create the new break event object.
Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
break_points_hit };
return CallFunction("MakeBreakEvent", arraysize(argv), argv);
}
MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
bool uncaught,
Handle<Object> promise) {
@ -1750,29 +1716,15 @@ void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) {
int inspector_break_points_count = 0;
// This array contains breakpoints installed using JS debug API.
for (int i = 0; i < break_points_hit->length(); ++i) {
Object* break_point = break_points_hit->get(i);
if (break_point->IsBreakPoint()) {
inspector_break_points_hit.push_back(BreakPoint::cast(break_point)->id());
BreakPoint* break_point = BreakPoint::cast(break_points_hit->get(i));
inspector_break_points_hit.push_back(break_point->id());
++inspector_break_points_count;
} else {
break_points_hit->set(i - inspector_break_points_count, break_point);
}
}
int break_points_length =
break_points_hit->length() - inspector_break_points_count;
Handle<Object> break_points;
if (break_points_length) {
break_points_hit->Shrink(break_points_length);
break_points = isolate_->factory()->NewJSArrayWithElements(
break_points_hit, PACKED_ELEMENTS, break_points_length);
} else {
break_points = isolate_->factory()->undefined_value();
}
debug_delegate_->BreakProgramRequested(
GetDebugEventContext(isolate_),
v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
v8::Utils::ToLocal(break_points), inspector_break_points_hit);
inspector_break_points_hit);
}
@ -2278,17 +2230,10 @@ void LegacyDebugDelegate::ScriptCompiled(v8::Local<v8::debug::Script> script,
void LegacyDebugDelegate::BreakProgramRequested(
v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> break_points_hit,
const std::vector<debug::BreakpointId>&) {
Handle<Object> event_data;
if (isolate_->debug()
->MakeBreakEvent(v8::Utils::OpenHandle(*break_points_hit))
.ToHandle(&event_data)) {
ProcessDebugEvent(
v8::Break, Handle<JSObject>::cast(event_data),
ProcessDebugEvent(v8::Break, isolate_->factory()->NewJSObjectWithNullProto(),
Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
}
}
void LegacyDebugDelegate::ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
@ -2314,32 +2259,6 @@ void LegacyDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
}
}
JavaScriptDebugDelegate::JavaScriptDebugDelegate(Isolate* isolate,
Handle<JSFunction> listener,
Handle<Object> data)
: LegacyDebugDelegate(isolate) {
GlobalHandles* global_handles = isolate->global_handles();
listener_ = global_handles->Create(*listener);
data_ = global_handles->Create(*data);
}
JavaScriptDebugDelegate::~JavaScriptDebugDelegate() {
GlobalHandles::Destroy(Handle<Object>::cast(listener_).location());
GlobalHandles::Destroy(data_.location());
}
void JavaScriptDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data,
Handle<JSObject> exec_state) {
AllowJavascriptExecutionDebugOnly allow_script(isolate_);
Handle<Object> argv[] = {Handle<Object>(Smi::FromInt(event), isolate_),
exec_state, event_data, data_};
Handle<JSReceiver> global = isolate_->global_proxy();
// Listener must not throw.
Execution::Call(isolate_, listener_, global, arraysize(argv), argv)
.ToHandleChecked();
}
NativeDebugDelegate::NativeDebugDelegate(Isolate* isolate,
v8::Debug::EventCallback callback,
Handle<Object> data)

View File

@ -241,12 +241,11 @@ class Debug {
// Break point handling.
bool SetBreakPoint(Handle<JSFunction> function,
Handle<Object> break_point_object,
int* source_position);
Handle<BreakPoint> break_point, int* source_position);
bool SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
Handle<BreakPoint> break_point,
int* source_position);
void ClearBreakPoint(Handle<Object> break_point_object);
void ClearBreakPoint(Handle<BreakPoint> break_point);
void ChangeBreakOnException(ExceptionBreakType type, bool enable);
bool IsBreakOnException(ExceptionBreakType type);
@ -254,12 +253,11 @@ class Debug {
int* offset, int* id);
void RemoveBreakpoint(int id);
// The parameter is either a BreakPointInfo object, or a FixedArray of
// BreakPointInfo objects.
// The parameter is either a BreakPoint object, or a FixedArray of
// BreakPoint objects.
// Returns an empty handle if no breakpoint is hit, or a FixedArray with all
// hit breakpoints.
MaybeHandle<FixedArray> GetHitBreakPointObjects(
Handle<Object> break_point_objects);
// hit BreakPoint objects.
MaybeHandle<FixedArray> GetHitBreakPoints(Handle<Object> break_points);
// Stepping handling.
void PrepareStep(StepAction step_action);
@ -437,8 +435,6 @@ class Debug {
// Constructors for debug event objects.
MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent(
Handle<Object> break_points_hit);
MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent(
Handle<Object> exception,
bool uncaught,
@ -472,7 +468,7 @@ class Debug {
BreakLocation* location,
bool* has_break_points = nullptr);
bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
bool CheckBreakPoint(Handle<Object> break_point_object);
bool CheckBreakPoint(Handle<BreakPoint> break_point);
MaybeHandle<Object> CallFunction(const char* name, int argc,
Handle<Object> args[],
bool catch_exceptions = true);
@ -604,7 +600,6 @@ class LegacyDebugDelegate : public v8::debug::DebugDelegate {
bool has_compile_error) override;
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> break_points_hit,
const std::vector<debug::BreakpointId>&) override;
void ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
@ -626,20 +621,6 @@ class LegacyDebugDelegate : public v8::debug::DebugDelegate {
Handle<JSObject> exec_state) = 0;
};
class JavaScriptDebugDelegate : public LegacyDebugDelegate {
public:
JavaScriptDebugDelegate(Isolate* isolate, Handle<JSFunction> listener,
Handle<Object> data);
virtual ~JavaScriptDebugDelegate();
private:
void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
Handle<JSObject> exec_state) override;
Handle<JSFunction> listener_;
Handle<Object> data_;
};
class NativeDebugDelegate : public LegacyDebugDelegate {
public:
NativeDebugDelegate(Isolate* isolate, v8::Debug::EventCallback callback,

View File

@ -19,16 +19,8 @@ var ValueMirror = global.ValueMirror;
//----------------------------------------------------------------------------
// Default number of frames to include in the response to backtrace request.
var kDefaultBacktraceLength = 10;
var Debug = {};
// Regular expression to skip "crud" at the beginning of a source line which is
// not really code. Currently the regular expression matches whitespace and
// comments.
var sourceLineBeginningSkip = /^(?:\s*(?:\/\*.*?\*\/)*)*/;
// Debug events which can occur in the V8 JavaScript engine. These originate
// from the API include file debug.h.
Debug.DebugEvent = { Break: 1,
@ -58,29 +50,12 @@ Debug.ScriptCompilationType = { Host: 0,
Eval: 1,
JSON: 2 };
// The different script break point types.
Debug.ScriptBreakPointType = { ScriptId: 0,
ScriptName: 1,
ScriptRegExp: 2 };
function ScriptTypeFlag(type) {
return (1 << type);
}
// Globals.
var next_response_seq = 0;
var next_break_point_number = 1;
var break_points = [];
var script_break_points = [];
var debugger_flags = {
breakPointsActive: {
value: true,
getValue: function() { return this.value; },
setValue: function(value) {
this.value = !!value;
%SetBreakPointsActive(this.value);
}
},
breakOnCaughtException: {
getValue: function() { return Debug.isBreakOnException(); },
setValue: function(value) {
@ -104,308 +79,6 @@ var debugger_flags = {
};
// Create a new break point object and add it to the list of break points.
function MakeBreakPoint(source_position, opt_script_break_point) {
var break_point = new BreakPoint(source_position, opt_script_break_point);
break_points.push(break_point);
return break_point;
}
// Object representing a break point.
// NOTE: This object does not have a reference to the function having break
// point as this would cause function not to be garbage collected when it is
// not used any more. We do not want break points to keep functions alive.
function BreakPoint(source_position, opt_script_break_point) {
this.source_position_ = source_position;
if (opt_script_break_point) {
this.script_break_point_ = opt_script_break_point;
} else {
this.number_ = next_break_point_number++;
}
this.active_ = true;
this.condition_ = null;
}
BreakPoint.prototype.number = function() {
return this.number_;
};
BreakPoint.prototype.func = function() {
return this.func_;
};
BreakPoint.prototype.source_position = function() {
return this.source_position_;
};
BreakPoint.prototype.active = function() {
if (this.script_break_point()) {
return this.script_break_point().active();
}
return this.active_;
};
BreakPoint.prototype.condition = function() {
if (this.script_break_point() && this.script_break_point().condition()) {
return this.script_break_point().condition();
}
return this.condition_;
};
BreakPoint.prototype.script_break_point = function() {
return this.script_break_point_;
};
BreakPoint.prototype.enable = function() {
this.active_ = true;
};
BreakPoint.prototype.disable = function() {
this.active_ = false;
};
BreakPoint.prototype.setCondition = function(condition) {
this.condition_ = condition;
};
BreakPoint.prototype.isTriggered = function(exec_state) {
// Break point not active - not triggered.
if (!this.active()) return false;
// Check for conditional break point.
if (this.condition()) {
// If break point has condition try to evaluate it in the top frame.
try {
var mirror = exec_state.frame(0).evaluate(this.condition());
// If no sensible mirror or non true value break point not triggered.
if (!(mirror instanceof ValueMirror) || !mirror.value_) {
return false;
}
} catch (e) {
// Exception evaluating condition counts as not triggered.
return false;
}
}
// Break point triggered.
return true;
};
// Function called from the runtime when a break point is hit. Returns true if
// the break point is triggered and supposed to break execution.
function IsBreakPointTriggered(break_id, break_point) {
return break_point.isTriggered(MakeExecutionState(break_id));
}
// Object representing a script break point. The script is referenced by its
// script name or script id and the break point is represented as line and
// column.
function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
opt_groupId) {
this.type_ = type;
if (type == Debug.ScriptBreakPointType.ScriptId) {
this.script_id_ = script_id_or_name;
} else if (type == Debug.ScriptBreakPointType.ScriptName) {
this.script_name_ = script_id_or_name;
} else if (type == Debug.ScriptBreakPointType.ScriptRegExp) {
this.script_regexp_object_ = new GlobalRegExp(script_id_or_name);
} else {
throw %make_error(kDebugger, "Unexpected breakpoint type " + type);
}
this.line_ = opt_line || 0;
this.column_ = opt_column;
this.groupId_ = opt_groupId;
this.active_ = true;
this.condition_ = null;
this.break_points_ = [];
}
ScriptBreakPoint.prototype.number = function() {
return this.number_;
};
ScriptBreakPoint.prototype.groupId = function() {
return this.groupId_;
};
ScriptBreakPoint.prototype.type = function() {
return this.type_;
};
ScriptBreakPoint.prototype.script_id = function() {
return this.script_id_;
};
ScriptBreakPoint.prototype.script_name = function() {
return this.script_name_;
};
ScriptBreakPoint.prototype.script_regexp_object = function() {
return this.script_regexp_object_;
};
ScriptBreakPoint.prototype.line = function() {
return this.line_;
};
ScriptBreakPoint.prototype.column = function() {
return this.column_;
};
ScriptBreakPoint.prototype.actual_locations = function() {
var locations = [];
for (var i = 0; i < this.break_points_.length; i++) {
locations.push(this.break_points_[i].actual_location);
}
return locations;
};
ScriptBreakPoint.prototype.update_positions = function(line, column) {
this.line_ = line;
this.column_ = column;
};
ScriptBreakPoint.prototype.active = function() {
return this.active_;
};
ScriptBreakPoint.prototype.condition = function() {
return this.condition_;
};
ScriptBreakPoint.prototype.enable = function() {
this.active_ = true;
};
ScriptBreakPoint.prototype.disable = function() {
this.active_ = false;
};
ScriptBreakPoint.prototype.setCondition = function(condition) {
this.condition_ = condition;
};
// Check whether a script matches this script break point. Currently this is
// only based on script name.
ScriptBreakPoint.prototype.matchesScript = function(script) {
if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
return this.script_id_ == script.id;
} else {
// We might want to account columns here as well.
if (!(script.line_offset <= this.line_ &&
this.line_ < script.line_offset + %ScriptLineCount(script))) {
return false;
}
if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
return this.script_name_ == script.nameOrSourceURL();
} else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
return this.script_regexp_object_.test(script.nameOrSourceURL());
} else {
throw %make_error(kDebugger, "Unexpected breakpoint type " + this.type_);
}
}
};
// Set the script break point in a script.
ScriptBreakPoint.prototype.set = function (script) {
var column = this.column();
var line = this.line();
// If the column is undefined the break is on the line. To help locate the
// first piece of breakable code on the line try to find the column on the
// line which contains some source.
if (IS_UNDEFINED(column)) {
var source_line = %ScriptSourceLine(script, line || script.line_offset);
// Allocate array for caching the columns where the actual source starts.
if (!script.sourceColumnStart_) {
script.sourceColumnStart_ = new GlobalArray(%ScriptLineCount(script));
}
// Fill cache if needed and get column where the actual source starts.
if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
script.sourceColumnStart_[line] =
source_line.match(sourceLineBeginningSkip)[0].length;
}
column = script.sourceColumnStart_[line];
}
// Convert the line and column into an absolute position within the script.
var position = Debug.findScriptSourcePosition(script, this.line(), column);
// If the position is not found in the script (the script might be shorter
// than it used to be) just ignore it.
if (IS_NULL(position)) return;
// Create a break point object and set the break point.
var break_point = MakeBreakPoint(position, this);
var actual_position = %SetScriptBreakPoint(script, position,
break_point);
if (IS_UNDEFINED(actual_position)) {
actual_position = position;
}
var actual_location = script.locationFromPosition(actual_position, true);
break_point.actual_location = { line: actual_location.line,
column: actual_location.column,
script_id: script.id };
this.break_points_.push(break_point);
return break_point;
};
// Clear all the break points created from this script break point
ScriptBreakPoint.prototype.clear = function () {
var remaining_break_points = [];
for (var i = 0; i < break_points.length; i++) {
if (break_points[i].script_break_point() &&
break_points[i].script_break_point() === this) {
%ClearBreakPoint(break_points[i]);
} else {
remaining_break_points.push(break_points[i]);
}
}
break_points = remaining_break_points;
this.break_points_ = [];
};
Debug.setListener = function(listener, opt_data) {
if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
throw %make_type_error(kDebuggerType);
}
%SetDebugEventListener(listener, opt_data);
};
// Returns a Script object. If the parameter is a function the return value
// is the script in which the function is defined. If the parameter is a string
// the return value is the script for which the script name has that string
@ -475,246 +148,6 @@ Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
return location ? location.position : null;
};
Debug.findBreakPoint = function(break_point_number, remove) {
var break_point;
for (var i = 0; i < break_points.length; i++) {
if (break_points[i].number() == break_point_number) {
break_point = break_points[i];
// Remove the break point from the list if requested.
if (remove) {
break_points.splice(i, 1);
}
break;
}
}
if (break_point) {
return break_point;
} else {
return this.findScriptBreakPoint(break_point_number, remove);
}
};
Debug.findBreakPointActualLocations = function(break_point_number) {
for (var i = 0; i < script_break_points.length; i++) {
if (script_break_points[i].number() == break_point_number) {
return script_break_points[i].actual_locations();
}
}
for (var i = 0; i < break_points.length; i++) {
if (break_points[i].number() == break_point_number) {
return [break_points[i].actual_location];
}
}
return [];
};
Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
if (!IS_FUNCTION(func)) throw %make_type_error(kDebuggerType);
// Break points in API functions are not supported.
if (%FunctionIsAPIFunction(func)) {
throw %make_error(kDebugger, 'Cannot set break point in native code.');
}
// Find source position.
var source_position =
this.findFunctionSourceLocation(func, opt_line, opt_column).position;
// Find the script for the function.
var script = %FunctionGetScript(func);
// Break in builtin JavaScript code is not supported.
if (script.type == Debug.ScriptType.Native) {
throw %make_error(kDebugger, 'Cannot set break point in native code.');
}
// If the script for the function has a name convert this to a script break
// point.
if (script && script.id) {
// Find line and column for the position in the script and set a script
// break point from that.
var location = script.locationFromPosition(source_position, false);
return this.setScriptBreakPointById(script.id,
location.line, location.column,
opt_condition);
} else {
// Set a break point directly on the function.
var break_point = MakeBreakPoint(source_position);
var actual_position =
%SetFunctionBreakPoint(func, source_position, break_point);
var actual_location = script.locationFromPosition(actual_position, true);
break_point.actual_location = { line: actual_location.line,
column: actual_location.column,
script_id: script.id };
break_point.setCondition(opt_condition);
return break_point.number();
}
};
Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
condition, enabled)
{
var break_point = MakeBreakPoint(position);
break_point.setCondition(condition);
if (!enabled) {
break_point.disable();
}
var script = scriptById(script_id);
if (script) {
break_point.actual_position = %SetScriptBreakPoint(script, position, break_point);
}
return break_point;
};
Debug.enableBreakPoint = function(break_point_number) {
var break_point = this.findBreakPoint(break_point_number, false);
// Only enable if the breakpoint hasn't been deleted:
if (break_point) {
break_point.enable();
}
};
Debug.disableBreakPoint = function(break_point_number) {
var break_point = this.findBreakPoint(break_point_number, false);
// Only enable if the breakpoint hasn't been deleted:
if (break_point) {
break_point.disable();
}
};
Debug.changeBreakPointCondition = function(break_point_number, condition) {
var break_point = this.findBreakPoint(break_point_number, false);
break_point.setCondition(condition);
};
Debug.clearBreakPoint = function(break_point_number) {
var break_point = this.findBreakPoint(break_point_number, true);
if (break_point) {
return %ClearBreakPoint(break_point);
} else {
break_point = this.findScriptBreakPoint(break_point_number, true);
if (!break_point) throw %make_error(kDebugger, 'Invalid breakpoint');
}
};
Debug.clearAllBreakPoints = function() {
for (var i = 0; i < break_points.length; i++) {
var break_point = break_points[i];
%ClearBreakPoint(break_point);
}
break_points = [];
};
Debug.disableAllBreakPoints = function() {
// Disable all user defined breakpoints:
for (var i = 1; i < next_break_point_number; i++) {
Debug.disableBreakPoint(i);
}
// Disable all exception breakpoints:
%ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
%ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
};
Debug.findScriptBreakPoint = function(break_point_number, remove) {
var script_break_point;
for (var i = 0; i < script_break_points.length; i++) {
if (script_break_points[i].number() == break_point_number) {
script_break_point = script_break_points[i];
// Remove the break point from the list if requested.
if (remove) {
script_break_point.clear();
script_break_points.splice(i,1);
}
break;
}
}
return script_break_point;
};
// Sets a breakpoint in a script identified through id or name at the
// specified source line and column within that line.
Debug.setScriptBreakPoint = function(type, script_id_or_name,
opt_line, opt_column, opt_condition,
opt_groupId) {
// Create script break point object.
var script_break_point =
new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
opt_groupId);
// Assign number to the new script break point and add it.
script_break_point.number_ = next_break_point_number++;
script_break_point.setCondition(opt_condition);
script_break_points.push(script_break_point);
// Run through all scripts to see if this script break point matches any
// loaded scripts.
var scripts = this.scripts();
for (var i = 0; i < scripts.length; i++) {
if (script_break_point.matchesScript(scripts[i])) {
script_break_point.set(scripts[i]);
}
}
return script_break_point.number();
};
Debug.setScriptBreakPointById = function(script_id,
opt_line, opt_column,
opt_condition, opt_groupId) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
script_id, opt_line, opt_column,
opt_condition, opt_groupId);
};
Debug.setScriptBreakPointByName = function(script_name,
opt_line, opt_column,
opt_condition, opt_groupId) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
script_name, opt_line, opt_column,
opt_condition, opt_groupId);
};
Debug.setScriptBreakPointByRegExp = function(script_regexp,
opt_line, opt_column,
opt_condition, opt_groupId) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptRegExp,
script_regexp, opt_line, opt_column,
opt_condition, opt_groupId);
};
Debug.enableScriptBreakPoint = function(break_point_number) {
var script_break_point = this.findScriptBreakPoint(break_point_number, false);
script_break_point.enable();
};
Debug.disableScriptBreakPoint = function(break_point_number) {
var script_break_point = this.findScriptBreakPoint(break_point_number, false);
script_break_point.disable();
};
Debug.changeScriptBreakPointCondition = function(
break_point_number, condition) {
var script_break_point = this.findScriptBreakPoint(break_point_number, false);
script_break_point.setCondition(condition);
};
Debug.scriptBreakPoints = function() {
return script_break_points;
};
Debug.clearStepping = function() {
%ClearStepping();
};
@ -743,28 +176,6 @@ Debug.isBreakOnUncaughtException = function() {
return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
};
Debug.showBreakPoints = function(f, full) {
if (!IS_FUNCTION(f)) throw %make_error(kDebuggerType);
var source = full ? this.scriptSource(f) : this.source(f);
var offset = full ? 0 : this.sourcePosition(f);
var locations = %GetBreakLocations(f);
if (!locations) return source;
locations.sort(function(x, y) { return x - y; });
var result = "";
var prev_pos = 0;
var pos;
for (var i = 0; i < locations.length; i++) {
pos = locations[i] - offset;
result += source.slice(prev_pos, pos);
result += "[B" + i + "]";
prev_pos = pos;
}
pos = source.length;
result += source.substring(prev_pos, pos);
return result;
};
// Get all the scripts currently loaded. Locating all the scripts is based on
// scanning the heap.
Debug.scripts = function() {
@ -837,46 +248,6 @@ ExecutionState.prototype.selectedFrame = function() {
return this.selected_frame;
};
function MakeBreakEvent(break_id, break_points_hit) {
return new BreakEvent(break_id, break_points_hit);
}
function BreakEvent(break_id, break_points_hit) {
this.frame_ = new FrameMirror(break_id, 0);
this.break_points_hit_ = break_points_hit;
}
BreakEvent.prototype.eventType = function() {
return Debug.DebugEvent.Break;
};
BreakEvent.prototype.func = function() {
return this.frame_.func();
};
BreakEvent.prototype.sourceLine = function() {
return this.frame_.sourceLine();
};
BreakEvent.prototype.sourceColumn = function() {
return this.frame_.sourceColumn();
};
BreakEvent.prototype.sourceLineText = function() {
return this.frame_.sourceLineText();
};
BreakEvent.prototype.breakPointsHit = function() {
return this.break_points_hit_;
};
function MakeExceptionEvent(break_id, exception, uncaught, promise) {
return new ExceptionEvent(break_id, exception, uncaught, promise);
@ -994,19 +365,15 @@ AsyncTaskEvent.prototype.id = function() {
utils.InstallConstants(global, [
"Debug", Debug,
"BreakEvent", BreakEvent,
"CompileEvent", CompileEvent,
"BreakPoint", BreakPoint,
]);
// Functions needed by the debugger runtime.
utils.InstallConstants(utils, [
"MakeExecutionState", MakeExecutionState,
"MakeExceptionEvent", MakeExceptionEvent,
"MakeBreakEvent", MakeBreakEvent,
"MakeCompileEvent", MakeCompileEvent,
"MakeAsyncTaskEvent", MakeAsyncTaskEvent,
"IsBreakPointTriggered", IsBreakPointTriggered,
]);
})

View File

@ -2717,7 +2717,7 @@ Handle<BreakPointInfo> Factory::NewBreakPointInfo(int source_position) {
Handle<BreakPointInfo> new_break_point_info =
Handle<BreakPointInfo>::cast(NewStruct(TUPLE2_TYPE, TENURED));
new_break_point_info->set_source_position(source_position);
new_break_point_info->set_break_point_objects(*undefined_value());
new_break_point_info->set_break_points(*undefined_value());
return new_break_point_info;
}

View File

@ -494,7 +494,6 @@ void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script,
void V8Debugger::BreakProgramRequested(
v8::Local<v8::Context> pausedContext, v8::Local<v8::Object>,
v8::Local<v8::Value>,
const std::vector<v8::debug::BreakpointId>& break_points_hit) {
handleProgramBreak(pausedContext, v8::Local<v8::Value>(), break_points_hit);
}

View File

@ -169,7 +169,6 @@ class V8Debugger : public v8::debug::DebugDelegate {
bool has_compile_error) override;
void BreakProgramRequested(
v8::Local<v8::Context> paused_context, v8::Local<v8::Object>,
v8::Local<v8::Value>,
const std::vector<v8::debug::BreakpointId>& break_points_hit) override;
void ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object>, v8::Local<v8::Value> exception,

View File

@ -28,7 +28,7 @@ ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateOffset)
ACCESSORS(DebugInfo, coverage_info, Object, kCoverageInfoOffset)
SMI_ACCESSORS(BreakPointInfo, source_position, kSourcePositionOffset)
ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsOffset)
ACCESSORS(BreakPointInfo, break_points, Object, kBreakPointsOffset)
SMI_ACCESSORS(BreakPoint, id, kIdOffset)
ACCESSORS(BreakPoint, condition, String, kConditionOffset)

View File

@ -76,7 +76,7 @@ Object* DebugInfo::GetBreakPointInfo(int source_position) {
}
bool DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
Handle<Object> break_point_object) {
Handle<BreakPoint> break_point) {
DCHECK(debug_info->HasBreakInfo());
Isolate* isolate = debug_info->GetIsolate();
@ -84,9 +84,8 @@ bool DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
if (BreakPointInfo::HasBreakPointObject(break_point_info,
break_point_object)) {
BreakPointInfo::ClearBreakPoint(break_point_info, break_point_object);
if (BreakPointInfo::HasBreakPoint(break_point_info, break_point)) {
BreakPointInfo::ClearBreakPoint(break_point_info, break_point);
return true;
}
}
@ -94,14 +93,14 @@ bool DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
}
void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
Handle<Object> break_point_object) {
Handle<BreakPoint> break_point) {
DCHECK(debug_info->HasBreakInfo());
Isolate* isolate = debug_info->GetIsolate();
Handle<Object> break_point_info(
debug_info->GetBreakPointInfo(source_position), isolate);
if (!break_point_info->IsUndefined(isolate)) {
BreakPointInfo::SetBreakPoint(
Handle<BreakPointInfo>::cast(break_point_info), break_point_object);
Handle<BreakPointInfo>::cast(break_point_info), break_point);
return;
}
@ -117,8 +116,8 @@ void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
}
if (index == kNoBreakPointInfo) {
// No free slot - extend break point info array.
Handle<FixedArray> old_break_points = Handle<FixedArray>(
FixedArray::cast(debug_info->break_points()), isolate);
Handle<FixedArray> old_break_points =
Handle<FixedArray>(debug_info->break_points(), isolate);
Handle<FixedArray> new_break_points = isolate->factory()->NewFixedArray(
old_break_points->length() +
DebugInfo::kEstimatedNofBreakPointsInFunction);
@ -134,20 +133,20 @@ void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
// Allocate new BreakPointInfo object and set the break point.
Handle<BreakPointInfo> new_break_point_info =
isolate->factory()->NewBreakPointInfo(source_position);
BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
BreakPointInfo::SetBreakPoint(new_break_point_info, break_point);
debug_info->break_points()->set(index, *new_break_point_info);
}
// Get the break point objects for a source position.
Handle<Object> DebugInfo::GetBreakPointObjects(int source_position) {
Handle<Object> DebugInfo::GetBreakPoints(int source_position) {
DCHECK(HasBreakInfo());
Object* break_point_info = GetBreakPointInfo(source_position);
Isolate* isolate = GetIsolate();
if (break_point_info->IsUndefined(isolate)) {
return isolate->factory()->undefined_value();
}
return Handle<Object>(
BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate);
return Handle<Object>(BreakPointInfo::cast(break_point_info)->break_points(),
isolate);
}
// Get the total number of break points.
@ -165,16 +164,15 @@ int DebugInfo::GetBreakPointCount() {
return count;
}
Handle<Object> DebugInfo::FindBreakPointInfo(
Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
Handle<Object> DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
Handle<BreakPoint> break_point) {
DCHECK(debug_info->HasBreakInfo());
Isolate* isolate = debug_info->GetIsolate();
for (int i = 0; i < debug_info->break_points()->length(); i++) {
if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
if (BreakPointInfo::HasBreakPointObject(break_point_info,
break_point_object)) {
if (BreakPointInfo::HasBreakPoint(break_point_info, break_point)) {
return break_point_info;
}
}
@ -199,40 +197,34 @@ bool DebugInfo::ClearCoverageInfo() {
}
namespace {
bool IsEqual(Object* break_point1, Object* break_point2) {
// TODO(kozyatinskiy): remove non-BreakPoint logic once the JS debug API has
// been removed.
if (break_point1->IsBreakPoint() != break_point2->IsBreakPoint())
return false;
if (!break_point1->IsBreakPoint()) return break_point1 == break_point2;
return BreakPoint::cast(break_point1)->id() ==
BreakPoint::cast(break_point2)->id();
bool IsEqual(BreakPoint* break_point1, BreakPoint* break_point2) {
return break_point1->id() == break_point2->id();
}
} // namespace
// Remove the specified break point object.
void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
Handle<Object> break_point_object) {
Handle<BreakPoint> break_point) {
Isolate* isolate = break_point_info->GetIsolate();
// If there are no break points just ignore.
if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
if (break_point_info->break_points()->IsUndefined(isolate)) return;
// If there is a single break point clear it if it is the same.
if (!break_point_info->break_point_objects()->IsFixedArray()) {
if (IsEqual(break_point_info->break_point_objects(), *break_point_object)) {
break_point_info->set_break_point_objects(
isolate->heap()->undefined_value());
if (!break_point_info->break_points()->IsFixedArray()) {
if (IsEqual(BreakPoint::cast(break_point_info->break_points()),
*break_point)) {
break_point_info->set_break_points(isolate->heap()->undefined_value());
}
return;
}
// If there are multiple break points shrink the array
DCHECK(break_point_info->break_point_objects()->IsFixedArray());
Handle<FixedArray> old_array = Handle<FixedArray>(
FixedArray::cast(break_point_info->break_point_objects()));
DCHECK(break_point_info->break_points()->IsFixedArray());
Handle<FixedArray> old_array =
Handle<FixedArray>(FixedArray::cast(break_point_info->break_points()));
Handle<FixedArray> new_array =
isolate->factory()->NewFixedArray(old_array->length() - 1);
int found_count = 0;
for (int i = 0; i < old_array->length(); i++) {
if (IsEqual(old_array->get(i), *break_point_object)) {
if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) {
DCHECK_EQ(found_count, 0);
found_count++;
} else {
@ -240,61 +232,60 @@ void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
}
}
// If the break point was found in the list change it.
if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
if (found_count > 0) break_point_info->set_break_points(*new_array);
}
// Add the specified break point object.
void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
Handle<Object> break_point_object) {
Handle<BreakPoint> break_point) {
Isolate* isolate = break_point_info->GetIsolate();
// If there was no break point objects before just set it.
if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
break_point_info->set_break_point_objects(*break_point_object);
if (break_point_info->break_points()->IsUndefined(isolate)) {
break_point_info->set_break_points(*break_point);
return;
}
// If the break point object is the same as before just ignore.
if (break_point_info->break_point_objects() == *break_point_object) return;
if (break_point_info->break_points() == *break_point) return;
// If there was one break point object before replace with array.
if (!break_point_info->break_point_objects()->IsFixedArray()) {
if (!break_point_info->break_points()->IsFixedArray()) {
Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
array->set(0, break_point_info->break_point_objects());
array->set(1, *break_point_object);
break_point_info->set_break_point_objects(*array);
array->set(0, break_point_info->break_points());
array->set(1, *break_point);
break_point_info->set_break_points(*array);
return;
}
// If there was more than one break point before extend array.
Handle<FixedArray> old_array = Handle<FixedArray>(
FixedArray::cast(break_point_info->break_point_objects()));
Handle<FixedArray> old_array =
Handle<FixedArray>(FixedArray::cast(break_point_info->break_points()));
Handle<FixedArray> new_array =
isolate->factory()->NewFixedArray(old_array->length() + 1);
for (int i = 0; i < old_array->length(); i++) {
// If the break point was there before just ignore.
if (IsEqual(old_array->get(i), *break_point_object)) return;
if (IsEqual(BreakPoint::cast(old_array->get(i)), *break_point)) return;
new_array->set(i, old_array->get(i));
}
// Add the new break point.
new_array->set(old_array->length(), *break_point_object);
break_point_info->set_break_point_objects(*new_array);
new_array->set(old_array->length(), *break_point);
break_point_info->set_break_points(*new_array);
}
bool BreakPointInfo::HasBreakPointObject(
Handle<BreakPointInfo> break_point_info,
Handle<Object> break_point_object) {
bool BreakPointInfo::HasBreakPoint(Handle<BreakPointInfo> break_point_info,
Handle<BreakPoint> break_point) {
// No break point.
Isolate* isolate = break_point_info->GetIsolate();
if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
if (break_point_info->break_points()->IsUndefined(isolate)) {
return false;
}
// Single break point.
if (!break_point_info->break_point_objects()->IsFixedArray()) {
return IsEqual(break_point_info->break_point_objects(),
*break_point_object);
if (!break_point_info->break_points()->IsFixedArray()) {
return IsEqual(BreakPoint::cast(break_point_info->break_points()),
*break_point);
}
// Multiple break points.
FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
FixedArray* array = FixedArray::cast(break_point_info->break_points());
for (int i = 0; i < array->length(); i++) {
if (IsEqual(array->get(i), *break_point_object)) {
if (IsEqual(BreakPoint::cast(array->get(i)), *break_point)) {
return true;
}
}
@ -304,11 +295,11 @@ bool BreakPointInfo::HasBreakPointObject(
// Get the number of break points.
int BreakPointInfo::GetBreakPointCount() {
// No break point.
if (break_point_objects()->IsUndefined(GetIsolate())) return 0;
if (break_points()->IsUndefined(GetIsolate())) return 0;
// Single break point.
if (!break_point_objects()->IsFixedArray()) return 1;
if (!break_points()->IsFixedArray()) return 1;
// Multiple break points.
return FixedArray::cast(break_point_objects())->length();
return FixedArray::cast(break_points())->length();
}
int CoverageInfo::SlotCount() const {

View File

@ -14,6 +14,7 @@
namespace v8 {
namespace internal {
class BreakPoint;
class BytecodeArray;
// The DebugInfo class holds additional information for a function being
@ -69,15 +70,15 @@ class DebugInfo : public Struct {
bool HasBreakPoint(int source_position);
// Attempt to clear a break point. Return true if successful.
static bool ClearBreakPoint(Handle<DebugInfo> debug_info,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
// Set a break point.
static void SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
// Get the break point objects for a source position.
Handle<Object> GetBreakPointObjects(int source_position);
Handle<Object> GetBreakPoints(int source_position);
// Find the break point info holding this break point object.
static Handle<Object> FindBreakPointInfo(Handle<DebugInfo> debug_info,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
// Get the number of break points for this function.
int GetBreakPointCount();
@ -134,17 +135,17 @@ class BreakPointInfo : public Tuple2 {
// The position in the source for the break position.
DECL_INT_ACCESSORS(source_position)
// List of related JavaScript break points.
DECL_ACCESSORS(break_point_objects, Object)
DECL_ACCESSORS(break_points, Object)
// Removes a break point.
static void ClearBreakPoint(Handle<BreakPointInfo> info,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
// Set a break point.
static void SetBreakPoint(Handle<BreakPointInfo> info,
Handle<Object> break_point_object);
// Check if break point info has this break point object.
static bool HasBreakPointObject(Handle<BreakPointInfo> info,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
// Check if break point info has this break point.
static bool HasBreakPoint(Handle<BreakPointInfo> info,
Handle<BreakPoint> break_point);
// Get the number of break points for this code offset.
int GetBreakPointCount();
@ -153,7 +154,7 @@ class BreakPointInfo : public Tuple2 {
DECL_CAST(BreakPointInfo)
static const int kSourcePositionOffset = kValue1Offset;
static const int kBreakPointObjectsOffset = kValue2Offset;
static const int kBreakPointsOffset = kValue2Offset;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);

View File

@ -85,27 +85,6 @@ RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
}
// Adds a JavaScript function as a debug event listener.
// args[0]: debug event listener function to set or null or undefined for
// clearing the event listener function
// args[1]: object supplied during callback
RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
CHECK(args[0]->IsJSFunction() || args[0]->IsNullOrUndefined(isolate));
CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
if (callback->IsJSFunction()) {
JavaScriptDebugDelegate* delegate = new JavaScriptDebugDelegate(
isolate, Handle<JSFunction>::cast(callback), data);
isolate->debug()->SetDebugDelegate(delegate, true);
} else {
isolate->debug()->SetDebugDelegate(nullptr, false);
}
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
@ -1041,16 +1020,6 @@ RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
return isolate->heap()->ToBoolean(res);
}
// Sets the disable break state
// args[0]: disable break state
RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
isolate->debug()->set_break_points_active(active);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
HandleScope scope(isolate);
@ -1070,71 +1039,6 @@ RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
}
// Set a break point in a function.
// args[0]: function
// args[1]: number: break source position (within the function source)
// args[2]: number: break point object
RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CHECK(isolate->debug()->is_active());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
CHECK(source_position >= function->shared()->start_position() &&
source_position <= function->shared()->end_position());
CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
// Set break point.
CHECK(isolate->debug()->SetBreakPoint(function, break_point_object_arg,
&source_position));
return Smi::FromInt(source_position);
}
// Changes the state of a break point in a script and returns source position
// where break point was set. NOTE: Regarding performance see the NOTE for
// GetScriptFromScriptData.
// args[0]: script to set break point in
// args[1]: number: break source position (within the script source)
// args[2]: number: break point object
RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CHECK(isolate->debug()->is_active());
CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
CHECK_GE(source_position, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
// Get the script from the script wrapper.
CHECK(wrapper->value()->IsScript());
Handle<Script> script(Script::cast(wrapper->value()));
// Set break point.
if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
&source_position)) {
return isolate->heap()->undefined_value();
}
return Smi::FromInt(source_position);
}
// Clear a break point
// args[0]: number: break point object
RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CHECK(isolate->debug()->is_active());
CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
// Clear break point.
isolate->debug()->ClearBreakPoint(break_point_object_arg);
return isolate->heap()->undefined_value();
}
// Change the state of break on exceptions.
// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
// args[1]: Boolean indicating on/off.
@ -1720,44 +1624,6 @@ RUNTIME_FUNCTION(Runtime_ScriptPositionInfo2) {
return *GetJSPositionInfo(script, position, offset_flag, isolate);
}
// Returns the given line as a string, or null if line is out of bounds.
// The parameter line is expected to include the script's line offset.
// TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(JSValue, script, 0);
CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
CHECK(script->value()->IsScript());
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
if (script_handle->type() == Script::TYPE_WASM) {
// Return null for now; this function will disappear soon anyway.
return isolate->heap()->null_value();
}
Script::InitLineEnds(script_handle);
FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
const int line_count = line_ends_array->length();
line -= script_handle->line_offset();
if (line < 0 || line_count <= line) {
return isolate->heap()->null_value();
}
const int start =
(line == 0) ? 0 : Smi::ToInt(line_ends_array->get(line - 1)) + 1;
const int end = Smi::ToInt(line_ends_array->get(line));
Handle<String> source =
handle(String::cast(script_handle->source()), isolate);
Handle<String> str = isolate->factory()->NewSubString(source, start, end);
return *str;
}
// On function call, depending on circumstances, prepare for stepping in,
// or perform a side effect check.
RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {

View File

@ -128,7 +128,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_DEBUG(F) \
F(HandleDebuggerStatement, 0, 1) \
F(SetDebugEventListener, 2, 1) \
F(ScheduleBreak, 0, 1) \
F(DebugGetInternalProperties, 1, 1) \
F(DebugGetPropertyDetails, 2, 1) \
@ -146,11 +145,7 @@ namespace internal {
F(GetGeneratorScopeCount, 1, 1) \
F(GetGeneratorScopeDetails, 2, 1) \
F(SetScopeVariableValue, 6, 1) \
F(SetBreakPointsActive, 1, 1) \
F(GetBreakLocations, 1, 1) \
F(SetFunctionBreakPoint, 3, 1) \
F(SetScriptBreakPoint, 3, 1) \
F(ClearBreakPoint, 1, 1) \
F(ChangeBreakOnException, 2, 1) \
F(IsBreakOnException, 1, 1) \
F(PrepareStep, 2, 1) \
@ -173,7 +168,6 @@ namespace internal {
F(ScriptLocationFromLine2, 4, 1) \
F(ScriptPositionInfo, 3, 1) \
F(ScriptPositionInfo2, 3, 1) \
F(ScriptSourceLine, 2, 1) \
F(DebugOnFunctionCall, 1, 1) \
F(DebugPrepareStepInSuspendedGenerator, 0, 1) \
F(DebugPushPromise, 1, 1) \

View File

@ -1049,7 +1049,7 @@ int FindBreakpointInfoInsertPos(Isolate* isolate,
void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
int position,
Handle<Object> break_point_object) {
Handle<BreakPoint> break_point) {
Isolate* isolate = shared->GetIsolate();
Handle<FixedArray> breakpoint_infos;
if (shared->has_breakpoint_infos()) {
@ -1069,7 +1069,7 @@ void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
position) {
Handle<BreakPointInfo> old_info(
BreakPointInfo::cast(breakpoint_infos->get(insert_pos)), isolate);
BreakPointInfo::SetBreakPoint(old_info, break_point_object);
BreakPointInfo::SetBreakPoint(old_info, break_point);
return;
}
@ -1096,7 +1096,7 @@ void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
// Generate new BreakpointInfo.
Handle<BreakPointInfo> breakpoint_info =
isolate->factory()->NewBreakPointInfo(position);
BreakPointInfo::SetBreakPoint(breakpoint_info, break_point_object);
BreakPointInfo::SetBreakPoint(breakpoint_info, break_point);
// Now insert new position at insert_pos.
new_breakpoint_infos->set(insert_pos, *breakpoint_info);
@ -1368,9 +1368,8 @@ MaybeHandle<FixedArray> WasmSharedModuleData::CheckBreakPoints(
Handle<BreakPointInfo>::cast(maybe_breakpoint_info);
if (breakpoint_info->source_position() != position) return {};
Handle<Object> breakpoint_objects(breakpoint_info->break_point_objects(),
isolate);
return isolate->debug()->GetHitBreakPointObjects(breakpoint_objects);
Handle<Object> break_points(breakpoint_info->break_points(), isolate);
return isolate->debug()->GetHitBreakPoints(break_points);
}
Handle<WasmCompiledModule> WasmCompiledModule::New(
@ -1809,10 +1808,9 @@ bool WasmSharedModuleData::GetPositionInfo(uint32_t position,
return true;
}
bool WasmCompiledModule::SetBreakPoint(
Handle<WasmCompiledModule> compiled_module, int* position,
Handle<Object> break_point_object) {
Handle<BreakPoint> break_point) {
Isolate* isolate = compiled_module->GetIsolate();
Handle<WasmSharedModuleData> shared(compiled_module->shared(), isolate);
@ -1827,7 +1825,7 @@ bool WasmCompiledModule::SetBreakPoint(
DCHECK(IsBreakablePosition(*shared, func_index, offset_in_func));
// Insert new break point into break_positions of shared module data.
WasmSharedModuleData::AddBreakpoint(shared, *position, break_point_object);
WasmSharedModuleData::AddBreakpoint(shared, *position, break_point);
// Iterate over all instances of this module and tell them to set this new
// breakpoint.

View File

@ -337,7 +337,7 @@ class WasmSharedModuleData : public FixedArray {
Handle<WasmSharedModuleData>);
static void AddBreakpoint(Handle<WasmSharedModuleData>, int position,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
static void SetBreakpointsOnNewInstance(Handle<WasmSharedModuleData>,
Handle<WasmInstanceObject>);
@ -569,7 +569,7 @@ class WasmCompiledModule : public FixedArray {
// If it points outside a function, or behind the last breakable location,
// this function returns false and does not set any breakpoint.
static bool SetBreakPoint(Handle<WasmCompiledModule>, int* position,
Handle<Object> break_point_object);
Handle<BreakPoint> break_point);
inline void ReplaceCodeTableForTesting(
std::vector<wasm::WasmCode*>&& testing_table);

View File

@ -2971,7 +2971,6 @@ class CountBreakDebugDelegate : public v8::debug::DebugDelegate {
public:
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> break_points_hit,
const std::vector<int>&) override {
debug_break_count++;
}

File diff suppressed because it is too large Load Diff

View File

@ -88,7 +88,6 @@ class BreakHandler : public debug::DebugDelegate {
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> break_points_hit,
const std::vector<int>&) override {
printf("Break #%d\n", count_);
CHECK_GT(expected_breaks_.size(), count_);
@ -114,26 +113,6 @@ class BreakHandler : public debug::DebugDelegate {
}
};
Handle<JSObject> MakeFakeBreakpoint(Isolate* isolate, int position) {
Handle<JSObject> obj =
isolate->factory()->NewJSObject(isolate->object_function());
// Generate an "isTriggered" method that always returns true.
// This can/must be refactored once we remove remaining JS parts from the
// debugger (bug 5530).
Handle<String> source = isolate->factory()->NewStringFromStaticChars("true");
Handle<Context> context(isolate->context(), isolate);
Handle<JSFunction> triggered_fun =
Compiler::GetFunctionFromString(context, source, NO_PARSE_RESTRICTION,
kNoSourcePosition)
.ToHandleChecked();
PropertyDescriptor desc;
desc.set_value(triggered_fun);
Handle<String> name =
isolate->factory()->InternalizeUtf8String(CStrVector("isTriggered"));
CHECK(JSObject::DefineOwnProperty(isolate, obj, name, &desc, kDontThrow)
.FromMaybe(false));
return obj;
}
void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset,
int expected_set_byte_offset = -1) {
@ -143,10 +122,12 @@ void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset,
if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset;
Handle<WasmInstanceObject> instance = runner.builder().instance_object();
Handle<WasmCompiledModule> compiled_module(instance->compiled_module());
Handle<JSObject> fake_breakpoint_object =
MakeFakeBreakpoint(runner.main_isolate(), code_offset);
static int break_index = 0;
Handle<BreakPoint> break_point =
runner.main_isolate()->factory()->NewBreakPoint(
break_index++, runner.main_isolate()->factory()->empty_string());
CHECK(WasmCompiledModule::SetBreakPoint(compiled_module, &code_offset,
fake_breakpoint_object));
break_point));
int set_byte_offset = code_offset - func_offset;
CHECK_EQ(expected_set_byte_offset, set_byte_offset);
// Also set breakpoint on the debug info of the instance directly, since the
@ -212,7 +193,6 @@ class CollectValuesBreakHandler : public debug::DebugDelegate {
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> break_points_hit,
const std::vector<int>&) override {
printf("Break #%d\n", count_);
CHECK_GT(expected_values_.size(), count_);

View File

@ -5,7 +5,7 @@
// Flags: --allow-natives-syntax --cache=code
// Test that script ids are unique and we found the correct ones.
var Debug = %GetDebugContext().Debug;
var Debug = debug.Debug;
Debug.setListener(function(){});
var scripts = %DebugGetLoadedScripts();

View File

@ -1,35 +0,0 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Test that setting break point works correctly when the debugger is
// activated late, which leads to duplicate shared function infos.
(function() {
var Debug = %GetDebugContext().Debug;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
assertTrue(/foo/.test(exec_state.frame(0).sourceLineText()));
break_count++;
} catch (e) {
exception = e;
}
}
for (var i = 0; i < 3; i++) {
var foo = function() { a = 1; }
var exception = null;
var break_count = 0;
Debug.setListener(listener);
if (i < 2) Debug.setBreakPoint(foo, 0, 0);
assertTrue(/\[B\d\]a = 1/.test(Debug.showBreakPoints(foo)));
foo();
assertEquals(1, break_count);
assertNull(exception);
}
Debug.setListener(null);
})();

View File

@ -7,7 +7,7 @@
try { } catch(e) { }
try { try { } catch (e) { } } catch(e) { }
try {
var Debug = %GetDebugContext().Debug;
var Debug = debug.Debug;
Debug.setListener(function(){});
} catch(e) { }
(function() {