| 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 |