OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 __ Push(original_constructor); | 324 __ Push(original_constructor); |
325 __ CallRuntime(Runtime::kNewObject, 2); | 325 __ CallRuntime(Runtime::kNewObject, 2); |
326 __ Mov(x4, x0); | 326 __ Mov(x4, x0); |
327 __ jmp(allocated); | 327 __ jmp(allocated); |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 | 331 |
332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
333 bool is_api_function, | 333 bool is_api_function, |
| 334 bool use_new_target, |
334 bool create_memento) { | 335 bool create_memento) { |
335 // ----------- S t a t e ------------- | 336 // ----------- S t a t e ------------- |
336 // -- x0 : number of arguments | 337 // -- x0 : number of arguments |
337 // -- x1 : constructor function | 338 // -- x1 : constructor function |
338 // -- x2 : allocation site or undefined | 339 // -- x2 : allocation site or undefined |
339 // -- x3 : original constructor | 340 // -- x3 : original constructor |
340 // -- lr : return address | 341 // -- lr : return address |
341 // -- sp[...]: constructor arguments | 342 // -- sp[...]: constructor arguments |
342 // ----------------------------------- | 343 // ----------------------------------- |
343 | 344 |
344 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); | 345 ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); |
345 // Should never create mementos for api functions. | 346 // Should never create mementos for api functions. |
346 DCHECK(!is_api_function || !create_memento); | 347 DCHECK(!is_api_function || !create_memento); |
347 | 348 |
348 Isolate* isolate = masm->isolate(); | 349 Isolate* isolate = masm->isolate(); |
349 | 350 |
350 // Enter a construct frame. | 351 // Enter a construct frame. |
351 { | 352 { |
352 FrameScope scope(masm, StackFrame::CONSTRUCT); | 353 FrameScope scope(masm, StackFrame::CONSTRUCT); |
353 | 354 |
354 // Preserve the three incoming parameters on the stack. | 355 // Preserve the three incoming parameters on the stack. |
355 if (create_memento) { | 356 if (create_memento) { |
356 __ AssertUndefinedOrAllocationSite(x2, x10); | 357 __ AssertUndefinedOrAllocationSite(x2, x10); |
357 __ Push(x2); | 358 __ Push(x2); |
358 } | 359 } |
359 | 360 |
360 Register argc = x0; | 361 Register argc = x0; |
361 Register constructor = x1; | 362 Register constructor = x1; |
362 Register original_constructor = x3; | 363 Register original_constructor = x3; |
363 // x1: constructor function | 364 |
| 365 // Preserve the incoming parameters on the stack. |
364 __ SmiTag(argc); | 366 __ SmiTag(argc); |
365 __ Push(argc, constructor); | 367 if (use_new_target) { |
366 // sp[0] : Constructor function. | 368 __ Push(argc, constructor, original_constructor); |
367 // sp[1]: number of arguments (smi-tagged) | 369 } else { |
| 370 __ Push(argc, constructor); |
| 371 } |
| 372 // sp[0]: new.target (if used) |
| 373 // sp[0/1]: Constructor function. |
| 374 // sp[1/2]: number of arguments (smi-tagged) |
368 | 375 |
369 Label rt_call, count_incremented, allocated, normal_new; | 376 Label rt_call, count_incremented, allocated, normal_new; |
370 __ Cmp(constructor, original_constructor); | 377 __ Cmp(constructor, original_constructor); |
371 __ B(eq, &normal_new); | 378 __ B(eq, &normal_new); |
372 Generate_Runtime_NewObject(masm, create_memento, original_constructor, | 379 Generate_Runtime_NewObject(masm, create_memento, original_constructor, |
373 &count_incremented, &allocated); | 380 &count_incremented, &allocated); |
374 | 381 |
375 __ Bind(&normal_new); | 382 __ Bind(&normal_new); |
376 | 383 |
377 // Try to allocate the object without transitioning into C code. If any of | 384 // Try to allocate the object without transitioning into C code. If any of |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 // Allocate the new receiver object using the runtime call. | 580 // Allocate the new receiver object using the runtime call. |
574 __ Bind(&rt_call); | 581 __ Bind(&rt_call); |
575 Generate_Runtime_NewObject(masm, create_memento, constructor, | 582 Generate_Runtime_NewObject(masm, create_memento, constructor, |
576 &count_incremented, &allocated); | 583 &count_incremented, &allocated); |
577 | 584 |
578 // Receiver for constructor call allocated. | 585 // Receiver for constructor call allocated. |
579 // x4: JSObject | 586 // x4: JSObject |
580 __ Bind(&allocated); | 587 __ Bind(&allocated); |
581 | 588 |
582 if (create_memento) { | 589 if (create_memento) { |
583 __ Peek(x10, 2 * kXRegSize); | 590 int offset = (use_new_target ? 3 : 2) * kXRegSize; |
| 591 __ Peek(x10, offset); |
584 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); | 592 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); |
585 // r2 is an AllocationSite. We are creating a memento from it, so we | 593 // r2 is an AllocationSite. We are creating a memento from it, so we |
586 // need to increment the memento create count. | 594 // need to increment the memento create count. |
587 __ Ldr(x5, FieldMemOperand(x10, | 595 __ Ldr(x5, FieldMemOperand(x10, |
588 AllocationSite::kPretenureCreateCountOffset)); | 596 AllocationSite::kPretenureCreateCountOffset)); |
589 __ Add(x5, x5, Operand(Smi::FromInt(1))); | 597 __ Add(x5, x5, Operand(Smi::FromInt(1))); |
590 __ Str(x5, FieldMemOperand(x10, | 598 __ Str(x5, FieldMemOperand(x10, |
591 AllocationSite::kPretenureCreateCountOffset)); | 599 AllocationSite::kPretenureCreateCountOffset)); |
592 __ bind(&count_incremented); | 600 __ bind(&count_incremented); |
593 } | 601 } |
594 | 602 |
| 603 // Restore the parameters. |
| 604 if (use_new_target) { |
| 605 __ Pop(original_constructor); |
| 606 } |
595 __ Pop(constructor); | 607 __ Pop(constructor); |
596 | 608 |
597 __ Push(x4, x4); | |
598 | |
599 // Reload the number of arguments from the stack. | 609 // Reload the number of arguments from the stack. |
600 // Set it up in x0 for the function call below. | 610 // Set it up in x0 for the function call below. |
601 // jssp[0]: receiver | 611 // jssp[0]: number of arguments (smi-tagged) |
602 // jssp[1]: receiver | 612 __ Peek(argc, 0); // Load number of arguments. |
603 // jssp[2]: number of arguments (smi-tagged) | |
604 __ Peek(argc, 2 * kXRegSize); // Load number of arguments. | |
605 __ SmiUntag(argc); | 613 __ SmiUntag(argc); |
606 | 614 |
| 615 if (use_new_target) { |
| 616 __ Push(original_constructor, x4, x4); |
| 617 } else { |
| 618 __ Push(x4, x4); |
| 619 } |
| 620 |
607 // Set up pointer to last argument. | 621 // Set up pointer to last argument. |
608 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); | 622 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); |
609 | 623 |
610 // Copy arguments and receiver to the expression stack. | 624 // Copy arguments and receiver to the expression stack. |
611 // Copy 2 values every loop to use ldp/stp. | 625 // Copy 2 values every loop to use ldp/stp. |
612 // x0: number of arguments | 626 // x0: number of arguments |
613 // x1: constructor function | 627 // x1: constructor function |
614 // x2: address of last argument (caller sp) | 628 // x2: address of last argument (caller sp) |
615 // jssp[0]: receiver | 629 // jssp[0]: receiver |
616 // jssp[1]: receiver | 630 // jssp[1]: receiver |
617 // jssp[2]: number of arguments (smi-tagged) | 631 // jssp[2]: new.target (if used) |
| 632 // jssp[2/3]: number of arguments (smi-tagged) |
618 // Compute the start address of the copy in x3. | 633 // Compute the start address of the copy in x3. |
619 __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); | 634 __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); |
620 Label loop, entry, done_copying_arguments; | 635 Label loop, entry, done_copying_arguments; |
621 __ B(&entry); | 636 __ B(&entry); |
622 __ Bind(&loop); | 637 __ Bind(&loop); |
623 __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); | 638 __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); |
624 __ Push(x11, x10); | 639 __ Push(x11, x10); |
625 __ Bind(&entry); | 640 __ Bind(&entry); |
626 __ Cmp(x3, x2); | 641 __ Cmp(x3, x2); |
627 __ B(gt, &loop); | 642 __ B(gt, &loop); |
(...skipping 10 matching lines...) Expand all Loading... |
638 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); | 653 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); |
639 Handle<Code> code = | 654 Handle<Code> code = |
640 masm->isolate()->builtins()->HandleApiCallConstruct(); | 655 masm->isolate()->builtins()->HandleApiCallConstruct(); |
641 __ Call(code, RelocInfo::CODE_TARGET); | 656 __ Call(code, RelocInfo::CODE_TARGET); |
642 } else { | 657 } else { |
643 ParameterCount actual(argc); | 658 ParameterCount actual(argc); |
644 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); | 659 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); |
645 } | 660 } |
646 | 661 |
647 // Store offset of return address for deoptimizer. | 662 // Store offset of return address for deoptimizer. |
648 if (!is_api_function) { | 663 // TODO(arv): Remove the "!use_new_target" before supporting optimization |
| 664 // of functions that reference new.target |
| 665 if (!is_api_function && !use_new_target) { |
649 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 666 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
650 } | 667 } |
651 | 668 |
652 // Restore the context from the frame. | 669 // Restore the context from the frame. |
653 // x0: result | 670 // x0: result |
654 // jssp[0]: receiver | 671 // jssp[0]: receiver |
655 // jssp[1]: number of arguments (smi-tagged) | 672 // jssp[1]: new.target (if used) |
| 673 // jssp[1/2]: number of arguments (smi-tagged) |
656 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 674 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
657 | 675 |
658 // If the result is an object (in the ECMA sense), we should get rid | 676 // If the result is an object (in the ECMA sense), we should get rid |
659 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 677 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
660 // on page 74. | 678 // on page 74. |
661 Label use_receiver, exit; | 679 Label use_receiver, exit; |
662 | 680 |
663 // If the result is a smi, it is *not* an object in the ECMA sense. | 681 // If the result is a smi, it is *not* an object in the ECMA sense. |
664 // x0: result | 682 // x0: result |
665 // jssp[0]: receiver (newly allocated object) | 683 // jssp[0]: receiver (newly allocated object) |
666 // jssp[1]: number of arguments (smi-tagged) | 684 // jssp[1]: number of arguments (smi-tagged) |
667 __ JumpIfSmi(x0, &use_receiver); | 685 __ JumpIfSmi(x0, &use_receiver); |
668 | 686 |
669 // If the type of the result (stored in its map) is less than | 687 // If the type of the result (stored in its map) is less than |
670 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 688 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
671 __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); | 689 __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); |
672 | 690 |
673 // Throw away the result of the constructor invocation and use the | 691 // Throw away the result of the constructor invocation and use the |
674 // on-stack receiver as the result. | 692 // on-stack receiver as the result. |
675 __ Bind(&use_receiver); | 693 __ Bind(&use_receiver); |
676 __ Peek(x0, 0); | 694 __ Peek(x0, 0); |
677 | 695 |
678 // Remove the receiver from the stack, remove caller arguments, and | 696 // Remove the receiver from the stack, remove caller arguments, and |
679 // return. | 697 // return. |
680 __ Bind(&exit); | 698 __ Bind(&exit); |
681 // x0: result | 699 // x0: result |
682 // jssp[0]: receiver (newly allocated object) | 700 // jssp[0]: receiver (newly allocated object) |
683 // jssp[1]: number of arguments (smi-tagged) | 701 // jssp[1]: new.target (if used) |
684 __ Peek(x1, kXRegSize); | 702 // jssp[1/2]: number of arguments (smi-tagged) |
| 703 int offset = (use_new_target ? 2 : 1) * kXRegSize; |
| 704 __ Peek(x1, offset); |
685 | 705 |
686 // Leave construct frame. | 706 // Leave construct frame. |
687 } | 707 } |
688 | 708 |
689 __ DropBySMI(x1); | 709 __ DropBySMI(x1); |
690 __ Drop(1); | 710 __ Drop(1); |
691 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); | 711 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); |
692 __ Ret(); | 712 __ Ret(); |
693 } | 713 } |
694 | 714 |
695 | 715 |
696 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 716 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
697 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 717 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
698 } | 718 } |
699 | 719 |
700 | 720 |
701 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 721 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
702 Generate_JSConstructStubHelper(masm, true, false); | 722 Generate_JSConstructStubHelper(masm, true, false, false); |
703 } | 723 } |
704 | 724 |
705 | 725 |
| 726 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { |
| 727 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); |
| 728 } |
| 729 |
| 730 |
706 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 731 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
707 // ----------- S t a t e ------------- | 732 // ----------- S t a t e ------------- |
708 // -- x0 : number of arguments | 733 // -- x0 : number of arguments |
709 // -- x1 : constructor function | 734 // -- x1 : constructor function |
710 // -- x2 : allocation site or undefined | 735 // -- x2 : allocation site or undefined |
711 // -- x3 : original constructor | 736 // -- x3 : original constructor |
712 // -- lr : return address | 737 // -- lr : return address |
713 // -- sp[...]: constructor arguments | 738 // -- sp[...]: constructor arguments |
714 // ----------------------------------- | 739 // ----------------------------------- |
715 ASM_LOCATION("Builtins::Generate_JSConstructStubForDerived"); | 740 ASM_LOCATION("Builtins::Generate_JSConstructStubForDerived"); |
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 } | 1858 } |
1834 } | 1859 } |
1835 | 1860 |
1836 | 1861 |
1837 #undef __ | 1862 #undef __ |
1838 | 1863 |
1839 } // namespace internal | 1864 } // namespace internal |
1840 } // namespace v8 | 1865 } // namespace v8 |
1841 | 1866 |
1842 #endif // V8_TARGET_ARCH_ARM | 1867 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |