Chromium Code Reviews| Index: src/ia32/code-stubs-ia32.cc |
| diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
| index 01ffb0e3504118107603c030382c4768082c34b5..cba58d114d886a0eeb1de8a201613622d7ec6d24 100644 |
| --- a/src/ia32/code-stubs-ia32.cc |
| +++ b/src/ia32/code-stubs-ia32.cc |
| @@ -3913,28 +3913,46 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { |
| // If the receiver might be a value (string, number or boolean) check for this |
| // and box it if it is. |
| - if (ReceiverMightBeValue()) { |
| + if (ReceiverMightBeValue() || NonValueReceiverMightBeImplicit()) { |
|
Kevin Millikin (Chromium)
2011/05/18 15:57:23
I can't figure out if these are separate bits or i
Mads Ager (chromium)
2011/05/23 16:31:34
I can't actually hit the non-object case in the ca
|
| + Label explicit_receiver, receiver_is_value, receiver_is_js_object; |
| + |
| // Get the receiver from the stack. |
| // +1 ~ return address |
| - Label receiver_is_value, receiver_is_js_object; |
| __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); |
| - |
| - // Check if receiver is a smi (which is a number value). |
| - __ test(eax, Immediate(kSmiTagMask)); |
| - __ j(zero, &receiver_is_value); |
| - |
| - // Check if the receiver is a valid JS object. |
| - __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edi); |
| - __ j(above_equal, &receiver_is_js_object); |
| - |
| - // Call the runtime to box the value. |
| - __ bind(&receiver_is_value); |
| - __ EnterInternalFrame(); |
| - __ push(eax); |
| - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| - __ LeaveInternalFrame(); |
| - __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax); |
| - |
| + // Implicit global receiver is indicated with the hole. |
| + __ cmp(eax, masm->isolate()->factory()->the_hole_value()); |
| + __ j(not_equal, &explicit_receiver, Label::kNear); |
| + // Patch the receiver on the stack with the global receiver object. |
| + __ mov(ebx, GlobalObjectOperand()); |
| + __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
|
Kevin Millikin (Chromium)
2011/05/18 15:57:23
This should go in eax? Otherwise the ReceiverMigh
Mads Ager (chromium)
2011/05/23 16:31:34
Doesn't matter. We unconditionally jmp over the TO
|
| + __ mov(Operand(esp, (argc_ + 1) * kPointerSize), ebx); |
| + // Mark as implicit receiver call. |
|
Kevin Millikin (Chromium)
2011/05/18 15:57:23
We should be able to avoid setting ecx to check it
Mads Ager (chromium)
2011/05/23 16:31:34
Done.
|
| + __ SetReceiverType(ecx, IMPLICIT_RECEIVER); |
| + __ jmp(&receiver_is_js_object); |
| + __ bind(&explicit_receiver); |
| + __ SetReceiverType(ecx, EXPLICIT_RECEIVER); |
| + |
| + if (ReceiverMightBeValue()) { |
| + // Check if receiver is a smi (which is a number value). |
| + __ test(eax, Immediate(kSmiTagMask)); |
| + __ j(zero, &receiver_is_value); |
| + |
| + // Check if the receiver is a valid JS object. |
| + __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edi); |
| + __ j(above_equal, &receiver_is_js_object); |
| + |
| + // Call the runtime to box the value. |
| + __ bind(&receiver_is_value); |
| + __ EnterInternalFrame(); |
| + // Save implicit receiver information. |
| + __ push(ecx); |
| + __ push(eax); |
| + __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| + // Restore implicit receiver information. |
| + __ pop(ecx); |
| + __ LeaveInternalFrame(); |
| + __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax); |
| + } |
| __ bind(&receiver_is_js_object); |
| } |
| @@ -3946,12 +3964,24 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { |
| __ test(edi, Immediate(kSmiTagMask)); |
| __ j(zero, &slow); |
| // Goto slow case if we do not have a function. |
| - __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| + __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); |
| __ j(not_equal, &slow); |
| // Fast-case: Just invoke the function. |
| ParameterCount actual(argc_); |
| - __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
| + |
| + if (ReceiverMightBeValue() || NonValueReceiverMightBeImplicit()) { |
| + Label implicit_receiver_call; |
| + __ test(ecx, Operand(ecx)); |
| + __ j(not_zero, &implicit_receiver_call); |
| + __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
| + __ bind(&implicit_receiver_call); |
| + } |
| + __ InvokeFunction(edi, |
| + actual, |
| + JUMP_FUNCTION, |
| + NullCallWrapper(), |
| + IMPLICIT_RECEIVER); |
| // Slow-case: Non-function called. |
| __ bind(&slow); |
| @@ -4245,6 +4275,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
| } |
| __ mov(edx, Operand(edx, 0)); // deref address |
| __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
| + __ SetReceiverType(ecx, EXPLICIT_RECEIVER); |
| __ call(Operand(edx)); |
| // Unlink this frame from the handler chain. |