Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1225)

Unified Diff: src/runtime.cc

Issue 7343005: Support scope information and evaluation in optimized frames (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed review comments Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime.h ('k') | test/mjsunit/debug-evaluate-locals-optimized.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 117e5ab36f6f7b7743ea43ef2e666220ee090e23..d340f45c2fe44b8834edce2559402345de53f85b 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -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.
- 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
// parameters for the function and fill more if more parameters are provided.
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()) {
- ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
- } else {
- if (argument_count < it.frame()->ComputeParametersCount()) {
- argument_count = it.frame()->ComputeParametersCount();
- }
+ 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,16 +10277,11 @@ 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));
+ if (i < it.frame()->ComputeParametersCount()) {
+ // Get the value from the stack.
+ details->set(details_index++, frame_inspector.GetParameter(i));
} else {
- if (i < it.frame()->ComputeParametersCount()) {
- // Get the value from the stack.
- details->set(details_index++, it.frame()->GetParameter(i));
- } else {
- details->set(details_index++, heap->undefined_value());
- }
+ details->set(details_index++, heap->undefined_value());
}
}
@@ -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);
« no previous file with comments | « src/runtime.h ('k') | test/mjsunit/debug-evaluate-locals-optimized.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698