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/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2022 CallStubInRecordCallTarget(masm, &create_stub, is_super); | 2022 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
2023 __ jmp(&done); | 2023 __ jmp(&done); |
2024 | 2024 |
2025 __ bind(¬_array_function); | 2025 __ bind(¬_array_function); |
2026 CreateWeakCellStub weak_cell_stub(isolate); | 2026 CreateWeakCellStub weak_cell_stub(isolate); |
2027 CallStubInRecordCallTarget(masm, &weak_cell_stub, is_super); | 2027 CallStubInRecordCallTarget(masm, &weak_cell_stub, is_super); |
2028 __ bind(&done); | 2028 __ bind(&done); |
2029 } | 2029 } |
2030 | 2030 |
2031 | 2031 |
2032 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | |
2033 // ----------- S t a t e ------------- | |
2034 // -- edi : the function to call | |
2035 // -- edx : the function's shared function info | |
2036 // ----------------------------------- | |
2037 // Do not transform the receiver for strict mode functions. | |
2038 __ test_b(FieldOperand(edx, SharedFunctionInfo::kStrictModeByteOffset), | |
2039 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | |
2040 __ j(not_equal, cont); | |
2041 | |
2042 // Do not transform the receiver for natives (shared already in ecx). | |
2043 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), | |
2044 1 << SharedFunctionInfo::kNativeBitWithinByte); | |
2045 __ j(not_equal, cont); | |
2046 } | |
2047 | |
2048 | |
2049 static void EmitSlowCase(Isolate* isolate, MacroAssembler* masm, int argc) { | |
2050 __ Set(eax, argc); | |
2051 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
2052 } | |
2053 | |
2054 | |
2055 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { | |
2056 // Wrap the receiver and patch it back onto the stack. | |
2057 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
2058 __ push(edi); | |
2059 ToObjectStub stub(masm->isolate()); | |
2060 __ CallStub(&stub); | |
2061 __ pop(edi); | |
2062 } | |
2063 __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); | |
2064 __ jmp(cont); | |
2065 } | |
2066 | |
2067 | |
2068 static void EmitClassConstructorCallCheck(MacroAssembler* masm) { | |
2069 // ----------- S t a t e ------------- | |
2070 // -- edi : the function to call | |
2071 // -- edx : the function's shared function info | |
2072 // ----------------------------------- | |
2073 // ClassConstructor Check: ES6 section 9.2.1 [[Call]] | |
2074 Label non_class_constructor; | |
2075 // Check whether the current function is a classConstructor. | |
2076 __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), | |
2077 SharedFunctionInfo::kClassConstructorBitsWithinByte); | |
2078 __ j(zero, &non_class_constructor, Label::kNear); | |
2079 // If we call a classConstructor Function throw a TypeError | |
2080 // indirectly via the CallFunction builtin. | |
2081 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | |
2082 __ bind(&non_class_constructor); | |
2083 } | |
2084 | |
2085 | |
2086 static void CallFunctionNoFeedback(MacroAssembler* masm, | |
2087 int argc, bool needs_checks, | |
2088 bool call_as_method) { | |
2089 // edi : the function to call | |
2090 Label slow, wrap, cont; | |
2091 | |
2092 if (needs_checks) { | |
2093 // Check that the function really is a JavaScript function. | |
2094 __ JumpIfSmi(edi, &slow); | |
2095 | |
2096 // Goto slow case if we do not have a function. | |
2097 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | |
2098 __ j(not_equal, &slow); | |
2099 } | |
2100 | |
2101 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
2102 EmitClassConstructorCallCheck(masm); | |
2103 | |
2104 // Fast-case: Just invoke the function. | |
2105 ParameterCount actual(argc); | |
2106 | |
2107 if (call_as_method) { | |
2108 if (needs_checks) { | |
2109 EmitContinueIfStrictOrNative(masm, &cont); | |
2110 } | |
2111 | |
2112 // Load the receiver from the stack. | |
2113 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); | |
2114 | |
2115 if (needs_checks) { | |
2116 __ JumpIfSmi(eax, &wrap); | |
2117 | |
2118 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | |
2119 __ j(below, &wrap); | |
2120 } else { | |
2121 __ jmp(&wrap); | |
2122 } | |
2123 | |
2124 __ bind(&cont); | |
2125 } | |
2126 | |
2127 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); | |
2128 | |
2129 if (needs_checks) { | |
2130 // Slow-case: Non-function called. | |
2131 __ bind(&slow); | |
2132 EmitSlowCase(masm->isolate(), masm, argc); | |
2133 } | |
2134 | |
2135 if (call_as_method) { | |
2136 __ bind(&wrap); | |
2137 EmitWrapCase(masm, argc, &cont); | |
2138 } | |
2139 } | |
2140 | |
2141 | |
2142 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
2143 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); | |
2144 } | |
2145 | |
2146 | |
2147 void CallConstructStub::Generate(MacroAssembler* masm) { | 2032 void CallConstructStub::Generate(MacroAssembler* masm) { |
2148 // eax : number of arguments | 2033 // eax : number of arguments |
2149 // ebx : feedback vector | 2034 // ebx : feedback vector |
2150 // ecx : original constructor (for IsSuperConstructorCall) | 2035 // ecx : original constructor (for IsSuperConstructorCall) |
2151 // edx : slot in feedback vector (Smi, for RecordCallTarget) | 2036 // edx : slot in feedback vector (Smi, for RecordCallTarget) |
2152 // edi : constructor function | 2037 // edi : constructor function |
2153 | 2038 |
2154 if (IsSuperConstructorCall()) { | 2039 if (IsSuperConstructorCall()) { |
2155 __ push(ecx); | 2040 __ push(ecx); |
2156 } | 2041 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2229 | 2114 |
2230 void CallICStub::Generate(MacroAssembler* masm) { | 2115 void CallICStub::Generate(MacroAssembler* masm) { |
2231 // edi - function | 2116 // edi - function |
2232 // edx - slot id | 2117 // edx - slot id |
2233 // ebx - vector | 2118 // ebx - vector |
2234 Isolate* isolate = masm->isolate(); | 2119 Isolate* isolate = masm->isolate(); |
2235 const int with_types_offset = | 2120 const int with_types_offset = |
2236 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 2121 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
2237 const int generic_offset = | 2122 const int generic_offset = |
2238 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 2123 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
2239 Label extra_checks_or_miss, slow_start; | 2124 Label extra_checks_or_miss, call; |
2240 Label slow, wrap, cont; | |
2241 Label have_js_function; | |
2242 int argc = arg_count(); | 2125 int argc = arg_count(); |
2243 ParameterCount actual(argc); | 2126 ParameterCount actual(argc); |
2244 | 2127 |
2245 // The checks. First, does edi match the recorded monomorphic target? | 2128 // The checks. First, does edi match the recorded monomorphic target? |
2246 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, | 2129 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, |
2247 FixedArray::kHeaderSize)); | 2130 FixedArray::kHeaderSize)); |
2248 | 2131 |
2249 // We don't know that we have a weak cell. We might have a private symbol | 2132 // We don't know that we have a weak cell. We might have a private symbol |
2250 // or an AllocationSite, but the memory is safe to examine. | 2133 // or an AllocationSite, but the memory is safe to examine. |
2251 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to | 2134 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |
(...skipping 13 matching lines...) Expand all Loading... |
2265 | 2148 |
2266 // The compare above could have been a SMI/SMI comparison. Guard against this | 2149 // The compare above could have been a SMI/SMI comparison. Guard against this |
2267 // convincing us that we have a monomorphic JSFunction. | 2150 // convincing us that we have a monomorphic JSFunction. |
2268 __ JumpIfSmi(edi, &extra_checks_or_miss); | 2151 __ JumpIfSmi(edi, &extra_checks_or_miss); |
2269 | 2152 |
2270 // Increment the call count for monomorphic function calls. | 2153 // Increment the call count for monomorphic function calls. |
2271 __ add(FieldOperand(ebx, edx, times_half_pointer_size, | 2154 __ add(FieldOperand(ebx, edx, times_half_pointer_size, |
2272 FixedArray::kHeaderSize + kPointerSize), | 2155 FixedArray::kHeaderSize + kPointerSize), |
2273 Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement))); | 2156 Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement))); |
2274 | 2157 |
2275 __ bind(&have_js_function); | 2158 __ bind(&call); |
2276 | 2159 __ Set(eax, argc); |
2277 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2160 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
2278 EmitClassConstructorCallCheck(masm); | |
2279 | |
2280 if (CallAsMethod()) { | |
2281 EmitContinueIfStrictOrNative(masm, &cont); | |
2282 | |
2283 // Load the receiver from the stack. | |
2284 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); | |
2285 | |
2286 __ JumpIfSmi(eax, &wrap); | |
2287 | |
2288 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | |
2289 __ j(below, &wrap); | |
2290 | |
2291 __ bind(&cont); | |
2292 } | |
2293 | |
2294 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); | |
2295 | |
2296 __ bind(&slow); | |
2297 EmitSlowCase(isolate, masm, argc); | |
2298 | |
2299 if (CallAsMethod()) { | |
2300 __ bind(&wrap); | |
2301 EmitWrapCase(masm, argc, &cont); | |
2302 } | |
2303 | 2161 |
2304 __ bind(&extra_checks_or_miss); | 2162 __ bind(&extra_checks_or_miss); |
2305 Label uninitialized, miss, not_allocation_site; | 2163 Label uninitialized, miss, not_allocation_site; |
2306 | 2164 |
2307 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); | 2165 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); |
2308 __ j(equal, &slow_start); | 2166 __ j(equal, &call); |
2309 | 2167 |
2310 // Check if we have an allocation site. | 2168 // Check if we have an allocation site. |
2311 __ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset), | 2169 __ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset), |
2312 Heap::kAllocationSiteMapRootIndex); | 2170 Heap::kAllocationSiteMapRootIndex); |
2313 __ j(not_equal, ¬_allocation_site); | 2171 __ j(not_equal, ¬_allocation_site); |
2314 | 2172 |
2315 // We have an allocation site. | 2173 // We have an allocation site. |
2316 HandleArrayCase(masm, &miss); | 2174 HandleArrayCase(masm, &miss); |
2317 | 2175 |
2318 __ bind(¬_allocation_site); | 2176 __ bind(¬_allocation_site); |
(...skipping 11 matching lines...) Expand all Loading... |
2330 // to handle it here. More complex cases are dealt with in the runtime. | 2188 // to handle it here. More complex cases are dealt with in the runtime. |
2331 __ AssertNotSmi(ecx); | 2189 __ AssertNotSmi(ecx); |
2332 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); | 2190 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); |
2333 __ j(not_equal, &miss); | 2191 __ j(not_equal, &miss); |
2334 __ mov( | 2192 __ mov( |
2335 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), | 2193 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), |
2336 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); | 2194 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); |
2337 // We have to update statistics for runtime profiling. | 2195 // We have to update statistics for runtime profiling. |
2338 __ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1))); | 2196 __ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1))); |
2339 __ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1))); | 2197 __ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1))); |
2340 __ jmp(&slow_start); | 2198 __ jmp(&call); |
2341 | 2199 |
2342 __ bind(&uninitialized); | 2200 __ bind(&uninitialized); |
2343 | 2201 |
2344 // We are going monomorphic, provided we actually have a JSFunction. | 2202 // We are going monomorphic, provided we actually have a JSFunction. |
2345 __ JumpIfSmi(edi, &miss); | 2203 __ JumpIfSmi(edi, &miss); |
2346 | 2204 |
2347 // Goto miss case if we do not have a function. | 2205 // Goto miss case if we do not have a function. |
2348 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2206 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2349 __ j(not_equal, &miss); | 2207 __ j(not_equal, &miss); |
2350 | 2208 |
(...skipping 16 matching lines...) Expand all Loading... |
2367 // edx - slot | 2225 // edx - slot |
2368 // edi - function | 2226 // edi - function |
2369 { | 2227 { |
2370 FrameScope scope(masm, StackFrame::INTERNAL); | 2228 FrameScope scope(masm, StackFrame::INTERNAL); |
2371 CreateWeakCellStub create_stub(isolate); | 2229 CreateWeakCellStub create_stub(isolate); |
2372 __ push(edi); | 2230 __ push(edi); |
2373 __ CallStub(&create_stub); | 2231 __ CallStub(&create_stub); |
2374 __ pop(edi); | 2232 __ pop(edi); |
2375 } | 2233 } |
2376 | 2234 |
2377 __ jmp(&have_js_function); | 2235 __ jmp(&call); |
2378 | 2236 |
2379 // We are here because tracing is on or we encountered a MISS case we can't | 2237 // We are here because tracing is on or we encountered a MISS case we can't |
2380 // handle here. | 2238 // handle here. |
2381 __ bind(&miss); | 2239 __ bind(&miss); |
2382 GenerateMiss(masm); | 2240 GenerateMiss(masm); |
2383 | 2241 |
2384 // the slow case | 2242 __ jmp(&call); |
2385 __ bind(&slow_start); | |
2386 | |
2387 // Check that the function really is a JavaScript function. | |
2388 __ JumpIfSmi(edi, &slow); | |
2389 | |
2390 // Goto slow case if we do not have a function. | |
2391 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | |
2392 __ j(not_equal, &slow); | |
2393 __ jmp(&have_js_function); | |
2394 | 2243 |
2395 // Unreachable | 2244 // Unreachable |
2396 __ int3(); | 2245 __ int3(); |
2397 } | 2246 } |
2398 | 2247 |
2399 | 2248 |
2400 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2249 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2401 FrameScope scope(masm, StackFrame::INTERNAL); | 2250 FrameScope scope(masm, StackFrame::INTERNAL); |
2402 | 2251 |
2403 // Push the function and feedback info. | 2252 // Push the function and feedback info. |
(...skipping 3492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5896 Operand(ebp, 7 * kPointerSize), NULL); | 5745 Operand(ebp, 7 * kPointerSize), NULL); |
5897 } | 5746 } |
5898 | 5747 |
5899 | 5748 |
5900 #undef __ | 5749 #undef __ |
5901 | 5750 |
5902 } // namespace internal | 5751 } // namespace internal |
5903 } // namespace v8 | 5752 } // namespace v8 |
5904 | 5753 |
5905 #endif // V8_TARGET_ARCH_IA32 | 5754 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |