| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 __ tst(r3, Operand(kIsNotStringMask)); | 575 __ tst(r3, Operand(kIsNotStringMask)); |
| 576 __ b(ne, &convert_argument); | 576 __ b(ne, &convert_argument); |
| 577 __ mov(argument, r0); | 577 __ mov(argument, r0); |
| 578 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); | 578 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); |
| 579 __ b(&argument_is_string); | 579 __ b(&argument_is_string); |
| 580 | 580 |
| 581 // Invoke the conversion builtin and put the result into r2. | 581 // Invoke the conversion builtin and put the result into r2. |
| 582 __ bind(&convert_argument); | 582 __ bind(&convert_argument); |
| 583 __ push(function); // Preserve the function. | 583 __ push(function); // Preserve the function. |
| 584 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); | 584 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); |
| 585 __ EnterInternalFrame(); | 585 { |
| 586 __ push(r0); | 586 FrameScope scope(masm, StackFrame::INTERNAL); |
| 587 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); | 587 __ push(r0); |
| 588 __ LeaveInternalFrame(); | 588 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); |
| 589 } |
| 589 __ pop(function); | 590 __ pop(function); |
| 590 __ mov(argument, r0); | 591 __ mov(argument, r0); |
| 591 __ b(&argument_is_string); | 592 __ b(&argument_is_string); |
| 592 | 593 |
| 593 // Load the empty string into r2, remove the receiver from the | 594 // Load the empty string into r2, remove the receiver from the |
| 594 // stack, and jump back to the case where the argument is a string. | 595 // stack, and jump back to the case where the argument is a string. |
| 595 __ bind(&no_arguments); | 596 __ bind(&no_arguments); |
| 596 __ LoadRoot(argument, Heap::kEmptyStringRootIndex); | 597 __ LoadRoot(argument, Heap::kEmptyStringRootIndex); |
| 597 __ Drop(1); | 598 __ Drop(1); |
| 598 __ b(&argument_is_string); | 599 __ b(&argument_is_string); |
| 599 | 600 |
| 600 // At this point the argument is already a string. Call runtime to | 601 // At this point the argument is already a string. Call runtime to |
| 601 // create a string wrapper. | 602 // create a string wrapper. |
| 602 __ bind(&gc_required); | 603 __ bind(&gc_required); |
| 603 __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); | 604 __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); |
| 604 __ EnterInternalFrame(); | 605 { |
| 605 __ push(argument); | 606 FrameScope scope(masm, StackFrame::INTERNAL); |
| 606 __ CallRuntime(Runtime::kNewStringWrapper, 1); | 607 __ push(argument); |
| 607 __ LeaveInternalFrame(); | 608 __ CallRuntime(Runtime::kNewStringWrapper, 1); |
| 609 } |
| 608 __ Ret(); | 610 __ Ret(); |
| 609 } | 611 } |
| 610 | 612 |
| 611 | 613 |
| 612 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { | 614 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
| 613 // ----------- S t a t e ------------- | 615 // ----------- S t a t e ------------- |
| 614 // -- r0 : number of arguments | 616 // -- r0 : number of arguments |
| 615 // -- r1 : constructor function | 617 // -- r1 : constructor function |
| 616 // -- lr : return address | 618 // -- lr : return address |
| 617 // -- sp[...]: constructor arguments | 619 // -- sp[...]: constructor arguments |
| 618 // ----------------------------------- | 620 // ----------------------------------- |
| 619 | 621 |
| 620 Label non_function_call; | 622 Label slow, non_function_call; |
| 621 // Check that the function is not a smi. | 623 // Check that the function is not a smi. |
| 622 __ JumpIfSmi(r1, &non_function_call); | 624 __ JumpIfSmi(r1, &non_function_call); |
| 623 // Check that the function is a JSFunction. | 625 // Check that the function is a JSFunction. |
| 624 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 626 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 625 __ b(ne, &non_function_call); | 627 __ b(ne, &slow); |
| 626 | 628 |
| 627 // Jump to the function-specific construct stub. | 629 // Jump to the function-specific construct stub. |
| 628 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 630 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 629 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); | 631 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); |
| 630 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); | 632 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 631 | 633 |
| 632 // r0: number of arguments | 634 // r0: number of arguments |
| 633 // r1: called object | 635 // r1: called object |
| 636 // r2: object type |
| 637 Label do_call; |
| 638 __ bind(&slow); |
| 639 __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 640 __ b(ne, &non_function_call); |
| 641 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 642 __ jmp(&do_call); |
| 643 |
| 634 __ bind(&non_function_call); | 644 __ bind(&non_function_call); |
| 645 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 646 __ bind(&do_call); |
| 635 // Set expected number of arguments to zero (not changing r0). | 647 // Set expected number of arguments to zero (not changing r0). |
| 636 __ mov(r2, Operand(0, RelocInfo::NONE)); | 648 __ mov(r2, Operand(0, RelocInfo::NONE)); |
| 637 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | |
| 638 __ SetCallKind(r5, CALL_AS_METHOD); | 649 __ SetCallKind(r5, CALL_AS_METHOD); |
| 639 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 650 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 640 RelocInfo::CODE_TARGET); | 651 RelocInfo::CODE_TARGET); |
| 641 } | 652 } |
| 642 | 653 |
| 643 | 654 |
| 644 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 655 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 645 bool is_api_function, | 656 bool is_api_function, |
| 646 bool count_constructions) { | 657 bool count_constructions) { |
| 647 // Should never count constructions for api objects. | 658 // Should never count constructions for api objects. |
| 648 ASSERT(!is_api_function || !count_constructions); | 659 ASSERT(!is_api_function || !count_constructions); |
| 649 | 660 |
| 650 Isolate* isolate = masm->isolate(); | 661 Isolate* isolate = masm->isolate(); |
| 651 | 662 |
| 652 // Enter a construct frame. | 663 // Enter a construct frame. |
| 653 __ EnterConstructFrame(); | 664 { |
| 654 | 665 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 655 // Preserve the two incoming parameters on the stack. | 666 |
| 656 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 667 // Preserve the two incoming parameters on the stack. |
| 657 __ push(r0); // Smi-tagged arguments count. | 668 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
| 658 __ push(r1); // Constructor function. | 669 __ push(r0); // Smi-tagged arguments count. |
| 659 | 670 __ push(r1); // Constructor function. |
| 660 // Try to allocate the object without transitioning into C code. If any of the | 671 |
| 661 // preconditions is not met, the code bails out to the runtime call. | 672 // Try to allocate the object without transitioning into C code. If any of |
| 662 Label rt_call, allocated; | 673 // the preconditions is not met, the code bails out to the runtime call. |
| 663 if (FLAG_inline_new) { | 674 Label rt_call, allocated; |
| 664 Label undo_allocation; | 675 if (FLAG_inline_new) { |
| 676 Label undo_allocation; |
| 665 #ifdef ENABLE_DEBUGGER_SUPPORT | 677 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 666 ExternalReference debug_step_in_fp = | 678 ExternalReference debug_step_in_fp = |
| 667 ExternalReference::debug_step_in_fp_address(isolate); | 679 ExternalReference::debug_step_in_fp_address(isolate); |
| 668 __ mov(r2, Operand(debug_step_in_fp)); | 680 __ mov(r2, Operand(debug_step_in_fp)); |
| 669 __ ldr(r2, MemOperand(r2)); | 681 __ ldr(r2, MemOperand(r2)); |
| 670 __ tst(r2, r2); | 682 __ tst(r2, r2); |
| 671 __ b(ne, &rt_call); | 683 __ b(ne, &rt_call); |
| 672 #endif | 684 #endif |
| 673 | 685 |
| 674 // Load the initial map and verify that it is in fact a map. | 686 // Load the initial map and verify that it is in fact a map. |
| 675 // r1: constructor function | 687 // r1: constructor function |
| 676 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 688 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 677 __ JumpIfSmi(r2, &rt_call); | 689 __ JumpIfSmi(r2, &rt_call); |
| 678 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 690 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
| 679 __ b(ne, &rt_call); | 691 __ b(ne, &rt_call); |
| 680 | 692 |
| 681 // Check that the constructor is not constructing a JSFunction (see comments | 693 // Check that the constructor is not constructing a JSFunction (see |
| 682 // in Runtime_NewObject in runtime.cc). In which case the initial map's | 694 // comments in Runtime_NewObject in runtime.cc). In which case the |
| 683 // instance type would be JS_FUNCTION_TYPE. | 695 // initial map's instance type would be JS_FUNCTION_TYPE. |
| 684 // r1: constructor function | 696 // r1: constructor function |
| 685 // r2: initial map | 697 // r2: initial map |
| 686 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); | 698 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); |
| 687 __ b(eq, &rt_call); | 699 __ b(eq, &rt_call); |
| 688 | 700 |
| 689 if (count_constructions) { | |
| 690 Label allocate; | |
| 691 // Decrease generous allocation count. | |
| 692 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
| 693 MemOperand constructor_count = | |
| 694 FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); | |
| 695 __ ldrb(r4, constructor_count); | |
| 696 __ sub(r4, r4, Operand(1), SetCC); | |
| 697 __ strb(r4, constructor_count); | |
| 698 __ b(ne, &allocate); | |
| 699 | |
| 700 __ Push(r1, r2); | |
| 701 | |
| 702 __ push(r1); // constructor | |
| 703 // The call will replace the stub, so the countdown is only done once. | |
| 704 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | |
| 705 | |
| 706 __ pop(r2); | |
| 707 __ pop(r1); | |
| 708 | |
| 709 __ bind(&allocate); | |
| 710 } | |
| 711 | |
| 712 // Now allocate the JSObject on the heap. | |
| 713 // r1: constructor function | |
| 714 // r2: initial map | |
| 715 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); | |
| 716 __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); | |
| 717 | |
| 718 // Allocated the JSObject, now initialize the fields. Map is set to initial | |
| 719 // map and properties and elements are set to empty fixed array. | |
| 720 // r1: constructor function | |
| 721 // r2: initial map | |
| 722 // r3: object size | |
| 723 // r4: JSObject (not tagged) | |
| 724 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); | |
| 725 __ mov(r5, r4); | |
| 726 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); | |
| 727 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); | |
| 728 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); | |
| 729 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | |
| 730 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); | |
| 731 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | |
| 732 | |
| 733 // Fill all the in-object properties with the appropriate filler. | |
| 734 // r1: constructor function | |
| 735 // r2: initial map | |
| 736 // r3: object size (in words) | |
| 737 // r4: JSObject (not tagged) | |
| 738 // r5: First in-object property of JSObject (not tagged) | |
| 739 __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | |
| 740 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); | |
| 741 { Label loop, entry; | |
| 742 if (count_constructions) { | 701 if (count_constructions) { |
| 702 Label allocate; |
| 703 // Decrease generous allocation count. |
| 704 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 705 MemOperand constructor_count = |
| 706 FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); |
| 707 __ ldrb(r4, constructor_count); |
| 708 __ sub(r4, r4, Operand(1), SetCC); |
| 709 __ strb(r4, constructor_count); |
| 710 __ b(ne, &allocate); |
| 711 |
| 712 __ Push(r1, r2); |
| 713 |
| 714 __ push(r1); // constructor |
| 715 // The call will replace the stub, so the countdown is only done once. |
| 716 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 717 |
| 718 __ pop(r2); |
| 719 __ pop(r1); |
| 720 |
| 721 __ bind(&allocate); |
| 722 } |
| 723 |
| 724 // Now allocate the JSObject on the heap. |
| 725 // r1: constructor function |
| 726 // r2: initial map |
| 727 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); |
| 728 __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); |
| 729 |
| 730 // Allocated the JSObject, now initialize the fields. Map is set to |
| 731 // initial map and properties and elements are set to empty fixed array. |
| 732 // r1: constructor function |
| 733 // r2: initial map |
| 734 // r3: object size |
| 735 // r4: JSObject (not tagged) |
| 736 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); |
| 737 __ mov(r5, r4); |
| 738 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
| 739 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); |
| 740 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); |
| 741 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
| 742 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); |
| 743 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
| 744 |
| 745 // Fill all the in-object properties with the appropriate filler. |
| 746 // r1: constructor function |
| 747 // r2: initial map |
| 748 // r3: object size (in words) |
| 749 // r4: JSObject (not tagged) |
| 750 // r5: First in-object property of JSObject (not tagged) |
| 751 __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
| 752 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
| 753 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); |
| 754 if (count_constructions) { |
| 755 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); |
| 756 __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, |
| 757 kBitsPerByte); |
| 758 __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); |
| 759 // r0: offset of first field after pre-allocated fields |
| 760 if (FLAG_debug_code) { |
| 761 __ cmp(r0, r6); |
| 762 __ Assert(le, "Unexpected number of pre-allocated property fields."); |
| 763 } |
| 764 __ InitializeFieldsWithFiller(r5, r0, r7); |
| 743 // To allow for truncation. | 765 // To allow for truncation. |
| 744 __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); | 766 __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); |
| 745 } else { | |
| 746 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); | |
| 747 } | 767 } |
| 748 __ b(&entry); | 768 __ InitializeFieldsWithFiller(r5, r6, r7); |
| 749 __ bind(&loop); | 769 |
| 750 __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); | 770 // Add the object tag to make the JSObject real, so that we can continue |
| 751 __ bind(&entry); | 771 // and jump into the continuation code at any time from now on. Any |
| 752 __ cmp(r5, r6); | 772 // failures need to undo the allocation, so that the heap is in a |
| 753 __ b(lt, &loop); | 773 // consistent state and verifiable. |
| 774 __ add(r4, r4, Operand(kHeapObjectTag)); |
| 775 |
| 776 // Check if a non-empty properties array is needed. Continue with |
| 777 // allocated object if not fall through to runtime call if it is. |
| 778 // r1: constructor function |
| 779 // r4: JSObject |
| 780 // r5: start of next object (not tagged) |
| 781 __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); |
| 782 // The field instance sizes contains both pre-allocated property fields |
| 783 // and in-object properties. |
| 784 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); |
| 785 __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, |
| 786 kBitsPerByte); |
| 787 __ add(r3, r3, Operand(r6)); |
| 788 __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte, |
| 789 kBitsPerByte); |
| 790 __ sub(r3, r3, Operand(r6), SetCC); |
| 791 |
| 792 // Done if no extra properties are to be allocated. |
| 793 __ b(eq, &allocated); |
| 794 __ Assert(pl, "Property allocation count failed."); |
| 795 |
| 796 // Scale the number of elements by pointer size and add the header for |
| 797 // FixedArrays to the start of the next object calculation from above. |
| 798 // r1: constructor |
| 799 // r3: number of elements in properties array |
| 800 // r4: JSObject |
| 801 // r5: start of next object |
| 802 __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 803 __ AllocateInNewSpace( |
| 804 r0, |
| 805 r5, |
| 806 r6, |
| 807 r2, |
| 808 &undo_allocation, |
| 809 static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); |
| 810 |
| 811 // Initialize the FixedArray. |
| 812 // r1: constructor |
| 813 // r3: number of elements in properties array |
| 814 // r4: JSObject |
| 815 // r5: FixedArray (not tagged) |
| 816 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); |
| 817 __ mov(r2, r5); |
| 818 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
| 819 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); |
| 820 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); |
| 821 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); |
| 822 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); |
| 823 |
| 824 // Initialize the fields to undefined. |
| 825 // r1: constructor function |
| 826 // r2: First element of FixedArray (not tagged) |
| 827 // r3: number of elements in properties array |
| 828 // r4: JSObject |
| 829 // r5: FixedArray (not tagged) |
| 830 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
| 831 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); |
| 832 { Label loop, entry; |
| 833 if (count_constructions) { |
| 834 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); |
| 835 } else if (FLAG_debug_code) { |
| 836 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
| 837 __ cmp(r7, r8); |
| 838 __ Assert(eq, "Undefined value not loaded."); |
| 839 } |
| 840 __ b(&entry); |
| 841 __ bind(&loop); |
| 842 __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); |
| 843 __ bind(&entry); |
| 844 __ cmp(r2, r6); |
| 845 __ b(lt, &loop); |
| 846 } |
| 847 |
| 848 // Store the initialized FixedArray into the properties field of |
| 849 // the JSObject |
| 850 // r1: constructor function |
| 851 // r4: JSObject |
| 852 // r5: FixedArray (not tagged) |
| 853 __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. |
| 854 __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); |
| 855 |
| 856 // Continue with JSObject being successfully allocated |
| 857 // r1: constructor function |
| 858 // r4: JSObject |
| 859 __ jmp(&allocated); |
| 860 |
| 861 // Undo the setting of the new top so that the heap is verifiable. For |
| 862 // example, the map's unused properties potentially do not match the |
| 863 // allocated objects unused properties. |
| 864 // r4: JSObject (previous new top) |
| 865 __ bind(&undo_allocation); |
| 866 __ UndoAllocationInNewSpace(r4, r5); |
| 754 } | 867 } |
| 755 | 868 |
| 756 // Add the object tag to make the JSObject real, so that we can continue and | 869 // Allocate the new receiver object using the runtime call. |
| 757 // jump into the continuation code at any time from now on. Any failures | |
| 758 // need to undo the allocation, so that the heap is in a consistent state | |
| 759 // and verifiable. | |
| 760 __ add(r4, r4, Operand(kHeapObjectTag)); | |
| 761 | |
| 762 // Check if a non-empty properties array is needed. Continue with allocated | |
| 763 // object if not fall through to runtime call if it is. | |
| 764 // r1: constructor function | 870 // r1: constructor function |
| 871 __ bind(&rt_call); |
| 872 __ push(r1); // argument for Runtime_NewObject |
| 873 __ CallRuntime(Runtime::kNewObject, 1); |
| 874 __ mov(r4, r0); |
| 875 |
| 876 // Receiver for constructor call allocated. |
| 765 // r4: JSObject | 877 // r4: JSObject |
| 766 // r5: start of next object (not tagged) | 878 __ bind(&allocated); |
| 767 __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); | 879 __ push(r4); |
| 768 // The field instance sizes contains both pre-allocated property fields and | 880 |
| 769 // in-object properties. | 881 // Push the function and the allocated receiver from the stack. |
| 770 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); | 882 // sp[0]: receiver (newly allocated object) |
| 771 __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8); | 883 // sp[1]: constructor function |
| 772 __ add(r3, r3, Operand(r6)); | 884 // sp[2]: number of arguments (smi-tagged) |
| 773 __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8); | 885 __ ldr(r1, MemOperand(sp, kPointerSize)); |
| 774 __ sub(r3, r3, Operand(r6), SetCC); | 886 __ push(r1); // Constructor function. |
| 775 | 887 __ push(r4); // Receiver. |
| 776 // Done if no extra properties are to be allocated. | 888 |
| 777 __ b(eq, &allocated); | 889 // Reload the number of arguments from the stack. |
| 778 __ Assert(pl, "Property allocation count failed."); | |
| 779 | |
| 780 // Scale the number of elements by pointer size and add the header for | |
| 781 // FixedArrays to the start of the next object calculation from above. | |
| 782 // r1: constructor | |
| 783 // r3: number of elements in properties array | |
| 784 // r4: JSObject | |
| 785 // r5: start of next object | |
| 786 __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); | |
| 787 __ AllocateInNewSpace( | |
| 788 r0, | |
| 789 r5, | |
| 790 r6, | |
| 791 r2, | |
| 792 &undo_allocation, | |
| 793 static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); | |
| 794 | |
| 795 // Initialize the FixedArray. | |
| 796 // r1: constructor | |
| 797 // r3: number of elements in properties array | |
| 798 // r4: JSObject | |
| 799 // r5: FixedArray (not tagged) | |
| 800 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); | |
| 801 __ mov(r2, r5); | |
| 802 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); | |
| 803 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); | |
| 804 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); | |
| 805 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); | |
| 806 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); | |
| 807 | |
| 808 // Initialize the fields to undefined. | |
| 809 // r1: constructor function | 890 // r1: constructor function |
| 810 // r2: First element of FixedArray (not tagged) | 891 // sp[0]: receiver |
| 811 // r3: number of elements in properties array | 892 // sp[1]: constructor function |
| 812 // r4: JSObject | 893 // sp[2]: receiver |
| 813 // r5: FixedArray (not tagged) | 894 // sp[3]: constructor function |
| 814 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | 895 // sp[4]: number of arguments (smi-tagged) |
| 815 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); | 896 __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); |
| 816 { Label loop, entry; | 897 |
| 817 if (count_constructions) { | 898 // Setup pointer to last argument. |
| 818 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); | 899 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 819 } else if (FLAG_debug_code) { | 900 |
| 820 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 901 // Setup number of arguments for function call below |
| 821 __ cmp(r7, r8); | 902 __ mov(r0, Operand(r3, LSR, kSmiTagSize)); |
| 822 __ Assert(eq, "Undefined value not loaded."); | 903 |
| 823 } | 904 // Copy arguments and receiver to the expression stack. |
| 824 __ b(&entry); | 905 // r0: number of arguments |
| 825 __ bind(&loop); | 906 // r2: address of last argument (caller sp) |
| 826 __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); | 907 // r1: constructor function |
| 827 __ bind(&entry); | 908 // r3: number of arguments (smi-tagged) |
| 828 __ cmp(r2, r6); | 909 // sp[0]: receiver |
| 829 __ b(lt, &loop); | 910 // sp[1]: constructor function |
| 911 // sp[2]: receiver |
| 912 // sp[3]: constructor function |
| 913 // sp[4]: number of arguments (smi-tagged) |
| 914 Label loop, entry; |
| 915 __ b(&entry); |
| 916 __ bind(&loop); |
| 917 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); |
| 918 __ push(ip); |
| 919 __ bind(&entry); |
| 920 __ sub(r3, r3, Operand(2), SetCC); |
| 921 __ b(ge, &loop); |
| 922 |
| 923 // Call the function. |
| 924 // r0: number of arguments |
| 925 // r1: constructor function |
| 926 if (is_api_function) { |
| 927 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 928 Handle<Code> code = |
| 929 masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 930 ParameterCount expected(0); |
| 931 __ InvokeCode(code, expected, expected, |
| 932 RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); |
| 933 } else { |
| 934 ParameterCount actual(r0); |
| 935 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
| 936 NullCallWrapper(), CALL_AS_METHOD); |
| 830 } | 937 } |
| 831 | 938 |
| 832 // Store the initialized FixedArray into the properties field of | 939 // Pop the function from the stack. |
| 833 // the JSObject | 940 // sp[0]: constructor function |
| 834 // r1: constructor function | 941 // sp[2]: receiver |
| 835 // r4: JSObject | 942 // sp[3]: constructor function |
| 836 // r5: FixedArray (not tagged) | 943 // sp[4]: number of arguments (smi-tagged) |
| 837 __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. | 944 __ pop(); |
| 838 __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); | 945 |
| 839 | 946 // Restore context from the frame. |
| 840 // Continue with JSObject being successfully allocated | 947 // r0: result |
| 841 // r1: constructor function | 948 // sp[0]: receiver |
| 842 // r4: JSObject | 949 // sp[1]: constructor function |
| 843 __ jmp(&allocated); | 950 // sp[2]: number of arguments (smi-tagged) |
| 844 | 951 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 845 // Undo the setting of the new top so that the heap is verifiable. For | 952 |
| 846 // example, the map's unused properties potentially do not match the | 953 // If the result is an object (in the ECMA sense), we should get rid |
| 847 // allocated objects unused properties. | 954 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
| 848 // r4: JSObject (previous new top) | 955 // on page 74. |
| 849 __ bind(&undo_allocation); | 956 Label use_receiver, exit; |
| 850 __ UndoAllocationInNewSpace(r4, r5); | 957 |
| 958 // If the result is a smi, it is *not* an object in the ECMA sense. |
| 959 // r0: result |
| 960 // sp[0]: receiver (newly allocated object) |
| 961 // sp[1]: constructor function |
| 962 // sp[2]: number of arguments (smi-tagged) |
| 963 __ JumpIfSmi(r0, &use_receiver); |
| 964 |
| 965 // If the type of the result (stored in its map) is less than |
| 966 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
| 967 __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
| 968 __ b(ge, &exit); |
| 969 |
| 970 // Throw away the result of the constructor invocation and use the |
| 971 // on-stack receiver as the result. |
| 972 __ bind(&use_receiver); |
| 973 __ ldr(r0, MemOperand(sp)); |
| 974 |
| 975 // Remove receiver from the stack, remove caller arguments, and |
| 976 // return. |
| 977 __ bind(&exit); |
| 978 // r0: result |
| 979 // sp[0]: receiver (newly allocated object) |
| 980 // sp[1]: constructor function |
| 981 // sp[2]: number of arguments (smi-tagged) |
| 982 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
| 983 |
| 984 // Leave construct frame. |
| 851 } | 985 } |
| 852 | 986 |
| 853 // Allocate the new receiver object using the runtime call. | |
| 854 // r1: constructor function | |
| 855 __ bind(&rt_call); | |
| 856 __ push(r1); // argument for Runtime_NewObject | |
| 857 __ CallRuntime(Runtime::kNewObject, 1); | |
| 858 __ mov(r4, r0); | |
| 859 | |
| 860 // Receiver for constructor call allocated. | |
| 861 // r4: JSObject | |
| 862 __ bind(&allocated); | |
| 863 __ push(r4); | |
| 864 | |
| 865 // Push the function and the allocated receiver from the stack. | |
| 866 // sp[0]: receiver (newly allocated object) | |
| 867 // sp[1]: constructor function | |
| 868 // sp[2]: number of arguments (smi-tagged) | |
| 869 __ ldr(r1, MemOperand(sp, kPointerSize)); | |
| 870 __ push(r1); // Constructor function. | |
| 871 __ push(r4); // Receiver. | |
| 872 | |
| 873 // Reload the number of arguments from the stack. | |
| 874 // r1: constructor function | |
| 875 // sp[0]: receiver | |
| 876 // sp[1]: constructor function | |
| 877 // sp[2]: receiver | |
| 878 // sp[3]: constructor function | |
| 879 // sp[4]: number of arguments (smi-tagged) | |
| 880 __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); | |
| 881 | |
| 882 // Setup pointer to last argument. | |
| 883 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | |
| 884 | |
| 885 // Setup number of arguments for function call below | |
| 886 __ mov(r0, Operand(r3, LSR, kSmiTagSize)); | |
| 887 | |
| 888 // Copy arguments and receiver to the expression stack. | |
| 889 // r0: number of arguments | |
| 890 // r2: address of last argument (caller sp) | |
| 891 // r1: constructor function | |
| 892 // r3: number of arguments (smi-tagged) | |
| 893 // sp[0]: receiver | |
| 894 // sp[1]: constructor function | |
| 895 // sp[2]: receiver | |
| 896 // sp[3]: constructor function | |
| 897 // sp[4]: number of arguments (smi-tagged) | |
| 898 Label loop, entry; | |
| 899 __ b(&entry); | |
| 900 __ bind(&loop); | |
| 901 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); | |
| 902 __ push(ip); | |
| 903 __ bind(&entry); | |
| 904 __ sub(r3, r3, Operand(2), SetCC); | |
| 905 __ b(ge, &loop); | |
| 906 | |
| 907 // Call the function. | |
| 908 // r0: number of arguments | |
| 909 // r1: constructor function | |
| 910 if (is_api_function) { | |
| 911 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | |
| 912 Handle<Code> code = | |
| 913 masm->isolate()->builtins()->HandleApiCallConstruct(); | |
| 914 ParameterCount expected(0); | |
| 915 __ InvokeCode(code, expected, expected, | |
| 916 RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); | |
| 917 } else { | |
| 918 ParameterCount actual(r0); | |
| 919 __ InvokeFunction(r1, actual, CALL_FUNCTION, | |
| 920 NullCallWrapper(), CALL_AS_METHOD); | |
| 921 } | |
| 922 | |
| 923 // Pop the function from the stack. | |
| 924 // sp[0]: constructor function | |
| 925 // sp[2]: receiver | |
| 926 // sp[3]: constructor function | |
| 927 // sp[4]: number of arguments (smi-tagged) | |
| 928 __ pop(); | |
| 929 | |
| 930 // Restore context from the frame. | |
| 931 // r0: result | |
| 932 // sp[0]: receiver | |
| 933 // sp[1]: constructor function | |
| 934 // sp[2]: number of arguments (smi-tagged) | |
| 935 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 936 | |
| 937 // If the result is an object (in the ECMA sense), we should get rid | |
| 938 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | |
| 939 // on page 74. | |
| 940 Label use_receiver, exit; | |
| 941 | |
| 942 // If the result is a smi, it is *not* an object in the ECMA sense. | |
| 943 // r0: result | |
| 944 // sp[0]: receiver (newly allocated object) | |
| 945 // sp[1]: constructor function | |
| 946 // sp[2]: number of arguments (smi-tagged) | |
| 947 __ JumpIfSmi(r0, &use_receiver); | |
| 948 | |
| 949 // If the type of the result (stored in its map) is less than | |
| 950 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | |
| 951 __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE); | |
| 952 __ b(ge, &exit); | |
| 953 | |
| 954 // Throw away the result of the constructor invocation and use the | |
| 955 // on-stack receiver as the result. | |
| 956 __ bind(&use_receiver); | |
| 957 __ ldr(r0, MemOperand(sp)); | |
| 958 | |
| 959 // Remove receiver from the stack, remove caller arguments, and | |
| 960 // return. | |
| 961 __ bind(&exit); | |
| 962 // r0: result | |
| 963 // sp[0]: receiver (newly allocated object) | |
| 964 // sp[1]: constructor function | |
| 965 // sp[2]: number of arguments (smi-tagged) | |
| 966 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); | |
| 967 __ LeaveConstructFrame(); | |
| 968 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 987 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
| 969 __ add(sp, sp, Operand(kPointerSize)); | 988 __ add(sp, sp, Operand(kPointerSize)); |
| 970 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); | 989 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
| 971 __ Jump(lr); | 990 __ Jump(lr); |
| 972 } | 991 } |
| 973 | 992 |
| 974 | 993 |
| 975 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 994 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
| 976 Generate_JSConstructStubHelper(masm, false, true); | 995 Generate_JSConstructStubHelper(masm, false, true); |
| 977 } | 996 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 990 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 1009 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
| 991 bool is_construct) { | 1010 bool is_construct) { |
| 992 // Called from Generate_JS_Entry | 1011 // Called from Generate_JS_Entry |
| 993 // r0: code entry | 1012 // r0: code entry |
| 994 // r1: function | 1013 // r1: function |
| 995 // r2: receiver | 1014 // r2: receiver |
| 996 // r3: argc | 1015 // r3: argc |
| 997 // r4: argv | 1016 // r4: argv |
| 998 // r5-r7, cp may be clobbered | 1017 // r5-r7, cp may be clobbered |
| 999 | 1018 |
| 1000 // Clear the context before we push it when entering the JS frame. | 1019 // Clear the context before we push it when entering the internal frame. |
| 1001 __ mov(cp, Operand(0, RelocInfo::NONE)); | 1020 __ mov(cp, Operand(0, RelocInfo::NONE)); |
| 1002 | 1021 |
| 1003 // Enter an internal frame. | 1022 // Enter an internal frame. |
| 1004 __ EnterInternalFrame(); | 1023 { |
| 1024 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1005 | 1025 |
| 1006 // Set up the context from the function argument. | 1026 // Set up the context from the function argument. |
| 1007 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1027 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1008 | 1028 |
| 1009 // Set up the roots register. | 1029 // Set up the roots register. |
| 1010 ExternalReference roots_address = | 1030 ExternalReference roots_address = |
| 1011 ExternalReference::roots_address(masm->isolate()); | 1031 ExternalReference::roots_address(masm->isolate()); |
| 1012 __ mov(r10, Operand(roots_address)); | 1032 __ mov(r10, Operand(roots_address)); |
| 1013 | 1033 |
| 1014 // Push the function and the receiver onto the stack. | 1034 // Push the function and the receiver onto the stack. |
| 1015 __ push(r1); | 1035 __ push(r1); |
| 1016 __ push(r2); | 1036 __ push(r2); |
| 1017 | 1037 |
| 1018 // Copy arguments to the stack in a loop. | 1038 // Copy arguments to the stack in a loop. |
| 1019 // r1: function | 1039 // r1: function |
| 1020 // r3: argc | 1040 // r3: argc |
| 1021 // r4: argv, i.e. points to first arg | 1041 // r4: argv, i.e. points to first arg |
| 1022 Label loop, entry; | 1042 Label loop, entry; |
| 1023 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); | 1043 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); |
| 1024 // r2 points past last arg. | 1044 // r2 points past last arg. |
| 1025 __ b(&entry); | 1045 __ b(&entry); |
| 1026 __ bind(&loop); | 1046 __ bind(&loop); |
| 1027 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter | 1047 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter |
| 1028 __ ldr(r0, MemOperand(r0)); // dereference handle | 1048 __ ldr(r0, MemOperand(r0)); // dereference handle |
| 1029 __ push(r0); // push parameter | 1049 __ push(r0); // push parameter |
| 1030 __ bind(&entry); | 1050 __ bind(&entry); |
| 1031 __ cmp(r4, r2); | 1051 __ cmp(r4, r2); |
| 1032 __ b(ne, &loop); | 1052 __ b(ne, &loop); |
| 1033 | 1053 |
| 1034 // Initialize all JavaScript callee-saved registers, since they will be seen | 1054 // Initialize all JavaScript callee-saved registers, since they will be seen |
| 1035 // by the garbage collector as part of handlers. | 1055 // by the garbage collector as part of handlers. |
| 1036 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 1056 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
| 1037 __ mov(r5, Operand(r4)); | 1057 __ mov(r5, Operand(r4)); |
| 1038 __ mov(r6, Operand(r4)); | 1058 __ mov(r6, Operand(r4)); |
| 1039 __ mov(r7, Operand(r4)); | 1059 __ mov(r7, Operand(r4)); |
| 1040 if (kR9Available == 1) { | 1060 if (kR9Available == 1) { |
| 1041 __ mov(r9, Operand(r4)); | 1061 __ mov(r9, Operand(r4)); |
| 1062 } |
| 1063 |
| 1064 // Invoke the code and pass argc as r0. |
| 1065 __ mov(r0, Operand(r3)); |
| 1066 if (is_construct) { |
| 1067 __ Call(masm->isolate()->builtins()->JSConstructCall()); |
| 1068 } else { |
| 1069 ParameterCount actual(r0); |
| 1070 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
| 1071 NullCallWrapper(), CALL_AS_METHOD); |
| 1072 } |
| 1073 // Exit the JS frame and remove the parameters (except function), and |
| 1074 // return. |
| 1075 // Respect ABI stack constraint. |
| 1042 } | 1076 } |
| 1043 | |
| 1044 // Invoke the code and pass argc as r0. | |
| 1045 __ mov(r0, Operand(r3)); | |
| 1046 if (is_construct) { | |
| 1047 __ Call(masm->isolate()->builtins()->JSConstructCall()); | |
| 1048 } else { | |
| 1049 ParameterCount actual(r0); | |
| 1050 __ InvokeFunction(r1, actual, CALL_FUNCTION, | |
| 1051 NullCallWrapper(), CALL_AS_METHOD); | |
| 1052 } | |
| 1053 | |
| 1054 // Exit the JS frame and remove the parameters (except function), and return. | |
| 1055 // Respect ABI stack constraint. | |
| 1056 __ LeaveInternalFrame(); | |
| 1057 __ Jump(lr); | 1077 __ Jump(lr); |
| 1058 | 1078 |
| 1059 // r0: result | 1079 // r0: result |
| 1060 } | 1080 } |
| 1061 | 1081 |
| 1062 | 1082 |
| 1063 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 1083 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
| 1064 Generate_JSEntryTrampolineHelper(masm, false); | 1084 Generate_JSEntryTrampolineHelper(masm, false); |
| 1065 } | 1085 } |
| 1066 | 1086 |
| 1067 | 1087 |
| 1068 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 1088 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
| 1069 Generate_JSEntryTrampolineHelper(masm, true); | 1089 Generate_JSEntryTrampolineHelper(masm, true); |
| 1070 } | 1090 } |
| 1071 | 1091 |
| 1072 | 1092 |
| 1073 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { | 1093 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { |
| 1074 // Enter an internal frame. | 1094 // Enter an internal frame. |
| 1075 __ EnterInternalFrame(); | 1095 { |
| 1096 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1076 | 1097 |
| 1077 // Preserve the function. | 1098 // Preserve the function. |
| 1078 __ push(r1); | 1099 __ push(r1); |
| 1079 // Push call kind information. | 1100 // Push call kind information. |
| 1080 __ push(r5); | 1101 __ push(r5); |
| 1081 | 1102 |
| 1082 // Push the function on the stack as the argument to the runtime function. | 1103 // Push the function on the stack as the argument to the runtime function. |
| 1083 __ push(r1); | 1104 __ push(r1); |
| 1084 __ CallRuntime(Runtime::kLazyCompile, 1); | 1105 __ CallRuntime(Runtime::kLazyCompile, 1); |
| 1085 // Calculate the entry point. | 1106 // Calculate the entry point. |
| 1086 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1107 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1087 | 1108 |
| 1088 // Restore call kind information. | 1109 // Restore call kind information. |
| 1089 __ pop(r5); | 1110 __ pop(r5); |
| 1090 // Restore saved function. | 1111 // Restore saved function. |
| 1091 __ pop(r1); | 1112 __ pop(r1); |
| 1092 | 1113 |
| 1093 // Tear down temporary frame. | 1114 // Tear down internal frame. |
| 1094 __ LeaveInternalFrame(); | 1115 } |
| 1095 | 1116 |
| 1096 // Do a tail-call of the compiled function. | 1117 // Do a tail-call of the compiled function. |
| 1097 __ Jump(r2); | 1118 __ Jump(r2); |
| 1098 } | 1119 } |
| 1099 | 1120 |
| 1100 | 1121 |
| 1101 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { | 1122 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { |
| 1102 // Enter an internal frame. | 1123 // Enter an internal frame. |
| 1103 __ EnterInternalFrame(); | 1124 { |
| 1125 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1104 | 1126 |
| 1105 // Preserve the function. | 1127 // Preserve the function. |
| 1106 __ push(r1); | 1128 __ push(r1); |
| 1107 // Push call kind information. | 1129 // Push call kind information. |
| 1108 __ push(r5); | 1130 __ push(r5); |
| 1109 | 1131 |
| 1110 // Push the function on the stack as the argument to the runtime function. | 1132 // Push the function on the stack as the argument to the runtime function. |
| 1111 __ push(r1); | 1133 __ push(r1); |
| 1112 __ CallRuntime(Runtime::kLazyRecompile, 1); | 1134 __ CallRuntime(Runtime::kLazyRecompile, 1); |
| 1113 // Calculate the entry point. | 1135 // Calculate the entry point. |
| 1114 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1136 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1115 | 1137 |
| 1116 // Restore call kind information. | 1138 // Restore call kind information. |
| 1117 __ pop(r5); | 1139 __ pop(r5); |
| 1118 // Restore saved function. | 1140 // Restore saved function. |
| 1119 __ pop(r1); | 1141 __ pop(r1); |
| 1120 | 1142 |
| 1121 // Tear down temporary frame. | 1143 // Tear down internal frame. |
| 1122 __ LeaveInternalFrame(); | 1144 } |
| 1123 | 1145 |
| 1124 // Do a tail-call of the compiled function. | 1146 // Do a tail-call of the compiled function. |
| 1125 __ Jump(r2); | 1147 __ Jump(r2); |
| 1126 } | 1148 } |
| 1127 | 1149 |
| 1128 | 1150 |
| 1129 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, | 1151 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, |
| 1130 Deoptimizer::BailoutType type) { | 1152 Deoptimizer::BailoutType type) { |
| 1131 __ EnterInternalFrame(); | 1153 { |
| 1132 // Pass the function and deoptimization type to the runtime system. | 1154 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1133 __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); | 1155 // Pass the function and deoptimization type to the runtime system. |
| 1134 __ push(r0); | 1156 __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); |
| 1135 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); | 1157 __ push(r0); |
| 1136 __ LeaveInternalFrame(); | 1158 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); |
| 1159 } |
| 1137 | 1160 |
| 1138 // Get the full codegen state from the stack and untag it -> r6. | 1161 // Get the full codegen state from the stack and untag it -> r6. |
| 1139 __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); | 1162 __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); |
| 1140 __ SmiUntag(r6); | 1163 __ SmiUntag(r6); |
| 1141 // Switch on the state. | 1164 // Switch on the state. |
| 1142 Label with_tos_register, unknown_state; | 1165 Label with_tos_register, unknown_state; |
| 1143 __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); | 1166 __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); |
| 1144 __ b(ne, &with_tos_register); | 1167 __ b(ne, &with_tos_register); |
| 1145 __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. | 1168 __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. |
| 1146 __ Ret(); | 1169 __ Ret(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1166 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | 1189 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
| 1167 } | 1190 } |
| 1168 | 1191 |
| 1169 | 1192 |
| 1170 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { | 1193 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { |
| 1171 // For now, we are relying on the fact that Runtime::NotifyOSR | 1194 // For now, we are relying on the fact that Runtime::NotifyOSR |
| 1172 // doesn't do any garbage collection which allows us to save/restore | 1195 // doesn't do any garbage collection which allows us to save/restore |
| 1173 // the registers without worrying about which of them contain | 1196 // the registers without worrying about which of them contain |
| 1174 // pointers. This seems a bit fragile. | 1197 // pointers. This seems a bit fragile. |
| 1175 __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); | 1198 __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); |
| 1176 __ EnterInternalFrame(); | 1199 { |
| 1177 __ CallRuntime(Runtime::kNotifyOSR, 0); | 1200 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1178 __ LeaveInternalFrame(); | 1201 __ CallRuntime(Runtime::kNotifyOSR, 0); |
| 1202 } |
| 1179 __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); | 1203 __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); |
| 1180 __ Ret(); | 1204 __ Ret(); |
| 1181 } | 1205 } |
| 1182 | 1206 |
| 1183 | 1207 |
| 1184 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 1208 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
| 1185 CpuFeatures::TryForceFeatureScope scope(VFP3); | 1209 CpuFeatures::TryForceFeatureScope scope(VFP3); |
| 1186 if (!CpuFeatures::IsSupported(VFP3)) { | 1210 if (!CpuFeatures::IsSupported(VFP3)) { |
| 1187 __ Abort("Unreachable code: Cannot optimize without VFP3 support."); | 1211 __ Abort("Unreachable code: Cannot optimize without VFP3 support."); |
| 1188 return; | 1212 return; |
| 1189 } | 1213 } |
| 1190 | 1214 |
| 1191 // Lookup the function in the JavaScript frame and push it as an | 1215 // Lookup the function in the JavaScript frame and push it as an |
| 1192 // argument to the on-stack replacement function. | 1216 // argument to the on-stack replacement function. |
| 1193 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1217 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1194 __ EnterInternalFrame(); | 1218 { |
| 1195 __ push(r0); | 1219 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1196 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); | 1220 __ push(r0); |
| 1197 __ LeaveInternalFrame(); | 1221 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); |
| 1222 } |
| 1198 | 1223 |
| 1199 // If the result was -1 it means that we couldn't optimize the | 1224 // If the result was -1 it means that we couldn't optimize the |
| 1200 // function. Just return and continue in the unoptimized version. | 1225 // function. Just return and continue in the unoptimized version. |
| 1201 Label skip; | 1226 Label skip; |
| 1202 __ cmp(r0, Operand(Smi::FromInt(-1))); | 1227 __ cmp(r0, Operand(Smi::FromInt(-1))); |
| 1203 __ b(ne, &skip); | 1228 __ b(ne, &skip); |
| 1204 __ Ret(); | 1229 __ Ret(); |
| 1205 | 1230 |
| 1206 __ bind(&skip); | 1231 __ bind(&skip); |
| 1207 // Untag the AST id and push it on the stack. | 1232 // Untag the AST id and push it on the stack. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 __ b(eq, &use_global_receiver); | 1294 __ b(eq, &use_global_receiver); |
| 1270 __ LoadRoot(r3, Heap::kNullValueRootIndex); | 1295 __ LoadRoot(r3, Heap::kNullValueRootIndex); |
| 1271 __ cmp(r2, r3); | 1296 __ cmp(r2, r3); |
| 1272 __ b(eq, &use_global_receiver); | 1297 __ b(eq, &use_global_receiver); |
| 1273 | 1298 |
| 1274 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1299 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 1275 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); | 1300 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
| 1276 __ b(ge, &shift_arguments); | 1301 __ b(ge, &shift_arguments); |
| 1277 | 1302 |
| 1278 __ bind(&convert_to_object); | 1303 __ bind(&convert_to_object); |
| 1279 __ EnterInternalFrame(); // In order to preserve argument count. | |
| 1280 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. | |
| 1281 __ push(r0); | |
| 1282 | 1304 |
| 1283 __ push(r2); | 1305 { |
| 1284 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1306 // Enter an internal frame in order to preserve argument count. |
| 1285 __ mov(r2, r0); | 1307 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1308 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. |
| 1309 __ push(r0); |
| 1286 | 1310 |
| 1287 __ pop(r0); | 1311 __ push(r2); |
| 1288 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 1312 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 1289 __ LeaveInternalFrame(); | 1313 __ mov(r2, r0); |
| 1314 |
| 1315 __ pop(r0); |
| 1316 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
| 1317 |
| 1318 // Exit the internal frame. |
| 1319 } |
| 1320 |
| 1290 // Restore the function to r1, and the flag to r4. | 1321 // Restore the function to r1, and the flag to r4. |
| 1291 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 1322 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |
| 1292 __ mov(r4, Operand(0, RelocInfo::NONE)); | 1323 __ mov(r4, Operand(0, RelocInfo::NONE)); |
| 1293 __ jmp(&patch_receiver); | 1324 __ jmp(&patch_receiver); |
| 1294 | 1325 |
| 1295 // Use the global receiver object from the called function as the | 1326 // Use the global receiver object from the called function as the |
| 1296 // receiver. | 1327 // receiver. |
| 1297 __ bind(&use_global_receiver); | 1328 __ bind(&use_global_receiver); |
| 1298 const int kGlobalIndex = | 1329 const int kGlobalIndex = |
| 1299 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 1330 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1399 } | 1430 } |
| 1400 | 1431 |
| 1401 | 1432 |
| 1402 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1433 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 1403 const int kIndexOffset = -5 * kPointerSize; | 1434 const int kIndexOffset = -5 * kPointerSize; |
| 1404 const int kLimitOffset = -4 * kPointerSize; | 1435 const int kLimitOffset = -4 * kPointerSize; |
| 1405 const int kArgsOffset = 2 * kPointerSize; | 1436 const int kArgsOffset = 2 * kPointerSize; |
| 1406 const int kRecvOffset = 3 * kPointerSize; | 1437 const int kRecvOffset = 3 * kPointerSize; |
| 1407 const int kFunctionOffset = 4 * kPointerSize; | 1438 const int kFunctionOffset = 4 * kPointerSize; |
| 1408 | 1439 |
| 1409 __ EnterInternalFrame(); | 1440 { |
| 1441 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 1410 | 1442 |
| 1411 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | 1443 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
| 1412 __ push(r0); | 1444 __ push(r0); |
| 1413 __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array | 1445 __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array |
| 1414 __ push(r0); | 1446 __ push(r0); |
| 1415 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1447 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
| 1416 | 1448 |
| 1417 // Check the stack for overflow. We are not trying to catch | 1449 // Check the stack for overflow. We are not trying to catch |
| 1418 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1450 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 1419 // limit" is checked. | 1451 // limit" is checked. |
| 1420 Label okay; | 1452 Label okay; |
| 1421 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | 1453 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
| 1422 // Make r2 the space we have left. The stack might already be overflowed | 1454 // Make r2 the space we have left. The stack might already be overflowed |
| 1423 // here which will cause r2 to become negative. | 1455 // here which will cause r2 to become negative. |
| 1424 __ sub(r2, sp, r2); | 1456 __ sub(r2, sp, r2); |
| 1425 // Check if the arguments will overflow the stack. | 1457 // Check if the arguments will overflow the stack. |
| 1426 __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1458 __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1427 __ b(gt, &okay); // Signed comparison. | 1459 __ b(gt, &okay); // Signed comparison. |
| 1428 | 1460 |
| 1429 // Out of stack space. | 1461 // Out of stack space. |
| 1430 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1462 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1431 __ push(r1); | 1463 __ push(r1); |
| 1432 __ push(r0); | 1464 __ push(r0); |
| 1433 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); | 1465 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); |
| 1434 // End of stack check. | 1466 // End of stack check. |
| 1435 | 1467 |
| 1436 // Push current limit and index. | 1468 // Push current limit and index. |
| 1437 __ bind(&okay); | 1469 __ bind(&okay); |
| 1438 __ push(r0); // limit | 1470 __ push(r0); // limit |
| 1439 __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index | 1471 __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index |
| 1440 __ push(r1); | 1472 __ push(r1); |
| 1441 | 1473 |
| 1442 // Get the receiver. | 1474 // Get the receiver. |
| 1443 __ ldr(r0, MemOperand(fp, kRecvOffset)); | 1475 __ ldr(r0, MemOperand(fp, kRecvOffset)); |
| 1444 | 1476 |
| 1445 // Check that the function is a JS function (otherwise it must be a proxy). | 1477 // Check that the function is a JS function (otherwise it must be a proxy). |
| 1446 Label push_receiver; | 1478 Label push_receiver; |
| 1447 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1479 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1448 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1480 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1449 __ b(ne, &push_receiver); | 1481 __ b(ne, &push_receiver); |
| 1450 | 1482 |
| 1451 // Change context eagerly to get the right global object if necessary. | 1483 // Change context eagerly to get the right global object if necessary. |
| 1452 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1484 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1453 // Load the shared function info while the function is still in r1. | 1485 // Load the shared function info while the function is still in r1. |
| 1454 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1486 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1455 | 1487 |
| 1456 // Compute the receiver. | 1488 // Compute the receiver. |
| 1457 // Do not transform the receiver for strict mode functions. | 1489 // Do not transform the receiver for strict mode functions. |
| 1458 Label call_to_object, use_global_receiver; | 1490 Label call_to_object, use_global_receiver; |
| 1459 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); | 1491 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1460 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | 1492 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
| 1461 kSmiTagSize))); | 1493 kSmiTagSize))); |
| 1462 __ b(ne, &push_receiver); | 1494 __ b(ne, &push_receiver); |
| 1463 | 1495 |
| 1464 // Do not transform the receiver for strict mode functions. | 1496 // Do not transform the receiver for strict mode functions. |
| 1465 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 1497 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
| 1466 __ b(ne, &push_receiver); | 1498 __ b(ne, &push_receiver); |
| 1467 | 1499 |
| 1468 // Compute the receiver in non-strict mode. | 1500 // Compute the receiver in non-strict mode. |
| 1469 __ JumpIfSmi(r0, &call_to_object); | 1501 __ JumpIfSmi(r0, &call_to_object); |
| 1470 __ LoadRoot(r1, Heap::kNullValueRootIndex); | 1502 __ LoadRoot(r1, Heap::kNullValueRootIndex); |
| 1471 __ cmp(r0, r1); | 1503 __ cmp(r0, r1); |
| 1472 __ b(eq, &use_global_receiver); | 1504 __ b(eq, &use_global_receiver); |
| 1473 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 1505 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 1474 __ cmp(r0, r1); | 1506 __ cmp(r0, r1); |
| 1475 __ b(eq, &use_global_receiver); | 1507 __ b(eq, &use_global_receiver); |
| 1476 | 1508 |
| 1477 // Check if the receiver is already a JavaScript object. | 1509 // Check if the receiver is already a JavaScript object. |
| 1478 // r0: receiver | 1510 // r0: receiver |
| 1479 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1511 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 1480 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); | 1512 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); |
| 1481 __ b(ge, &push_receiver); | 1513 __ b(ge, &push_receiver); |
| 1482 | 1514 |
| 1483 // Convert the receiver to a regular object. | 1515 // Convert the receiver to a regular object. |
| 1484 // r0: receiver | 1516 // r0: receiver |
| 1485 __ bind(&call_to_object); | 1517 __ bind(&call_to_object); |
| 1486 __ push(r0); | 1518 __ push(r0); |
| 1487 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1519 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 1488 __ b(&push_receiver); | 1520 __ b(&push_receiver); |
| 1489 | 1521 |
| 1490 // Use the current global receiver object as the receiver. | 1522 // Use the current global receiver object as the receiver. |
| 1491 __ bind(&use_global_receiver); | 1523 __ bind(&use_global_receiver); |
| 1492 const int kGlobalOffset = | 1524 const int kGlobalOffset = |
| 1493 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 1525 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 1494 __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); | 1526 __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); |
| 1495 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); | 1527 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); |
| 1496 __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); | 1528 __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); |
| 1497 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 1529 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
| 1498 | 1530 |
| 1499 // Push the receiver. | 1531 // Push the receiver. |
| 1500 // r0: receiver | 1532 // r0: receiver |
| 1501 __ bind(&push_receiver); | 1533 __ bind(&push_receiver); |
| 1502 __ push(r0); | 1534 __ push(r0); |
| 1503 | 1535 |
| 1504 // Copy all arguments from the array to the stack. | 1536 // Copy all arguments from the array to the stack. |
| 1505 Label entry, loop; | 1537 Label entry, loop; |
| 1506 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1538 __ ldr(r0, MemOperand(fp, kIndexOffset)); |
| 1507 __ b(&entry); | 1539 __ b(&entry); |
| 1508 | 1540 |
| 1509 // Load the current argument from the arguments array and push it to the | 1541 // Load the current argument from the arguments array and push it to the |
| 1510 // stack. | 1542 // stack. |
| 1511 // r0: current argument index | 1543 // r0: current argument index |
| 1512 __ bind(&loop); | 1544 __ bind(&loop); |
| 1513 __ ldr(r1, MemOperand(fp, kArgsOffset)); | 1545 __ ldr(r1, MemOperand(fp, kArgsOffset)); |
| 1514 __ push(r1); | 1546 __ push(r1); |
| 1515 __ push(r0); | 1547 __ push(r0); |
| 1516 | 1548 |
| 1517 // Call the runtime to access the property in the arguments array. | 1549 // Call the runtime to access the property in the arguments array. |
| 1518 __ CallRuntime(Runtime::kGetProperty, 2); | 1550 __ CallRuntime(Runtime::kGetProperty, 2); |
| 1519 __ push(r0); | 1551 __ push(r0); |
| 1520 | 1552 |
| 1521 // Use inline caching to access the arguments. | 1553 // Use inline caching to access the arguments. |
| 1522 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1554 __ ldr(r0, MemOperand(fp, kIndexOffset)); |
| 1523 __ add(r0, r0, Operand(1 << kSmiTagSize)); | 1555 __ add(r0, r0, Operand(1 << kSmiTagSize)); |
| 1524 __ str(r0, MemOperand(fp, kIndexOffset)); | 1556 __ str(r0, MemOperand(fp, kIndexOffset)); |
| 1525 | 1557 |
| 1526 // Test if the copy loop has finished copying all the elements from the | 1558 // Test if the copy loop has finished copying all the elements from the |
| 1527 // arguments object. | 1559 // arguments object. |
| 1528 __ bind(&entry); | 1560 __ bind(&entry); |
| 1529 __ ldr(r1, MemOperand(fp, kLimitOffset)); | 1561 __ ldr(r1, MemOperand(fp, kLimitOffset)); |
| 1530 __ cmp(r0, r1); | 1562 __ cmp(r0, r1); |
| 1531 __ b(ne, &loop); | 1563 __ b(ne, &loop); |
| 1532 | 1564 |
| 1533 // Invoke the function. | 1565 // Invoke the function. |
| 1534 Label call_proxy; | 1566 Label call_proxy; |
| 1535 ParameterCount actual(r0); | 1567 ParameterCount actual(r0); |
| 1536 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 1568 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
| 1537 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1569 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1538 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1570 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1539 __ b(ne, &call_proxy); | 1571 __ b(ne, &call_proxy); |
| 1540 __ InvokeFunction(r1, actual, CALL_FUNCTION, | 1572 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
| 1541 NullCallWrapper(), CALL_AS_METHOD); | 1573 NullCallWrapper(), CALL_AS_METHOD); |
| 1542 | 1574 |
| 1543 // Tear down the internal frame and remove function, receiver and args. | 1575 frame_scope.GenerateLeaveFrame(); |
| 1544 __ LeaveInternalFrame(); | 1576 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 1545 __ add(sp, sp, Operand(3 * kPointerSize)); | 1577 __ Jump(lr); |
| 1546 __ Jump(lr); | |
| 1547 | 1578 |
| 1548 // Invoke the function proxy. | 1579 // Invoke the function proxy. |
| 1549 __ bind(&call_proxy); | 1580 __ bind(&call_proxy); |
| 1550 __ push(r1); // add function proxy as last argument | 1581 __ push(r1); // add function proxy as last argument |
| 1551 __ add(r0, r0, Operand(1)); | 1582 __ add(r0, r0, Operand(1)); |
| 1552 __ mov(r2, Operand(0, RelocInfo::NONE)); | 1583 __ mov(r2, Operand(0, RelocInfo::NONE)); |
| 1553 __ SetCallKind(r5, CALL_AS_METHOD); | 1584 __ SetCallKind(r5, CALL_AS_METHOD); |
| 1554 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); | 1585 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); |
| 1555 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1586 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1556 RelocInfo::CODE_TARGET); | 1587 RelocInfo::CODE_TARGET); |
| 1557 | 1588 |
| 1558 __ LeaveInternalFrame(); | 1589 // Tear down the internal frame and remove function, receiver and args. |
| 1590 } |
| 1559 __ add(sp, sp, Operand(3 * kPointerSize)); | 1591 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 1560 __ Jump(lr); | 1592 __ Jump(lr); |
| 1561 } | 1593 } |
| 1562 | 1594 |
| 1563 | 1595 |
| 1564 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1596 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
| 1565 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 1597 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
| 1566 __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1598 __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1567 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); | 1599 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); |
| 1568 __ add(fp, sp, Operand(3 * kPointerSize)); | 1600 __ add(fp, sp, Operand(3 * kPointerSize)); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1686 __ bind(&dont_adapt_arguments); | 1718 __ bind(&dont_adapt_arguments); |
| 1687 __ Jump(r3); | 1719 __ Jump(r3); |
| 1688 } | 1720 } |
| 1689 | 1721 |
| 1690 | 1722 |
| 1691 #undef __ | 1723 #undef __ |
| 1692 | 1724 |
| 1693 } } // namespace v8::internal | 1725 } } // namespace v8::internal |
| 1694 | 1726 |
| 1695 #endif // V8_TARGET_ARCH_ARM | 1727 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |