OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 | 93 |
94 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 94 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
95 GenerateTailCallToReturnedCode(masm); | 95 GenerateTailCallToReturnedCode(masm); |
96 | 96 |
97 __ bind(&ok); | 97 __ bind(&ok); |
98 GenerateTailCallToSharedCode(masm); | 98 GenerateTailCallToSharedCode(masm); |
99 } | 99 } |
100 | 100 |
101 | 101 |
102 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 102 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
103 bool is_api_function, | 103 bool is_api_function) { |
104 bool create_memento) { | |
105 // ----------- S t a t e ------------- | 104 // ----------- S t a t e ------------- |
106 // -- eax: number of arguments | 105 // -- eax: number of arguments |
107 // -- edi: constructor function | 106 // -- edi: constructor function |
108 // -- ebx: allocation site or undefined | 107 // -- ebx: allocation site or undefined |
109 // -- edx: original constructor | 108 // -- edx: original constructor |
110 // ----------------------------------- | 109 // ----------------------------------- |
111 | 110 |
112 // Should never create mementos for api functions. | |
113 DCHECK(!is_api_function || !create_memento); | |
114 | |
115 // Enter a construct frame. | 111 // Enter a construct frame. |
116 { | 112 { |
117 FrameScope scope(masm, StackFrame::CONSTRUCT); | 113 FrameScope scope(masm, StackFrame::CONSTRUCT); |
118 | 114 |
119 // Preserve the incoming parameters on the stack. | 115 // Preserve the incoming parameters on the stack. |
120 __ AssertUndefinedOrAllocationSite(ebx); | 116 __ AssertUndefinedOrAllocationSite(ebx); |
121 __ push(ebx); | 117 __ push(ebx); |
122 __ SmiTag(eax); | 118 __ SmiTag(eax); |
123 __ push(eax); | 119 __ push(eax); |
124 __ push(edi); | 120 __ push(edi); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 __ mov(esi, Map::kSlackTrackingCounterEnd - 1); | 181 __ mov(esi, Map::kSlackTrackingCounterEnd - 1); |
186 | 182 |
187 __ bind(&allocate); | 183 __ bind(&allocate); |
188 } | 184 } |
189 | 185 |
190 // Now allocate the JSObject on the heap. | 186 // Now allocate the JSObject on the heap. |
191 // edi: constructor | 187 // edi: constructor |
192 // eax: initial map | 188 // eax: initial map |
193 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); | 189 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); |
194 __ shl(edi, kPointerSizeLog2); | 190 __ shl(edi, kPointerSizeLog2); |
195 if (create_memento) { | |
196 __ add(edi, Immediate(AllocationMemento::kSize)); | |
197 } | |
198 | 191 |
199 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | 192 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); |
200 | 193 |
201 Factory* factory = masm->isolate()->factory(); | 194 Factory* factory = masm->isolate()->factory(); |
202 | 195 |
203 // Allocated the JSObject, now initialize the fields. | 196 // Allocated the JSObject, now initialize the fields. |
204 // eax: initial map | 197 // eax: initial map |
205 // ebx: JSObject | 198 // ebx: JSObject |
206 // edi: start of next object (including memento if create_memento) | 199 // edi: start of next object |
207 __ mov(Operand(ebx, JSObject::kMapOffset), eax); | 200 __ mov(Operand(ebx, JSObject::kMapOffset), eax); |
208 __ mov(ecx, factory->empty_fixed_array()); | 201 __ mov(ecx, factory->empty_fixed_array()); |
209 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); | 202 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); |
210 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); | 203 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); |
211 // Set extra fields in the newly allocated object. | 204 // Set extra fields in the newly allocated object. |
212 // eax: initial map | 205 // eax: initial map |
213 // ebx: JSObject | 206 // ebx: JSObject |
214 // edi: start of next object (including memento if create_memento) | 207 // edi: start of next object |
215 // esi: slack tracking counter (non-API function case) | 208 // esi: slack tracking counter (non-API function case) |
216 __ mov(edx, factory->undefined_value()); | 209 __ mov(edx, factory->undefined_value()); |
217 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); | 210 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); |
218 if (!is_api_function) { | 211 if (!is_api_function) { |
219 Label no_inobject_slack_tracking; | 212 Label no_inobject_slack_tracking; |
220 | 213 |
221 // Check if slack tracking is enabled. | 214 // Check if slack tracking is enabled. |
222 __ cmp(esi, Map::kSlackTrackingCounterEnd); | 215 __ cmp(esi, Map::kSlackTrackingCounterEnd); |
223 __ j(less, &no_inobject_slack_tracking); | 216 __ j(less, &no_inobject_slack_tracking); |
224 | 217 |
(...skipping 12 matching lines...) Expand all Loading... |
237 __ Assert(less_equal, | 230 __ Assert(less_equal, |
238 kUnexpectedNumberOfPreAllocatedPropertyFields); | 231 kUnexpectedNumberOfPreAllocatedPropertyFields); |
239 } | 232 } |
240 __ InitializeFieldsWithFiller(ecx, esi, edx); | 233 __ InitializeFieldsWithFiller(ecx, esi, edx); |
241 __ mov(edx, factory->one_pointer_filler_map()); | 234 __ mov(edx, factory->one_pointer_filler_map()); |
242 // Fill the remaining fields with one pointer filler map. | 235 // Fill the remaining fields with one pointer filler map. |
243 | 236 |
244 __ bind(&no_inobject_slack_tracking); | 237 __ bind(&no_inobject_slack_tracking); |
245 } | 238 } |
246 | 239 |
247 if (create_memento) { | 240 __ InitializeFieldsWithFiller(ecx, edi, edx); |
248 __ lea(esi, Operand(edi, -AllocationMemento::kSize)); | |
249 __ InitializeFieldsWithFiller(ecx, esi, edx); | |
250 | |
251 // Fill in memento fields if necessary. | |
252 // esi: points to the allocated but uninitialized memento. | |
253 __ mov(Operand(esi, AllocationMemento::kMapOffset), | |
254 factory->allocation_memento_map()); | |
255 // Get the cell or undefined. | |
256 __ mov(edx, Operand(esp, 3 * kPointerSize)); | |
257 __ AssertUndefinedOrAllocationSite(edx); | |
258 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), | |
259 edx); | |
260 } else { | |
261 __ InitializeFieldsWithFiller(ecx, edi, edx); | |
262 } | |
263 | 241 |
264 // Add the object tag to make the JSObject real, so that we can continue | 242 // Add the object tag to make the JSObject real, so that we can continue |
265 // and jump into the continuation code at any time from now on. | 243 // and jump into the continuation code at any time from now on. |
266 // ebx: JSObject (untagged) | 244 // ebx: JSObject (untagged) |
267 __ or_(ebx, Immediate(kHeapObjectTag)); | 245 __ or_(ebx, Immediate(kHeapObjectTag)); |
268 | 246 |
269 // Continue with JSObject being successfully allocated | 247 // Continue with JSObject being successfully allocated |
270 // ebx: JSObject (tagged) | 248 // ebx: JSObject (tagged) |
271 __ jmp(&allocated); | 249 __ jmp(&allocated); |
272 } | 250 } |
273 | 251 |
274 // Allocate the new receiver object using the runtime call. | 252 // Allocate the new receiver object using the runtime call. |
275 // edx: original constructor | 253 // edx: original constructor |
276 __ bind(&rt_call); | 254 __ bind(&rt_call); |
277 int offset = kPointerSize; | 255 int offset = kPointerSize; |
278 if (create_memento) { | |
279 // Get the cell or allocation site. | |
280 __ mov(edi, Operand(esp, kPointerSize * 3)); | |
281 __ push(edi); // argument 1: allocation site | |
282 offset += kPointerSize; | |
283 } | |
284 | 256 |
285 // Must restore esi (context) and edi (constructor) before calling | 257 // Must restore esi (context) and edi (constructor) before calling |
286 // runtime. | 258 // runtime. |
287 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 259 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
288 __ mov(edi, Operand(esp, offset)); | 260 __ mov(edi, Operand(esp, offset)); |
289 __ push(edi); // argument 2/1: constructor function | 261 __ push(edi); // argument 2/1: constructor function |
290 __ push(edx); // argument 3/2: original constructor | 262 __ push(edx); // argument 3/2: original constructor |
291 if (create_memento) { | 263 __ CallRuntime(Runtime::kNewObject, 2); |
292 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | |
293 } else { | |
294 __ CallRuntime(Runtime::kNewObject, 2); | |
295 } | |
296 __ mov(ebx, eax); // store result in ebx | 264 __ mov(ebx, eax); // store result in ebx |
297 | 265 |
298 // Runtime_NewObjectWithAllocationSite increments allocation count. | |
299 // Skip the increment. | |
300 Label count_incremented; | |
301 if (create_memento) { | |
302 __ jmp(&count_incremented); | |
303 } | |
304 | |
305 // New object allocated. | 266 // New object allocated. |
306 // ebx: newly allocated object | 267 // ebx: newly allocated object |
307 __ bind(&allocated); | 268 __ bind(&allocated); |
308 | 269 |
309 if (create_memento) { | |
310 __ mov(ecx, Operand(esp, 3 * kPointerSize)); | |
311 __ cmp(ecx, masm->isolate()->factory()->undefined_value()); | |
312 __ j(equal, &count_incremented); | |
313 // ecx is an AllocationSite. We are creating a memento from it, so we | |
314 // need to increment the memento create count. | |
315 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset), | |
316 Immediate(Smi::FromInt(1))); | |
317 __ bind(&count_incremented); | |
318 } | |
319 | |
320 // Restore the parameters. | 270 // Restore the parameters. |
321 __ pop(edx); // new.target | 271 __ pop(edx); // new.target |
322 __ pop(edi); // Constructor function. | 272 __ pop(edi); // Constructor function. |
323 | 273 |
324 // Retrieve smi-tagged arguments count from the stack. | 274 // Retrieve smi-tagged arguments count from the stack. |
325 __ mov(eax, Operand(esp, 0)); | 275 __ mov(eax, Operand(esp, 0)); |
326 __ SmiUntag(eax); | 276 __ SmiUntag(eax); |
327 | 277 |
328 // Push new.target onto the construct frame. This is stored just below the | 278 // Push new.target onto the construct frame. This is stored just below the |
329 // receiver on the stack. | 279 // receiver on the stack. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 348 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
399 __ pop(ecx); | 349 __ pop(ecx); |
400 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 350 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
401 __ push(ecx); | 351 __ push(ecx); |
402 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); | 352 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); |
403 __ ret(0); | 353 __ ret(0); |
404 } | 354 } |
405 | 355 |
406 | 356 |
407 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 357 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
408 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 358 Generate_JSConstructStubHelper(masm, false); |
409 } | 359 } |
410 | 360 |
411 | 361 |
412 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 362 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
413 Generate_JSConstructStubHelper(masm, true, false); | 363 Generate_JSConstructStubHelper(masm, true); |
414 } | 364 } |
415 | 365 |
416 | 366 |
417 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 367 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
418 // ----------- S t a t e ------------- | 368 // ----------- S t a t e ------------- |
419 // -- eax: number of arguments | 369 // -- eax: number of arguments |
420 // -- edi: constructor function | 370 // -- edi: constructor function |
421 // -- ebx: allocation site or undefined | 371 // -- ebx: allocation site or undefined |
422 // -- edx: original constructor | 372 // -- edx: original constructor |
423 // ----------------------------------- | 373 // ----------------------------------- |
(...skipping 1396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 | 1770 |
1821 __ bind(&ok); | 1771 __ bind(&ok); |
1822 __ ret(0); | 1772 __ ret(0); |
1823 } | 1773 } |
1824 | 1774 |
1825 #undef __ | 1775 #undef __ |
1826 } // namespace internal | 1776 } // namespace internal |
1827 } // namespace v8 | 1777 } // namespace v8 |
1828 | 1778 |
1829 #endif // V8_TARGET_ARCH_IA32 | 1779 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |