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;
const kFrameDetailsValueIndex = 1;
const kFrameDetailsNameValueSize = 2;
const kFrameDetailsFlagDebuggerFrame = 1;
const kFrameDetailsFlagOptimizedFrame = 2;
const kFrameDetailsFlagInlinedFrame = 4;
const kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
const kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
const kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
/**
* Wrapper for the frame details information retreived from the VM. The frame
......@@ -1266,7 +1266,7 @@ const kFrameDetailsFlagInlinedFrame = 4;
* 5: Source position
* 6: Construct call
* 7: Is at return
* 8: Flags (debugger frame, optimized frame, inlined frame)
* 8: Flags (debugger frame, optimized frame, inlined frame index)
* Arguments name, value
* Locals name, value
* Return value if any
......@@ -1312,22 +1312,27 @@ FrameDetails.prototype.isAtReturn = function() {
FrameDetails.prototype.isDebuggerFrame = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagDebuggerFrame;
var f = kFrameDetailsFlagDebuggerFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
}
FrameDetails.prototype.isOptimizedFrame = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagOptimizedFrame;
var f = kFrameDetailsFlagOptimizedFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
}
FrameDetails.prototype.isInlinedFrame = function() {
return this.inlinedFrameIndex() > 0;
}
FrameDetails.prototype.inlinedFrameIndex = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagInlinedFrame;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
var f = kFrameDetailsFlagInlinedFrameIndexMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2
}
......@@ -1476,6 +1481,11 @@ FrameMirror.prototype.isInlinedFrame = function() {
};
FrameMirror.prototype.inlinedFrameIndex = function() {
return this.details_.inlinedFrameIndex();
};
FrameMirror.prototype.argumentCount = function() {
return this.details_.argumentCount();
};
......@@ -1565,8 +1575,12 @@ FrameMirror.prototype.scope = function(index) {
FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
source, Boolean(disable_break), opt_context_object);
var result = %DebugEvaluate(this.break_id_,
this.details_.frameId(),
this.details_.inlinedFrameIndex(),
source,
Boolean(disable_break),
opt_context_object);
return MakeMirror(result);
};
......@@ -1719,6 +1733,7 @@ function ScopeDetails(frame, index) {
this.break_id_ = frame.break_id_;
this.details_ = %GetScopeDetails(frame.break_id_,
frame.details_.frameId(),
frame.details_.inlinedFrameIndex(),
index);
}
......
......@@ -9976,6 +9976,71 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
}
class FrameInspector {
public:
FrameInspector(JavaScriptFrame* frame,
int inlined_frame_index,
Isolate* isolate)
: frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
// Calculate the deoptimized frame.
if (frame->is_optimized()) {
deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
frame, inlined_frame_index, isolate);
}
has_adapted_arguments_ = frame_->has_adapted_arguments();
is_optimized_ = frame_->is_optimized();
}
~FrameInspector() {
// Get rid of the calculated deoptimized frame if any.
if (deoptimized_frame_ != NULL) {
Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
isolate_);
}
}
int GetParametersCount() {
return is_optimized_
? deoptimized_frame_->parameters_count()
: frame_->ComputeParametersCount();
}
int expression_count() { return deoptimized_frame_->expression_count(); }
Object* GetFunction() {
return is_optimized_
? deoptimized_frame_->GetFunction()
: frame_->function();
}
Object* GetParameter(int index) {
return is_optimized_
? deoptimized_frame_->GetParameter(index)
: frame_->GetParameter(index);
}
Object* GetExpression(int index) {
return is_optimized_
? deoptimized_frame_->GetExpression(index)
: frame_->GetExpression(index);
}
// To inspect all the provided arguments the frame might need to be
// replaced with the arguments frame.
void SetArgumentsFrame(JavaScriptFrame* frame) {
ASSERT(has_adapted_arguments_);
frame_ = frame;
is_optimized_ = frame_->is_optimized();
ASSERT(!is_optimized_);
}
private:
JavaScriptFrame* frame_;
DeoptimizedFrameInfo* deoptimized_frame_;
Isolate* isolate_;
bool is_optimized_;
bool has_adapted_arguments_;
DISALLOW_COPY_AND_ASSIGN(FrameInspector);
};
static const int kFrameDetailsFrameIdIndex = 0;
static const int kFrameDetailsReceiverIndex = 1;
static const int kFrameDetailsFunctionIndex = 2;
......@@ -10024,8 +10089,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
return heap->undefined_value();
}
int deoptimized_frame_index = -1; // Frame index in optimized frame.
DeoptimizedFrameInfo* deoptimized_frame = NULL;
int inlined_frame_index = 0; // Inlined frame index in optimized frame.
int count = 0;
JavaScriptFrameIterator it(isolate, id);
......@@ -10036,13 +10100,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
if (it.done()) return heap->undefined_value();
if (it.frame()->is_optimized()) {
deoptimized_frame_index =
inlined_frame_index =
it.frame()->GetInlineCount() - (index - count) - 1;
deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
it.frame(),
deoptimized_frame_index,
isolate);
}
FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
// Traverse the saved contexts chain to find the active context for the
// selected frame.
......@@ -10061,7 +10122,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Check for constructor frame. Inlined frames cannot be construct calls.
bool inlined_frame =
it.frame()->is_optimized() && deoptimized_frame_index != 0;
it.frame()->is_optimized() && inlined_frame_index != 0;
bool constructor = !inlined_frame && it.frame()->IsConstructor();
// Get scope info and read from it for local variable information.
......@@ -10083,14 +10144,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
for (; i < info.number_of_stack_slots(); ++i) {
// Use the value from the stack.
locals->set(i * 2, *info.LocalName(i));
if (it.frame()->is_optimized()) {
// Get the value from the deoptimized frame.
locals->set(i * 2 + 1,
deoptimized_frame->GetExpression(i));
} else {
// Get the value from the stack.
locals->set(i * 2 + 1, it.frame()->GetExpression(i));
}
locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
}
if (i < info.NumberOfLocals()) {
// Get the context containing declarations.
......@@ -10147,18 +10201,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same.
if (it.frame()->has_adapted_arguments()) {
it.AdvanceToArgumentsFrame();
frame_inspector.SetArgumentsFrame(it.frame());
}
// Find the number of arguments to fill. At least fill the number of
// parameters for the function and fill more if more parameters are provided.
int argument_count = info.number_of_parameters();
if (it.frame()->is_optimized()) {
ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
} else {
if (argument_count < it.frame()->ComputeParametersCount()) {
argument_count = it.frame()->ComputeParametersCount();
if (argument_count < frame_inspector.GetParametersCount()) {
argument_count = frame_inspector.GetParametersCount();
}
#ifdef DEBUG
if (it.frame()->is_optimized()) {
ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
}
#endif
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
......@@ -10170,13 +10228,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function (same as in function frame).
if (it.frame()->is_optimized()) {
// Get the function from the deoptimized frame.
details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction());
} else {
// Get the function from the stack.
details->set(kFrameDetailsFunctionIndex, it.frame()->function());
}
details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
// Add the arguments count.
details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
......@@ -10208,9 +10260,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
if (it.frame()->is_optimized()) {
flags |= 1 << 1;
if (deoptimized_frame_index > 0) {
flags |= 1 << 2;
}
flags |= inlined_frame_index << 2;
}
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
......@@ -10227,18 +10277,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
// Parameter value.
if (it.frame()->is_optimized()) {
// Get the value from the deoptimized frame.
details->set(details_index++, deoptimized_frame->GetParameter(i));
} else {
if (i < it.frame()->ComputeParametersCount()) {
// Get the value from the stack.
details->set(details_index++, it.frame()->GetParameter(i));
details->set(details_index++, frame_inspector.GetParameter(i));
} else {
details->set(details_index++, heap->undefined_value());
}
}
}
// Add locals name and value from the temporary copy from the function frame.
for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
......@@ -10268,12 +10313,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
details->set(kFrameDetailsReceiverIndex, *receiver);
// Get rid of the calculated deoptimized frame if any.
if (deoptimized_frame != NULL) {
Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame,
isolate);
}
ASSERT_EQ(details_size, details_index);
return *isolate->factory()->NewJSArrayWithElements(details);
}
......@@ -10309,12 +10348,15 @@ static bool CopyContextLocalsToScopeObject(
// Create a plain JSObject which materializes the local scope for the specified
// frame.
static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
JavaScriptFrame* frame) {
static Handle<JSObject> MaterializeLocalScope(
Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<SharedFunctionInfo> shared(function->shared());
Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
ScopeInfo<> scope_info(*serialized_scope_info);
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
// Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function.
......@@ -10327,7 +10369,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate,
SetProperty(local_scope,
scope_info.parameter_name(i),
Handle<Object>(frame->GetParameter(i), isolate),
Handle<Object>(frame_inspector.GetParameter(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
......@@ -10339,7 +10381,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate,
SetProperty(local_scope,
scope_info.stack_slot_name(i),
Handle<Object>(frame->GetExpression(i), isolate),
Handle<Object>(frame_inspector.GetExpression(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
......@@ -10459,9 +10501,12 @@ class ScopeIterator {
ScopeTypeCatch
};
ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index)
: isolate_(isolate),
frame_(frame),
inlined_frame_index_(inlined_frame_index),
function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())),
local_done_(false),
......@@ -10546,7 +10591,7 @@ class ScopeIterator {
return Handle<JSObject>(CurrentContext()->global());
case ScopeIterator::ScopeTypeLocal:
// Materialize the content of the local scope into a JSObject.
return MaterializeLocalScope(isolate_, frame_);
return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
case ScopeIterator::ScopeTypeWith:
// Return the with object.
return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
......@@ -10626,6 +10671,7 @@ class ScopeIterator {
private:
Isolate* isolate_;
JavaScriptFrame* frame_;
int inlined_frame_index_;
Handle<JSFunction> function_;
Handle<Context> context_;
bool local_done_;
......@@ -10654,7 +10700,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
// Count the visible scopes.
int n = 0;
for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
for (ScopeIterator it(isolate, frame, 0);
!it.Done();
it.Next()) {
n++;
}
......@@ -10669,14 +10717,15 @@ static const int kScopeDetailsSize = 2;
// Return an array with scope details
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: scope index
// args[2]: number: inlined frame index
// args[3]: number: scope index
//
// The array returned contains the following information:
// 0: Scope type
// 1: Scope object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
ASSERT(args.length() == 4);
// Check arguments.
Object* check;
......@@ -10685,7 +10734,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (!maybe_check->ToObject(&check)) return maybe_check;
}
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
// Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id);
......@@ -10694,7 +10744,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
// Find the requested scope.
int n = 0;
ScopeIterator it(isolate, frame);
ScopeIterator it(isolate, frame, inlined_frame_index);
for (; !it.Done() && n < index; it.Next()) {
n++;
}
......@@ -10724,7 +10774,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
// Print the scopes for the top frame.
StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
for (ScopeIterator it(isolate, frame, 0);
!it.Done();
it.Next()) {
it.DebugPrint();
}
#endif
......@@ -11117,6 +11169,7 @@ static Handle<Context> CopyWithContextChain(Isolate* isolate,
// Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index,
Handle<JSFunction> function,
Handle<SerializedScopeInfo> scope_info,
const ScopeInfo<>* sinfo,
......@@ -11128,6 +11181,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
if (sinfo->number_of_stack_slots() > 0) {
index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
if (index != -1) {
CHECK(false);
return Handle<Object>(frame->GetExpression(index), isolate);
}
}
......@@ -11140,7 +11194,9 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
}
}
const int length = frame->ComputeParametersCount();
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
int length = frame_inspector.GetParametersCount();
Handle<JSObject> arguments =
isolate->factory()->NewArgumentsObject(function, length);
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
......@@ -11148,7 +11204,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) {
array->set(i, frame->GetParameter(i), mode);
array->set(i, frame_inspector.GetParameter(i), mode);
}
arguments->set_elements(*array);
return arguments;
......@@ -11175,7 +11231,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
// Check the execution state and decode arguments frame and source to be
// evaluated.
ASSERT(args.length() == 5);
ASSERT(args.length() == 6);
Object* check_result;
{ MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args));
......@@ -11184,9 +11240,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
}
}
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_ARG_CHECKED(String, source, 2);
CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
Handle<Object> additional_context(args[4]);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
CONVERT_ARG_CHECKED(String, source, 3);
CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
Handle<Object> additional_context(args[5]);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
......@@ -11226,7 +11283,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
#endif
// Materialize the content of the local scope into a JSObject.
Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
Handle<JSObject> local_scope = MaterializeLocalScope(
isolate, frame, inlined_frame_index);
RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
// Allocate a new context for the debug evaluation and set the extension
......@@ -11275,7 +11333,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
&has_pending_exception);
if (has_pending_exception) return Failure::Exception();
Handle<Object> arguments = GetArgumentsObject(isolate, frame,
Handle<Object> arguments = GetArgumentsObject(isolate,
frame, inlined_frame_index,
function, scope_info,
&sinfo, function_context);
......
......@@ -372,7 +372,7 @@ namespace internal {
F(GetFrameCount, 1, 1) \
F(GetFrameDetails, 2, 1) \
F(GetScopeCount, 2, 1) \
F(GetScopeDetails, 3, 1) \
F(GetScopeDetails, 4, 1) \
F(DebugPrintScopes, 0, 1) \
F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \
......@@ -385,7 +385,7 @@ namespace internal {
F(IsBreakOnException, 1, 1) \
F(PrepareStep, 3, 1) \
F(ClearStepping, 0, 1) \
F(DebugEvaluate, 5, 1) \
F(DebugEvaluate, 6, 1) \
F(DebugEvaluateGlobal, 4, 1) \
F(DebugGetLoadedScripts, 0, 1) \
F(DebugReferencedBy, 3, 1) \
......
......@@ -44,21 +44,44 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i);
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.
assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1));
assertEquals(i * 2 + 1 + (i * 2 + 1) / 100,
frame.localValue(0).value());
assertEquals(i * 2 + 2 + (i * 2 + 2) / 100,
frame.localValue(1).value());
assertEquals(expected_a, frame.localValue(0).value());
assertEquals(expected_b, frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1));
assertEquals((i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100,
frame.argumentValue(0).value());
assertEquals((i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100,
frame.argumentValue(1).value());
assertEquals(expected_x, frame.argumentValue(0).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.
......@@ -75,12 +98,13 @@ function listener(event, exec_state, event_data, data) {
// Check for construct call.
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.
if (%GetOptimizationStatus(f) == 2) {
if (%GetOptimizationStatus(f) == 1) {
if (i == 1 || i == 2 || i == 3) {
assertTrue(frame.isOptimizedFrame());
assertTrue(frame.isInlinedFrame());
assertEquals(4 - i, frame.inlinedFrameIndex());
} else if (i == 4) {
assertTrue(frame.isOptimizedFrame());
assertFalse(frame.isInlinedFrame());
......
......@@ -44,17 +44,44 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i);
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.
assertEquals('a', frame.localName(0));
assertEquals('b', frame.localName(1));
assertEquals(i * 2 + 1, frame.localValue(0).value());
assertEquals(i * 2 + 2, frame.localValue(1).value());
assertEquals(expected_a, frame.localValue(0).value());
assertEquals(expected_b, frame.localValue(1).value());
// All frames except the bottom one has arguments variables x and y.
assertEquals('x', frame.argumentName(0));
assertEquals('y', frame.argumentName(1));
assertEquals((i + 1) * 2 + 1, frame.argumentValue(0).value());
assertEquals((i + 1) * 2 + 2, frame.argumentValue(1).value());
assertEquals(expected_x, frame.argumentValue(0).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.
......@@ -71,12 +98,13 @@ function listener(event, exec_state, event_data, data) {
// Check for construct call.
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.
if (%GetOptimizationStatus(f) == 2) {
if (%GetOptimizationStatus(f) == 1) {
if (i == 1 || i == 2 || i == 3) {
assertTrue(frame.isOptimizedFrame());
assertTrue(frame.isInlinedFrame());
assertEquals(4 - i, frame.inlinedFrameIndex());
} else if (i == 4) {
assertTrue(frame.isOptimizedFrame());
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