Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 3613) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -815,7 +815,7 @@ |
frame_->Push(&fn); |
frame_->Push(&a1); |
frame_->Push(&a2); |
- CallFunctionStub call_function(2, NOT_IN_LOOP); |
+ CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS); |
Result res = frame_->CallStub(&call_function, 3); |
frame_->Push(&res); |
@@ -2706,7 +2706,7 @@ |
// Call the function. |
CodeForSourcePosition(node->position()); |
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
- CallFunctionStub call_function(arg_count, in_loop); |
+ CallFunctionStub call_function(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
result = frame_->CallStub(&call_function, arg_count + 1); |
// Restore the context and overwrite the function on the stack with |
@@ -2767,7 +2767,7 @@ |
frame_->EmitPush(rdx); |
// Call the function. |
- CallWithArguments(args, node->position()); |
+ CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
} else if (property != NULL) { |
// Check if the key is a literal string. |
@@ -2832,7 +2832,7 @@ |
} |
// Call the function. |
- CallWithArguments(args, node->position()); |
+ CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
} |
} else { |
@@ -2847,7 +2847,7 @@ |
LoadGlobalReceiver(); |
// Call the function. |
- CallWithArguments(args, node->position()); |
+ CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
} |
} |
@@ -6558,6 +6558,7 @@ |
// Call the function just below TOS on the stack with the given |
// arguments. The receiver is the TOS. |
void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
+ CallFunctionFlags flags, |
int position) { |
// Push the arguments ("left-to-right") on the stack. |
int arg_count = args->length(); |
@@ -6570,7 +6571,7 @@ |
// Use the shared code stub to call the function. |
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
- CallFunctionStub call_function(arg_count, in_loop); |
+ CallFunctionStub call_function(arg_count, in_loop, flags); |
Result answer = frame_->CallStub(&call_function, arg_count + 1); |
// Restore context and replace function on the stack with the |
// result of the stub invocation. |
@@ -6968,6 +6969,32 @@ |
void CallFunctionStub::Generate(MacroAssembler* masm) { |
Label slow; |
+ // If the receiver might be a value (string, number or boolean) check for this |
+ // and box it if it is. |
+ if (ReceiverMightBeValue()) { |
+ // Get the receiver from the stack. |
+ // +1 ~ return address |
+ Label receiver_is_value, receiver_is_js_object; |
+ __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize)); |
+ |
+ // Check if receiver is a smi (which is a number value). |
+ __ JumpIfSmi(rax, &receiver_is_value); |
+ |
+ // Check if the receiver is a valid JS object. |
+ __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rdi); |
+ __ j(above_equal, &receiver_is_js_object); |
+ |
+ // Call the runtime to box the value. |
+ __ bind(&receiver_is_value); |
+ __ EnterInternalFrame(); |
+ __ push(rax); |
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
+ __ LeaveInternalFrame(); |
+ __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rax); |
+ |
+ __ bind(&receiver_is_js_object); |
+ } |
+ |
// Get the function to call from the stack. |
// +2 ~ receiver, return address |
__ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize)); |