OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 // the generic Function.prototype.apply implementation can deal with | 808 // the generic Function.prototype.apply implementation can deal with |
809 // the call like it usually does. | 809 // the call like it usually does. |
810 Result a2 = frame_->Pop(); | 810 Result a2 = frame_->Pop(); |
811 Result a1 = frame_->Pop(); | 811 Result a1 = frame_->Pop(); |
812 Result ap = frame_->Pop(); | 812 Result ap = frame_->Pop(); |
813 Result fn = frame_->Pop(); | 813 Result fn = frame_->Pop(); |
814 frame_->Push(&ap); | 814 frame_->Push(&ap); |
815 frame_->Push(&fn); | 815 frame_->Push(&fn); |
816 frame_->Push(&a1); | 816 frame_->Push(&a1); |
817 frame_->Push(&a2); | 817 frame_->Push(&a2); |
818 CallFunctionStub call_function(2, NOT_IN_LOOP); | 818 CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS); |
819 Result res = frame_->CallStub(&call_function, 3); | 819 Result res = frame_->CallStub(&call_function, 3); |
820 frame_->Push(&res); | 820 frame_->Push(&res); |
821 | 821 |
822 // All done. Restore context register after call. | 822 // All done. Restore context register after call. |
823 if (try_lazy) done.Bind(); | 823 if (try_lazy) done.Bind(); |
824 frame_->RestoreContextRegister(); | 824 frame_->RestoreContextRegister(); |
825 } | 825 } |
826 | 826 |
827 | 827 |
828 class DeferredStackCheck: public DeferredCode { | 828 class DeferredStackCheck: public DeferredCode { |
(...skipping 1870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2699 // The runtime call returns a pair of values in rax (function) and | 2699 // The runtime call returns a pair of values in rax (function) and |
2700 // rdx (receiver). Touch up the stack with the right values. | 2700 // rdx (receiver). Touch up the stack with the right values. |
2701 Result receiver = allocator_->Allocate(rdx); | 2701 Result receiver = allocator_->Allocate(rdx); |
2702 frame_->SetElementAt(arg_count + 1, &result); | 2702 frame_->SetElementAt(arg_count + 1, &result); |
2703 frame_->SetElementAt(arg_count, &receiver); | 2703 frame_->SetElementAt(arg_count, &receiver); |
2704 receiver.Unuse(); | 2704 receiver.Unuse(); |
2705 | 2705 |
2706 // Call the function. | 2706 // Call the function. |
2707 CodeForSourcePosition(node->position()); | 2707 CodeForSourcePosition(node->position()); |
2708 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 2708 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
2709 CallFunctionStub call_function(arg_count, in_loop); | 2709 CallFunctionStub call_function(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
2710 result = frame_->CallStub(&call_function, arg_count + 1); | 2710 result = frame_->CallStub(&call_function, arg_count + 1); |
2711 | 2711 |
2712 // Restore the context and overwrite the function on the stack with | 2712 // Restore the context and overwrite the function on the stack with |
2713 // the result. | 2713 // the result. |
2714 frame_->RestoreContextRegister(); | 2714 frame_->RestoreContextRegister(); |
2715 frame_->SetElementAt(0, &result); | 2715 frame_->SetElementAt(0, &result); |
2716 | 2716 |
2717 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2717 } else if (var != NULL && !var->is_this() && var->is_global()) { |
2718 // ---------------------------------- | 2718 // ---------------------------------- |
2719 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 2719 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2760 // eagerly since they are arguments to an inevitable call (and are | 2760 // eagerly since they are arguments to an inevitable call (and are |
2761 // not sharable by the arguments). | 2761 // not sharable by the arguments). |
2762 ASSERT(!allocator()->is_used(rax)); | 2762 ASSERT(!allocator()->is_used(rax)); |
2763 frame_->EmitPush(rax); | 2763 frame_->EmitPush(rax); |
2764 | 2764 |
2765 // Load the receiver. | 2765 // Load the receiver. |
2766 ASSERT(!allocator()->is_used(rdx)); | 2766 ASSERT(!allocator()->is_used(rdx)); |
2767 frame_->EmitPush(rdx); | 2767 frame_->EmitPush(rdx); |
2768 | 2768 |
2769 // Call the function. | 2769 // Call the function. |
2770 CallWithArguments(args, node->position()); | 2770 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
2771 | 2771 |
2772 } else if (property != NULL) { | 2772 } else if (property != NULL) { |
2773 // Check if the key is a literal string. | 2773 // Check if the key is a literal string. |
2774 Literal* literal = property->key()->AsLiteral(); | 2774 Literal* literal = property->key()->AsLiteral(); |
2775 | 2775 |
2776 if (literal != NULL && literal->handle()->IsSymbol()) { | 2776 if (literal != NULL && literal->handle()->IsSymbol()) { |
2777 // ------------------------------------------------------------------ | 2777 // ------------------------------------------------------------------ |
2778 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 2778 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' |
2779 // ------------------------------------------------------------------ | 2779 // ------------------------------------------------------------------ |
2780 | 2780 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2825 // Pass receiver to called function. | 2825 // Pass receiver to called function. |
2826 if (property->is_synthetic()) { | 2826 if (property->is_synthetic()) { |
2827 // Use global object as receiver. | 2827 // Use global object as receiver. |
2828 LoadGlobalReceiver(); | 2828 LoadGlobalReceiver(); |
2829 } else { | 2829 } else { |
2830 // The reference's size is non-negative. | 2830 // The reference's size is non-negative. |
2831 frame_->PushElementAt(ref.size()); | 2831 frame_->PushElementAt(ref.size()); |
2832 } | 2832 } |
2833 | 2833 |
2834 // Call the function. | 2834 // Call the function. |
2835 CallWithArguments(args, node->position()); | 2835 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
2836 } | 2836 } |
2837 | 2837 |
2838 } else { | 2838 } else { |
2839 // ---------------------------------- | 2839 // ---------------------------------- |
2840 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 2840 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
2841 // ---------------------------------- | 2841 // ---------------------------------- |
2842 | 2842 |
2843 // Load the function. | 2843 // Load the function. |
2844 Load(function); | 2844 Load(function); |
2845 | 2845 |
2846 // Pass the global proxy as the receiver. | 2846 // Pass the global proxy as the receiver. |
2847 LoadGlobalReceiver(); | 2847 LoadGlobalReceiver(); |
2848 | 2848 |
2849 // Call the function. | 2849 // Call the function. |
2850 CallWithArguments(args, node->position()); | 2850 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
2851 } | 2851 } |
2852 } | 2852 } |
2853 | 2853 |
2854 | 2854 |
2855 void CodeGenerator::VisitCallNew(CallNew* node) { | 2855 void CodeGenerator::VisitCallNew(CallNew* node) { |
2856 Comment cmnt(masm_, "[ CallNew"); | 2856 Comment cmnt(masm_, "[ CallNew"); |
2857 | 2857 |
2858 // According to ECMA-262, section 11.2.2, page 44, the function | 2858 // According to ECMA-262, section 11.2.2, page 44, the function |
2859 // expression in new calls must be evaluated before the | 2859 // expression in new calls must be evaluated before the |
2860 // arguments. This is different from ordinary calls, where the | 2860 // arguments. This is different from ordinary calls, where the |
(...skipping 3690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6551 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); | 6551 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); |
6552 ASSERT(kSymbolTag != 0); | 6552 ASSERT(kSymbolTag != 0); |
6553 __ testb(scratch, Immediate(kIsSymbolMask)); | 6553 __ testb(scratch, Immediate(kIsSymbolMask)); |
6554 __ j(zero, label); | 6554 __ j(zero, label); |
6555 } | 6555 } |
6556 | 6556 |
6557 | 6557 |
6558 // Call the function just below TOS on the stack with the given | 6558 // Call the function just below TOS on the stack with the given |
6559 // arguments. The receiver is the TOS. | 6559 // arguments. The receiver is the TOS. |
6560 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 6560 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
| 6561 CallFunctionFlags flags, |
6561 int position) { | 6562 int position) { |
6562 // Push the arguments ("left-to-right") on the stack. | 6563 // Push the arguments ("left-to-right") on the stack. |
6563 int arg_count = args->length(); | 6564 int arg_count = args->length(); |
6564 for (int i = 0; i < arg_count; i++) { | 6565 for (int i = 0; i < arg_count; i++) { |
6565 Load(args->at(i)); | 6566 Load(args->at(i)); |
6566 } | 6567 } |
6567 | 6568 |
6568 // Record the position for debugging purposes. | 6569 // Record the position for debugging purposes. |
6569 CodeForSourcePosition(position); | 6570 CodeForSourcePosition(position); |
6570 | 6571 |
6571 // Use the shared code stub to call the function. | 6572 // Use the shared code stub to call the function. |
6572 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 6573 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
6573 CallFunctionStub call_function(arg_count, in_loop); | 6574 CallFunctionStub call_function(arg_count, in_loop, flags); |
6574 Result answer = frame_->CallStub(&call_function, arg_count + 1); | 6575 Result answer = frame_->CallStub(&call_function, arg_count + 1); |
6575 // Restore context and replace function on the stack with the | 6576 // Restore context and replace function on the stack with the |
6576 // result of the stub invocation. | 6577 // result of the stub invocation. |
6577 frame_->RestoreContextRegister(); | 6578 frame_->RestoreContextRegister(); |
6578 frame_->SetElementAt(0, &answer); | 6579 frame_->SetElementAt(0, &answer); |
6579 } | 6580 } |
6580 | 6581 |
6581 | 6582 |
6582 void InstanceofStub::Generate(MacroAssembler* masm) { | 6583 void InstanceofStub::Generate(MacroAssembler* masm) { |
6583 // Implements "value instanceof function" operator. | 6584 // Implements "value instanceof function" operator. |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6961 | 6962 |
6962 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize, | 6963 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize, |
6963 StackHandlerConstants::kPCOffset); | 6964 StackHandlerConstants::kPCOffset); |
6964 __ ret(0); | 6965 __ ret(0); |
6965 } | 6966 } |
6966 | 6967 |
6967 | 6968 |
6968 void CallFunctionStub::Generate(MacroAssembler* masm) { | 6969 void CallFunctionStub::Generate(MacroAssembler* masm) { |
6969 Label slow; | 6970 Label slow; |
6970 | 6971 |
| 6972 // If the receiver might be a value (string, number or boolean) check for this |
| 6973 // and box it if it is. |
| 6974 if (ReceiverMightBeValue()) { |
| 6975 // Get the receiver from the stack. |
| 6976 // +1 ~ return address |
| 6977 Label receiver_is_value, receiver_is_js_object; |
| 6978 __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize)); |
| 6979 |
| 6980 // Check if receiver is a smi (which is a number value). |
| 6981 __ JumpIfSmi(rax, &receiver_is_value); |
| 6982 |
| 6983 // Check if the receiver is a valid JS object. |
| 6984 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rdi); |
| 6985 __ j(above_equal, &receiver_is_js_object); |
| 6986 |
| 6987 // Call the runtime to box the value. |
| 6988 __ bind(&receiver_is_value); |
| 6989 __ EnterInternalFrame(); |
| 6990 __ push(rax); |
| 6991 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 6992 __ LeaveInternalFrame(); |
| 6993 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rax); |
| 6994 |
| 6995 __ bind(&receiver_is_js_object); |
| 6996 } |
| 6997 |
6971 // Get the function to call from the stack. | 6998 // Get the function to call from the stack. |
6972 // +2 ~ receiver, return address | 6999 // +2 ~ receiver, return address |
6973 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize)); | 7000 __ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize)); |
6974 | 7001 |
6975 // Check that the function really is a JavaScript function. | 7002 // Check that the function really is a JavaScript function. |
6976 __ JumpIfSmi(rdi, &slow); | 7003 __ JumpIfSmi(rdi, &slow); |
6977 // Goto slow case if we do not have a function. | 7004 // Goto slow case if we do not have a function. |
6978 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 7005 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
6979 __ j(not_equal, &slow); | 7006 __ j(not_equal, &slow); |
6980 | 7007 |
(...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8216 masm.GetCode(&desc); | 8243 masm.GetCode(&desc); |
8217 // Call the function from C++. | 8244 // Call the function from C++. |
8218 return FUNCTION_CAST<ModuloFunction>(buffer); | 8245 return FUNCTION_CAST<ModuloFunction>(buffer); |
8219 } | 8246 } |
8220 | 8247 |
8221 #endif | 8248 #endif |
8222 | 8249 |
8223 #undef __ | 8250 #undef __ |
8224 | 8251 |
8225 } } // namespace v8::internal | 8252 } } // namespace v8::internal |
OLD | NEW |