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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 320 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
321 GenerateTailCallToReturnedCode(masm); | 321 GenerateTailCallToReturnedCode(masm); |
322 | 322 |
323 __ Bind(&ok); | 323 __ Bind(&ok); |
324 GenerateTailCallToSharedCode(masm); | 324 GenerateTailCallToSharedCode(masm); |
325 } | 325 } |
326 | 326 |
327 | 327 |
328 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 328 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
329 bool is_api_function, | 329 bool is_api_function, |
330 bool count_constructions) { | 330 bool count_constructions, |
| 331 bool create_memento) { |
331 // ----------- S t a t e ------------- | 332 // ----------- S t a t e ------------- |
332 // -- x0 : number of arguments | 333 // -- x0 : number of arguments |
333 // -- x1 : constructor function | 334 // -- x1 : constructor function |
| 335 // -- x2 : allocation site or undefined |
334 // -- lr : return address | 336 // -- lr : return address |
335 // -- sp[...]: constructor arguments | 337 // -- sp[...]: constructor arguments |
336 // ----------------------------------- | 338 // ----------------------------------- |
337 | 339 |
338 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); | 340 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); |
339 // Should never count constructions for api objects. | 341 // Should never count constructions for api objects. |
340 ASSERT(!is_api_function || !count_constructions); | 342 ASSERT(!is_api_function || !count_constructions); |
| 343 // Should never create mementos for api functions. |
| 344 ASSERT(!is_api_function || !create_memento); |
| 345 // Should never create mementos before slack tracking is finished. |
| 346 ASSERT(!count_constructions || !create_memento); |
341 | 347 |
342 Isolate* isolate = masm->isolate(); | 348 Isolate* isolate = masm->isolate(); |
343 | 349 |
344 // Enter a construct frame. | 350 // Enter a construct frame. |
345 { | 351 { |
346 FrameScope scope(masm, StackFrame::CONSTRUCT); | 352 FrameScope scope(masm, StackFrame::CONSTRUCT); |
347 | 353 |
348 // Preserve the two incoming parameters on the stack. | 354 // Preserve the three incoming parameters on the stack. |
| 355 if (create_memento) { |
| 356 __ AssertUndefinedOrAllocationSite(x2, x10); |
| 357 __ Push(x2); |
| 358 } |
| 359 |
349 Register argc = x0; | 360 Register argc = x0; |
350 Register constructor = x1; | 361 Register constructor = x1; |
351 // x1: constructor function | 362 // x1: constructor function |
352 __ SmiTag(argc); | 363 __ SmiTag(argc); |
353 __ Push(argc, constructor); | 364 __ Push(argc, constructor); |
354 // sp[0] : Constructor function. | 365 // sp[0] : Constructor function. |
355 // sp[1]: number of arguments (smi-tagged) | 366 // sp[1]: number of arguments (smi-tagged) |
356 | 367 |
357 // Try to allocate the object without transitioning into C code. If any of | 368 // Try to allocate the object without transitioning into C code. If any of |
358 // the preconditions is not met, the code bails out to the runtime call. | 369 // the preconditions is not met, the code bails out to the runtime call. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 // The call will replace the stub, so the countdown is only done once. | 409 // The call will replace the stub, so the countdown is only done once. |
399 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 410 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
400 __ Pop(init_map, constructor); | 411 __ Pop(init_map, constructor); |
401 __ Bind(&allocate); | 412 __ Bind(&allocate); |
402 } | 413 } |
403 | 414 |
404 // Now allocate the JSObject on the heap. | 415 // Now allocate the JSObject on the heap. |
405 Register obj_size = x3; | 416 Register obj_size = x3; |
406 Register new_obj = x4; | 417 Register new_obj = x4; |
407 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); | 418 __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); |
408 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); | 419 if (create_memento) { |
| 420 __ Add(x7, obj_size, |
| 421 Operand(AllocationMemento::kSize / kPointerSize)); |
| 422 __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); |
| 423 } else { |
| 424 __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); |
| 425 } |
409 | 426 |
410 // Allocated the JSObject, now initialize the fields. Map is set to | 427 // Allocated the JSObject, now initialize the fields. Map is set to |
411 // initial map and properties and elements are set to empty fixed array. | 428 // initial map and properties and elements are set to empty fixed array. |
412 // NB. the object pointer is not tagged, so MemOperand is used. | 429 // NB. the object pointer is not tagged, so MemOperand is used. |
413 Register empty = x5; | 430 Register empty = x5; |
414 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); | 431 __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); |
415 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); | 432 __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); |
416 STATIC_ASSERT(JSObject::kElementsOffset == | 433 STATIC_ASSERT(JSObject::kElementsOffset == |
417 (JSObject::kPropertiesOffset + kPointerSize)); | 434 (JSObject::kPropertiesOffset + kPointerSize)); |
418 __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); | 435 __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 } | 477 } |
461 | 478 |
462 // Fill the remaining fields with one pointer filler map. | 479 // Fill the remaining fields with one pointer filler map. |
463 Register one_pointer_filler = x5; | 480 Register one_pointer_filler = x5; |
464 Register non_prealloc_fields = x6; | 481 Register non_prealloc_fields = x6; |
465 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); | 482 __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); |
466 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); | 483 __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); |
467 __ FillFields(first_non_prealloc, non_prealloc_fields, | 484 __ FillFields(first_non_prealloc, non_prealloc_fields, |
468 one_pointer_filler); | 485 one_pointer_filler); |
469 prop_fields = NoReg; | 486 prop_fields = NoReg; |
| 487 } else if (create_memento) { |
| 488 // Fill the pre-allocated fields with undef. |
| 489 __ FillFields(first_prop, prop_fields, undef); |
| 490 __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); |
| 491 __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex); |
| 492 ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); |
| 493 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); |
| 494 // Load the AllocationSite |
| 495 __ Peek(x14, 2 * kXRegSize); |
| 496 ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); |
| 497 __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); |
| 498 first_prop = NoReg; |
470 } else { | 499 } else { |
471 // Fill all of the property fields with undef. | 500 // Fill all of the property fields with undef. |
472 __ FillFields(first_prop, prop_fields, undef); | 501 __ FillFields(first_prop, prop_fields, undef); |
473 first_prop = NoReg; | 502 first_prop = NoReg; |
474 prop_fields = NoReg; | 503 prop_fields = NoReg; |
475 } | 504 } |
476 | 505 |
477 // Add the object tag to make the JSObject real, so that we can continue | 506 // Add the object tag to make the JSObject real, so that we can continue |
478 // and jump into the continuation code at any time from now on. Any | 507 // and jump into the continuation code at any time from now on. Any |
479 // failures need to undo the allocation, so that the heap is in a | 508 // failures need to undo the allocation, so that the heap is in a |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 | 553 |
525 // Undo the setting of the new top so that the heap is verifiable. For | 554 // Undo the setting of the new top so that the heap is verifiable. For |
526 // example, the map's unused properties potentially do not match the | 555 // example, the map's unused properties potentially do not match the |
527 // allocated objects unused properties. | 556 // allocated objects unused properties. |
528 __ Bind(&undo_allocation); | 557 __ Bind(&undo_allocation); |
529 __ UndoAllocationInNewSpace(new_obj, x14); | 558 __ UndoAllocationInNewSpace(new_obj, x14); |
530 } | 559 } |
531 | 560 |
532 // Allocate the new receiver object using the runtime call. | 561 // Allocate the new receiver object using the runtime call. |
533 __ Bind(&rt_call); | 562 __ Bind(&rt_call); |
534 __ Push(constructor); // Argument for Runtime_NewObject. | 563 Label count_incremented; |
535 __ CallRuntime(Runtime::kNewObject, 1); | 564 if (create_memento) { |
536 __ Mov(x4, x0); | 565 // Get the cell or allocation site. |
| 566 __ Peek(x4, 2 * kXRegSize); |
| 567 __ Push(x4); |
| 568 __ Push(constructor); // Argument for Runtime_NewObject. |
| 569 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2); |
| 570 __ Mov(x4, x0); |
| 571 // If we ended up using the runtime, and we want a memento, then the |
| 572 // runtime call made it for us, and we shouldn't do create count |
| 573 // increment. |
| 574 __ jmp(&count_incremented); |
| 575 } else { |
| 576 __ Push(constructor); // Argument for Runtime_NewObject. |
| 577 __ CallRuntime(Runtime::kNewObject, 1); |
| 578 __ Mov(x4, x0); |
| 579 } |
537 | 580 |
538 // Receiver for constructor call allocated. | 581 // Receiver for constructor call allocated. |
539 // x4: JSObject | 582 // x4: JSObject |
540 __ Bind(&allocated); | 583 __ Bind(&allocated); |
| 584 |
| 585 if (create_memento) { |
| 586 __ Peek(x10, 2 * kXRegSize); |
| 587 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); |
| 588 // r2 is an AllocationSite. We are creating a memento from it, so we |
| 589 // need to increment the memento create count. |
| 590 __ Ldr(x5, FieldMemOperand(x10, |
| 591 AllocationSite::kPretenureCreateCountOffset)); |
| 592 __ Add(x5, x5, Operand(Smi::FromInt(1))); |
| 593 __ Str(x5, FieldMemOperand(x10, |
| 594 AllocationSite::kPretenureCreateCountOffset)); |
| 595 __ bind(&count_incremented); |
| 596 } |
| 597 |
541 __ Push(x4, x4); | 598 __ Push(x4, x4); |
542 | 599 |
543 // Reload the number of arguments from the stack. | 600 // Reload the number of arguments from the stack. |
544 // Set it up in x0 for the function call below. | 601 // Set it up in x0 for the function call below. |
545 // jssp[0]: receiver | 602 // jssp[0]: receiver |
546 // jssp[1]: receiver | 603 // jssp[1]: receiver |
547 // jssp[2]: constructor function | 604 // jssp[2]: constructor function |
548 // jssp[3]: number of arguments (smi-tagged) | 605 // jssp[3]: number of arguments (smi-tagged) |
549 __ Peek(constructor, 2 * kXRegSize); // Load constructor. | 606 __ Peek(constructor, 2 * kXRegSize); // Load constructor. |
550 __ Peek(argc, 3 * kXRegSize); // Load number of arguments. | 607 __ Peek(argc, 3 * kXRegSize); // Load number of arguments. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 } | 694 } |
638 | 695 |
639 __ DropBySMI(x1); | 696 __ DropBySMI(x1); |
640 __ Drop(1); | 697 __ Drop(1); |
641 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); | 698 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); |
642 __ Ret(); | 699 __ Ret(); |
643 } | 700 } |
644 | 701 |
645 | 702 |
646 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 703 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
647 Generate_JSConstructStubHelper(masm, false, true); | 704 Generate_JSConstructStubHelper(masm, false, true, false); |
648 } | 705 } |
649 | 706 |
650 | 707 |
651 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 708 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
652 Generate_JSConstructStubHelper(masm, false, false); | 709 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
653 } | 710 } |
654 | 711 |
655 | 712 |
656 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 713 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
657 Generate_JSConstructStubHelper(masm, true, false); | 714 Generate_JSConstructStubHelper(masm, true, false, false); |
658 } | 715 } |
659 | 716 |
660 | 717 |
661 // Input: | 718 // Input: |
662 // x0: code entry. | 719 // x0: code entry. |
663 // x1: function. | 720 // x1: function. |
664 // x2: receiver. | 721 // x2: receiver. |
665 // x3: argc. | 722 // x3: argc. |
666 // x4: argv. | 723 // x4: argv. |
667 // Output: | 724 // Output: |
(...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1496 __ Bind(&dont_adapt_arguments); | 1553 __ Bind(&dont_adapt_arguments); |
1497 __ Jump(code_entry); | 1554 __ Jump(code_entry); |
1498 } | 1555 } |
1499 | 1556 |
1500 | 1557 |
1501 #undef __ | 1558 #undef __ |
1502 | 1559 |
1503 } } // namespace v8::internal | 1560 } } // namespace v8::internal |
1504 | 1561 |
1505 #endif // V8_TARGET_ARCH_ARM | 1562 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |