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 2151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 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 : Feedback vector | 2168 // rbx : Feedback vector |
2169 // rdx : slot in feedback vector (Smi) | 2169 // rdx : slot in feedback vector (Smi) |
2170 // rdi : the function to call | 2170 // rdi : the function to call |
2171 Isolate* isolate = masm->isolate(); | 2171 Isolate* isolate = masm->isolate(); |
2172 Label initialize, done, miss, megamorphic, not_array_function, | 2172 Label check_array, initialize_array, initialize_non_array, megamorphic, done; |
2173 done_no_smi_convert; | |
2174 | 2173 |
2175 // Load the cache state into rcx. | 2174 // Load the cache state into rcx. |
2176 __ SmiToInteger32(rdx, rdx); | 2175 __ SmiToInteger32(rdx, rdx); |
2177 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, | 2176 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, |
2178 FixedArray::kHeaderSize)); | 2177 FixedArray::kHeaderSize)); |
2179 | 2178 |
2180 // A monomorphic cache hit or an already megamorphic state: invoke the | 2179 // A monomorphic cache hit or an already megamorphic state: invoke the |
2181 // function without changing the state. | 2180 // function without changing the state. |
2182 __ cmpq(rcx, rdi); | 2181 __ cmpq(rcx, rdi); |
2183 __ j(equal, &done); | 2182 __ j(equal, &done); |
2184 __ Cmp(rcx, TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2183 __ Cmp(rcx, TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
2185 __ j(equal, &done); | 2184 __ j(equal, &done); |
2186 | 2185 |
2187 // If we came here, we need to see if we are the array function. | 2186 // Check if we're dealing with the Array function or not. |
2188 // 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 | |
2190 // AllocationSite. Do a map check on the object in rcx. | |
2191 Handle<Map> allocation_site_map = | |
2192 masm->isolate()->factory()->allocation_site_map(); | |
2193 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); | |
2194 __ j(not_equal, &miss); | |
2195 | |
2196 // Make sure the function is the Array() function | |
2197 __ LoadArrayFunction(rcx); | 2187 __ LoadArrayFunction(rcx); |
2198 __ cmpq(rdi, rcx); | 2188 __ cmpq(rdi, rcx); |
| 2189 __ j(equal, &check_array); |
| 2190 |
| 2191 // Non-array cache: Reload the cache state and check it. |
| 2192 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, |
| 2193 FixedArray::kHeaderSize)); |
| 2194 __ Cmp(rcx, TypeFeedbackInfo::PremonomorphicSentinel(isolate)); |
| 2195 __ j(equal, &initialize_non_array); |
| 2196 __ Cmp(rcx, TypeFeedbackInfo::UninitializedSentinel(isolate)); |
2199 __ j(not_equal, &megamorphic); | 2197 __ j(not_equal, &megamorphic); |
2200 __ jmp(&done); | |
2201 | 2198 |
2202 __ bind(&miss); | 2199 // Non-array cache: Uninitialized -> premonomorphic. The sentinel is an |
| 2200 // immortal immovable object (null) so no write-barrier is needed. |
| 2201 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
| 2202 TypeFeedbackInfo::PremonomorphicSentinel(isolate)); |
| 2203 __ jmp(&done, Label::kFar); |
2203 | 2204 |
2204 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2205 // Array cache: Reload the cache state and check to see if we're in a |
2205 // megamorphic. | 2206 // monomorphic state where the state object is an AllocationSite object. |
| 2207 __ bind(&check_array); |
| 2208 __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size, |
| 2209 FixedArray::kHeaderSize)); |
| 2210 Handle<Map> allocation_site_map = isolate->factory()->allocation_site_map(); |
| 2211 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); |
| 2212 __ j(equal, &done); |
| 2213 |
| 2214 // Array cache: Uninitialized or premonomorphic -> monomorphic. |
2206 __ Cmp(rcx, TypeFeedbackInfo::UninitializedSentinel(isolate)); | 2215 __ Cmp(rcx, TypeFeedbackInfo::UninitializedSentinel(isolate)); |
2207 __ j(equal, &initialize); | 2216 __ j(equal, &initialize_array); |
2208 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2217 __ Cmp(rcx, TypeFeedbackInfo::PremonomorphicSentinel(isolate)); |
2209 // write-barrier is needed. | 2218 __ j(equal, &initialize_array); |
| 2219 |
| 2220 // Both caches: Monomorphic -> megamorphic. The sentinel is an |
| 2221 // immortal immovable object (undefined) so no write-barrier is needed. |
2210 __ bind(&megamorphic); | 2222 __ bind(&megamorphic); |
2211 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), | 2223 __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
2212 TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2224 TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
2213 __ jmp(&done); | 2225 __ jmp(&done); |
2214 | 2226 |
2215 // An uninitialized cache is patched with the function or sentinel to | 2227 // Array cache: Uninitialized or premonomorphic -> monomorphic. |
2216 // indicate the ElementsKind if function is the Array constructor. | 2228 __ bind(&initialize_array); |
2217 __ bind(&initialize); | |
2218 // Make sure the function is the Array() function | |
2219 __ LoadArrayFunction(rcx); | |
2220 __ cmpq(rdi, rcx); | |
2221 __ j(not_equal, ¬_array_function); | |
2222 | |
2223 // The target function is the Array constructor, | |
2224 // Create an AllocationSite if we don't already have it, store it in the slot. | |
2225 { | 2229 { |
2226 FrameScope scope(masm, StackFrame::INTERNAL); | 2230 FrameScope scope(masm, StackFrame::INTERNAL); |
2227 | 2231 |
2228 // Arguments register must be smi-tagged to call out. | 2232 // Arguments register must be smi-tagged to call out. |
2229 __ Integer32ToSmi(rax, rax); | 2233 __ Integer32ToSmi(rax, rax); |
2230 __ push(rax); | 2234 __ push(rax); |
2231 __ push(rdi); | 2235 __ push(rdi); |
2232 __ Integer32ToSmi(rdx, rdx); | 2236 __ Integer32ToSmi(rdx, rdx); |
2233 __ push(rdx); | 2237 __ push(rdx); |
2234 __ push(rbx); | 2238 __ push(rbx); |
2235 | 2239 |
2236 CreateAllocationSiteStub create_stub; | 2240 CreateAllocationSiteStub create_stub; |
2237 __ CallStub(&create_stub); | 2241 __ CallStub(&create_stub); |
2238 | 2242 |
2239 __ pop(rbx); | 2243 __ pop(rbx); |
2240 __ pop(rdx); | 2244 __ pop(rdx); |
2241 __ pop(rdi); | 2245 __ pop(rdi); |
2242 __ pop(rax); | 2246 __ pop(rax); |
2243 __ SmiToInteger32(rax, rax); | 2247 __ SmiToInteger32(rax, rax); |
2244 } | 2248 } |
| 2249 Label done_no_smi_convert; |
2245 __ jmp(&done_no_smi_convert); | 2250 __ jmp(&done_no_smi_convert); |
2246 | 2251 |
2247 __ bind(¬_array_function); | 2252 // Non-array cache: Premonomorphic -> monomorphic. |
| 2253 __ bind(&initialize_non_array); |
2248 __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), | 2254 __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize), |
2249 rdi); | 2255 rdi); |
2250 | |
2251 // We won't need rdx or rbx anymore, just save rdi | |
2252 __ push(rdi); | 2256 __ push(rdi); |
2253 __ push(rbx); | 2257 __ push(rbx); |
2254 __ push(rdx); | 2258 __ push(rdx); |
2255 __ RecordWriteArray(rbx, rdi, rdx, kDontSaveFPRegs, | 2259 __ RecordWriteArray(rbx, rdi, rdx, kDontSaveFPRegs, |
2256 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 2260 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
2257 __ pop(rdx); | 2261 __ pop(rdx); |
2258 __ pop(rbx); | 2262 __ pop(rbx); |
2259 __ pop(rdi); | 2263 __ pop(rdi); |
2260 | 2264 |
2261 __ bind(&done); | 2265 __ bind(&done); |
(...skipping 3067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5329 return_value_operand, | 5333 return_value_operand, |
5330 NULL); | 5334 NULL); |
5331 } | 5335 } |
5332 | 5336 |
5333 | 5337 |
5334 #undef __ | 5338 #undef __ |
5335 | 5339 |
5336 } } // namespace v8::internal | 5340 } } // namespace v8::internal |
5337 | 5341 |
5338 #endif // V8_TARGET_ARCH_X64 | 5342 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |