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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 // -- eax : argArray | 996 // -- eax : argArray |
997 // -- edi : receiver | 997 // -- edi : receiver |
998 // -- esp[0] : return address | 998 // -- esp[0] : return address |
999 // -- esp[4] : thisArg | 999 // -- esp[4] : thisArg |
1000 // ----------------------------------- | 1000 // ----------------------------------- |
1001 | 1001 |
1002 // 2. Make sure the receiver is actually callable. | 1002 // 2. Make sure the receiver is actually callable. |
1003 Label receiver_not_callable; | 1003 Label receiver_not_callable; |
1004 __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); | 1004 __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); |
1005 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 1005 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
1006 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); | 1006 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 1007 Immediate(1 << Map::kIsCallable)); |
1007 __ j(zero, &receiver_not_callable, Label::kNear); | 1008 __ j(zero, &receiver_not_callable, Label::kNear); |
1008 | 1009 |
1009 // 3. Tail call with no arguments if argArray is null or undefined. | 1010 // 3. Tail call with no arguments if argArray is null or undefined. |
1010 Label no_arguments; | 1011 Label no_arguments; |
1011 __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); | 1012 __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); |
1012 __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments, | 1013 __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments, |
1013 Label::kNear); | 1014 Label::kNear); |
1014 | 1015 |
1015 // 4a. Apply the receiver to the given argArray (passing undefined for | 1016 // 4a. Apply the receiver to the given argArray (passing undefined for |
1016 // new.target). | 1017 // new.target). |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 // -- eax : argumentsList | 1120 // -- eax : argumentsList |
1120 // -- edi : target | 1121 // -- edi : target |
1121 // -- esp[0] : return address | 1122 // -- esp[0] : return address |
1122 // -- esp[4] : thisArgument | 1123 // -- esp[4] : thisArgument |
1123 // ----------------------------------- | 1124 // ----------------------------------- |
1124 | 1125 |
1125 // 2. Make sure the target is actually callable. | 1126 // 2. Make sure the target is actually callable. |
1126 Label target_not_callable; | 1127 Label target_not_callable; |
1127 __ JumpIfSmi(edi, &target_not_callable, Label::kNear); | 1128 __ JumpIfSmi(edi, &target_not_callable, Label::kNear); |
1128 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 1129 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
1129 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); | 1130 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 1131 Immediate(1 << Map::kIsCallable)); |
1130 __ j(zero, &target_not_callable, Label::kNear); | 1132 __ j(zero, &target_not_callable, Label::kNear); |
1131 | 1133 |
1132 // 3a. Apply the target to the given argumentsList (passing undefined for | 1134 // 3a. Apply the target to the given argumentsList (passing undefined for |
1133 // new.target). | 1135 // new.target). |
1134 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); | 1136 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |
1135 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 1137 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
1136 | 1138 |
1137 // 3b. The target is not callable, throw an appropriate TypeError. | 1139 // 3b. The target is not callable, throw an appropriate TypeError. |
1138 __ bind(&target_not_callable); | 1140 __ bind(&target_not_callable); |
1139 { | 1141 { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 // -- edx : new.target | 1186 // -- edx : new.target |
1185 // -- edi : target | 1187 // -- edi : target |
1186 // -- esp[0] : return address | 1188 // -- esp[0] : return address |
1187 // -- esp[4] : receiver (undefined) | 1189 // -- esp[4] : receiver (undefined) |
1188 // ----------------------------------- | 1190 // ----------------------------------- |
1189 | 1191 |
1190 // 2. Make sure the target is actually a constructor. | 1192 // 2. Make sure the target is actually a constructor. |
1191 Label target_not_constructor; | 1193 Label target_not_constructor; |
1192 __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); | 1194 __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); |
1193 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 1195 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
1194 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); | 1196 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 1197 Immediate(1 << Map::kIsConstructor)); |
1195 __ j(zero, &target_not_constructor, Label::kNear); | 1198 __ j(zero, &target_not_constructor, Label::kNear); |
1196 | 1199 |
1197 // 3. Make sure the target is actually a constructor. | 1200 // 3. Make sure the target is actually a constructor. |
1198 Label new_target_not_constructor; | 1201 Label new_target_not_constructor; |
1199 __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); | 1202 __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); |
1200 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 1203 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
1201 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); | 1204 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 1205 Immediate(1 << Map::kIsConstructor)); |
1202 __ j(zero, &new_target_not_constructor, Label::kNear); | 1206 __ j(zero, &new_target_not_constructor, Label::kNear); |
1203 | 1207 |
1204 // 4a. Construct the target with the given new.target and argumentsList. | 1208 // 4a. Construct the target with the given new.target and argumentsList. |
1205 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 1209 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
1206 | 1210 |
1207 // 4b. The target is not a constructor, throw an appropriate TypeError. | 1211 // 4b. The target is not a constructor, throw an appropriate TypeError. |
1208 __ bind(&target_not_constructor); | 1212 __ bind(&target_not_constructor); |
1209 { | 1213 { |
1210 __ mov(Operand(esp, kPointerSize), edi); | 1214 __ mov(Operand(esp, kPointerSize), edi); |
1211 __ TailCallRuntime(Runtime::kThrowCalledNonCallable); | 1215 __ TailCallRuntime(Runtime::kThrowCalledNonCallable); |
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1921 // -- eax : the number of arguments (not including the receiver) | 1925 // -- eax : the number of arguments (not including the receiver) |
1922 // -- edi : the function to call (checked to be a JSFunction) | 1926 // -- edi : the function to call (checked to be a JSFunction) |
1923 // ----------------------------------- | 1927 // ----------------------------------- |
1924 __ AssertFunction(edi); | 1928 __ AssertFunction(edi); |
1925 | 1929 |
1926 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1930 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
1927 // Check that the function is not a "classConstructor". | 1931 // Check that the function is not a "classConstructor". |
1928 Label class_constructor; | 1932 Label class_constructor; |
1929 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1933 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1930 __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), | 1934 __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), |
1931 SharedFunctionInfo::kClassConstructorBitsWithinByte); | 1935 Immediate(SharedFunctionInfo::kClassConstructorBitsWithinByte)); |
1932 __ j(not_zero, &class_constructor); | 1936 __ j(not_zero, &class_constructor); |
1933 | 1937 |
1934 // Enter the context of the function; ToObject has to run in the function | 1938 // Enter the context of the function; ToObject has to run in the function |
1935 // context, and we also need to take the global proxy from the function | 1939 // context, and we also need to take the global proxy from the function |
1936 // context in case of conversion. | 1940 // context in case of conversion. |
1937 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == | 1941 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == |
1938 SharedFunctionInfo::kStrictModeByteOffset); | 1942 SharedFunctionInfo::kStrictModeByteOffset); |
1939 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1943 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
1940 // We need to convert the receiver for non-native sloppy mode functions. | 1944 // We need to convert the receiver for non-native sloppy mode functions. |
1941 Label done_convert; | 1945 Label done_convert; |
1942 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), | 1946 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), |
1943 (1 << SharedFunctionInfo::kNativeBitWithinByte) | | 1947 Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) | |
1944 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | 1948 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); |
1945 __ j(not_zero, &done_convert); | 1949 __ j(not_zero, &done_convert); |
1946 { | 1950 { |
1947 // ----------- S t a t e ------------- | 1951 // ----------- S t a t e ------------- |
1948 // -- eax : the number of arguments (not including the receiver) | 1952 // -- eax : the number of arguments (not including the receiver) |
1949 // -- edx : the shared function info. | 1953 // -- edx : the shared function info. |
1950 // -- edi : the function to call (checked to be a JSFunction) | 1954 // -- edi : the function to call (checked to be a JSFunction) |
1951 // -- esi : the function context. | 1955 // -- esi : the function context. |
1952 // ----------------------------------- | 1956 // ----------------------------------- |
1953 | 1957 |
1954 if (mode == ConvertReceiverMode::kNullOrUndefined) { | 1958 if (mode == ConvertReceiverMode::kNullOrUndefined) { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2156 __ JumpIfSmi(edi, &non_callable); | 2160 __ JumpIfSmi(edi, &non_callable); |
2157 __ bind(&non_smi); | 2161 __ bind(&non_smi); |
2158 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2162 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2159 __ j(equal, masm->isolate()->builtins()->CallFunction(mode, tail_call_mode), | 2163 __ j(equal, masm->isolate()->builtins()->CallFunction(mode, tail_call_mode), |
2160 RelocInfo::CODE_TARGET); | 2164 RelocInfo::CODE_TARGET); |
2161 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); | 2165 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
2162 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(tail_call_mode), | 2166 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(tail_call_mode), |
2163 RelocInfo::CODE_TARGET); | 2167 RelocInfo::CODE_TARGET); |
2164 | 2168 |
2165 // Check if target has a [[Call]] internal method. | 2169 // Check if target has a [[Call]] internal method. |
2166 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); | 2170 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 2171 Immediate(1 << Map::kIsCallable)); |
2167 __ j(zero, &non_callable); | 2172 __ j(zero, &non_callable); |
2168 | 2173 |
2169 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 2174 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
2170 __ j(not_equal, &non_function); | 2175 __ j(not_equal, &non_function); |
2171 | 2176 |
2172 // 0. Prepare for tail call if necessary. | 2177 // 0. Prepare for tail call if necessary. |
2173 if (tail_call_mode == TailCallMode::kAllow) { | 2178 if (tail_call_mode == TailCallMode::kAllow) { |
2174 PrepareForTailCall(masm, eax, ebx, ecx, edx); | 2179 PrepareForTailCall(masm, eax, ebx, ecx, edx); |
2175 } | 2180 } |
2176 | 2181 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2292 // Check if target is a Smi. | 2297 // Check if target is a Smi. |
2293 Label non_constructor; | 2298 Label non_constructor; |
2294 __ JumpIfSmi(edi, &non_constructor, Label::kNear); | 2299 __ JumpIfSmi(edi, &non_constructor, Label::kNear); |
2295 | 2300 |
2296 // Dispatch based on instance type. | 2301 // Dispatch based on instance type. |
2297 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2302 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2298 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | 2303 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
2299 RelocInfo::CODE_TARGET); | 2304 RelocInfo::CODE_TARGET); |
2300 | 2305 |
2301 // Check if target has a [[Construct]] internal method. | 2306 // Check if target has a [[Construct]] internal method. |
2302 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); | 2307 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 2308 Immediate(1 << Map::kIsConstructor)); |
2303 __ j(zero, &non_constructor, Label::kNear); | 2309 __ j(zero, &non_constructor, Label::kNear); |
2304 | 2310 |
2305 // Only dispatch to bound functions after checking whether they are | 2311 // Only dispatch to bound functions after checking whether they are |
2306 // constructors. | 2312 // constructors. |
2307 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); | 2313 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
2308 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), | 2314 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |
2309 RelocInfo::CODE_TARGET); | 2315 RelocInfo::CODE_TARGET); |
2310 | 2316 |
2311 // Only dispatch to proxies after checking whether they are constructors. | 2317 // Only dispatch to proxies after checking whether they are constructors. |
2312 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 2318 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2582 // And "return" to the OSR entry point of the function. | 2588 // And "return" to the OSR entry point of the function. |
2583 __ ret(0); | 2589 __ ret(0); |
2584 } | 2590 } |
2585 | 2591 |
2586 | 2592 |
2587 #undef __ | 2593 #undef __ |
2588 } // namespace internal | 2594 } // namespace internal |
2589 } // namespace v8 | 2595 } // namespace v8 |
2590 | 2596 |
2591 #endif // V8_TARGET_ARCH_IA32 | 2597 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |