| 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
|
|
|