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

Unified Diff: src/runtime.cc

Issue 125115: Added mutation of locals to debugger (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 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/frames.cc ('k') | test/mjsunit/debug-evaluate.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
===================================================================
--- src/runtime.cc (revision 2164)
+++ src/runtime.cc (working copy)
@@ -6162,6 +6162,96 @@
}
+// Write back the to the local scope from a materialized local scope.
+static void DematerializeLocalScope(JavaScriptFrame* frame,
+ Handle<JSObject> local_scope,
+ Handle<JSObject> arguments) {
+ Handle<JSFunction> function(JSFunction::cast(frame->function()));
+ Handle<Code> code(function->code());
+ ScopeInfo<> scope_info(*code);
+ Handle<Context> frame_context(Context::cast(frame->context()));
+ Handle<Context> function_context(frame_context->fcontext());
+
+ // Locate the arguments shadow (.arguments) variable if it exists either as a
+ // context allocated or stack allocated variable.
+ Handle<JSObject> arguments_shadow;
+
+ // First write back to the function context extension. This will be variables
+ // introduced by eval.
+ if (function_context->has_extension() &&
+ !function_context->IsGlobalContext()) {
+ Handle<JSObject> ext(JSObject::cast(function_context->extension()));
+ Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
+ for (int i = 0; i < keys->length(); i++) {
+ // Names of variables introduced by eval are strings.
+ ASSERT(keys->get(i)->IsString());
+ Handle<String> key(String::cast(keys->get(i)));
+ SetProperty(ext, key, GetProperty(local_scope, key), NONE);
+ }
+ }
+
+ // Second write back all context locals.
+ for (int i = Context::MIN_CONTEXT_SLOTS;
+ i < scope_info.number_of_context_slots();
+ i++) {
+ Handle<String> name = scope_info.context_slot_name(i);
+ // Don't write to the arguments shadow (.arguments).
+ if (*name != Heap::arguments_shadow_symbol()) {
+ function_context->set(i, *GetProperty(local_scope, name));
+ } else {
+ arguments_shadow =
+ Handle<JSObject>(JSObject::cast(function_context->get(i)));
+ }
+ }
+
+ // Third write back all stack locals.
+ for (int i = 0; i < scope_info.number_of_stack_slots(); i++) {
+ Handle<String> name = scope_info.stack_slot_name(i);
+ // Don't write to the arguments shadow (.arguments).
+ if (*name != Heap::arguments_shadow_symbol()) {
+ frame->SetExpression(i, *GetProperty(local_scope, name));
+ } else {
+ arguments_shadow =
+ Handle<JSObject>(JSObject::cast(frame->GetExpression(i)));
+ }
+ }
+
+ // Finally write back all parameters. Parameters are written to the stack and
+ // to the arguments shadow (.arguments) variable if it exists.
+ for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
+ Handle<Object> obj =
+ GetProperty(local_scope, scope_info.parameter_name(i));
+ frame->SetParameter(i, *obj);
+
+ // Write to arguments shadow if it exists.
+ if (!arguments_shadow.is_null()) {
+ SetElement(arguments_shadow, i, obj);
+ }
+ }
+
+ // If the frame has an adaptor frame then the parameters needs to be written
+ // back to this frame as well.
+ if (frame->has_adapted_arguments()) {
+ StackFrameIterator it(false, frame->fp(), frame->sp());
+ ASSERT(it.frame()->is_java_script());
+ it.Advance();
+ ASSERT(!it.done());
+ ASSERT(it.frame()->is_arguments_adaptor());
+ JavaScriptFrame* adaptor_frame =
+ reinterpret_cast<JavaScriptFrame*>(it.frame());
+ for (int i = 0; i < adaptor_frame->GetProvidedParametersCount(); i++) {
+ if (i < scope_info.number_of_parameters()) {
+ Handle<Object> obj =
+ GetProperty(local_scope, scope_info.parameter_name(i));
+ adaptor_frame->SetParameter(i, *obj);
+ } else {
+ adaptor_frame->SetParameter(i, arguments->GetElement(i));
+ }
+ }
+ }
+}
+
+
// Create a plain JSObject which materializes the closure content for the
// context.
static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
@@ -6346,6 +6436,7 @@
Handle<Code> code(function_->code());
ScopeInfo<> scope_info(*code);
scope_info.Print();
+
if (!CurrentContext().is_null()) {
CurrentContext()->Print();
if (CurrentContext()->has_extension()) {
@@ -6854,11 +6945,11 @@
// Helper function to find or create the arguments object for
// Runtime_DebugEvaluate.
-static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
- Handle<JSFunction> function,
- Handle<Code> code,
- const ScopeInfo<>* sinfo,
- Handle<Context> function_context) {
+static Handle<JSObject> GetArgumentsObject(JavaScriptFrame* frame,
+ Handle<JSFunction> function,
+ Handle<Code> code,
+ const ScopeInfo<>* sinfo,
+ Handle<Context> function_context) {
// Try to find the value of 'arguments' to pass as parameter. If it is not
// found (that is the debugged function does not reference 'arguments' and
// does not support eval) then create an 'arguments' object.
@@ -6866,7 +6957,7 @@
if (sinfo->number_of_stack_slots() > 0) {
index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
if (index != -1) {
- return Handle<Object>(frame->GetExpression(index));
+ return Handle<JSObject>(JSObject::cast(frame->GetExpression(index)));
}
}
@@ -6874,16 +6965,29 @@
index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
NULL);
if (index != -1) {
- return Handle<Object>(function_context->get(index));
+ return Handle<JSObject>(JSObject::cast(function_context->get(index)));
}
}
- const int length = frame->GetProvidedParametersCount();
+ // Locate the actual frame which holds all the passed arguments. Either the
+ // current JavaScript frame or the adaptor frame just below it.
+ JavaScriptFrame* actual_frame = frame;
+ StackFrameIterator it(false, frame->fp(), frame->sp());
+ if (frame->has_adapted_arguments()) {
+ ASSERT(it.frame()->is_java_script());
+ it.Advance();
+ ASSERT(!it.done());
+ ASSERT(it.frame()->is_arguments_adaptor());
+ actual_frame = reinterpret_cast<JavaScriptFrame*>(it.frame());
+ }
+
+ // Fill an array with all the passed arguments.
+ const int length = actual_frame->GetProvidedParametersCount();
Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
Handle<FixedArray> array = Factory::NewFixedArray(length);
WriteBarrierMode mode = array->GetWriteBarrierMode();
for (int i = 0; i < length; i++) {
- array->set(i, frame->GetParameter(i), mode);
+ array->set(i, actual_frame->GetParameter(i), mode);
}
arguments->set_elements(*array);
return arguments;
@@ -6990,16 +7094,20 @@
&has_pending_exception);
if (has_pending_exception) return Failure::Exception();
- Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
- function_context);
+ Handle<JSObject> arguments = GetArgumentsObject(frame, function, code, &sinfo,
+ function_context);
// Invoke the evaluation function and return the result.
const int argc = 2;
- Object** argv[argc] = { arguments.location(),
+ Object** argv[argc] = { reinterpret_cast<Object**>(arguments.location()),
Handle<Object>::cast(source).location() };
Handle<Object> result =
Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
argc, argv, &has_pending_exception);
+ // Write back the content of the materialized scope to where it came from to
+ // reflect changes from the evaluation.This must be done before returning any
+ // exceptions.
+ DematerializeLocalScope(frame, local_scope, arguments);
if (has_pending_exception) return Failure::Exception();
// Skip the global proxy as it has no properties and always delegates to the
« no previous file with comments | « src/frames.cc ('k') | test/mjsunit/debug-evaluate.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698