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