| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 556)
|
| +++ src/runtime.cc (working copy)
|
| @@ -474,7 +474,7 @@
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
|
| - Handle<Object> context_obj =
|
| + Handle<Object> holder =
|
| context->Lookup(name, flags, &index, &attributes);
|
|
|
| if (attributes != ABSENT) {
|
| @@ -494,14 +494,14 @@
|
| // The variable or constant context slot should always be in
|
| // the function context; not in any outer context nor in the
|
| // arguments object.
|
| - ASSERT(context_obj.is_identical_to(context));
|
| + ASSERT(holder.is_identical_to(context));
|
| if (((attributes & READ_ONLY) == 0) ||
|
| context->get(index)->IsTheHole()) {
|
| context->set(index, *initial_value);
|
| }
|
| } else {
|
| // Slow case: The property is not in the FixedArray part of the context.
|
| - Handle<JSObject> context_ext = Handle<JSObject>::cast(context_obj);
|
| + Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
|
| SetProperty(context_ext, name, initial_value, mode);
|
| }
|
| }
|
| @@ -702,7 +702,7 @@
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
|
| - Handle<Object> context_obj =
|
| + Handle<Object> holder =
|
| context->Lookup(name, flags, &index, &attributes);
|
|
|
| // The property should always be present. It is always declared
|
| @@ -714,7 +714,7 @@
|
| if (index >= 0) {
|
| // The constant context slot should always be in the function
|
| // context; not in any outer context nor in the arguments object.
|
| - ASSERT(context_obj.is_identical_to(context));
|
| + ASSERT(holder.is_identical_to(context));
|
| if (context->get(index)->IsTheHole()) {
|
| context->set(index, *value);
|
| }
|
| @@ -722,7 +722,7 @@
|
| }
|
|
|
| // Otherwise, the slot must be in a JS object extension.
|
| - Handle<JSObject> context_ext(JSObject::cast(*context_obj));
|
| + Handle<JSObject> context_ext(JSObject::cast(*holder));
|
|
|
| // We must initialize the value only if it wasn't initialized
|
| // before, e.g. for const declarations in a loop. The property has
|
| @@ -3301,12 +3301,12 @@
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| - Handle<Object> context_obj =
|
| + Handle<Object> holder =
|
| context->Lookup(name, flags, &index, &attributes);
|
|
|
| - if (index < 0 && *context_obj != NULL) {
|
| - ASSERT(context_obj->IsJSObject());
|
| - return *context_obj;
|
| + if (index < 0 && *holder != NULL) {
|
| + ASSERT(holder->IsJSObject());
|
| + return *holder;
|
| }
|
|
|
| // No intermediate context found. Use global object by default.
|
| @@ -3335,6 +3335,40 @@
|
| }
|
|
|
|
|
| +static Object* ComputeContextSlotReceiver(Object* holder) {
|
| + // If the "property" we were looking for is a local variable or an
|
| + // argument in a context, the receiver is the global object; see
|
| + // ECMA-262, 3rd., 10.1.6 and 10.2.3.
|
| + HeapObject* object = HeapObject::cast(holder);
|
| + Context* top = Top::context();
|
| + if (holder->IsContext()) return top->global()->global_receiver();
|
| +
|
| + // TODO(xxx): Find a better - and faster way - of checking for
|
| + // arguments and context extension objects. This kinda sucks.
|
| + JSFunction* context_extension_function =
|
| + top->global_context()->context_extension_function();
|
| + JSObject* arguments_boilerplate =
|
| + top->global_context()->arguments_boilerplate();
|
| + JSFunction* arguments_function =
|
| + JSFunction::cast(arguments_boilerplate->map()->constructor());
|
| + // If the holder is an arguments object or a context extension then the
|
| + // receiver is also the global object;
|
| + Object* constructor = HeapObject::cast(holder)->map()->constructor();
|
| + if (constructor == context_extension_function ||
|
| + constructor == arguments_function) {
|
| + return Top::context()->global()->global_receiver();
|
| + }
|
| +
|
| + // If the holder is a global object, we have to be careful to wrap
|
| + // it in its proxy if necessary.
|
| + if (object->IsGlobalObject()) {
|
| + return GlobalObject::cast(object)->global_receiver();
|
| + } else {
|
| + return object;
|
| + }
|
| +}
|
| +
|
| +
|
| static ObjPair LoadContextSlotHelper(Arguments args, bool throw_error) {
|
| HandleScope scope;
|
| ASSERT(args.length() == 2);
|
| @@ -3346,34 +3380,32 @@
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| - Handle<Object> context_obj =
|
| + Handle<Object> holder =
|
| context->Lookup(name, flags, &index, &attributes);
|
|
|
| if (index >= 0) {
|
| - if (context_obj->IsContext()) {
|
| - // The context is an Execution context, and the "property" we were looking
|
| - // for is a local variable in that context. According to ECMA-262, 3rd.,
|
| - // 10.1.6 and 10.2.3, the receiver is the global object.
|
| - return MakePair(
|
| - Unhole(Handle<Context>::cast(context_obj)->get(index), attributes),
|
| - Top::context()->global());
|
| + Handle<Object> receiver =
|
| + Handle<Object>(ComputeContextSlotReceiver(*holder));
|
| + Handle<Object> value;
|
| + if (holder->IsContext()) {
|
| + value = Handle<Object>(Context::cast(*holder)->get(index));
|
| } else {
|
| - return MakePair(
|
| - Unhole(Handle<JSObject>::cast(context_obj)->GetElement(index),
|
| - attributes),
|
| - *context_obj);
|
| + // Arguments object.
|
| + value = Handle<Object>(JSObject::cast(*holder)->GetElement(index));
|
| }
|
| + return MakePair(Unhole(*value, attributes), *receiver);
|
| }
|
|
|
| - if (*context_obj != NULL) {
|
| - ASSERT(Handle<JSObject>::cast(context_obj)->HasProperty(*name));
|
| - // Note: As of 5/29/2008, GetProperty does the "unholing" and so this call
|
| - // here is redundant. We left it anyway, to be explicit; also it's not clear
|
| - // why GetProperty should do the unholing in the first place.
|
| + if (*holder != NULL) {
|
| + ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
|
| + // Note: As of 5/29/2008, GetProperty does the "unholing" and so
|
| + // this call here is redundant. We left it anyway, to be explicit;
|
| + // also it's not clear why GetProperty should do the unholing in
|
| + // the first place.
|
| return MakePair(
|
| - Unhole(Handle<JSObject>::cast(context_obj)->GetProperty(*name),
|
| + Unhole(Handle<JSObject>::cast(holder)->GetProperty(*name),
|
| attributes),
|
| - *context_obj);
|
| + ComputeContextSlotReceiver(*holder));
|
| }
|
|
|
| if (throw_error) {
|
| @@ -3409,19 +3441,19 @@
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| - Handle<Object> context_obj =
|
| + Handle<Object> holder =
|
| context->Lookup(name, flags, &index, &attributes);
|
|
|
| if (index >= 0) {
|
| - if (context_obj->IsContext()) {
|
| + if (holder->IsContext()) {
|
| // Ignore if read_only variable.
|
| if ((attributes & READ_ONLY) == 0) {
|
| - Handle<Context>::cast(context_obj)->set(index, *value);
|
| + Handle<Context>::cast(holder)->set(index, *value);
|
| }
|
| } else {
|
| ASSERT((attributes & READ_ONLY) == 0);
|
| Object* result =
|
| - Handle<JSObject>::cast(context_obj)->SetElement(index, *value);
|
| + Handle<JSObject>::cast(holder)->SetElement(index, *value);
|
| USE(result);
|
| ASSERT(!result->IsFailure());
|
| }
|
| @@ -3432,9 +3464,9 @@
|
| // It is either in an JSObject extension context or it was not found.
|
| Handle<JSObject> context_ext;
|
|
|
| - if (*context_obj != NULL) {
|
| + if (*holder != NULL) {
|
| // The property exists in the extension context.
|
| - context_ext = Handle<JSObject>::cast(context_obj);
|
| + context_ext = Handle<JSObject>::cast(holder);
|
| } else {
|
| // The property was not found. It needs to be stored in the global context.
|
| ASSERT(attributes == ABSENT);
|
|
|