Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ia32/builtins-ia32.cc

Issue 132963012: Pretenure call new support. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.cc ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); 118 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
119 GenerateTailCallToReturnedCode(masm); 119 GenerateTailCallToReturnedCode(masm);
120 120
121 __ bind(&ok); 121 __ bind(&ok);
122 GenerateTailCallToSharedCode(masm); 122 GenerateTailCallToSharedCode(masm);
123 } 123 }
124 124
125 125
126 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 126 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
127 bool is_api_function, 127 bool is_api_function,
128 bool count_constructions) { 128 bool count_constructions,
129 bool create_memento) {
129 // ----------- S t a t e ------------- 130 // ----------- S t a t e -------------
130 // -- eax: number of arguments 131 // -- eax: number of arguments
131 // -- edi: constructor function 132 // -- edi: constructor function
133 // -- ebx: allocation site or undefined
132 // ----------------------------------- 134 // -----------------------------------
133 135
134 // Should never count constructions for api objects. 136 // Should never count constructions for api objects.
135 ASSERT(!is_api_function || !count_constructions); 137 ASSERT(!is_api_function || !count_constructions);
136 138
139 // Should never create mementos for api functions.
140 ASSERT(!is_api_function || !create_memento);
141
142 // Should never create mementos before slack tracking is finished.
143 ASSERT(!count_constructions || !create_memento);
144
137 // Enter a construct frame. 145 // Enter a construct frame.
138 { 146 {
139 FrameScope scope(masm, StackFrame::CONSTRUCT); 147 FrameScope scope(masm, StackFrame::CONSTRUCT);
140 148
149 if (create_memento) {
150 __ AssertUndefinedOrAllocationSite(ebx);
151 __ push(ebx);
152 }
153
141 // Store a smi-tagged arguments count on the stack. 154 // Store a smi-tagged arguments count on the stack.
142 __ SmiTag(eax); 155 __ SmiTag(eax);
143 __ push(eax); 156 __ push(eax);
144 157
145 // Push the function to invoke on the stack. 158 // Push the function to invoke on the stack.
146 __ push(edi); 159 __ push(edi);
147 160
148 // Try to allocate the object without transitioning into C code. If any of 161 // Try to allocate the object without transitioning into C code. If any of
149 // the preconditions is not met, the code bails out to the runtime call. 162 // the preconditions is not met, the code bails out to the runtime call.
150 Label rt_call, allocated; 163 Label rt_call, allocated;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 __ pop(eax); 208 __ pop(eax);
196 209
197 __ bind(&allocate); 210 __ bind(&allocate);
198 } 211 }
199 212
200 // Now allocate the JSObject on the heap. 213 // Now allocate the JSObject on the heap.
201 // edi: constructor 214 // edi: constructor
202 // eax: initial map 215 // eax: initial map
203 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 216 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
204 __ shl(edi, kPointerSizeLog2); 217 __ shl(edi, kPointerSizeLog2);
218 if (create_memento) {
219 __ add(edi, Immediate(AllocationMemento::kSize));
220 }
221
205 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 222 __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
223
224 Factory* factory = masm->isolate()->factory();
225
206 // Allocated the JSObject, now initialize the fields. 226 // Allocated the JSObject, now initialize the fields.
207 // eax: initial map 227 // eax: initial map
208 // ebx: JSObject 228 // ebx: JSObject
209 // edi: start of next object 229 // edi: start of next object (including memento if create_memento)
210 __ mov(Operand(ebx, JSObject::kMapOffset), eax); 230 __ mov(Operand(ebx, JSObject::kMapOffset), eax);
211 Factory* factory = masm->isolate()->factory();
212 __ mov(ecx, factory->empty_fixed_array()); 231 __ mov(ecx, factory->empty_fixed_array());
213 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); 232 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
214 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); 233 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
215 // Set extra fields in the newly allocated object. 234 // Set extra fields in the newly allocated object.
216 // eax: initial map 235 // eax: initial map
217 // ebx: JSObject 236 // ebx: JSObject
218 // edi: start of next object 237 // edi: start of next object (including memento if create_memento)
219 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 238 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
220 __ mov(edx, factory->undefined_value()); 239 __ mov(edx, factory->undefined_value());
221 if (count_constructions) { 240 if (count_constructions) {
222 __ movzx_b(esi, 241 __ movzx_b(esi,
223 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 242 FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
224 __ lea(esi, 243 __ lea(esi,
225 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); 244 Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
226 // esi: offset of first field after pre-allocated fields 245 // esi: offset of first field after pre-allocated fields
227 if (FLAG_debug_code) { 246 if (FLAG_debug_code) {
228 __ cmp(esi, edi); 247 __ cmp(esi, edi);
229 __ Assert(less_equal, 248 __ Assert(less_equal,
230 kUnexpectedNumberOfPreAllocatedPropertyFields); 249 kUnexpectedNumberOfPreAllocatedPropertyFields);
231 } 250 }
232 __ InitializeFieldsWithFiller(ecx, esi, edx); 251 __ InitializeFieldsWithFiller(ecx, esi, edx);
233 __ mov(edx, factory->one_pointer_filler_map()); 252 __ mov(edx, factory->one_pointer_filler_map());
253 __ InitializeFieldsWithFiller(ecx, edi, edx);
254 } else if (create_memento) {
255 __ lea(esi, Operand(edi, -AllocationMemento::kSize));
256 __ InitializeFieldsWithFiller(ecx, esi, edx);
257
258 // Fill in memento fields if necessary.
259 // esi: points to the allocated but uninitialized memento.
260 Handle<Map> allocation_memento_map = factory->allocation_memento_map();
261 __ mov(Operand(esi, AllocationMemento::kMapOffset),
262 allocation_memento_map);
263 // Get the cell or undefined.
264 __ mov(edx, Operand(esp, kPointerSize*2));
265 __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset),
266 edx);
267 } else {
268 __ InitializeFieldsWithFiller(ecx, edi, edx);
234 } 269 }
235 __ InitializeFieldsWithFiller(ecx, edi, edx);
236 270
237 // Add the object tag to make the JSObject real, so that we can continue 271 // Add the object tag to make the JSObject real, so that we can continue
238 // and jump into the continuation code at any time from now on. Any 272 // and jump into the continuation code at any time from now on. Any
239 // failures need to undo the allocation, so that the heap is in a 273 // failures need to undo the allocation, so that the heap is in a
240 // consistent state and verifiable. 274 // consistent state and verifiable.
241 // eax: initial map 275 // eax: initial map
242 // ebx: JSObject 276 // ebx: JSObject
243 // edi: start of next object 277 // edi: start of next object
244 __ or_(ebx, Immediate(kHeapObjectTag)); 278 __ or_(ebx, Immediate(kHeapObjectTag));
245 279
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 // Undo the setting of the new top so that the heap is verifiable. For 350 // Undo the setting of the new top so that the heap is verifiable. For
317 // example, the map's unused properties potentially do not match the 351 // example, the map's unused properties potentially do not match the
318 // allocated objects unused properties. 352 // allocated objects unused properties.
319 // ebx: JSObject (previous new top) 353 // ebx: JSObject (previous new top)
320 __ bind(&undo_allocation); 354 __ bind(&undo_allocation);
321 __ UndoAllocationInNewSpace(ebx); 355 __ UndoAllocationInNewSpace(ebx);
322 } 356 }
323 357
324 // Allocate the new receiver object using the runtime call. 358 // Allocate the new receiver object using the runtime call.
325 __ bind(&rt_call); 359 __ bind(&rt_call);
360 int offset = 0;
361 if (create_memento) {
362 // Get the cell or allocation site.
363 __ mov(edi, Operand(esp, kPointerSize * 2));
364 __ push(edi);
365 offset = kPointerSize;
366 }
367
326 // Must restore edi (constructor) before calling runtime. 368 // Must restore edi (constructor) before calling runtime.
327 __ mov(edi, Operand(esp, 0)); 369 __ mov(edi, Operand(esp, offset));
328 // edi: function (constructor) 370 // edi: function (constructor)
329 __ push(edi); 371 __ push(edi);
330 __ CallRuntime(Runtime::kNewObject, 1); 372 if (create_memento) {
373 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2);
374 } else {
375 __ CallRuntime(Runtime::kNewObject, 1);
376 }
331 __ mov(ebx, eax); // store result in ebx 377 __ mov(ebx, eax); // store result in ebx
332 378
379 // If we ended up using the runtime, and we want a memento, then the
380 // runtime call made it for us, and we shouldn't do create count
381 // increment.
382 Label count_incremented;
383 if (create_memento) {
384 __ jmp(&count_incremented);
385 }
386
333 // New object allocated. 387 // New object allocated.
334 // ebx: newly allocated object 388 // ebx: newly allocated object
335 __ bind(&allocated); 389 __ bind(&allocated);
390
391 if (create_memento) {
392 __ mov(ecx, Operand(esp, kPointerSize * 2));
393 __ cmp(ecx, masm->isolate()->factory()->undefined_value());
394 __ j(equal, &count_incremented);
395 // ecx is an AllocationSite. We are creating a memento from it, so we
396 // need to increment the memento create count.
397 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset),
398 Immediate(Smi::FromInt(1)));
399 __ bind(&count_incremented);
400 }
401
336 // Retrieve the function from the stack. 402 // Retrieve the function from the stack.
337 __ pop(edi); 403 __ pop(edi);
338 404
339 // Retrieve smi-tagged arguments count from the stack. 405 // Retrieve smi-tagged arguments count from the stack.
340 __ mov(eax, Operand(esp, 0)); 406 __ mov(eax, Operand(esp, 0));
341 __ SmiUntag(eax); 407 __ SmiUntag(eax);
342 408
343 // Push the allocated receiver to the stack. We need two copies 409 // Push the allocated receiver to the stack. We need two copies
344 // because we may have to return the original one and the calling 410 // because we may have to return the original one and the calling
345 // conventions dictate that the called function pops the receiver. 411 // conventions dictate that the called function pops the receiver.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 474 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
409 __ pop(ecx); 475 __ pop(ecx);
410 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 476 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
411 __ push(ecx); 477 __ push(ecx);
412 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 478 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
413 __ ret(0); 479 __ ret(0);
414 } 480 }
415 481
416 482
417 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 483 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
418 Generate_JSConstructStubHelper(masm, false, true); 484 Generate_JSConstructStubHelper(masm, false, true, false);
419 } 485 }
420 486
421 487
422 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 488 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
423 Generate_JSConstructStubHelper(masm, false, false); 489 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
424 } 490 }
425 491
426 492
427 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 493 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
428 Generate_JSConstructStubHelper(masm, true, false); 494 Generate_JSConstructStubHelper(masm, true, false, false);
429 } 495 }
430 496
431 497
432 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 498 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
433 bool is_construct) { 499 bool is_construct) {
434 ProfileEntryHookStub::MaybeCallEntryHook(masm); 500 ProfileEntryHookStub::MaybeCallEntryHook(masm);
435 501
436 // Clear the context before we push it when entering the internal frame. 502 // Clear the context before we push it when entering the internal frame.
437 __ Set(esi, Immediate(0)); 503 __ Set(esi, Immediate(0));
438 504
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 1426
1361 __ bind(&ok); 1427 __ bind(&ok);
1362 __ ret(0); 1428 __ ret(0);
1363 } 1429 }
1364 1430
1365 #undef __ 1431 #undef __
1366 } 1432 }
1367 } // namespace v8::internal 1433 } // namespace v8::internal
1368 1434
1369 #endif // V8_TARGET_ARCH_IA32 1435 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698