| 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 |