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);
} }
......
...@@ -9976,6 +9976,71 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) { ...@@ -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 kFrameDetailsFrameIdIndex = 0;
static const int kFrameDetailsReceiverIndex = 1; static const int kFrameDetailsReceiverIndex = 1;
static const int kFrameDetailsFunctionIndex = 2; static const int kFrameDetailsFunctionIndex = 2;
...@@ -10024,8 +10089,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10024,8 +10089,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
return heap->undefined_value(); return heap->undefined_value();
} }
int deoptimized_frame_index = -1; // Frame index in optimized frame. int inlined_frame_index = 0; // Inlined frame index in optimized frame.
DeoptimizedFrameInfo* deoptimized_frame = NULL;
int count = 0; int count = 0;
JavaScriptFrameIterator it(isolate, id); JavaScriptFrameIterator it(isolate, id);
...@@ -10036,13 +10100,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10036,13 +10100,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
if (it.done()) return heap->undefined_value(); if (it.done()) return heap->undefined_value();
if (it.frame()->is_optimized()) { if (it.frame()->is_optimized()) {
deoptimized_frame_index = inlined_frame_index =
it.frame()->GetInlineCount() - (index - count) - 1; 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 // Traverse the saved contexts chain to find the active context for the
// selected frame. // selected frame.
...@@ -10061,7 +10122,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10061,7 +10122,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Check for constructor frame. Inlined frames cannot be construct calls. // Check for constructor frame. Inlined frames cannot be construct calls.
bool inlined_frame = 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(); bool constructor = !inlined_frame && it.frame()->IsConstructor();
// Get scope info and read from it for local variable information. // Get scope info and read from it for local variable information.
...@@ -10083,14 +10144,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10083,14 +10144,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
for (; i < info.number_of_stack_slots(); ++i) { for (; i < info.number_of_stack_slots(); ++i) {
// Use the value from the stack. // Use the value from the stack.
locals->set(i * 2, *info.LocalName(i)); locals->set(i * 2, *info.LocalName(i));
if (it.frame()->is_optimized()) { locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
// 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));
}
} }
if (i < info.NumberOfLocals()) { if (i < info.NumberOfLocals()) {
// Get the context containing declarations. // Get the context containing declarations.
...@@ -10147,18 +10201,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10147,18 +10201,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// the provided parameters whereas the function frame always have the number // the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the // of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same. // information (except for what is collected above) is the same.
it.AdvanceToArgumentsFrame(); 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 // 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. // parameters for the function and fill more if more parameters are provided.
int argument_count = info.number_of_parameters(); int argument_count = info.number_of_parameters();
if (argument_count < frame_inspector.GetParametersCount()) {
argument_count = frame_inspector.GetParametersCount();
}
#ifdef DEBUG
if (it.frame()->is_optimized()) { if (it.frame()->is_optimized()) {
ASSERT_EQ(argument_count, deoptimized_frame->parameters_count()); ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
} else {
if (argument_count < it.frame()->ComputeParametersCount()) {
argument_count = it.frame()->ComputeParametersCount();
}
} }
#endif
// Calculate the size of the result. // Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex + int details_size = kFrameDetailsFirstDynamicIndex +
...@@ -10170,13 +10228,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10170,13 +10228,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
details->set(kFrameDetailsFrameIdIndex, *frame_id); details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function (same as in function frame). // Add the function (same as in function frame).
if (it.frame()->is_optimized()) { details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
// 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());
}
// Add the arguments count. // Add the arguments count.
details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count)); details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
...@@ -10208,9 +10260,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10208,9 +10260,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
} }
if (it.frame()->is_optimized()) { if (it.frame()->is_optimized()) {
flags |= 1 << 1; flags |= 1 << 1;
if (deoptimized_frame_index > 0) { flags |= inlined_frame_index << 2;
flags |= 1 << 2;
}
} }
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
...@@ -10227,16 +10277,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10227,16 +10277,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
} }
// Parameter value. // Parameter value.
if (it.frame()->is_optimized()) { if (i < it.frame()->ComputeParametersCount()) {
// Get the value from the deoptimized frame. // Get the value from the stack.
details->set(details_index++, deoptimized_frame->GetParameter(i)); details->set(details_index++, frame_inspector.GetParameter(i));
} else { } else {
if (i < it.frame()->ComputeParametersCount()) { details->set(details_index++, heap->undefined_value());
// Get the value from the stack.
details->set(details_index++, it.frame()->GetParameter(i));
} else {
details->set(details_index++, heap->undefined_value());
}
} }
} }
...@@ -10268,12 +10313,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { ...@@ -10268,12 +10313,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
} }
details->set(kFrameDetailsReceiverIndex, *receiver); 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); ASSERT_EQ(details_size, details_index);
return *isolate->factory()->NewJSArrayWithElements(details); return *isolate->factory()->NewJSArrayWithElements(details);
} }
...@@ -10309,12 +10348,15 @@ static bool CopyContextLocalsToScopeObject( ...@@ -10309,12 +10348,15 @@ static bool CopyContextLocalsToScopeObject(
// Create a plain JSObject which materializes the local scope for the specified // Create a plain JSObject which materializes the local scope for the specified
// frame. // frame.
static Handle<JSObject> MaterializeLocalScope(Isolate* isolate, static Handle<JSObject> MaterializeLocalScope(
JavaScriptFrame* frame) { Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index) {
Handle<JSFunction> function(JSFunction::cast(frame->function())); Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
ScopeInfo<> scope_info(*serialized_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 // Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function. // heap locals and extension properties of the debugged function.
...@@ -10327,7 +10369,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate, ...@@ -10327,7 +10369,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate, isolate,
SetProperty(local_scope, SetProperty(local_scope,
scope_info.parameter_name(i), scope_info.parameter_name(i),
Handle<Object>(frame->GetParameter(i), isolate), Handle<Object>(frame_inspector.GetParameter(i)),
NONE, NONE,
kNonStrictMode), kNonStrictMode),
Handle<JSObject>()); Handle<JSObject>());
...@@ -10339,7 +10381,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate, ...@@ -10339,7 +10381,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate, isolate,
SetProperty(local_scope, SetProperty(local_scope,
scope_info.stack_slot_name(i), scope_info.stack_slot_name(i),
Handle<Object>(frame->GetExpression(i), isolate), Handle<Object>(frame_inspector.GetExpression(i)),
NONE, NONE,
kNonStrictMode), kNonStrictMode),
Handle<JSObject>()); Handle<JSObject>());
...@@ -10459,9 +10501,12 @@ class ScopeIterator { ...@@ -10459,9 +10501,12 @@ class ScopeIterator {
ScopeTypeCatch ScopeTypeCatch
}; };
ScopeIterator(Isolate* isolate, JavaScriptFrame* frame) ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index)
: isolate_(isolate), : isolate_(isolate),
frame_(frame), frame_(frame),
inlined_frame_index_(inlined_frame_index),
function_(JSFunction::cast(frame->function())), function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())), context_(Context::cast(frame->context())),
local_done_(false), local_done_(false),
...@@ -10546,7 +10591,7 @@ class ScopeIterator { ...@@ -10546,7 +10591,7 @@ class ScopeIterator {
return Handle<JSObject>(CurrentContext()->global()); return Handle<JSObject>(CurrentContext()->global());
case ScopeIterator::ScopeTypeLocal: case ScopeIterator::ScopeTypeLocal:
// Materialize the content of the local scope into a JSObject. // Materialize the content of the local scope into a JSObject.
return MaterializeLocalScope(isolate_, frame_); return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
case ScopeIterator::ScopeTypeWith: case ScopeIterator::ScopeTypeWith:
// Return the with object. // Return the with object.
return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
...@@ -10626,6 +10671,7 @@ class ScopeIterator { ...@@ -10626,6 +10671,7 @@ class ScopeIterator {
private: private:
Isolate* isolate_; Isolate* isolate_;
JavaScriptFrame* frame_; JavaScriptFrame* frame_;
int inlined_frame_index_;
Handle<JSFunction> function_; Handle<JSFunction> function_;
Handle<Context> context_; Handle<Context> context_;
bool local_done_; bool local_done_;
...@@ -10654,7 +10700,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) { ...@@ -10654,7 +10700,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
// Count the visible scopes. // Count the visible scopes.
int n = 0; int n = 0;
for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) { for (ScopeIterator it(isolate, frame, 0);
!it.Done();
it.Next()) {
n++; n++;
} }
...@@ -10669,14 +10717,15 @@ static const int kScopeDetailsSize = 2; ...@@ -10669,14 +10717,15 @@ static const int kScopeDetailsSize = 2;
// Return an array with scope details // Return an array with scope details
// args[0]: number: break id // args[0]: number: break id
// args[1]: number: frame index // 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: // The array returned contains the following information:
// 0: Scope type // 0: Scope type
// 1: Scope object // 1: Scope object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) { RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
HandleScope scope(isolate); HandleScope scope(isolate);
ASSERT(args.length() == 3); ASSERT(args.length() == 4);
// Check arguments. // Check arguments.
Object* check; Object* check;
...@@ -10685,7 +10734,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) { ...@@ -10685,7 +10734,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (!maybe_check->ToObject(&check)) return maybe_check; if (!maybe_check->ToObject(&check)) return maybe_check;
} }
CONVERT_CHECKED(Smi, wrapped_id, args[1]); 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. // Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id); StackFrame::Id id = UnwrapFrameId(wrapped_id);
...@@ -10694,7 +10744,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) { ...@@ -10694,7 +10744,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
// Find the requested scope. // Find the requested scope.
int n = 0; int n = 0;
ScopeIterator it(isolate, frame); ScopeIterator it(isolate, frame, inlined_frame_index);
for (; !it.Done() && n < index; it.Next()) { for (; !it.Done() && n < index; it.Next()) {
n++; n++;
} }
...@@ -10724,7 +10774,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) { ...@@ -10724,7 +10774,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
// Print the scopes for the top frame. // Print the scopes for the top frame.
StackFrameLocator locator; StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 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(); it.DebugPrint();
} }
#endif #endif
...@@ -11117,6 +11169,7 @@ static Handle<Context> CopyWithContextChain(Isolate* isolate, ...@@ -11117,6 +11169,7 @@ static Handle<Context> CopyWithContextChain(Isolate* isolate,
// Runtime_DebugEvaluate. // Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(Isolate* isolate, static Handle<Object> GetArgumentsObject(Isolate* isolate,
JavaScriptFrame* frame, JavaScriptFrame* frame,
int inlined_frame_index,
Handle<JSFunction> function, Handle<JSFunction> function,
Handle<SerializedScopeInfo> scope_info, Handle<SerializedScopeInfo> scope_info,
const ScopeInfo<>* sinfo, const ScopeInfo<>* sinfo,
...@@ -11128,6 +11181,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate, ...@@ -11128,6 +11181,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
if (sinfo->number_of_stack_slots() > 0) { if (sinfo->number_of_stack_slots() > 0) {
index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol()); index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
if (index != -1) { if (index != -1) {
CHECK(false);
return Handle<Object>(frame->GetExpression(index), isolate); return Handle<Object>(frame->GetExpression(index), isolate);
} }
} }
...@@ -11140,7 +11194,9 @@ static Handle<Object> GetArgumentsObject(Isolate* 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 = Handle<JSObject> arguments =
isolate->factory()->NewArgumentsObject(function, length); isolate->factory()->NewArgumentsObject(function, length);
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
...@@ -11148,7 +11204,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate, ...@@ -11148,7 +11204,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) { 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); arguments->set_elements(*array);
return arguments; return arguments;
...@@ -11175,7 +11231,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { ...@@ -11175,7 +11231,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
// Check the execution state and decode arguments frame and source to be // Check the execution state and decode arguments frame and source to be
// evaluated. // evaluated.
ASSERT(args.length() == 5); ASSERT(args.length() == 6);
Object* check_result; Object* check_result;
{ MaybeObject* maybe_check_result = Runtime_CheckExecutionState( { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args)); RUNTIME_ARGUMENTS(isolate, args));
...@@ -11184,9 +11240,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { ...@@ -11184,9 +11240,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
} }
} }
CONVERT_CHECKED(Smi, wrapped_id, args[1]); CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_ARG_CHECKED(String, source, 2); CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
CONVERT_BOOLEAN_CHECKED(disable_break, args[3]); CONVERT_ARG_CHECKED(String, source, 3);
Handle<Object> additional_context(args[4]); CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
Handle<Object> additional_context(args[5]);
// Handle the processing of break. // Handle the processing of break.
DisableBreak disable_break_save(disable_break); DisableBreak disable_break_save(disable_break);
...@@ -11226,7 +11283,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { ...@@ -11226,7 +11283,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
#endif #endif
// Materialize the content of the local scope into a JSObject. // 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); RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
// Allocate a new context for the debug evaluation and set the extension // Allocate a new context for the debug evaluation and set the extension
...@@ -11275,7 +11333,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { ...@@ -11275,7 +11333,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
&has_pending_exception); &has_pending_exception);
if (has_pending_exception) return Failure::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, function, scope_info,
&sinfo, function_context); &sinfo, function_context);
......
...@@ -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) {
// All frames except the bottom one has normal variables a and b. 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('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