Commit be1eee70 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Support scope information and evaluation in optimized frames

R=svenpanne@chromium.org

BUG=v8:1140
TEST=test/mjsunit/debug-evaluate-locals-optimized.js,test/mjsunit/debug-evaluate-locals-optimized-double.js

Review URL: http://codereview.chromium.org//7343005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8633 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 86b5123d
...@@ -1250,9 +1250,9 @@ const kFrameDetailsNameIndex = 0; ...@@ -1250,9 +1250,9 @@ const kFrameDetailsNameIndex = 0;
const kFrameDetailsValueIndex = 1; const kFrameDetailsValueIndex = 1;
const kFrameDetailsNameValueSize = 2; const kFrameDetailsNameValueSize = 2;
const kFrameDetailsFlagDebuggerFrame = 1; const kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
const kFrameDetailsFlagOptimizedFrame = 2; const kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
const kFrameDetailsFlagInlinedFrame = 4; const kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
/** /**
* Wrapper for the frame details information retreived from the VM. The frame * Wrapper for the frame details information retreived from the VM. The frame
...@@ -1266,7 +1266,7 @@ const kFrameDetailsFlagInlinedFrame = 4; ...@@ -1266,7 +1266,7 @@ const kFrameDetailsFlagInlinedFrame = 4;
* 5: Source position * 5: Source position
* 6: Construct call * 6: Construct call
* 7: Is at return * 7: Is at return
* 8: Flags (debugger frame, optimized frame, inlined frame) * 8: Flags (debugger frame, optimized frame, inlined frame index)
* Arguments name, value * Arguments name, value
* Locals name, value * Locals name, value
* Return value if any * Return value if any
...@@ -1312,22 +1312,27 @@ FrameDetails.prototype.isAtReturn = function() { ...@@ -1312,22 +1312,27 @@ FrameDetails.prototype.isAtReturn = function() {
FrameDetails.prototype.isDebuggerFrame = function() { FrameDetails.prototype.isDebuggerFrame = function() {
%CheckExecutionState(this.break_id_); %CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagDebuggerFrame; var f = kFrameDetailsFlagDebuggerFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f; return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
} }
FrameDetails.prototype.isOptimizedFrame = function() { FrameDetails.prototype.isOptimizedFrame = function() {
%CheckExecutionState(this.break_id_); %CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagOptimizedFrame; var f = kFrameDetailsFlagOptimizedFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f; return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
} }
FrameDetails.prototype.isInlinedFrame = function() { FrameDetails.prototype.isInlinedFrame = function() {
return this.inlinedFrameIndex() > 0;
}
FrameDetails.prototype.inlinedFrameIndex = function() {
%CheckExecutionState(this.break_id_); %CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagInlinedFrame; var f = kFrameDetailsFlagInlinedFrameIndexMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f; return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2
} }
...@@ -1476,6 +1481,11 @@ FrameMirror.prototype.isInlinedFrame = function() { ...@@ -1476,6 +1481,11 @@ FrameMirror.prototype.isInlinedFrame = function() {
}; };
FrameMirror.prototype.inlinedFrameIndex = function() {
return this.details_.inlinedFrameIndex();
};
FrameMirror.prototype.argumentCount = function() { FrameMirror.prototype.argumentCount = function() {
return this.details_.argumentCount(); return this.details_.argumentCount();
}; };
...@@ -1565,8 +1575,12 @@ FrameMirror.prototype.scope = function(index) { ...@@ -1565,8 +1575,12 @@ FrameMirror.prototype.scope = function(index) {
FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) { FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
var result = %DebugEvaluate(this.break_id_, this.details_.frameId(), var result = %DebugEvaluate(this.break_id_,
source, Boolean(disable_break), opt_context_object); this.details_.frameId(),
this.details_.inlinedFrameIndex(),
source,
Boolean(disable_break),
opt_context_object);
return MakeMirror(result); return MakeMirror(result);
}; };
...@@ -1719,6 +1733,7 @@ function ScopeDetails(frame, index) { ...@@ -1719,6 +1733,7 @@ function ScopeDetails(frame, index) {
this.break_id_ = frame.break_id_; this.break_id_ = frame.break_id_;
this.details_ = %GetScopeDetails(frame.break_id_, this.details_ = %GetScopeDetails(frame.break_id_,
frame.details_.frameId(), frame.details_.frameId(),
frame.details_.inlinedFrameIndex(),
index); index);
} }
......
This diff is collapsed.
...@@ -372,7 +372,7 @@ namespace internal { ...@@ -372,7 +372,7 @@ namespace internal {
F(GetFrameCount, 1, 1) \ F(GetFrameCount, 1, 1) \
F(GetFrameDetails, 2, 1) \ F(GetFrameDetails, 2, 1) \
F(GetScopeCount, 2, 1) \ F(GetScopeCount, 2, 1) \
F(GetScopeDetails, 3, 1) \ F(GetScopeDetails, 4, 1) \
F(DebugPrintScopes, 0, 1) \ F(DebugPrintScopes, 0, 1) \
F(GetThreadCount, 1, 1) \ F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \ F(GetThreadDetails, 2, 1) \
...@@ -385,7 +385,7 @@ namespace internal { ...@@ -385,7 +385,7 @@ namespace internal {
F(IsBreakOnException, 1, 1) \ F(IsBreakOnException, 1, 1) \
F(PrepareStep, 3, 1) \ F(PrepareStep, 3, 1) \
F(ClearStepping, 0, 1) \ F(ClearStepping, 0, 1) \
F(DebugEvaluate, 5, 1) \ F(DebugEvaluate, 6, 1) \
F(DebugEvaluateGlobal, 4, 1) \ F(DebugEvaluateGlobal, 4, 1) \
F(DebugGetLoadedScripts, 0, 1) \ F(DebugGetLoadedScripts, 0, 1) \
F(DebugReferencedBy, 3, 1) \ F(DebugReferencedBy, 3, 1) \
......
...@@ -44,21 +44,44 @@ function listener(event, exec_state, event_data, data) { ...@@ -44,21 +44,44 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) { for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i); var frame = exec_state.frame(i);
if (i < exec_state.frameCount() - 1) { if (i < exec_state.frameCount() - 1) {
var expected_a = i * 2 + 1 + (i * 2 + 1) / 100;
var expected_b = i * 2 + 2 + (i * 2 + 2) / 100;
var expected_x = (i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100;
var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100;
// All frames except the bottom one has normal variables a and b. // All frames except the bottom one has normal variables a and b.
assertEquals('a', frame.localName(0)); assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1)); assertEquals('b', frame.localName(1));
assertEquals(i * 2 + 1 + (i * 2 + 1) / 100, assertEquals(expected_a, frame.localValue(0).value());
frame.localValue(0).value()); assertEquals(expected_b, frame.localValue(1).value());
assertEquals(i * 2 + 2 + (i * 2 + 2) / 100,
frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y. // All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0)); assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1)); assertEquals('y', frame.argumentName(1));
assertEquals((i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100, assertEquals(expected_x, frame.argumentValue(0).value());
frame.argumentValue(0).value()); assertEquals(expected_y, frame.argumentValue(1).value());
assertEquals((i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100,
frame.argumentValue(1).value()); // All frames except the bottom one have two scopes.
assertEquals(2, frame.scopeCount());
assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']);
assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']);
assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']);
// Evaluate in the inlined frame.
assertEquals(expected_a, frame.evaluate('a').value());
assertEquals(expected_x, frame.evaluate('x').value());
assertEquals(expected_x, frame.evaluate('arguments[0]').value());
assertEquals(expected_a + expected_b + expected_x + expected_y,
frame.evaluate('a + b + x + y').value());
assertEquals(expected_x + expected_y,
frame.evaluate('arguments[0] + arguments[1]').value());
} else {
// The bottom frame only have the global scope.
assertEquals(1, frame.scopeCount());
assertEquals(debug.ScopeType.Global, frame.scope(0).scopeType());
} }
// Check the frame function. // Check the frame function.
...@@ -75,12 +98,13 @@ function listener(event, exec_state, event_data, data) { ...@@ -75,12 +98,13 @@ function listener(event, exec_state, event_data, data) {
// Check for construct call. // Check for construct call.
assertEquals(testingConstructCall && i == 4, frame.isConstructCall()); assertEquals(testingConstructCall && i == 4, frame.isConstructCall());
// When function f is optimized (2 means YES, see runtime.cc) we // When function f is optimized (1 means YES, see runtime.cc) we
// expect an optimized frame for f with g1, g2 and g3 inlined. // expect an optimized frame for f with g1, g2 and g3 inlined.
if (%GetOptimizationStatus(f) == 2) { if (%GetOptimizationStatus(f) == 1) {
if (i == 1 || i == 2 || i == 3) { if (i == 1 || i == 2 || i == 3) {
assertTrue(frame.isOptimizedFrame()); assertTrue(frame.isOptimizedFrame());
assertTrue(frame.isInlinedFrame()); assertTrue(frame.isInlinedFrame());
assertEquals(4 - i, frame.inlinedFrameIndex());
} else if (i == 4) { } else if (i == 4) {
assertTrue(frame.isOptimizedFrame()); assertTrue(frame.isOptimizedFrame());
assertFalse(frame.isInlinedFrame()); assertFalse(frame.isInlinedFrame());
......
...@@ -44,17 +44,44 @@ function listener(event, exec_state, event_data, data) { ...@@ -44,17 +44,44 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) { for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i); var frame = exec_state.frame(i);
if (i < exec_state.frameCount() - 1) { if (i < exec_state.frameCount() - 1) {
var expected_a = i * 2 + 1;
var expected_b = i * 2 + 2;
var expected_x = (i + 1) * 2 + 1;
var expected_y = (i + 1) * 2 + 2;
// All frames except the bottom one has normal variables a and b. // All frames except the bottom one has normal variables a and b.
assertEquals('a', frame.localName(0)); assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1)); assertEquals('b', frame.localName(1));
assertEquals(i * 2 + 1, frame.localValue(0).value()); assertEquals(expected_a, frame.localValue(0).value());
assertEquals(i * 2 + 2, frame.localValue(1).value()); assertEquals(expected_b, frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y. // All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0)); assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1)); assertEquals('y', frame.argumentName(1));
assertEquals((i + 1) * 2 + 1, frame.argumentValue(0).value()); assertEquals(expected_x, frame.argumentValue(0).value());
assertEquals((i + 1) * 2 + 2, frame.argumentValue(1).value()); assertEquals(expected_y, frame.argumentValue(1).value());
// All frames except the bottom one have two scopes.
assertEquals(2, frame.scopeCount());
assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']);
assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']);
assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']);
// Evaluate in the inlined frame.
assertEquals(expected_a, frame.evaluate('a').value());
assertEquals(expected_x, frame.evaluate('x').value());
assertEquals(expected_x, frame.evaluate('arguments[0]').value());
assertEquals(expected_a + expected_b + expected_x + expected_y,
frame.evaluate('a + b + x + y').value());
assertEquals(expected_x + expected_y,
frame.evaluate('arguments[0] + arguments[1]').value());
} else {
// The bottom frame only have the global scope.
assertEquals(1, frame.scopeCount());
assertEquals(debug.ScopeType.Global, frame.scope(0).scopeType());
} }
// Check the frame function. // Check the frame function.
...@@ -71,12 +98,13 @@ function listener(event, exec_state, event_data, data) { ...@@ -71,12 +98,13 @@ function listener(event, exec_state, event_data, data) {
// Check for construct call. // Check for construct call.
assertEquals(testingConstructCall && i == 4, frame.isConstructCall()); assertEquals(testingConstructCall && i == 4, frame.isConstructCall());
// When function f is optimized (2 means YES, see runtime.cc) we // When function f is optimized (1 means YES, see runtime.cc) we
// expect an optimized frame for f with g1, g2 and g3 inlined. // expect an optimized frame for f with g1, g2 and g3 inlined.
if (%GetOptimizationStatus(f) == 2) { if (%GetOptimizationStatus(f) == 1) {
if (i == 1 || i == 2 || i == 3) { if (i == 1 || i == 2 || i == 3) {
assertTrue(frame.isOptimizedFrame()); assertTrue(frame.isOptimizedFrame());
assertTrue(frame.isInlinedFrame()); assertTrue(frame.isInlinedFrame());
assertEquals(4 - i, frame.inlinedFrameIndex());
} else if (i == 4) { } else if (i == 4) {
assertTrue(frame.isOptimizedFrame()); assertTrue(frame.isOptimizedFrame());
assertFalse(frame.isInlinedFrame()); assertFalse(frame.isInlinedFrame());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment