OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 __ Set(edx, Immediate(0)); // restore | 774 __ Set(edx, Immediate(0)); // restore |
775 | 775 |
776 __ pop(eax); | 776 __ pop(eax); |
777 __ SmiUntag(eax); | 777 __ SmiUntag(eax); |
778 } | 778 } |
779 | 779 |
780 // Restore the function to edi. | 780 // Restore the function to edi. |
781 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 781 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
782 __ jmp(&patch_receiver); | 782 __ jmp(&patch_receiver); |
783 | 783 |
784 // Use the global receiver object from the called function as the | |
785 // receiver. | |
786 __ bind(&use_global_receiver); | 784 __ bind(&use_global_receiver); |
787 CallStubCompiler::FetchGlobalProxy(masm, ebx, edi); | 785 __ mov(ebx, |
| 786 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 787 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
788 | 788 |
789 __ bind(&patch_receiver); | 789 __ bind(&patch_receiver); |
790 __ mov(Operand(esp, eax, times_4, 0), ebx); | 790 __ mov(Operand(esp, eax, times_4, 0), ebx); |
791 | 791 |
792 __ jmp(&shift_arguments); | 792 __ jmp(&shift_arguments); |
793 } | 793 } |
794 | 794 |
795 // 3b. Check for function proxy. | 795 // 3b. Check for function proxy. |
796 __ bind(&slow); | 796 __ bind(&slow); |
797 __ Set(edx, Immediate(1)); // indicate function proxy | 797 __ Set(edx, Immediate(1)); // indicate function proxy |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 } | 848 } |
849 | 849 |
850 // 5b. Get the code to call from the function and check that the number of | 850 // 5b. Get the code to call from the function and check that the number of |
851 // expected arguments matches what we're providing. If so, jump | 851 // expected arguments matches what we're providing. If so, jump |
852 // (tail-call) to the code in register edx without checking arguments. | 852 // (tail-call) to the code in register edx without checking arguments. |
853 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 853 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
854 __ mov(ebx, | 854 __ mov(ebx, |
855 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 855 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
856 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 856 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
857 __ SmiUntag(ebx); | 857 __ SmiUntag(ebx); |
858 __ SetCallKind(ecx, CALL_AS_METHOD); | 858 __ SetCallKind(ecx, CALL_AS_FUNCTION); |
859 __ cmp(eax, ebx); | 859 __ cmp(eax, ebx); |
860 __ j(not_equal, | 860 __ j(not_equal, |
861 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); | 861 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); |
862 | 862 |
863 ParameterCount expected(0); | 863 ParameterCount expected(0); |
864 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper(), | 864 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper(), |
865 CALL_AS_METHOD); | 865 CALL_AS_FUNCTION); |
866 } | 866 } |
867 | 867 |
868 | 868 |
869 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 869 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
870 static const int kArgumentsOffset = 2 * kPointerSize; | 870 static const int kArgumentsOffset = 2 * kPointerSize; |
871 static const int kReceiverOffset = 3 * kPointerSize; | 871 static const int kReceiverOffset = 3 * kPointerSize; |
872 static const int kFunctionOffset = 4 * kPointerSize; | 872 static const int kFunctionOffset = 4 * kPointerSize; |
873 { | 873 { |
874 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 874 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
875 | 875 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 const int kLimitOffset = | 907 const int kLimitOffset = |
908 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 908 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
909 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 909 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
910 __ push(eax); // limit | 910 __ push(eax); // limit |
911 __ push(Immediate(0)); // index | 911 __ push(Immediate(0)); // index |
912 | 912 |
913 // Get the receiver. | 913 // Get the receiver. |
914 __ mov(ebx, Operand(ebp, kReceiverOffset)); | 914 __ mov(ebx, Operand(ebp, kReceiverOffset)); |
915 | 915 |
916 // Check that the function is a JS function (otherwise it must be a proxy). | 916 // Check that the function is a JS function (otherwise it must be a proxy). |
917 Label push_receiver; | 917 Label push_receiver, use_global_receiver; |
918 __ mov(edi, Operand(ebp, kFunctionOffset)); | 918 __ mov(edi, Operand(ebp, kFunctionOffset)); |
919 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 919 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
920 __ j(not_equal, &push_receiver); | 920 __ j(not_equal, &push_receiver); |
921 | 921 |
922 // Change context eagerly to get the right global object if necessary. | 922 // Change context eagerly to get the right global object if necessary. |
923 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 923 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
924 | 924 |
925 // Compute the receiver. | 925 // Compute the receiver. |
926 // Do not transform the receiver for strict mode functions. | 926 // Do not transform the receiver for strict mode functions. |
927 Label call_to_object, use_global_receiver; | 927 Label call_to_object; |
928 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 928 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
929 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), | 929 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), |
930 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 930 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
931 __ j(not_equal, &push_receiver); | 931 __ j(not_equal, &push_receiver); |
932 | 932 |
933 Factory* factory = masm->isolate()->factory(); | 933 Factory* factory = masm->isolate()->factory(); |
934 | 934 |
935 // Do not transform the receiver for natives (shared already in ecx). | 935 // Do not transform the receiver for natives (shared already in ecx). |
936 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), | 936 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), |
937 1 << SharedFunctionInfo::kNativeBitWithinByte); | 937 1 << SharedFunctionInfo::kNativeBitWithinByte); |
(...skipping 10 matching lines...) Expand all Loading... |
948 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 948 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
949 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); | 949 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); |
950 __ j(above_equal, &push_receiver); | 950 __ j(above_equal, &push_receiver); |
951 | 951 |
952 __ bind(&call_to_object); | 952 __ bind(&call_to_object); |
953 __ push(ebx); | 953 __ push(ebx); |
954 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 954 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
955 __ mov(ebx, eax); | 955 __ mov(ebx, eax); |
956 __ jmp(&push_receiver); | 956 __ jmp(&push_receiver); |
957 | 957 |
958 // Use the current global receiver object as the receiver. | |
959 __ bind(&use_global_receiver); | 958 __ bind(&use_global_receiver); |
960 CallStubCompiler::FetchGlobalProxy(masm, ebx, edi); | 959 __ mov(ebx, |
| 960 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 961 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
961 | 962 |
962 // Push the receiver. | 963 // Push the receiver. |
963 __ bind(&push_receiver); | 964 __ bind(&push_receiver); |
964 __ push(ebx); | 965 __ push(ebx); |
965 | 966 |
966 // Copy all arguments from the array to the stack. | 967 // Copy all arguments from the array to the stack. |
967 Label entry, loop; | 968 Label entry, loop; |
968 __ mov(ecx, Operand(ebp, kIndexOffset)); | 969 __ mov(ecx, Operand(ebp, kIndexOffset)); |
969 __ jmp(&entry); | 970 __ jmp(&entry); |
970 __ bind(&loop); | 971 __ bind(&loop); |
(...skipping 12 matching lines...) Expand all Loading... |
983 | 984 |
984 // Update the index on the stack and in register eax. | 985 // Update the index on the stack and in register eax. |
985 __ mov(ecx, Operand(ebp, kIndexOffset)); | 986 __ mov(ecx, Operand(ebp, kIndexOffset)); |
986 __ add(ecx, Immediate(1 << kSmiTagSize)); | 987 __ add(ecx, Immediate(1 << kSmiTagSize)); |
987 __ mov(Operand(ebp, kIndexOffset), ecx); | 988 __ mov(Operand(ebp, kIndexOffset), ecx); |
988 | 989 |
989 __ bind(&entry); | 990 __ bind(&entry); |
990 __ cmp(ecx, Operand(ebp, kLimitOffset)); | 991 __ cmp(ecx, Operand(ebp, kLimitOffset)); |
991 __ j(not_equal, &loop); | 992 __ j(not_equal, &loop); |
992 | 993 |
993 // Invoke the function. | 994 // Call the function. |
994 Label call_proxy; | 995 Label call_proxy; |
995 __ mov(eax, ecx); | 996 __ mov(eax, ecx); |
996 ParameterCount actual(eax); | 997 ParameterCount actual(eax); |
997 __ SmiUntag(eax); | 998 __ SmiUntag(eax); |
998 __ mov(edi, Operand(ebp, kFunctionOffset)); | 999 __ mov(edi, Operand(ebp, kFunctionOffset)); |
999 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1000 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1000 __ j(not_equal, &call_proxy); | 1001 __ j(not_equal, &call_proxy); |
1001 __ InvokeFunction(edi, actual, CALL_FUNCTION, | 1002 __ InvokeFunction(edi, actual, CALL_FUNCTION, |
1002 NullCallWrapper(), CALL_AS_METHOD); | 1003 NullCallWrapper(), CALL_AS_FUNCTION); |
1003 | 1004 |
1004 frame_scope.GenerateLeaveFrame(); | 1005 frame_scope.GenerateLeaveFrame(); |
1005 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1006 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1006 | 1007 |
1007 // Invoke the function proxy. | 1008 // Call the function proxy. |
1008 __ bind(&call_proxy); | 1009 __ bind(&call_proxy); |
1009 __ push(edi); // add function proxy as last argument | 1010 __ push(edi); // add function proxy as last argument |
1010 __ inc(eax); | 1011 __ inc(eax); |
1011 __ Set(ebx, Immediate(0)); | 1012 __ Set(ebx, Immediate(0)); |
1012 __ SetCallKind(ecx, CALL_AS_METHOD); | 1013 __ SetCallKind(ecx, CALL_AS_FUNCTION); |
1013 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); | 1014 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); |
1014 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1015 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1015 RelocInfo::CODE_TARGET); | 1016 RelocInfo::CODE_TARGET); |
1016 | 1017 |
1017 // Leave internal frame. | 1018 // Leave internal frame. |
1018 } | 1019 } |
1019 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1020 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1020 } | 1021 } |
1021 | 1022 |
1022 | 1023 |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1380 | 1381 |
1381 __ bind(&ok); | 1382 __ bind(&ok); |
1382 __ ret(0); | 1383 __ ret(0); |
1383 } | 1384 } |
1384 | 1385 |
1385 #undef __ | 1386 #undef __ |
1386 } | 1387 } |
1387 } // namespace v8::internal | 1388 } // namespace v8::internal |
1388 | 1389 |
1389 #endif // V8_TARGET_ARCH_IA32 | 1390 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |