Chromium Code Reviews| Index: src/ic.cc |
| diff --git a/src/ic.cc b/src/ic.cc |
| index 968b45d0b61f4ac27c102cdc8dae927cc8c51ff2..81b659efa9f89ee01a38e9680b383f11f4944598 100644 |
| --- a/src/ic.cc |
| +++ b/src/ic.cc |
| @@ -435,16 +435,25 @@ Object* CallICBase::TryCallAsFunction(Object* object) { |
| } |
| -void CallICBase::ReceiverToObject(Handle<Object> object) { |
| - HandleScope scope; |
| - Handle<Object> receiver(object); |
| +void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, |
| + Handle<Object> object) { |
| + if (callee->IsJSFunction()) { |
| + JSFunction* function = JSFunction::cast(*callee); |
| + if (function->shared()->strict_mode() || function->IsBuiltin()) { |
| + // Do not wrap receiver for strict mode functions or for builtins. |
| + return; |
| + } |
| + } |
| - // Change the receiver to the result of calling ToObject on it. |
| - const int argc = this->target()->arguments_count(); |
| - StackFrameLocator locator; |
| - JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| - int index = frame->ComputeExpressionsCount() - (argc + 1); |
| - frame->SetExpression(index, *Factory::ToObject(object)); |
| + // And only wrap string, number or boolean. |
| + if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
|
Martin Maly
2011/02/18 00:55:38
I don't understand why the object was double-wrapp
Mads Ager (chromium)
2011/02/18 07:22:48
Yes, there is no reason to rewrap the incoming obj
|
| + // Change the receiver to the result of calling ToObject on it. |
| + const int argc = this->target()->arguments_count(); |
| + StackFrameLocator locator; |
| + JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| + int index = frame->ComputeExpressionsCount() - (argc + 1); |
| + frame->SetExpression(index, *Factory::ToObject(object)); |
| + } |
| } |
| @@ -458,10 +467,6 @@ MaybeObject* CallICBase::LoadFunction(State state, |
| return TypeError("non_object_property_call", object, name); |
| } |
| - if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| - ReceiverToObject(object); |
| - } |
| - |
| // Check if the name is trivially convertible to an index and get |
| // the element if so. |
| uint32_t index; |
| @@ -500,11 +505,20 @@ MaybeObject* CallICBase::LoadFunction(State state, |
| // Get the property. |
| PropertyAttributes attr; |
| - Object* result; |
| + HandleScope scope; |
| + Handle<Object> result; |
|
Mads Ager (chromium)
2011/02/18 07:22:48
I would move the object_result out here (maybe cal
Martin Maly
2011/02/19 01:26:13
Done.
|
| { MaybeObject* maybe_result = |
| object->GetProperty(*object, &lookup, *name, &attr); |
| - if (!maybe_result->ToObject(&result)) return maybe_result; |
| + Object* object_result; |
| + if (!maybe_result->ToObject(&object_result)) return maybe_result; |
| + result = Handle<Object>(object_result); |
| } |
| + |
| + // Make receiver an object if the callee requires it. Strict mode or builtin |
| + // functions do not wrap the receiver, non-strict functions and objects |
| + // called as functions do. |
| + ReceiverToObjectIfRequired(result, object); |
| + |
| if (lookup.type() == INTERCEPTOR) { |
|
Mads Ager (chromium)
2011/02/18 07:22:48
It looks like you can move the wrapping below this
Martin Maly
2011/02/19 01:26:13
Done.
|
| // If the object does not have the requested property, check which |
| // exception we need to throw. |
| @@ -516,7 +530,7 @@ MaybeObject* CallICBase::LoadFunction(State state, |
| } |
| } |
| - ASSERT(result != Heap::the_hole_value()); |
| + ASSERT(*result != Heap::the_hole_value()); |
|
Mads Ager (chromium)
2011/02/18 07:22:48
ASSERT(!result->IsTheHole());
Martin Maly
2011/02/19 01:26:13
Done.
|
| if (result->IsJSFunction()) { |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| @@ -524,23 +538,20 @@ MaybeObject* CallICBase::LoadFunction(State state, |
| if (Debug::StepInActive()) { |
| // Protect the result in a handle as the debugger can allocate and might |
| // cause GC. |
| - HandleScope scope; |
| - Handle<JSFunction> function(JSFunction::cast(result)); |
| + Handle<JSFunction> function(JSFunction::cast(*result)); |
|
Martin Maly
2011/02/18 00:55:38
No HandleScope needed here, I believe ... the Hand
Mads Ager (chromium)
2011/02/18 07:22:48
Yes, that's fine.
|
| Debug::HandleStepIn(function, object, fp(), false); |
| return *function; |
| } |
| #endif |
| - return result; |
| + return *result; |
| } |
| // Try to find a suitable function delegate for the object at hand. |
| - result = TryCallAsFunction(result); |
| - MaybeObject* answer = result; |
| - if (!result->IsJSFunction()) { |
| - answer = TypeError("property_not_function", object, name); |
| - } |
| - return answer; |
| + result = Handle<Object>(TryCallAsFunction(*result)); |
| + if (result->IsJSFunction()) return *result; |
|
Martin Maly
2011/02/18 00:55:38
I am a bit hazy on using
"return handle.EscapeFrom
Mads Ager (chromium)
2011/02/18 07:22:48
This method returns a MaybeObject which is a raw o
|
| + |
| + return TypeError("property_not_function", object, name); |
| } |
| @@ -565,8 +576,8 @@ bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, |
| case kStringCharAt: |
| if (object->IsString()) { |
| String* string = String::cast(*object); |
| - // Check that there's the right wrapper in the receiver slot. |
| - ASSERT(string == JSValue::cast(args[0])->value()); |
| + // Check there's the right string value or wrapper in the receiver slot. |
| + ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); |
| // If we're in the default (fastest) state and the index is |
| // out of bounds, update the state to record this fact. |
| if (*extra_ic_state == DEFAULT_STRING_STUB && |
| @@ -775,10 +786,6 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, |
| return TypeError("non_object_property_call", object, key); |
| } |
| - if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| - ReceiverToObject(object); |
| - } |
| - |
| if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { |
| int argc = target()->arguments_count(); |
| InLoopFlag in_loop = target()->ic_in_loop(); |
| @@ -793,17 +800,25 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, |
| #endif |
| } |
| } |
| - Object* result; |
| + |
| + HandleScope scope; |
| + Handle<Object> result; |
|
Mads Ager (chromium)
2011/02/18 07:22:48
This case can be rewritten to just use handles. Yo
Martin Maly
2011/02/19 01:26:13
Done.
|
| { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key); |
| - if (!maybe_result->ToObject(&result)) return maybe_result; |
| + Object* object_result; |
| + if (!maybe_result->ToObject(&object_result)) return maybe_result; |
| + result = Handle<Object>(object_result); |
|
Martin Maly
2011/02/18 00:55:38
Is there an established V8 pattern to export objec
|
| } |
| - if (result->IsJSFunction()) return result; |
| - result = TryCallAsFunction(result); |
| - MaybeObject* answer = result; |
| - if (!result->IsJSFunction()) { |
| - answer = TypeError("property_not_function", object, key); |
| - } |
| - return answer; |
| + |
| + // Make receiver an object if the callee requires it. Strict mode or builtin |
| + // functions do not wrap the receiver, non-strict functions and objects |
| + // called as functions do. |
| + ReceiverToObjectIfRequired(result, object); |
| + |
| + if (result->IsJSFunction()) return *result; |
| + result = Handle<Object>(TryCallAsFunction(*result)); |
| + if (result->IsJSFunction()) return *result; |
| + |
| + return TypeError("property_not_function", object, key); |
|
Martin Maly
2011/02/18 00:55:38
This sequence seemed cleaner, get rid of "answer"
Mads Ager (chromium)
2011/02/18 07:22:48
Yes, thanks for cleaning that up! The original cod
|
| } |