ScriptName: 1,
ScriptRegExp: 2 };
+// The different types of breakpoint position alignments.
+// Must match BreakPositionAlignment in debug.h.
+Debug.BreakPositionAlignment = {
+ Statement: 0,
+ BreakPosition: 1
+};
+
function ScriptTypeFlag(type) {
return (1 << type);
}
// 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) {
+ opt_groupId, opt_position_alignment) {
this.type_ = type;
if (type == Debug.ScriptBreakPointType.ScriptId) {
this.script_id_ = script_id_or_name;
this.line_ = opt_line || 0;
this.column_ = opt_column;
this.groupId_ = opt_groupId;
+ this.position_alignment_ = IS_UNDEFINED(opt_position_alignment)
+ ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
this.hit_count_ = 0;
this.active_ = true;
this.condition_ = null;
//Creates a clone of script breakpoint that is linked to another script.
ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
- other_script.id, this.line_, this.column_, this.groupId_);
+ other_script.id, this.line_, this.column_, this.groupId_,
+ this.position_alignment_);
copy.number_ = next_break_point_number++;
script_break_points.push(copy);
// Create a break point object and set the break point.
break_point = MakeBreakPoint(position, this);
break_point.setIgnoreCount(this.ignoreCount());
- var actual_position = %SetScriptBreakPoint(script, position, break_point);
+ var actual_position = %SetScriptBreakPoint(script, position,
+ this.position_alignment_,
+ break_point);
if (IS_UNDEFINED(actual_position)) {
actual_position = position;
}
%Break();
};
-Debug.breakLocations = function(f) {
+Debug.breakLocations = function(f, opt_position_aligment) {
if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
- return %GetBreakLocations(f);
+ var position_aligment = IS_UNDEFINED(opt_position_aligment)
+ ? Debug.BreakPositionAlignment.Statement : opt_position_aligment;
+ return %GetBreakLocations(f, position_aligment);
};
// Returns a Script object. If the parameter is a function the return value
Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
- condition, enabled)
+ condition, enabled,
+ opt_position_alignment)
{
break_point = MakeBreakPoint(position);
break_point.setCondition(condition);
break_point.disable();
}
var scripts = this.scripts();
+ var position_alignment = IS_UNDEFINED(opt_position_alignment)
+ ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
for (var i = 0; i < scripts.length; i++) {
if (script_id == scripts[i].id) {
break_point.actual_position = %SetScriptBreakPoint(scripts[i], position,
- break_point);
+ position_alignment, break_point);
break;
}
}
// specified source line and column within that line.
Debug.setScriptBreakPoint = function(type, script_id_or_name,
opt_line, opt_column, opt_condition,
- opt_groupId) {
+ opt_groupId, opt_position_alignment) {
// Create script break point object.
var script_break_point =
new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
- opt_groupId);
+ opt_groupId, opt_position_alignment);
// Assign number to the new script break point and add it.
script_break_point.number_ = next_break_point_number++;
Debug.setScriptBreakPointById = function(script_id,
opt_line, opt_column,
- opt_condition, opt_groupId) {
+ opt_condition, opt_groupId,
+ opt_position_alignment) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
script_id, opt_line, opt_column,
- opt_condition, opt_groupId);
+ opt_condition, opt_groupId,
+ opt_position_alignment);
};
return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
};
-Debug.showBreakPoints = function(f, full) {
+Debug.showBreakPoints = function(f, full, opt_position_alignment) {
if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
var source = full ? this.scriptSource(f) : this.source(f);
var offset = full ? this.sourcePosition(f) : 0;
- var locations = this.breakLocations(f);
+ var locations = this.breakLocations(f, opt_position_alignment);
if (!locations) return source;
locations.sort(function(x, y) { return x - y; });
var result = "";
// Find the break point closest to the supplied source position.
-void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
+void BreakLocationIterator::FindBreakLocationFromPosition(int position,
+ BreakPositionAlignment alignment) {
// Run through all break points to locate the one closest to the source
// position.
int closest_break_point = 0;
int distance = kMaxInt;
+
while (!Done()) {
+ int next_position;
+ switch (alignment) {
+ case STATEMENT_ALIGNED:
+ next_position = this->statement_position();
+ break;
+ case BREAK_POSITION_ALIGNED:
+ next_position = this->position();
+ break;
+ default:
+ UNREACHABLE();
+ next_position = this->statement_position();
+ }
// Check if this break point is closer that what was previously found.
- if (position <= statement_position() &&
- statement_position() - position < distance) {
+ if (position <= next_position && next_position - position < distance) {
closest_break_point = break_point();
- distance = statement_position() - position;
+ distance = next_position - position;
// Check whether we can't get any closer.
if (distance == 0) break;
}
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
- it.FindBreakLocationFromPosition(*source_position);
+ it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
it.SetBreakPoint(break_point_object);
*source_position = it.position();
bool Debug::SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
- int* source_position) {
+ int* source_position,
+ BreakPositionAlignment alignment) {
HandleScope scope(isolate_);
PrepareForBreakPoints();
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
- it.FindBreakLocationFromPosition(position);
+ it.FindBreakLocationFromPosition(position, alignment);
it.SetBreakPoint(break_point_object);
*source_position = it.position() + shared->start_position();
// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
- Handle<SharedFunctionInfo> shared) {
+ Handle<SharedFunctionInfo> shared,
+ BreakPositionAlignment position_alignment) {
Isolate* isolate = Isolate::Current();
Heap* heap = isolate->heap();
if (!HasDebugInfo(shared)) {
BreakPointInfo* break_point_info =
BreakPointInfo::cast(debug_info->break_points()->get(i));
if (break_point_info->GetBreakPointCount() > 0) {
- locations->set(count++, break_point_info->statement_position());
+ Smi* position;
+ switch (position_alignment) {
+ case STATEMENT_ALIGNED:
+ position = break_point_info->statement_position();
+ break;
+ case BREAK_POSITION_ALIGNED:
+ position = break_point_info->source_position();
+ break;
+ default:
+ UNREACHABLE();
+ position = break_point_info->statement_position();
+ }
+
+ locations->set(count++, position);
}
}
}
};
+// The different types of breakpoint position alignments.
+// Must match Debug.BreakPositionAlignment in debug-debugger.js
+enum BreakPositionAlignment {
+ STATEMENT_ALIGNED = 0,
+ BREAK_POSITION_ALIGNED = 1
+};
+
+
// Class for iterating through the break points in a function and changing
// them.
class BreakLocationIterator {
void Next();
void Next(int count);
void FindBreakLocationFromAddress(Address pc);
- void FindBreakLocationFromPosition(int position);
+ void FindBreakLocationFromPosition(int position,
+ BreakPositionAlignment alignment);
void Reset();
bool Done() const;
void SetBreakPoint(Handle<Object> break_point_object);
int* source_position);
bool SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
- int* source_position);
+ int* source_position,
+ BreakPositionAlignment alignment);
void ClearBreakPoint(Handle<Object> break_point_object);
void ClearAllBreakPoints();
void FloodWithOneShot(Handle<JSFunction> function);
static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
static Handle<Object> GetSourceBreakLocations(
- Handle<SharedFunctionInfo> shared);
+ Handle<SharedFunctionInfo> shared,
+ BreakPositionAlignment position_aligment);
// Getter for the debug_context.
inline Handle<Context> debug_context() { return debug_context_; }
}
+static bool IsPositionAlignmentCodeCorrect(int alignment) {
+ return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
HandleScope scope(isolate);
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
+ CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
+
+ if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
+ return isolate->ThrowIllegalOperation();
+ }
+ BreakPositionAlignment alignment =
+ static_cast<BreakPositionAlignment>(statement_aligned_code);
+
Handle<SharedFunctionInfo> shared(fun->shared());
// Find the number of break points
- Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
+ Handle<Object> break_locations =
+ Debug::GetSourceBreakLocations(shared, alignment);
if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
// Return array as JS array
return *isolate->factory()->NewJSArrayWithElements(
// 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
+// args[2]: number, breakpoint position alignment
+// args[3]: number: break point object
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
HandleScope scope(isolate);
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
RUNTIME_ASSERT(source_position >= 0);
- Handle<Object> break_point_object_arg = args.at<Object>(2);
+ CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
+ Handle<Object> break_point_object_arg = args.at<Object>(3);
+
+ if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
+ return isolate->ThrowIllegalOperation();
+ }
+ BreakPositionAlignment alignment =
+ static_cast<BreakPositionAlignment>(statement_aligned_code);
// Get the script from the script wrapper.
RUNTIME_ASSERT(wrapper->value()->IsScript());
// Set break point.
if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
- &source_position)) {
+ &source_position,
+ alignment)) {
return isolate->heap()->undefined_value();
}
F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \
F(SetDisableBreak, 1, 1) \
- F(GetBreakLocations, 1, 1) \
+ F(GetBreakLocations, 2, 1) \
F(SetFunctionBreakPoint, 3, 1) \
- F(SetScriptBreakPoint, 3, 1) \
+ F(SetScriptBreakPoint, 4, 1) \
F(ClearBreakPoint, 1, 1) \
F(ChangeBreakOnException, 2, 1) \
F(IsBreakOnException, 1, 1) \
Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
CHECK(Debug::HasDebugInfo(shared));
TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
- it1.FindBreakLocationFromPosition(position);
+ it1.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode();
if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
actual_mode = v8::internal::RelocInfo::CODE_TARGET;
CHECK(!debug->HasDebugInfo(shared));
CHECK(debug->EnsureDebugInfo(shared, fun));
TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
- it2.FindBreakLocationFromPosition(position);
+ it2.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
actual_mode = it2.it()->rinfo()->rmode();
if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
actual_mode = v8::internal::RelocInfo::CODE_TARGET;
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
-function f() {a=1;b=2};
+function f() {a=1;b=2}
function g() {
a=1;
b=2;
// Tests for setting break points by script id and position.
-function setBreakpointByPosition(f, position)
+function setBreakpointByPosition(f, position, opt_position_alignment)
{
var break_point = Debug.setBreakPointByScriptIdAndPosition(
Debug.findScript(f).id,
position + Debug.sourcePosition(f),
"",
- true);
+ true, opt_position_alignment);
return break_point.number();
}
//b=2;
//}
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
+
+// Tests for setting break points without statement aligment.
+// (This may be sensitive to compiler break position map generation).
+function h() {a=f(f2(1,2),f3())+f3();b=f3();}
+var scenario = [
+ [5, "{a[B0]=f"],
+ [6, "{a=[B0]f("],
+ [7, "{a=f([B0]f2("],
+ [16, "f2(1,2),[B0]f3()"],
+ [22, "+[B0]f3()"]
+];
+for(var i = 0; i < scenario.length; i++) {
+ bp1 = setBreakpointByPosition(h, scenario[i][0],
+ Debug.BreakPositionAlignment.BreakPosition);
+ assertTrue(Debug.showBreakPoints(h, undefined,
+ Debug.BreakPositionAlignment.BreakPosition).indexOf(scenario[i][1]) > 0);
+ Debug.clearBreakPoint(bp1);
+}
+