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