| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 descriptor->register_param_count_ = 4; | 99 descriptor->register_param_count_ = 4; |
| 100 descriptor->register_params_ = registers; | 100 descriptor->register_params_ = registers; |
| 101 descriptor->deoptimization_handler_ = | 101 descriptor->deoptimization_handler_ = |
| 102 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry; | 102 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry; |
| 103 } | 103 } |
| 104 | 104 |
| 105 | 105 |
| 106 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | 106 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 107 Isolate* isolate, | 107 Isolate* isolate, |
| 108 CodeStubInterfaceDescriptor* descriptor) { | 108 CodeStubInterfaceDescriptor* descriptor) { |
| 109 static Register registers[] = { rbx, rdx }; | 109 static Register registers[] = { rbx }; |
| 110 descriptor->register_param_count_ = 2; | 110 descriptor->register_param_count_ = 1; |
| 111 descriptor->register_params_ = registers; | 111 descriptor->register_params_ = registers; |
| 112 descriptor->deoptimization_handler_ = NULL; | 112 descriptor->deoptimization_handler_ = NULL; |
| 113 } | 113 } |
| 114 | 114 |
| 115 | 115 |
| 116 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 116 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
| 117 Isolate* isolate, | 117 Isolate* isolate, |
| 118 CodeStubInterfaceDescriptor* descriptor) { | 118 CodeStubInterfaceDescriptor* descriptor) { |
| 119 static Register registers[] = { rdx, rax }; | 119 static Register registers[] = { rdx, rax }; |
| 120 descriptor->register_param_count_ = 2; | 120 descriptor->register_param_count_ = 2; |
| (...skipping 2033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2154 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 2154 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
| 2155 // tagged as a small integer. | 2155 // tagged as a small integer. |
| 2156 __ InvokeBuiltin(builtin, JUMP_FUNCTION); | 2156 __ InvokeBuiltin(builtin, JUMP_FUNCTION); |
| 2157 | 2157 |
| 2158 __ bind(&miss); | 2158 __ bind(&miss); |
| 2159 GenerateMiss(masm); | 2159 GenerateMiss(masm); |
| 2160 } | 2160 } |
| 2161 | 2161 |
| 2162 | 2162 |
| 2163 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 2163 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
| 2164 // Cache the called function in a feedback vector slot. Cache states | 2164 // Cache the called function in a global property cell. Cache states |
| 2165 // are uninitialized, monomorphic (indicated by a JSFunction), and | 2165 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 2166 // megamorphic. | 2166 // megamorphic. |
| 2167 // rax : number of arguments to the construct function | 2167 // rax : number of arguments to the construct function |
| 2168 // rbx : Feedback vector | 2168 // rbx : cache cell for call target |
| 2169 // rdx : slot in feedback vector (Smi) | |
| 2170 // rdi : the function to call | 2169 // rdi : the function to call |
| 2171 Isolate* isolate = masm->isolate(); | 2170 Isolate* isolate = masm->isolate(); |
| 2172 Label initialize, done, miss, megamorphic, not_array_function, | 2171 Label initialize, done, miss, megamorphic, not_array_function; |
| 2173 done_no_smi_convert; | |
| 2174 | 2172 |
| 2175 // Load the cache state into rcx. | 2173 // Load the cache state into rcx. |
| 2176 __ SmiToInteger32(rdx, rdx); | 2174 __ movp(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
| 2177 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, | |
| 2178 FixedArray::kHeaderSize)); | |
| 2179 | 2175 |
| 2180 // A monomorphic cache hit or an already megamorphic state: invoke the | 2176 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 2181 // function without changing the state. | 2177 // function without changing the state. |
| 2182 __ cmpq(rcx, rdi); | 2178 __ cmpq(rcx, rdi); |
| 2183 __ j(equal, &done); | 2179 __ j(equal, &done); |
| 2184 __ Cmp(rcx, TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2180 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 2185 __ j(equal, &done); | 2181 __ j(equal, &done); |
| 2186 | 2182 |
| 2187 // If we came here, we need to see if we are the array function. | 2183 // If we came here, we need to see if we are the array function. |
| 2188 // If we didn't have a matching function, and we didn't find the megamorph | 2184 // If we didn't have a matching function, and we didn't find the megamorph |
| 2189 // sentinel, then we have in the slot either some other function or an | 2185 // sentinel, then we have in the cell either some other function or an |
| 2190 // AllocationSite. Do a map check on the object in rcx. | 2186 // AllocationSite. Do a map check on the object in rcx. |
| 2191 Handle<Map> allocation_site_map = | 2187 Handle<Map> allocation_site_map = |
| 2192 masm->isolate()->factory()->allocation_site_map(); | 2188 masm->isolate()->factory()->allocation_site_map(); |
| 2193 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); | 2189 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); |
| 2194 __ j(not_equal, &miss); | 2190 __ j(not_equal, &miss); |
| 2195 | 2191 |
| 2196 // Make sure the function is the Array() function | 2192 // Make sure the function is the Array() function |
| 2197 __ LoadArrayFunction(rcx); | 2193 __ LoadArrayFunction(rcx); |
| 2198 __ cmpq(rdi, rcx); | 2194 __ cmpq(rdi, rcx); |
| 2199 __ j(not_equal, &megamorphic); | 2195 __ j(not_equal, &megamorphic); |
| 2200 __ jmp(&done); | 2196 __ jmp(&done); |
| 2201 | 2197 |
| 2202 __ bind(&miss); | 2198 __ bind(&miss); |
| 2203 | 2199 |
| 2204 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2200 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 2205 // megamorphic. | 2201 // megamorphic. |
| 2206 __ Cmp(rcx, TypeFeedbackInfo::UninitializedSentinel(isolate)); | 2202 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
| 2207 __ j(equal, &initialize); | 2203 __ j(equal, &initialize); |
| 2208 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2204 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 2209 // write-barrier is needed. | 2205 // write-barrier is needed. |
| 2210 __ bind(&megamorphic); | 2206 __ bind(&megamorphic); |
| 2211 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), | 2207 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
| 2212 TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2208 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 2213 __ jmp(&done); | 2209 __ jmp(&done); |
| 2214 | 2210 |
| 2215 // An uninitialized cache is patched with the function or sentinel to | 2211 // An uninitialized cache is patched with the function or sentinel to |
| 2216 // indicate the ElementsKind if function is the Array constructor. | 2212 // indicate the ElementsKind if function is the Array constructor. |
| 2217 __ bind(&initialize); | 2213 __ bind(&initialize); |
| 2218 // Make sure the function is the Array() function | 2214 // Make sure the function is the Array() function |
| 2219 __ LoadArrayFunction(rcx); | 2215 __ LoadArrayFunction(rcx); |
| 2220 __ cmpq(rdi, rcx); | 2216 __ cmpq(rdi, rcx); |
| 2221 __ j(not_equal, ¬_array_function); | 2217 __ j(not_equal, ¬_array_function); |
| 2222 | 2218 |
| 2223 // The target function is the Array constructor, | 2219 // The target function is the Array constructor, |
| 2224 // Create an AllocationSite if we don't already have it, store it in the slot. | 2220 // Create an AllocationSite if we don't already have it, store it in the cell |
| 2225 { | 2221 { |
| 2226 FrameScope scope(masm, StackFrame::INTERNAL); | 2222 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2227 | 2223 |
| 2228 // Arguments register must be smi-tagged to call out. | 2224 // Arguments register must be smi-tagged to call out. |
| 2229 __ Integer32ToSmi(rax, rax); | 2225 __ Integer32ToSmi(rax, rax); |
| 2230 __ push(rax); | 2226 __ push(rax); |
| 2231 __ push(rdi); | 2227 __ push(rdi); |
| 2232 __ Integer32ToSmi(rdx, rdx); | |
| 2233 __ push(rdx); | |
| 2234 __ push(rbx); | 2228 __ push(rbx); |
| 2235 | 2229 |
| 2236 CreateAllocationSiteStub create_stub; | 2230 CreateAllocationSiteStub create_stub; |
| 2237 __ CallStub(&create_stub); | 2231 __ CallStub(&create_stub); |
| 2238 | 2232 |
| 2239 __ pop(rbx); | 2233 __ pop(rbx); |
| 2240 __ pop(rdx); | |
| 2241 __ pop(rdi); | 2234 __ pop(rdi); |
| 2242 __ pop(rax); | 2235 __ pop(rax); |
| 2243 __ SmiToInteger32(rax, rax); | 2236 __ SmiToInteger32(rax, rax); |
| 2244 } | 2237 } |
| 2245 __ jmp(&done_no_smi_convert); | 2238 __ jmp(&done); |
| 2246 | 2239 |
| 2247 __ bind(¬_array_function); | 2240 __ bind(¬_array_function); |
| 2248 __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), | 2241 __ movp(FieldOperand(rbx, Cell::kValueOffset), rdi); |
| 2249 rdi); | 2242 // No need for a write barrier here - cells are rescanned. |
| 2250 | |
| 2251 // We won't need rdx or rbx anymore, just save rdi | |
| 2252 __ push(rdi); | |
| 2253 __ push(rbx); | |
| 2254 __ push(rdx); | |
| 2255 __ RecordWriteArray(rbx, rdi, rdx, kDontSaveFPRegs, | |
| 2256 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
| 2257 __ pop(rdx); | |
| 2258 __ pop(rbx); | |
| 2259 __ pop(rdi); | |
| 2260 | 2243 |
| 2261 __ bind(&done); | 2244 __ bind(&done); |
| 2262 __ Integer32ToSmi(rdx, rdx); | |
| 2263 | |
| 2264 __ bind(&done_no_smi_convert); | |
| 2265 } | 2245 } |
| 2266 | 2246 |
| 2267 | 2247 |
| 2268 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2248 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 2269 // rbx : feedback vector | 2249 // rbx : cache cell for call target |
| 2270 // rdx : (only if rbx is not undefined) slot in feedback vector (Smi) | |
| 2271 // rdi : the function to call | 2250 // rdi : the function to call |
| 2272 Isolate* isolate = masm->isolate(); | 2251 Isolate* isolate = masm->isolate(); |
| 2273 Label slow, non_function, wrap, cont; | 2252 Label slow, non_function, wrap, cont; |
| 2274 StackArgumentsAccessor args(rsp, argc_); | 2253 StackArgumentsAccessor args(rsp, argc_); |
| 2275 | 2254 |
| 2276 if (NeedsChecks()) { | 2255 if (NeedsChecks()) { |
| 2277 // Check that the function really is a JavaScript function. | 2256 // Check that the function really is a JavaScript function. |
| 2278 __ JumpIfSmi(rdi, &non_function); | 2257 __ JumpIfSmi(rdi, &non_function); |
| 2279 | 2258 |
| 2280 // Goto slow case if we do not have a function. | 2259 // Goto slow case if we do not have a function. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2297 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | 2276 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); |
| 2298 __ j(not_equal, &cont); | 2277 __ j(not_equal, &cont); |
| 2299 | 2278 |
| 2300 // Do not transform the receiver for natives. | 2279 // Do not transform the receiver for natives. |
| 2301 // SharedFunctionInfo is already loaded into rcx. | 2280 // SharedFunctionInfo is already loaded into rcx. |
| 2302 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), | 2281 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), |
| 2303 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | 2282 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
| 2304 __ j(not_equal, &cont); | 2283 __ j(not_equal, &cont); |
| 2305 } | 2284 } |
| 2306 | 2285 |
| 2307 | |
| 2308 // Load the receiver from the stack. | 2286 // Load the receiver from the stack. |
| 2309 __ movp(rax, args.GetReceiverOperand()); | 2287 __ movp(rax, args.GetReceiverOperand()); |
| 2310 | 2288 |
| 2311 if (NeedsChecks()) { | 2289 if (NeedsChecks()) { |
| 2312 __ JumpIfSmi(rax, &wrap); | 2290 __ JumpIfSmi(rax, &wrap); |
| 2313 | 2291 |
| 2314 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 2292 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); |
| 2315 __ j(below, &wrap); | 2293 __ j(below, &wrap); |
| 2316 } else { | 2294 } else { |
| 2317 __ jmp(&wrap); | 2295 __ jmp(&wrap); |
| 2318 } | 2296 } |
| 2319 | 2297 |
| 2320 __ bind(&cont); | 2298 __ bind(&cont); |
| 2321 } | 2299 } |
| 2322 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2300 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 2323 | 2301 |
| 2324 if (NeedsChecks()) { | 2302 if (NeedsChecks()) { |
| 2325 // Slow-case: Non-function called. | 2303 // Slow-case: Non-function called. |
| 2326 __ bind(&slow); | 2304 __ bind(&slow); |
| 2327 if (RecordCallTarget()) { | 2305 if (RecordCallTarget()) { |
| 2328 // If there is a call target cache, mark it megamorphic in the | 2306 // If there is a call target cache, mark it megamorphic in the |
| 2329 // non-function case. MegamorphicSentinel is an immortal immovable | 2307 // non-function case. MegamorphicSentinel is an immortal immovable |
| 2330 // object (undefined) so no write barrier is needed. | 2308 // object (undefined) so no write barrier is needed. |
| 2331 __ SmiToInteger32(rdx, rdx); | 2309 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
| 2332 __ Move(FieldOperand(rbx, rdx, times_pointer_size, | 2310 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 2333 FixedArray::kHeaderSize), | |
| 2334 TypeFeedbackInfo::MegamorphicSentinel(isolate)); | |
| 2335 __ Integer32ToSmi(rdx, rdx); | |
| 2336 } | 2311 } |
| 2337 // Check for function proxy. | 2312 // Check for function proxy. |
| 2338 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 2313 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
| 2339 __ j(not_equal, &non_function); | 2314 __ j(not_equal, &non_function); |
| 2340 __ PopReturnAddressTo(rcx); | 2315 __ PopReturnAddressTo(rcx); |
| 2341 __ push(rdi); // put proxy as additional argument under return address | 2316 __ push(rdi); // put proxy as additional argument under return address |
| 2342 __ PushReturnAddressFrom(rcx); | 2317 __ PushReturnAddressFrom(rcx); |
| 2343 __ Set(rax, argc_ + 1); | 2318 __ Set(rax, argc_ + 1); |
| 2344 __ Set(rbx, 0); | 2319 __ Set(rbx, 0); |
| 2345 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 2320 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2371 __ pop(rdi); | 2346 __ pop(rdi); |
| 2372 } | 2347 } |
| 2373 __ movp(args.GetReceiverOperand(), rax); | 2348 __ movp(args.GetReceiverOperand(), rax); |
| 2374 __ jmp(&cont); | 2349 __ jmp(&cont); |
| 2375 } | 2350 } |
| 2376 } | 2351 } |
| 2377 | 2352 |
| 2378 | 2353 |
| 2379 void CallConstructStub::Generate(MacroAssembler* masm) { | 2354 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 2380 // rax : number of arguments | 2355 // rax : number of arguments |
| 2381 // rbx : feedback vector | 2356 // rbx : cache cell for call target |
| 2382 // rdx : (only if rbx is not undefined) slot in feedback vector (Smi) | |
| 2383 // rdi : constructor function | 2357 // rdi : constructor function |
| 2384 Label slow, non_function_call; | 2358 Label slow, non_function_call; |
| 2385 | 2359 |
| 2386 // Check that function is not a smi. | 2360 // Check that function is not a smi. |
| 2387 __ JumpIfSmi(rdi, &non_function_call); | 2361 __ JumpIfSmi(rdi, &non_function_call); |
| 2388 // Check that function is a JSFunction. | 2362 // Check that function is a JSFunction. |
| 2389 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2363 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 2390 __ j(not_equal, &slow); | 2364 __ j(not_equal, &slow); |
| 2391 | 2365 |
| 2392 if (RecordCallTarget()) { | 2366 if (RecordCallTarget()) { |
| (...skipping 2493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4886 ArraySingleArgumentConstructorStub stub_holey(holey_initial, | 4860 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
| 4887 DISABLE_ALLOCATION_SITES); | 4861 DISABLE_ALLOCATION_SITES); |
| 4888 __ TailCallStub(&stub_holey); | 4862 __ TailCallStub(&stub_holey); |
| 4889 | 4863 |
| 4890 __ bind(&normal_sequence); | 4864 __ bind(&normal_sequence); |
| 4891 ArraySingleArgumentConstructorStub stub(initial, | 4865 ArraySingleArgumentConstructorStub stub(initial, |
| 4892 DISABLE_ALLOCATION_SITES); | 4866 DISABLE_ALLOCATION_SITES); |
| 4893 __ TailCallStub(&stub); | 4867 __ TailCallStub(&stub); |
| 4894 } else if (mode == DONT_OVERRIDE) { | 4868 } else if (mode == DONT_OVERRIDE) { |
| 4895 // We are going to create a holey array, but our kind is non-holey. | 4869 // We are going to create a holey array, but our kind is non-holey. |
| 4896 // Fix kind and retry (only if we have an allocation site in the slot). | 4870 // Fix kind and retry (only if we have an allocation site in the cell). |
| 4897 __ incl(rdx); | 4871 __ incl(rdx); |
| 4898 | 4872 |
| 4899 if (FLAG_debug_code) { | 4873 if (FLAG_debug_code) { |
| 4900 Handle<Map> allocation_site_map = | 4874 Handle<Map> allocation_site_map = |
| 4901 masm->isolate()->factory()->allocation_site_map(); | 4875 masm->isolate()->factory()->allocation_site_map(); |
| 4902 __ Cmp(FieldOperand(rbx, 0), allocation_site_map); | 4876 __ Cmp(FieldOperand(rbx, 0), allocation_site_map); |
| 4903 __ Assert(equal, kExpectedAllocationSite); | 4877 __ Assert(equal, kExpectedAllocationSite); |
| 4904 } | 4878 } |
| 4905 | 4879 |
| 4906 // Save the resulting elements kind in type info. We can't just store r3 | 4880 // Save the resulting elements kind in type info. We can't just store r3 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4996 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4970 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 4997 } else { | 4971 } else { |
| 4998 UNREACHABLE(); | 4972 UNREACHABLE(); |
| 4999 } | 4973 } |
| 5000 } | 4974 } |
| 5001 | 4975 |
| 5002 | 4976 |
| 5003 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 4977 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5004 // ----------- S t a t e ------------- | 4978 // ----------- S t a t e ------------- |
| 5005 // -- rax : argc | 4979 // -- rax : argc |
| 5006 // -- rbx : feedback vector (fixed array or undefined) | 4980 // -- rbx : type info cell |
| 5007 // -- rdx : slot index (if ebx is fixed array) | |
| 5008 // -- rdi : constructor | 4981 // -- rdi : constructor |
| 5009 // -- rsp[0] : return address | 4982 // -- rsp[0] : return address |
| 5010 // -- rsp[8] : last argument | 4983 // -- rsp[8] : last argument |
| 5011 // ----------------------------------- | 4984 // ----------------------------------- |
| 5012 Handle<Object> undefined_sentinel( | 4985 Handle<Object> undefined_sentinel( |
| 5013 masm->isolate()->heap()->undefined_value(), | 4986 masm->isolate()->heap()->undefined_value(), |
| 5014 masm->isolate()); | 4987 masm->isolate()); |
| 5015 | 4988 |
| 5016 if (FLAG_debug_code) { | 4989 if (FLAG_debug_code) { |
| 5017 // The array construct code is only set for the global and natives | 4990 // The array construct code is only set for the global and natives |
| 5018 // builtin Array functions which always have maps. | 4991 // builtin Array functions which always have maps. |
| 5019 | 4992 |
| 5020 // Initial map for the builtin Array function should be a map. | 4993 // Initial map for the builtin Array function should be a map. |
| 5021 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 4994 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
| 5022 // Will both indicate a NULL and a Smi. | 4995 // Will both indicate a NULL and a Smi. |
| 5023 STATIC_ASSERT(kSmiTag == 0); | 4996 STATIC_ASSERT(kSmiTag == 0); |
| 5024 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); | 4997 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); |
| 5025 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); | 4998 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); |
| 5026 __ CmpObjectType(rcx, MAP_TYPE, rcx); | 4999 __ CmpObjectType(rcx, MAP_TYPE, rcx); |
| 5027 __ Check(equal, kUnexpectedInitialMapForArrayFunction); | 5000 __ Check(equal, kUnexpectedInitialMapForArrayFunction); |
| 5028 | 5001 |
| 5029 // We should either have undefined in rbx or a valid fixed array. | 5002 // We should either have undefined in rbx or a valid cell |
| 5030 Label okay_here; | 5003 Label okay_here; |
| 5031 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); | 5004 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
| 5032 __ Cmp(rbx, undefined_sentinel); | 5005 __ Cmp(rbx, undefined_sentinel); |
| 5033 __ j(equal, &okay_here); | 5006 __ j(equal, &okay_here); |
| 5034 __ Cmp(FieldOperand(rbx, 0), fixed_array_map); | 5007 __ Cmp(FieldOperand(rbx, 0), cell_map); |
| 5035 __ Assert(equal, kExpectedFixedArrayInRegisterRbx); | 5008 __ Assert(equal, kExpectedPropertyCellInRegisterRbx); |
| 5036 | |
| 5037 // rdx should be a smi if we don't have undefined in rbx. | |
| 5038 __ AssertSmi(rdx); | |
| 5039 | |
| 5040 __ bind(&okay_here); | 5009 __ bind(&okay_here); |
| 5041 } | 5010 } |
| 5042 | 5011 |
| 5043 Label no_info; | 5012 Label no_info; |
| 5044 // If the feedback slot is undefined, or contains anything other than an | 5013 // If the type cell is undefined, or contains anything other than an |
| 5045 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5014 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 5046 __ Cmp(rbx, undefined_sentinel); | 5015 __ Cmp(rbx, undefined_sentinel); |
| 5047 __ j(equal, &no_info); | 5016 __ j(equal, &no_info); |
| 5048 __ SmiToInteger32(rdx, rdx); | 5017 __ movp(rbx, FieldOperand(rbx, Cell::kValueOffset)); |
| 5049 __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, | |
| 5050 FixedArray::kHeaderSize)); | |
| 5051 __ Integer32ToSmi(rdx, rdx); | |
| 5052 __ Cmp(FieldOperand(rbx, 0), | 5018 __ Cmp(FieldOperand(rbx, 0), |
| 5053 masm->isolate()->factory()->allocation_site_map()); | 5019 masm->isolate()->factory()->allocation_site_map()); |
| 5054 __ j(not_equal, &no_info); | 5020 __ j(not_equal, &no_info); |
| 5055 | 5021 |
| 5056 // Only look at the lower 16 bits of the transition info. | 5022 // Only look at the lower 16 bits of the transition info. |
| 5057 __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset)); | 5023 __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset)); |
| 5058 __ SmiToInteger32(rdx, rdx); | 5024 __ SmiToInteger32(rdx, rdx); |
| 5059 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5025 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
| 5060 __ and_(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); | 5026 __ and_(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); |
| 5061 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5027 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5098 | 5064 |
| 5099 __ bind(¬_one_case); | 5065 __ bind(¬_one_case); |
| 5100 InternalArrayNArgumentsConstructorStub stubN(kind); | 5066 InternalArrayNArgumentsConstructorStub stubN(kind); |
| 5101 __ TailCallStub(&stubN); | 5067 __ TailCallStub(&stubN); |
| 5102 } | 5068 } |
| 5103 | 5069 |
| 5104 | 5070 |
| 5105 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { | 5071 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5106 // ----------- S t a t e ------------- | 5072 // ----------- S t a t e ------------- |
| 5107 // -- rax : argc | 5073 // -- rax : argc |
| 5074 // -- rbx : type info cell |
| 5108 // -- rdi : constructor | 5075 // -- rdi : constructor |
| 5109 // -- rsp[0] : return address | 5076 // -- rsp[0] : return address |
| 5110 // -- rsp[8] : last argument | 5077 // -- rsp[8] : last argument |
| 5111 // ----------------------------------- | 5078 // ----------------------------------- |
| 5112 | 5079 |
| 5113 if (FLAG_debug_code) { | 5080 if (FLAG_debug_code) { |
| 5114 // The array construct code is only set for the global and natives | 5081 // The array construct code is only set for the global and natives |
| 5115 // builtin Array functions which always have maps. | 5082 // builtin Array functions which always have maps. |
| 5116 | 5083 |
| 5117 // Initial map for the builtin Array function should be a map. | 5084 // Initial map for the builtin Array function should be a map. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5170 // ----------------------------------- | 5137 // ----------------------------------- |
| 5171 | 5138 |
| 5172 Register callee = rax; | 5139 Register callee = rax; |
| 5173 Register call_data = rbx; | 5140 Register call_data = rbx; |
| 5174 Register holder = rcx; | 5141 Register holder = rcx; |
| 5175 Register api_function_address = rdx; | 5142 Register api_function_address = rdx; |
| 5176 Register return_address = rdi; | 5143 Register return_address = rdi; |
| 5177 Register context = rsi; | 5144 Register context = rsi; |
| 5178 | 5145 |
| 5179 int argc = ArgumentBits::decode(bit_field_); | 5146 int argc = ArgumentBits::decode(bit_field_); |
| 5180 bool is_store = IsStoreBits::decode(bit_field_); | 5147 bool restore_context = RestoreContextBits::decode(bit_field_); |
| 5181 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 5148 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); |
| 5182 | 5149 |
| 5183 typedef FunctionCallbackArguments FCA; | 5150 typedef FunctionCallbackArguments FCA; |
| 5184 | 5151 |
| 5185 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5152 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 5186 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5153 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 5187 STATIC_ASSERT(FCA::kDataIndex == 4); | 5154 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 5188 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5155 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 5189 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5156 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 5190 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5157 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5246 | 5213 |
| 5247 // It's okay if api_function_address == callback_arg | 5214 // It's okay if api_function_address == callback_arg |
| 5248 // but not arguments_arg | 5215 // but not arguments_arg |
| 5249 ASSERT(!api_function_address.is(arguments_arg)); | 5216 ASSERT(!api_function_address.is(arguments_arg)); |
| 5250 | 5217 |
| 5251 // v8::InvocationCallback's argument. | 5218 // v8::InvocationCallback's argument. |
| 5252 __ lea(arguments_arg, StackSpaceOperand(0)); | 5219 __ lea(arguments_arg, StackSpaceOperand(0)); |
| 5253 | 5220 |
| 5254 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 5221 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
| 5255 | 5222 |
| 5256 // Accessor for FunctionCallbackInfo and first js arg. | 5223 StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength, |
| 5257 StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, | |
| 5258 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 5224 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 5259 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( | 5225 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( |
| 5260 FCA::kArgsLength - FCA::kContextSaveIndex); | 5226 FCA::kArgsLength - 1 - FCA::kContextSaveIndex); |
| 5261 // Stores return the first js argument | |
| 5262 Operand return_value_operand = args_from_rbp.GetArgumentOperand( | 5227 Operand return_value_operand = args_from_rbp.GetArgumentOperand( |
| 5263 is_store ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset); | 5228 FCA::kArgsLength - 1 - FCA::kReturnValueOffset); |
| 5264 __ CallApiFunctionAndReturn( | 5229 __ CallApiFunctionAndReturn( |
| 5265 api_function_address, | 5230 api_function_address, |
| 5266 thunk_address, | 5231 thunk_address, |
| 5267 callback_arg, | 5232 callback_arg, |
| 5268 argc + FCA::kArgsLength + 1, | 5233 argc + FCA::kArgsLength + 1, |
| 5269 return_value_operand, | 5234 return_value_operand, |
| 5270 &context_restore_operand); | 5235 restore_context ? &context_restore_operand : NULL); |
| 5271 } | 5236 } |
| 5272 | 5237 |
| 5273 | 5238 |
| 5274 void CallApiGetterStub::Generate(MacroAssembler* masm) { | 5239 void CallApiGetterStub::Generate(MacroAssembler* masm) { |
| 5275 // ----------- S t a t e ------------- | 5240 // ----------- S t a t e ------------- |
| 5276 // -- rsp[0] : return address | 5241 // -- rsp[0] : return address |
| 5277 // -- rsp[8] : name | 5242 // -- rsp[8] : name |
| 5278 // -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object | 5243 // -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object |
| 5279 // -- ... | 5244 // -- ... |
| 5280 // -- r8 : api_function_address | 5245 // -- r8 : api_function_address |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5329 return_value_operand, | 5294 return_value_operand, |
| 5330 NULL); | 5295 NULL); |
| 5331 } | 5296 } |
| 5332 | 5297 |
| 5333 | 5298 |
| 5334 #undef __ | 5299 #undef __ |
| 5335 | 5300 |
| 5336 } } // namespace v8::internal | 5301 } } // namespace v8::internal |
| 5337 | 5302 |
| 5338 #endif // V8_TARGET_ARCH_X64 | 5303 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |