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 }; | 109 static Register registers[] = { rbx, rdx }; |
110 descriptor->register_param_count_ = 1; | 110 descriptor->register_param_count_ = 2; |
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 global property cell. Cache states | 2164 // Cache the called function in a feedback vector slot. 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 : cache cell for call target | 2168 // rbx : Feedback vector |
| 2169 // rdx : slot in feedback vector (Smi) |
2169 // rdi : the function to call | 2170 // rdi : the function to call |
2170 Isolate* isolate = masm->isolate(); | 2171 Isolate* isolate = masm->isolate(); |
2171 Label initialize, done, miss, megamorphic, not_array_function; | 2172 Label initialize, done, miss, megamorphic, not_array_function, |
| 2173 done_no_smi_convert; |
2172 | 2174 |
2173 // Load the cache state into rcx. | 2175 // Load the cache state into rcx. |
2174 __ movp(rcx, FieldOperand(rbx, Cell::kValueOffset)); | 2176 __ SmiToInteger32(rdx, rdx); |
| 2177 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, |
| 2178 FixedArray::kHeaderSize)); |
2175 | 2179 |
2176 // A monomorphic cache hit or an already megamorphic state: invoke the | 2180 // A monomorphic cache hit or an already megamorphic state: invoke the |
2177 // function without changing the state. | 2181 // function without changing the state. |
2178 __ cmpq(rcx, rdi); | 2182 __ cmpq(rcx, rdi); |
2179 __ j(equal, &done); | 2183 __ j(equal, &done); |
2180 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); | 2184 __ Cmp(rcx, TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
2181 __ j(equal, &done); | 2185 __ j(equal, &done); |
2182 | 2186 |
2183 // If we came here, we need to see if we are the array function. | 2187 // If we came here, we need to see if we are the array function. |
2184 // If we didn't have a matching function, and we didn't find the megamorph | 2188 // If we didn't have a matching function, and we didn't find the megamorph |
2185 // sentinel, then we have in the cell either some other function or an | 2189 // sentinel, then we have in the slot either some other function or an |
2186 // AllocationSite. Do a map check on the object in rcx. | 2190 // AllocationSite. Do a map check on the object in rcx. |
2187 Handle<Map> allocation_site_map = | 2191 Handle<Map> allocation_site_map = |
2188 masm->isolate()->factory()->allocation_site_map(); | 2192 masm->isolate()->factory()->allocation_site_map(); |
2189 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); | 2193 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); |
2190 __ j(not_equal, &miss); | 2194 __ j(not_equal, &miss); |
2191 | 2195 |
2192 // Make sure the function is the Array() function | 2196 // Make sure the function is the Array() function |
2193 __ LoadArrayFunction(rcx); | 2197 __ LoadArrayFunction(rcx); |
2194 __ cmpq(rdi, rcx); | 2198 __ cmpq(rdi, rcx); |
2195 __ j(not_equal, &megamorphic); | 2199 __ j(not_equal, &megamorphic); |
2196 __ jmp(&done); | 2200 __ jmp(&done); |
2197 | 2201 |
2198 __ bind(&miss); | 2202 __ bind(&miss); |
2199 | 2203 |
2200 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2204 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
2201 // megamorphic. | 2205 // megamorphic. |
2202 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); | 2206 __ Cmp(rcx, TypeFeedbackInfo::UninitializedSentinel(isolate)); |
2203 __ j(equal, &initialize); | 2207 __ j(equal, &initialize); |
2204 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2208 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
2205 // write-barrier is needed. | 2209 // write-barrier is needed. |
2206 __ bind(&megamorphic); | 2210 __ bind(&megamorphic); |
2207 __ Move(FieldOperand(rbx, Cell::kValueOffset), | 2211 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
2208 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 2212 TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
2209 __ jmp(&done); | 2213 __ jmp(&done); |
2210 | 2214 |
2211 // An uninitialized cache is patched with the function or sentinel to | 2215 // An uninitialized cache is patched with the function or sentinel to |
2212 // indicate the ElementsKind if function is the Array constructor. | 2216 // indicate the ElementsKind if function is the Array constructor. |
2213 __ bind(&initialize); | 2217 __ bind(&initialize); |
2214 // Make sure the function is the Array() function | 2218 // Make sure the function is the Array() function |
2215 __ LoadArrayFunction(rcx); | 2219 __ LoadArrayFunction(rcx); |
2216 __ cmpq(rdi, rcx); | 2220 __ cmpq(rdi, rcx); |
2217 __ j(not_equal, ¬_array_function); | 2221 __ j(not_equal, ¬_array_function); |
2218 | 2222 |
2219 // The target function is the Array constructor, | 2223 // The target function is the Array constructor, |
2220 // Create an AllocationSite if we don't already have it, store it in the cell | 2224 // Create an AllocationSite if we don't already have it, store it in the slot. |
2221 { | 2225 { |
2222 FrameScope scope(masm, StackFrame::INTERNAL); | 2226 FrameScope scope(masm, StackFrame::INTERNAL); |
2223 | 2227 |
2224 // Arguments register must be smi-tagged to call out. | 2228 // Arguments register must be smi-tagged to call out. |
2225 __ Integer32ToSmi(rax, rax); | 2229 __ Integer32ToSmi(rax, rax); |
2226 __ push(rax); | 2230 __ push(rax); |
2227 __ push(rdi); | 2231 __ push(rdi); |
| 2232 __ Integer32ToSmi(rdx, rdx); |
| 2233 __ push(rdx); |
2228 __ push(rbx); | 2234 __ push(rbx); |
2229 | 2235 |
2230 CreateAllocationSiteStub create_stub; | 2236 CreateAllocationSiteStub create_stub; |
2231 __ CallStub(&create_stub); | 2237 __ CallStub(&create_stub); |
2232 | 2238 |
2233 __ pop(rbx); | 2239 __ pop(rbx); |
| 2240 __ pop(rdx); |
2234 __ pop(rdi); | 2241 __ pop(rdi); |
2235 __ pop(rax); | 2242 __ pop(rax); |
2236 __ SmiToInteger32(rax, rax); | 2243 __ SmiToInteger32(rax, rax); |
2237 } | 2244 } |
2238 __ jmp(&done); | 2245 __ jmp(&done_no_smi_convert); |
2239 | 2246 |
2240 __ bind(¬_array_function); | 2247 __ bind(¬_array_function); |
2241 __ movp(FieldOperand(rbx, Cell::kValueOffset), rdi); | 2248 __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
2242 // No need for a write barrier here - cells are rescanned. | 2249 rdi); |
| 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); |
2243 | 2260 |
2244 __ bind(&done); | 2261 __ bind(&done); |
| 2262 __ Integer32ToSmi(rdx, rdx); |
| 2263 |
| 2264 __ bind(&done_no_smi_convert); |
2245 } | 2265 } |
2246 | 2266 |
2247 | 2267 |
2248 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2268 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2249 // rbx : cache cell for call target | 2269 // rbx : feedback vector |
| 2270 // rdx : (only if rbx is not undefined) slot in feedback vector (Smi) |
2250 // rdi : the function to call | 2271 // rdi : the function to call |
2251 Isolate* isolate = masm->isolate(); | 2272 Isolate* isolate = masm->isolate(); |
2252 Label slow, non_function, wrap, cont; | 2273 Label slow, non_function, wrap, cont; |
2253 StackArgumentsAccessor args(rsp, argc_); | 2274 StackArgumentsAccessor args(rsp, argc_); |
2254 | 2275 |
2255 if (NeedsChecks()) { | 2276 if (NeedsChecks()) { |
2256 // Check that the function really is a JavaScript function. | 2277 // Check that the function really is a JavaScript function. |
2257 __ JumpIfSmi(rdi, &non_function); | 2278 __ JumpIfSmi(rdi, &non_function); |
2258 | 2279 |
2259 // Goto slow case if we do not have a function. | 2280 // Goto slow case if we do not have a function. |
(...skipping 16 matching lines...) Expand all Loading... |
2276 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | 2297 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); |
2277 __ j(not_equal, &cont); | 2298 __ j(not_equal, &cont); |
2278 | 2299 |
2279 // Do not transform the receiver for natives. | 2300 // Do not transform the receiver for natives. |
2280 // SharedFunctionInfo is already loaded into rcx. | 2301 // SharedFunctionInfo is already loaded into rcx. |
2281 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), | 2302 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), |
2282 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | 2303 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
2283 __ j(not_equal, &cont); | 2304 __ j(not_equal, &cont); |
2284 } | 2305 } |
2285 | 2306 |
| 2307 |
2286 // Load the receiver from the stack. | 2308 // Load the receiver from the stack. |
2287 __ movp(rax, args.GetReceiverOperand()); | 2309 __ movp(rax, args.GetReceiverOperand()); |
2288 | 2310 |
2289 if (NeedsChecks()) { | 2311 if (NeedsChecks()) { |
2290 __ JumpIfSmi(rax, &wrap); | 2312 __ JumpIfSmi(rax, &wrap); |
2291 | 2313 |
2292 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 2314 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); |
2293 __ j(below, &wrap); | 2315 __ j(below, &wrap); |
2294 } else { | 2316 } else { |
2295 __ jmp(&wrap); | 2317 __ jmp(&wrap); |
2296 } | 2318 } |
2297 | 2319 |
2298 __ bind(&cont); | 2320 __ bind(&cont); |
2299 } | 2321 } |
2300 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2322 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2301 | 2323 |
2302 if (NeedsChecks()) { | 2324 if (NeedsChecks()) { |
2303 // Slow-case: Non-function called. | 2325 // Slow-case: Non-function called. |
2304 __ bind(&slow); | 2326 __ bind(&slow); |
2305 if (RecordCallTarget()) { | 2327 if (RecordCallTarget()) { |
2306 // If there is a call target cache, mark it megamorphic in the | 2328 // If there is a call target cache, mark it megamorphic in the |
2307 // non-function case. MegamorphicSentinel is an immortal immovable | 2329 // non-function case. MegamorphicSentinel is an immortal immovable |
2308 // object (undefined) so no write barrier is needed. | 2330 // object (undefined) so no write barrier is needed. |
2309 __ Move(FieldOperand(rbx, Cell::kValueOffset), | 2331 __ SmiToInteger32(rdx, rdx); |
2310 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 2332 __ Move(FieldOperand(rbx, rdx, times_pointer_size, |
| 2333 FixedArray::kHeaderSize), |
| 2334 TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
| 2335 __ Integer32ToSmi(rdx, rdx); |
2311 } | 2336 } |
2312 // Check for function proxy. | 2337 // Check for function proxy. |
2313 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 2338 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
2314 __ j(not_equal, &non_function); | 2339 __ j(not_equal, &non_function); |
2315 __ PopReturnAddressTo(rcx); | 2340 __ PopReturnAddressTo(rcx); |
2316 __ push(rdi); // put proxy as additional argument under return address | 2341 __ push(rdi); // put proxy as additional argument under return address |
2317 __ PushReturnAddressFrom(rcx); | 2342 __ PushReturnAddressFrom(rcx); |
2318 __ Set(rax, argc_ + 1); | 2343 __ Set(rax, argc_ + 1); |
2319 __ Set(rbx, 0); | 2344 __ Set(rbx, 0); |
2320 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 2345 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
(...skipping 25 matching lines...) Expand all Loading... |
2346 __ pop(rdi); | 2371 __ pop(rdi); |
2347 } | 2372 } |
2348 __ movp(args.GetReceiverOperand(), rax); | 2373 __ movp(args.GetReceiverOperand(), rax); |
2349 __ jmp(&cont); | 2374 __ jmp(&cont); |
2350 } | 2375 } |
2351 } | 2376 } |
2352 | 2377 |
2353 | 2378 |
2354 void CallConstructStub::Generate(MacroAssembler* masm) { | 2379 void CallConstructStub::Generate(MacroAssembler* masm) { |
2355 // rax : number of arguments | 2380 // rax : number of arguments |
2356 // rbx : cache cell for call target | 2381 // rbx : feedback vector |
| 2382 // rdx : (only if rbx is not undefined) slot in feedback vector (Smi) |
2357 // rdi : constructor function | 2383 // rdi : constructor function |
2358 Label slow, non_function_call; | 2384 Label slow, non_function_call; |
2359 | 2385 |
2360 // Check that function is not a smi. | 2386 // Check that function is not a smi. |
2361 __ JumpIfSmi(rdi, &non_function_call); | 2387 __ JumpIfSmi(rdi, &non_function_call); |
2362 // Check that function is a JSFunction. | 2388 // Check that function is a JSFunction. |
2363 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2389 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2364 __ j(not_equal, &slow); | 2390 __ j(not_equal, &slow); |
2365 | 2391 |
2366 if (RecordCallTarget()) { | 2392 if (RecordCallTarget()) { |
(...skipping 2493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4860 ArraySingleArgumentConstructorStub stub_holey(holey_initial, | 4886 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
4861 DISABLE_ALLOCATION_SITES); | 4887 DISABLE_ALLOCATION_SITES); |
4862 __ TailCallStub(&stub_holey); | 4888 __ TailCallStub(&stub_holey); |
4863 | 4889 |
4864 __ bind(&normal_sequence); | 4890 __ bind(&normal_sequence); |
4865 ArraySingleArgumentConstructorStub stub(initial, | 4891 ArraySingleArgumentConstructorStub stub(initial, |
4866 DISABLE_ALLOCATION_SITES); | 4892 DISABLE_ALLOCATION_SITES); |
4867 __ TailCallStub(&stub); | 4893 __ TailCallStub(&stub); |
4868 } else if (mode == DONT_OVERRIDE) { | 4894 } else if (mode == DONT_OVERRIDE) { |
4869 // We are going to create a holey array, but our kind is non-holey. | 4895 // We are going to create a holey array, but our kind is non-holey. |
4870 // Fix kind and retry (only if we have an allocation site in the cell). | 4896 // Fix kind and retry (only if we have an allocation site in the slot). |
4871 __ incl(rdx); | 4897 __ incl(rdx); |
4872 | 4898 |
4873 if (FLAG_debug_code) { | 4899 if (FLAG_debug_code) { |
4874 Handle<Map> allocation_site_map = | 4900 Handle<Map> allocation_site_map = |
4875 masm->isolate()->factory()->allocation_site_map(); | 4901 masm->isolate()->factory()->allocation_site_map(); |
4876 __ Cmp(FieldOperand(rbx, 0), allocation_site_map); | 4902 __ Cmp(FieldOperand(rbx, 0), allocation_site_map); |
4877 __ Assert(equal, kExpectedAllocationSite); | 4903 __ Assert(equal, kExpectedAllocationSite); |
4878 } | 4904 } |
4879 | 4905 |
4880 // Save the resulting elements kind in type info. We can't just store r3 | 4906 // 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... |
4970 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4996 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4971 } else { | 4997 } else { |
4972 UNREACHABLE(); | 4998 UNREACHABLE(); |
4973 } | 4999 } |
4974 } | 5000 } |
4975 | 5001 |
4976 | 5002 |
4977 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5003 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
4978 // ----------- S t a t e ------------- | 5004 // ----------- S t a t e ------------- |
4979 // -- rax : argc | 5005 // -- rax : argc |
4980 // -- rbx : type info cell | 5006 // -- rbx : feedback vector (fixed array or undefined) |
| 5007 // -- rdx : slot index (if ebx is fixed array) |
4981 // -- rdi : constructor | 5008 // -- rdi : constructor |
4982 // -- rsp[0] : return address | 5009 // -- rsp[0] : return address |
4983 // -- rsp[8] : last argument | 5010 // -- rsp[8] : last argument |
4984 // ----------------------------------- | 5011 // ----------------------------------- |
4985 Handle<Object> undefined_sentinel( | 5012 Handle<Object> undefined_sentinel( |
4986 masm->isolate()->heap()->undefined_value(), | 5013 masm->isolate()->heap()->undefined_value(), |
4987 masm->isolate()); | 5014 masm->isolate()); |
4988 | 5015 |
4989 if (FLAG_debug_code) { | 5016 if (FLAG_debug_code) { |
4990 // The array construct code is only set for the global and natives | 5017 // The array construct code is only set for the global and natives |
4991 // builtin Array functions which always have maps. | 5018 // builtin Array functions which always have maps. |
4992 | 5019 |
4993 // Initial map for the builtin Array function should be a map. | 5020 // Initial map for the builtin Array function should be a map. |
4994 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 5021 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
4995 // Will both indicate a NULL and a Smi. | 5022 // Will both indicate a NULL and a Smi. |
4996 STATIC_ASSERT(kSmiTag == 0); | 5023 STATIC_ASSERT(kSmiTag == 0); |
4997 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); | 5024 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); |
4998 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); | 5025 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); |
4999 __ CmpObjectType(rcx, MAP_TYPE, rcx); | 5026 __ CmpObjectType(rcx, MAP_TYPE, rcx); |
5000 __ Check(equal, kUnexpectedInitialMapForArrayFunction); | 5027 __ Check(equal, kUnexpectedInitialMapForArrayFunction); |
5001 | 5028 |
5002 // We should either have undefined in rbx or a valid cell | 5029 // We should either have undefined in rbx or a valid fixed array. |
5003 Label okay_here; | 5030 Label okay_here; |
5004 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 5031 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); |
5005 __ Cmp(rbx, undefined_sentinel); | 5032 __ Cmp(rbx, undefined_sentinel); |
5006 __ j(equal, &okay_here); | 5033 __ j(equal, &okay_here); |
5007 __ Cmp(FieldOperand(rbx, 0), cell_map); | 5034 __ Cmp(FieldOperand(rbx, 0), fixed_array_map); |
5008 __ Assert(equal, kExpectedPropertyCellInRegisterRbx); | 5035 __ Assert(equal, kExpectedFixedArrayInRegisterRbx); |
| 5036 |
| 5037 // rdx should be a smi if we don't have undefined in rbx. |
| 5038 __ AssertSmi(rdx); |
| 5039 |
5009 __ bind(&okay_here); | 5040 __ bind(&okay_here); |
5010 } | 5041 } |
5011 | 5042 |
5012 Label no_info; | 5043 Label no_info; |
5013 // If the type cell is undefined, or contains anything other than an | 5044 // If the feedback slot is undefined, or contains anything other than an |
5014 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5045 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
5015 __ Cmp(rbx, undefined_sentinel); | 5046 __ Cmp(rbx, undefined_sentinel); |
5016 __ j(equal, &no_info); | 5047 __ j(equal, &no_info); |
5017 __ movp(rbx, FieldOperand(rbx, Cell::kValueOffset)); | 5048 __ SmiToInteger32(rdx, rdx); |
| 5049 __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, |
| 5050 FixedArray::kHeaderSize)); |
| 5051 __ Integer32ToSmi(rdx, rdx); |
5018 __ Cmp(FieldOperand(rbx, 0), | 5052 __ Cmp(FieldOperand(rbx, 0), |
5019 masm->isolate()->factory()->allocation_site_map()); | 5053 masm->isolate()->factory()->allocation_site_map()); |
5020 __ j(not_equal, &no_info); | 5054 __ j(not_equal, &no_info); |
5021 | 5055 |
5022 // Only look at the lower 16 bits of the transition info. | 5056 // Only look at the lower 16 bits of the transition info. |
5023 __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset)); | 5057 __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset)); |
5024 __ SmiToInteger32(rdx, rdx); | 5058 __ SmiToInteger32(rdx, rdx); |
5025 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5059 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
5026 __ and_(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); | 5060 __ and_(rdx, Immediate(AllocationSite::ElementsKindBits::kMask)); |
5027 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5061 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5064 | 5098 |
5065 __ bind(¬_one_case); | 5099 __ bind(¬_one_case); |
5066 InternalArrayNArgumentsConstructorStub stubN(kind); | 5100 InternalArrayNArgumentsConstructorStub stubN(kind); |
5067 __ TailCallStub(&stubN); | 5101 __ TailCallStub(&stubN); |
5068 } | 5102 } |
5069 | 5103 |
5070 | 5104 |
5071 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { | 5105 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
5072 // ----------- S t a t e ------------- | 5106 // ----------- S t a t e ------------- |
5073 // -- rax : argc | 5107 // -- rax : argc |
5074 // -- rbx : type info cell | |
5075 // -- rdi : constructor | 5108 // -- rdi : constructor |
5076 // -- rsp[0] : return address | 5109 // -- rsp[0] : return address |
5077 // -- rsp[8] : last argument | 5110 // -- rsp[8] : last argument |
5078 // ----------------------------------- | 5111 // ----------------------------------- |
5079 | 5112 |
5080 if (FLAG_debug_code) { | 5113 if (FLAG_debug_code) { |
5081 // The array construct code is only set for the global and natives | 5114 // The array construct code is only set for the global and natives |
5082 // builtin Array functions which always have maps. | 5115 // builtin Array functions which always have maps. |
5083 | 5116 |
5084 // Initial map for the builtin Array function should be a map. | 5117 // Initial map for the builtin Array function should be a map. |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5294 return_value_operand, | 5327 return_value_operand, |
5295 NULL); | 5328 NULL); |
5296 } | 5329 } |
5297 | 5330 |
5298 | 5331 |
5299 #undef __ | 5332 #undef __ |
5300 | 5333 |
5301 } } // namespace v8::internal | 5334 } } // namespace v8::internal |
5302 | 5335 |
5303 #endif // V8_TARGET_ARCH_X64 | 5336 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |