| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
| (...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 // 1 ~ return address. | 758 // 1 ~ return address. |
| 759 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 759 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
| 760 __ JumpIfSmi(edi, &non_function); | 760 __ JumpIfSmi(edi, &non_function); |
| 761 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 761 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 762 __ j(not_equal, &slow); | 762 __ j(not_equal, &slow); |
| 763 | 763 |
| 764 | 764 |
| 765 // 3a. Patch the first argument if necessary when calling a function. | 765 // 3a. Patch the first argument if necessary when calling a function. |
| 766 Label shift_arguments; | 766 Label shift_arguments; |
| 767 __ Move(edx, Immediate(0)); // indicate regular JS_FUNCTION | 767 __ Move(edx, Immediate(0)); // indicate regular JS_FUNCTION |
| 768 { Label convert_to_object, use_global_receiver, patch_receiver; | 768 { Label convert_to_object, use_global_proxy, patch_receiver; |
| 769 // Change context eagerly in case we need the global receiver. | 769 // Change context eagerly in case we need the global receiver. |
| 770 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 770 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 771 | 771 |
| 772 // Do not transform the receiver for strict mode functions. | 772 // Do not transform the receiver for strict mode functions. |
| 773 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 773 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 774 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), | 774 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), |
| 775 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 775 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
| 776 __ j(not_equal, &shift_arguments); | 776 __ j(not_equal, &shift_arguments); |
| 777 | 777 |
| 778 // Do not transform the receiver for natives (shared already in ebx). | 778 // Do not transform the receiver for natives (shared already in ebx). |
| 779 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset), | 779 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset), |
| 780 1 << SharedFunctionInfo::kNativeBitWithinByte); | 780 1 << SharedFunctionInfo::kNativeBitWithinByte); |
| 781 __ j(not_equal, &shift_arguments); | 781 __ j(not_equal, &shift_arguments); |
| 782 | 782 |
| 783 // Compute the receiver in sloppy mode. | 783 // Compute the receiver in sloppy mode. |
| 784 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. | 784 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. |
| 785 | 785 |
| 786 // Call ToObject on the receiver if it is not an object, or use the | 786 // Call ToObject on the receiver if it is not an object, or use the |
| 787 // global object if it is null or undefined. | 787 // global object if it is null or undefined. |
| 788 __ JumpIfSmi(ebx, &convert_to_object); | 788 __ JumpIfSmi(ebx, &convert_to_object); |
| 789 __ cmp(ebx, factory->null_value()); | 789 __ cmp(ebx, factory->null_value()); |
| 790 __ j(equal, &use_global_receiver); | 790 __ j(equal, &use_global_proxy); |
| 791 __ cmp(ebx, factory->undefined_value()); | 791 __ cmp(ebx, factory->undefined_value()); |
| 792 __ j(equal, &use_global_receiver); | 792 __ j(equal, &use_global_proxy); |
| 793 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 793 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 794 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); | 794 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); |
| 795 __ j(above_equal, &shift_arguments); | 795 __ j(above_equal, &shift_arguments); |
| 796 | 796 |
| 797 __ bind(&convert_to_object); | 797 __ bind(&convert_to_object); |
| 798 | 798 |
| 799 { // In order to preserve argument count. | 799 { // In order to preserve argument count. |
| 800 FrameScope scope(masm, StackFrame::INTERNAL); | 800 FrameScope scope(masm, StackFrame::INTERNAL); |
| 801 __ SmiTag(eax); | 801 __ SmiTag(eax); |
| 802 __ push(eax); | 802 __ push(eax); |
| 803 | 803 |
| 804 __ push(ebx); | 804 __ push(ebx); |
| 805 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 805 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 806 __ mov(ebx, eax); | 806 __ mov(ebx, eax); |
| 807 __ Move(edx, Immediate(0)); // restore | 807 __ Move(edx, Immediate(0)); // restore |
| 808 | 808 |
| 809 __ pop(eax); | 809 __ pop(eax); |
| 810 __ SmiUntag(eax); | 810 __ SmiUntag(eax); |
| 811 } | 811 } |
| 812 | 812 |
| 813 // Restore the function to edi. | 813 // Restore the function to edi. |
| 814 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 814 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
| 815 __ jmp(&patch_receiver); | 815 __ jmp(&patch_receiver); |
| 816 | 816 |
| 817 __ bind(&use_global_receiver); | 817 __ bind(&use_global_proxy); |
| 818 __ mov(ebx, | 818 __ mov(ebx, |
| 819 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 819 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 820 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 820 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset)); |
| 821 | 821 |
| 822 __ bind(&patch_receiver); | 822 __ bind(&patch_receiver); |
| 823 __ mov(Operand(esp, eax, times_4, 0), ebx); | 823 __ mov(Operand(esp, eax, times_4, 0), ebx); |
| 824 | 824 |
| 825 __ jmp(&shift_arguments); | 825 __ jmp(&shift_arguments); |
| 826 } | 826 } |
| 827 | 827 |
| 828 // 3b. Check for function proxy. | 828 // 3b. Check for function proxy. |
| 829 __ bind(&slow); | 829 __ bind(&slow); |
| 830 __ Move(edx, Immediate(1)); // indicate function proxy | 830 __ Move(edx, Immediate(1)); // indicate function proxy |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 const int kLimitOffset = | 936 const int kLimitOffset = |
| 937 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 937 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
| 938 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 938 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
| 939 __ push(eax); // limit | 939 __ push(eax); // limit |
| 940 __ push(Immediate(0)); // index | 940 __ push(Immediate(0)); // index |
| 941 | 941 |
| 942 // Get the receiver. | 942 // Get the receiver. |
| 943 __ mov(ebx, Operand(ebp, kReceiverOffset)); | 943 __ mov(ebx, Operand(ebp, kReceiverOffset)); |
| 944 | 944 |
| 945 // Check that the function is a JS function (otherwise it must be a proxy). | 945 // Check that the function is a JS function (otherwise it must be a proxy). |
| 946 Label push_receiver, use_global_receiver; | 946 Label push_receiver, use_global_proxy; |
| 947 __ mov(edi, Operand(ebp, kFunctionOffset)); | 947 __ mov(edi, Operand(ebp, kFunctionOffset)); |
| 948 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 948 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 949 __ j(not_equal, &push_receiver); | 949 __ j(not_equal, &push_receiver); |
| 950 | 950 |
| 951 // Change context eagerly to get the right global object if necessary. | 951 // Change context eagerly to get the right global object if necessary. |
| 952 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 952 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 953 | 953 |
| 954 // Compute the receiver. | 954 // Compute the receiver. |
| 955 // Do not transform the receiver for strict mode functions. | 955 // Do not transform the receiver for strict mode functions. |
| 956 Label call_to_object; | 956 Label call_to_object; |
| 957 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 957 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 958 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), | 958 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), |
| 959 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 959 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
| 960 __ j(not_equal, &push_receiver); | 960 __ j(not_equal, &push_receiver); |
| 961 | 961 |
| 962 Factory* factory = masm->isolate()->factory(); | 962 Factory* factory = masm->isolate()->factory(); |
| 963 | 963 |
| 964 // Do not transform the receiver for natives (shared already in ecx). | 964 // Do not transform the receiver for natives (shared already in ecx). |
| 965 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), | 965 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), |
| 966 1 << SharedFunctionInfo::kNativeBitWithinByte); | 966 1 << SharedFunctionInfo::kNativeBitWithinByte); |
| 967 __ j(not_equal, &push_receiver); | 967 __ j(not_equal, &push_receiver); |
| 968 | 968 |
| 969 // Compute the receiver in sloppy mode. | 969 // Compute the receiver in sloppy mode. |
| 970 // Call ToObject on the receiver if it is not an object, or use the | 970 // Call ToObject on the receiver if it is not an object, or use the |
| 971 // global object if it is null or undefined. | 971 // global object if it is null or undefined. |
| 972 __ JumpIfSmi(ebx, &call_to_object); | 972 __ JumpIfSmi(ebx, &call_to_object); |
| 973 __ cmp(ebx, factory->null_value()); | 973 __ cmp(ebx, factory->null_value()); |
| 974 __ j(equal, &use_global_receiver); | 974 __ j(equal, &use_global_proxy); |
| 975 __ cmp(ebx, factory->undefined_value()); | 975 __ cmp(ebx, factory->undefined_value()); |
| 976 __ j(equal, &use_global_receiver); | 976 __ j(equal, &use_global_proxy); |
| 977 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 977 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 978 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); | 978 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); |
| 979 __ j(above_equal, &push_receiver); | 979 __ j(above_equal, &push_receiver); |
| 980 | 980 |
| 981 __ bind(&call_to_object); | 981 __ bind(&call_to_object); |
| 982 __ push(ebx); | 982 __ push(ebx); |
| 983 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 983 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 984 __ mov(ebx, eax); | 984 __ mov(ebx, eax); |
| 985 __ jmp(&push_receiver); | 985 __ jmp(&push_receiver); |
| 986 | 986 |
| 987 __ bind(&use_global_receiver); | 987 __ bind(&use_global_proxy); |
| 988 __ mov(ebx, | 988 __ mov(ebx, |
| 989 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 989 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 990 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 990 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset)); |
| 991 | 991 |
| 992 // Push the receiver. | 992 // Push the receiver. |
| 993 __ bind(&push_receiver); | 993 __ bind(&push_receiver); |
| 994 __ push(ebx); | 994 __ push(ebx); |
| 995 | 995 |
| 996 // Copy all arguments from the array to the stack. | 996 // Copy all arguments from the array to the stack. |
| 997 Label entry, loop; | 997 Label entry, loop; |
| 998 Register receiver = LoadIC::ReceiverRegister(); | 998 Register receiver = LoadIC::ReceiverRegister(); |
| 999 Register key = LoadIC::NameRegister(); | 999 Register key = LoadIC::NameRegister(); |
| 1000 __ mov(key, Operand(ebp, kIndexOffset)); | 1000 __ mov(key, Operand(ebp, kIndexOffset)); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 | 1445 |
| 1446 __ bind(&ok); | 1446 __ bind(&ok); |
| 1447 __ ret(0); | 1447 __ ret(0); |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 #undef __ | 1450 #undef __ |
| 1451 } | 1451 } |
| 1452 } // namespace v8::internal | 1452 } // namespace v8::internal |
| 1453 | 1453 |
| 1454 #endif // V8_TARGET_ARCH_X87 | 1454 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |