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