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