| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/debug.h" | 10 #include "src/debug.h" |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 if (create_memento) { | 336 if (create_memento) { |
| 337 __ jmp(count_incremented); | 337 __ jmp(count_incremented); |
| 338 } else { | 338 } else { |
| 339 __ jmp(allocated); | 339 __ jmp(allocated); |
| 340 } | 340 } |
| 341 } | 341 } |
| 342 | 342 |
| 343 | 343 |
| 344 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 344 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 345 bool is_api_function, | 345 bool is_api_function, |
| 346 bool use_new_target, |
| 346 bool create_memento) { | 347 bool create_memento) { |
| 347 // ----------- S t a t e ------------- | 348 // ----------- S t a t e ------------- |
| 348 // -- r0 : number of arguments | 349 // -- r0 : number of arguments |
| 349 // -- r1 : constructor function | 350 // -- r1 : constructor function |
| 350 // -- r2 : allocation site or undefined | 351 // -- r2 : allocation site or undefined |
| 351 // -- r3 : original constructor | 352 // -- r3 : original constructor |
| 352 // -- lr : return address | 353 // -- lr : return address |
| 353 // -- sp[...]: constructor arguments | 354 // -- sp[...]: constructor arguments |
| 354 // ----------------------------------- | 355 // ----------------------------------- |
| 355 | 356 |
| 356 // Should never create mementos for api functions. | 357 // Should never create mementos for api functions. |
| 357 DCHECK(!is_api_function || !create_memento); | 358 DCHECK(!is_api_function || !create_memento); |
| 358 | 359 |
| 359 Isolate* isolate = masm->isolate(); | 360 Isolate* isolate = masm->isolate(); |
| 360 | 361 |
| 361 // Enter a construct frame. | 362 // Enter a construct frame. |
| 362 { | 363 { |
| 363 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 364 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
| 364 | 365 |
| 365 if (create_memento) { | 366 if (create_memento) { |
| 366 __ AssertUndefinedOrAllocationSite(r2, r4); | 367 __ AssertUndefinedOrAllocationSite(r2, r4); |
| 367 __ push(r2); | 368 __ push(r2); |
| 368 } | 369 } |
| 369 | 370 |
| 370 // Preserve the two incoming parameters on the stack. | 371 // Preserve the incoming parameters on the stack. |
| 371 __ SmiTag(r0); | 372 __ SmiTag(r0); |
| 372 __ push(r0); // Smi-tagged arguments count. | 373 __ push(r0); |
| 373 __ push(r1); // Constructor function. | 374 __ push(r1); |
| 375 if (use_new_target) { |
| 376 __ push(r3); |
| 377 } |
| 374 | 378 |
| 375 Label rt_call, allocated, normal_new, count_incremented; | 379 Label rt_call, allocated, normal_new, count_incremented; |
| 376 __ cmp(r1, r3); | 380 __ cmp(r1, r3); |
| 377 __ b(eq, &normal_new); | 381 __ b(eq, &normal_new); |
| 378 | 382 |
| 379 // Original constructor and function are different. | 383 // Original constructor and function are different. |
| 380 Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented, | 384 Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented, |
| 381 &allocated); | 385 &allocated); |
| 382 __ bind(&normal_new); | 386 __ bind(&normal_new); |
| 383 | 387 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 // r1: constructor function | 607 // r1: constructor function |
| 604 __ bind(&rt_call); | 608 __ bind(&rt_call); |
| 605 Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented, | 609 Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented, |
| 606 &allocated); | 610 &allocated); |
| 607 | 611 |
| 608 // Receiver for constructor call allocated. | 612 // Receiver for constructor call allocated. |
| 609 // r4: JSObject | 613 // r4: JSObject |
| 610 __ bind(&allocated); | 614 __ bind(&allocated); |
| 611 | 615 |
| 612 if (create_memento) { | 616 if (create_memento) { |
| 613 __ ldr(r2, MemOperand(sp, kPointerSize * 2)); | 617 int offset = (use_new_target ? 3 : 2) * kPointerSize; |
| 618 __ ldr(r2, MemOperand(sp, offset)); |
| 614 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | 619 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 615 __ cmp(r2, r5); | 620 __ cmp(r2, r5); |
| 616 __ b(eq, &count_incremented); | 621 __ b(eq, &count_incremented); |
| 617 // r2 is an AllocationSite. We are creating a memento from it, so we | 622 // r2 is an AllocationSite. We are creating a memento from it, so we |
| 618 // need to increment the memento create count. | 623 // need to increment the memento create count. |
| 619 __ ldr(r3, FieldMemOperand(r2, | 624 __ ldr(r3, FieldMemOperand(r2, |
| 620 AllocationSite::kPretenureCreateCountOffset)); | 625 AllocationSite::kPretenureCreateCountOffset)); |
| 621 __ add(r3, r3, Operand(Smi::FromInt(1))); | 626 __ add(r3, r3, Operand(Smi::FromInt(1))); |
| 622 __ str(r3, FieldMemOperand(r2, | 627 __ str(r3, FieldMemOperand(r2, |
| 623 AllocationSite::kPretenureCreateCountOffset)); | 628 AllocationSite::kPretenureCreateCountOffset)); |
| 624 __ bind(&count_incremented); | 629 __ bind(&count_incremented); |
| 625 } | 630 } |
| 626 | 631 |
| 627 __ pop(r1); // Constructor function. | 632 // Restore the parameters. |
| 633 if (use_new_target) { |
| 634 __ pop(r3); |
| 635 } |
| 636 __ pop(r1); |
| 628 | 637 |
| 638 // Retrieve smi-tagged arguments count from the stack. |
| 639 __ ldr(r0, MemOperand(sp)); |
| 640 __ SmiUntag(r0); |
| 641 |
| 642 // Push new.target onto the construct frame. This is stored just below the |
| 643 // receiver on the stack. |
| 644 if (use_new_target) { |
| 645 __ push(r3); |
| 646 } |
| 629 __ push(r4); | 647 __ push(r4); |
| 630 __ push(r4); | 648 __ push(r4); |
| 631 | 649 |
| 632 // Reload the number of arguments from the stack. | |
| 633 // sp[0]: receiver | |
| 634 // sp[1]: receiver | |
| 635 // sp[2]: number of arguments (smi-tagged) | |
| 636 __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); | |
| 637 | |
| 638 // Set up pointer to last argument. | 650 // Set up pointer to last argument. |
| 639 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 651 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 640 | 652 |
| 641 // Set up number of arguments for function call below | |
| 642 __ SmiUntag(r0, r3); | |
| 643 | |
| 644 // Copy arguments and receiver to the expression stack. | 653 // Copy arguments and receiver to the expression stack. |
| 645 // r0: number of arguments | 654 // r0: number of arguments |
| 646 // r1: constructor function | 655 // r1: constructor function |
| 647 // r2: address of last argument (caller sp) | 656 // r2: address of last argument (caller sp) |
| 648 // r3: number of arguments (smi-tagged) | 657 // r3: number of arguments (smi-tagged) |
| 649 // sp[0]: receiver | 658 // sp[0]: receiver |
| 650 // sp[1]: receiver | 659 // sp[1]: receiver |
| 651 // sp[2]: number of arguments (smi-tagged) | 660 // sp[2]: new.target (if used) |
| 661 // sp[2/3]: number of arguments (smi-tagged) |
| 652 Label loop, entry; | 662 Label loop, entry; |
| 663 __ SmiTag(r3, r0); |
| 653 __ b(&entry); | 664 __ b(&entry); |
| 654 __ bind(&loop); | 665 __ bind(&loop); |
| 655 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); | 666 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); |
| 656 __ push(ip); | 667 __ push(ip); |
| 657 __ bind(&entry); | 668 __ bind(&entry); |
| 658 __ sub(r3, r3, Operand(2), SetCC); | 669 __ sub(r3, r3, Operand(2), SetCC); |
| 659 __ b(ge, &loop); | 670 __ b(ge, &loop); |
| 660 | 671 |
| 661 // Call the function. | 672 // Call the function. |
| 662 // r0: number of arguments | 673 // r0: number of arguments |
| 663 // r1: constructor function | 674 // r1: constructor function |
| 664 if (is_api_function) { | 675 if (is_api_function) { |
| 665 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 676 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 666 Handle<Code> code = | 677 Handle<Code> code = |
| 667 masm->isolate()->builtins()->HandleApiCallConstruct(); | 678 masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 668 __ Call(code, RelocInfo::CODE_TARGET); | 679 __ Call(code, RelocInfo::CODE_TARGET); |
| 669 } else { | 680 } else { |
| 670 ParameterCount actual(r0); | 681 ParameterCount actual(r0); |
| 671 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); | 682 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); |
| 672 } | 683 } |
| 673 | 684 |
| 674 // Store offset of return address for deoptimizer. | 685 // Store offset of return address for deoptimizer. |
| 675 if (!is_api_function) { | 686 // TODO(arv): Remove the "!use_new_target" before supporting optimization |
| 687 // of functions that reference new.target |
| 688 if (!is_api_function && !use_new_target) { |
| 676 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 689 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
| 677 } | 690 } |
| 678 | 691 |
| 679 // Restore context from the frame. | 692 // Restore context from the frame. |
| 680 // r0: result | 693 // r0: result |
| 681 // sp[0]: receiver | 694 // sp[0]: receiver |
| 682 // sp[1]: number of arguments (smi-tagged) | 695 // sp[1]: new.target (if used) |
| 696 // sp[1/2]: number of arguments (smi-tagged) |
| 683 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 697 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 684 | 698 |
| 685 // If the result is an object (in the ECMA sense), we should get rid | 699 // If the result is an object (in the ECMA sense), we should get rid |
| 686 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 700 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
| 687 // on page 74. | 701 // on page 74. |
| 688 Label use_receiver, exit; | 702 Label use_receiver, exit; |
| 689 | 703 |
| 690 // If the result is a smi, it is *not* an object in the ECMA sense. | 704 // If the result is a smi, it is *not* an object in the ECMA sense. |
| 691 // r0: result | 705 // r0: result |
| 692 // sp[0]: receiver (newly allocated object) | 706 // sp[0]: receiver (newly allocated object) |
| 693 // sp[1]: number of arguments (smi-tagged) | 707 // sp[1]: new.target (if used) |
| 708 // sp[1/2]: number of arguments (smi-tagged) |
| 694 __ JumpIfSmi(r0, &use_receiver); | 709 __ JumpIfSmi(r0, &use_receiver); |
| 695 | 710 |
| 696 // If the type of the result (stored in its map) is less than | 711 // If the type of the result (stored in its map) is less than |
| 697 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 712 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
| 698 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); | 713 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); |
| 699 __ b(ge, &exit); | 714 __ b(ge, &exit); |
| 700 | 715 |
| 701 // Throw away the result of the constructor invocation and use the | 716 // Throw away the result of the constructor invocation and use the |
| 702 // on-stack receiver as the result. | 717 // on-stack receiver as the result. |
| 703 __ bind(&use_receiver); | 718 __ bind(&use_receiver); |
| 704 __ ldr(r0, MemOperand(sp)); | 719 __ ldr(r0, MemOperand(sp)); |
| 705 | 720 |
| 706 // Remove receiver from the stack, remove caller arguments, and | 721 // Remove receiver from the stack, remove caller arguments, and |
| 707 // return. | 722 // return. |
| 708 __ bind(&exit); | 723 __ bind(&exit); |
| 709 // r0: result | 724 // r0: result |
| 710 // sp[0]: receiver (newly allocated object) | 725 // sp[0]: receiver (newly allocated object) |
| 711 // sp[1]: number of arguments (smi-tagged) | 726 // sp[1]: new.target (if used) |
| 712 __ ldr(r1, MemOperand(sp, kPointerSize)); | 727 // sp[1/2]: number of arguments (smi-tagged) |
| 728 int offset = (use_new_target ? 2 : 1) * kPointerSize; |
| 729 __ ldr(r1, MemOperand(sp, offset)); |
| 713 | 730 |
| 714 // Leave construct frame. | 731 // Leave construct frame. |
| 715 } | 732 } |
| 716 | 733 |
| 717 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 734 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
| 718 __ add(sp, sp, Operand(kPointerSize)); | 735 __ add(sp, sp, Operand(kPointerSize)); |
| 719 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); | 736 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
| 720 __ Jump(lr); | 737 __ Jump(lr); |
| 721 } | 738 } |
| 722 | 739 |
| 723 | 740 |
| 724 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 741 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 725 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 742 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
| 726 } | 743 } |
| 727 | 744 |
| 728 | 745 |
| 729 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 746 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 730 Generate_JSConstructStubHelper(masm, true, false); | 747 Generate_JSConstructStubHelper(masm, true, false, false); |
| 731 } | 748 } |
| 732 | 749 |
| 733 | 750 |
| 751 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { |
| 752 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); |
| 753 } |
| 754 |
| 755 |
| 734 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 756 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
| 735 // ----------- S t a t e ------------- | 757 // ----------- S t a t e ------------- |
| 736 // -- r0 : number of arguments | 758 // -- r0 : number of arguments |
| 737 // -- r1 : constructor function | 759 // -- r1 : constructor function |
| 738 // -- r2 : allocation site or undefined | 760 // -- r2 : allocation site or undefined |
| 739 // -- r3 : original constructor | 761 // -- r3 : original constructor |
| 740 // -- lr : return address | 762 // -- lr : return address |
| 741 // -- sp[...]: constructor arguments | 763 // -- sp[...]: constructor arguments |
| 742 // ----------------------------------- | 764 // ----------------------------------- |
| 743 | 765 |
| (...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1806 } | 1828 } |
| 1807 } | 1829 } |
| 1808 | 1830 |
| 1809 | 1831 |
| 1810 #undef __ | 1832 #undef __ |
| 1811 | 1833 |
| 1812 } // namespace internal | 1834 } // namespace internal |
| 1813 } // namespace v8 | 1835 } // namespace v8 |
| 1814 | 1836 |
| 1815 #endif // V8_TARGET_ARCH_ARM | 1837 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |