Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: src/arm/builtins-arm.cc

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-arm-inl.h ('k') | src/arm/code-stubs-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/assembler-arm-inl.h ('k') | src/arm/code-stubs-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698