OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 __ movq(dst, FieldOperand(src, offset)); | 126 __ movq(dst, FieldOperand(src, offset)); |
127 } else { | 127 } else { |
128 // Calculate the offset into the properties array. | 128 // Calculate the offset into the properties array. |
129 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 129 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
130 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 130 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
131 __ movq(dst, FieldOperand(dst, offset)); | 131 __ movq(dst, FieldOperand(dst, offset)); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 | 135 |
136 template <typename Pushable> | |
137 static void PushInterceptorArguments(MacroAssembler* masm, | 136 static void PushInterceptorArguments(MacroAssembler* masm, |
138 Register receiver, | 137 Register receiver, |
139 Register holder, | 138 Register holder, |
140 Pushable name, | 139 Register name, |
141 JSObject* holder_obj) { | 140 JSObject* holder_obj) { |
142 __ push(receiver); | 141 __ push(receiver); |
143 __ push(holder); | 142 __ push(holder); |
144 __ push(name); | 143 __ push(name); |
145 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 144 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
146 ASSERT(!Heap::InNewSpace(interceptor)); | 145 ASSERT(!Heap::InNewSpace(interceptor)); |
147 __ movq(kScratchRegister, Handle<Object>(interceptor), | 146 __ movq(kScratchRegister, Handle<Object>(interceptor), |
148 RelocInfo::EMBEDDED_OBJECT); | 147 RelocInfo::EMBEDDED_OBJECT); |
149 __ push(kScratchRegister); | 148 __ push(kScratchRegister); |
150 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); | 149 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 // Check if the wrapped value is a string and load the length | 340 // Check if the wrapped value is a string and load the length |
342 // directly if it is. | 341 // directly if it is. |
343 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 342 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
344 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 343 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
345 __ movl(rax, FieldOperand(scratch2, String::kLengthOffset)); | 344 __ movl(rax, FieldOperand(scratch2, String::kLengthOffset)); |
346 __ Integer32ToSmi(rax, rax); | 345 __ Integer32ToSmi(rax, rax); |
347 __ ret(0); | 346 __ ret(0); |
348 } | 347 } |
349 | 348 |
350 | 349 |
351 template <class Pushable> | |
352 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 350 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
353 Register receiver, | 351 Register receiver, |
354 Register holder, | 352 Register holder, |
355 Pushable name, | 353 Register name, |
356 JSObject* holder_obj) { | 354 JSObject* holder_obj) { |
357 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 355 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
358 | 356 |
359 ExternalReference ref = | 357 ExternalReference ref = |
360 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 358 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
361 __ movq(rax, Immediate(5)); | 359 __ movq(rax, Immediate(5)); |
362 __ movq(rbx, ref); | 360 __ movq(rbx, ref); |
363 | 361 |
364 CEntryStub stub(1); | 362 CEntryStub stub(1); |
365 __ CallStub(&stub); | 363 __ CallStub(&stub); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 __ TailCallRuntime(ref, 5, 1); | 551 __ TailCallRuntime(ref, 5, 1); |
554 } | 552 } |
555 | 553 |
556 private: | 554 private: |
557 Register name_; | 555 Register name_; |
558 }; | 556 }; |
559 | 557 |
560 | 558 |
561 class CallInterceptorCompiler BASE_EMBEDDED { | 559 class CallInterceptorCompiler BASE_EMBEDDED { |
562 public: | 560 public: |
563 explicit CallInterceptorCompiler(const ParameterCount& arguments) | 561 CallInterceptorCompiler(const ParameterCount& arguments, Register name) |
564 : arguments_(arguments), argc_(arguments.immediate()) {} | 562 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} |
565 | 563 |
566 void CompileCacheable(MacroAssembler* masm, | 564 void CompileCacheable(MacroAssembler* masm, |
567 StubCompiler* stub_compiler, | 565 StubCompiler* stub_compiler, |
568 Register receiver, | 566 Register receiver, |
569 Register holder, | 567 Register holder, |
570 Register scratch1, | 568 Register scratch1, |
571 Register scratch2, | 569 Register scratch2, |
572 JSObject* holder_obj, | 570 JSObject* holder_obj, |
573 LookupResult* lookup, | 571 LookupResult* lookup, |
574 String* name, | 572 String* name, |
(...skipping 10 matching lines...) Expand all Loading... |
585 optimize = true; | 583 optimize = true; |
586 } | 584 } |
587 } | 585 } |
588 | 586 |
589 if (!optimize) { | 587 if (!optimize) { |
590 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); | 588 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); |
591 return; | 589 return; |
592 } | 590 } |
593 | 591 |
594 __ EnterInternalFrame(); | 592 __ EnterInternalFrame(); |
595 __ push(holder); // save the holder | 593 __ push(holder); // Save the holder. |
| 594 __ push(name_); // Save the name. |
596 | 595 |
597 CompileCallLoadPropertyWithInterceptor( | 596 CompileCallLoadPropertyWithInterceptor(masm, |
598 masm, | 597 receiver, |
599 receiver, | 598 holder, |
600 holder, | 599 name_, |
601 // Under EnterInternalFrame this refers to name. | 600 holder_obj); |
602 Operand(rbp, (argc_ + 3) * kPointerSize), | |
603 holder_obj); | |
604 | 601 |
605 __ pop(receiver); // restore holder | 602 __ pop(name_); // Restore the name. |
| 603 __ pop(receiver); // Restore the holder. |
606 __ LeaveInternalFrame(); | 604 __ LeaveInternalFrame(); |
607 | 605 |
608 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 606 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
609 Label invoke; | 607 Label invoke; |
610 __ j(not_equal, &invoke); | 608 __ j(not_equal, &invoke); |
611 | 609 |
612 stub_compiler->CheckPrototypes(holder_obj, receiver, | 610 stub_compiler->CheckPrototypes(holder_obj, receiver, |
613 lookup->holder(), scratch1, | 611 lookup->holder(), scratch1, |
614 scratch2, | 612 scratch2, |
615 name, | 613 name, |
(...skipping 18 matching lines...) Expand all Loading... |
634 __ bind(&invoke); | 632 __ bind(&invoke); |
635 } | 633 } |
636 | 634 |
637 void CompileRegular(MacroAssembler* masm, | 635 void CompileRegular(MacroAssembler* masm, |
638 Register receiver, | 636 Register receiver, |
639 Register holder, | 637 Register holder, |
640 Register scratch, | 638 Register scratch, |
641 JSObject* holder_obj, | 639 JSObject* holder_obj, |
642 Label* miss_label) { | 640 Label* miss_label) { |
643 __ EnterInternalFrame(); | 641 __ EnterInternalFrame(); |
| 642 // Save the name_ register across the call. |
| 643 __ push(name_); |
644 | 644 |
645 PushInterceptorArguments(masm, | 645 PushInterceptorArguments(masm, |
646 receiver, | 646 receiver, |
647 holder, | 647 holder, |
648 Operand(rbp, (argc_ + 3) * kPointerSize), | 648 name_, |
649 holder_obj); | 649 holder_obj); |
650 | 650 |
651 ExternalReference ref = ExternalReference( | 651 ExternalReference ref = ExternalReference( |
652 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); | 652 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); |
653 __ movq(rax, Immediate(5)); | 653 __ movq(rax, Immediate(5)); |
654 __ movq(rbx, ref); | 654 __ movq(rbx, ref); |
655 | 655 |
656 CEntryStub stub(1); | 656 CEntryStub stub(1); |
657 __ CallStub(&stub); | 657 __ CallStub(&stub); |
658 | 658 |
| 659 __ pop(name_); |
659 __ LeaveInternalFrame(); | 660 __ LeaveInternalFrame(); |
660 } | 661 } |
661 | 662 |
662 private: | 663 private: |
663 const ParameterCount& arguments_; | 664 const ParameterCount& arguments_; |
664 int argc_; | 665 int argc_; |
| 666 Register name_; |
665 }; | 667 }; |
666 | 668 |
667 | 669 |
668 #undef __ | 670 #undef __ |
669 | 671 |
670 #define __ ACCESS_MASM((masm())) | 672 #define __ ACCESS_MASM((masm())) |
671 | 673 |
672 | 674 |
673 Object* CallStubCompiler::CompileCallConstant(Object* object, | 675 Object* CallStubCompiler::CompileCallConstant(Object* object, |
674 JSObject* holder, | 676 JSObject* holder, |
675 JSFunction* function, | 677 JSFunction* function, |
676 String* name, | 678 String* name, |
677 StubCompiler::CheckType check) { | 679 StubCompiler::CheckType check) { |
678 // ----------- S t a t e ------------- | 680 // ----------- S t a t e ------------- |
| 681 // rcx : function name |
| 682 // rsp[0] : return address |
| 683 // rsp[8] : argument argc |
| 684 // rsp[16] : argument argc - 1 |
| 685 // ... |
| 686 // rsp[argc * 8] : argument 1 |
| 687 // rsp[(argc + 1) * 8] : argument 0 = receiver |
679 // ----------------------------------- | 688 // ----------------------------------- |
680 // rsp[0] return address | |
681 // rsp[8] argument argc | |
682 // rsp[16] argument argc - 1 | |
683 // ... | |
684 // rsp[argc * 8] argument 1 | |
685 // rsp[(argc + 1) * 8] argument 0 = receiver | |
686 // rsp[(argc + 2) * 8] function name | |
687 | 689 |
688 Label miss; | 690 Label miss; |
689 | 691 |
690 // Get the receiver from the stack. | 692 // Get the receiver from the stack. |
691 const int argc = arguments().immediate(); | 693 const int argc = arguments().immediate(); |
692 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 694 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
693 | 695 |
694 // Check that the receiver isn't a smi. | 696 // Check that the receiver isn't a smi. |
695 if (check != NUMBER_CHECK) { | 697 if (check != NUMBER_CHECK) { |
696 __ JumpIfSmi(rdx, &miss); | 698 __ JumpIfSmi(rdx, &miss); |
697 } | 699 } |
698 | 700 |
699 // Make sure that it's okay not to patch the on stack receiver | 701 // Make sure that it's okay not to patch the on stack receiver |
700 // unless we're doing a receiver map check. | 702 // unless we're doing a receiver map check. |
701 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 703 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
702 | 704 |
703 switch (check) { | 705 switch (check) { |
704 case RECEIVER_MAP_CHECK: | 706 case RECEIVER_MAP_CHECK: |
705 // Check that the maps haven't changed. | 707 // Check that the maps haven't changed. |
706 CheckPrototypes(JSObject::cast(object), rdx, holder, | 708 CheckPrototypes(JSObject::cast(object), rdx, holder, |
707 rbx, rcx, name, &miss); | 709 rbx, rax, name, &miss); |
708 | 710 |
709 // Patch the receiver on the stack with the global proxy if | 711 // Patch the receiver on the stack with the global proxy if |
710 // necessary. | 712 // necessary. |
711 if (object->IsGlobalObject()) { | 713 if (object->IsGlobalObject()) { |
712 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 714 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
713 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 715 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
714 } | 716 } |
715 break; | 717 break; |
716 | 718 |
717 case STRING_CHECK: | 719 case STRING_CHECK: |
718 if (!function->IsBuiltin()) { | 720 if (!function->IsBuiltin()) { |
719 // Calling non-builtins with a value as receiver requires boxing. | 721 // Calling non-builtins with a value as receiver requires boxing. |
720 __ jmp(&miss); | 722 __ jmp(&miss); |
721 } else { | 723 } else { |
722 // Check that the object is a two-byte string or a symbol. | 724 // Check that the object is a two-byte string or a symbol. |
723 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rcx); | 725 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); |
724 __ j(above_equal, &miss); | 726 __ j(above_equal, &miss); |
725 // Check that the maps starting from the prototype haven't changed. | 727 // Check that the maps starting from the prototype haven't changed. |
726 GenerateLoadGlobalFunctionPrototype(masm(), | 728 GenerateLoadGlobalFunctionPrototype(masm(), |
727 Context::STRING_FUNCTION_INDEX, | 729 Context::STRING_FUNCTION_INDEX, |
728 rcx); | 730 rax); |
729 CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, | 731 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
730 rbx, rdx, name, &miss); | 732 rbx, rdx, name, &miss); |
731 } | 733 } |
732 break; | 734 break; |
733 | 735 |
734 case NUMBER_CHECK: { | 736 case NUMBER_CHECK: { |
735 if (!function->IsBuiltin()) { | 737 if (!function->IsBuiltin()) { |
736 // Calling non-builtins with a value as receiver requires boxing. | 738 // Calling non-builtins with a value as receiver requires boxing. |
737 __ jmp(&miss); | 739 __ jmp(&miss); |
738 } else { | 740 } else { |
739 Label fast; | 741 Label fast; |
740 // Check that the object is a smi or a heap number. | 742 // Check that the object is a smi or a heap number. |
741 __ JumpIfSmi(rdx, &fast); | 743 __ JumpIfSmi(rdx, &fast); |
742 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); | 744 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); |
743 __ j(not_equal, &miss); | 745 __ j(not_equal, &miss); |
744 __ bind(&fast); | 746 __ bind(&fast); |
745 // Check that the maps starting from the prototype haven't changed. | 747 // Check that the maps starting from the prototype haven't changed. |
746 GenerateLoadGlobalFunctionPrototype(masm(), | 748 GenerateLoadGlobalFunctionPrototype(masm(), |
747 Context::NUMBER_FUNCTION_INDEX, | 749 Context::NUMBER_FUNCTION_INDEX, |
748 rcx); | 750 rax); |
749 CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, | 751 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
750 rbx, rdx, name, &miss); | 752 rbx, rdx, name, &miss); |
751 } | 753 } |
752 break; | 754 break; |
753 } | 755 } |
754 | 756 |
755 case BOOLEAN_CHECK: { | 757 case BOOLEAN_CHECK: { |
756 if (!function->IsBuiltin()) { | 758 if (!function->IsBuiltin()) { |
757 // Calling non-builtins with a value as receiver requires boxing. | 759 // Calling non-builtins with a value as receiver requires boxing. |
758 __ jmp(&miss); | 760 __ jmp(&miss); |
759 } else { | 761 } else { |
760 Label fast; | 762 Label fast; |
761 // Check that the object is a boolean. | 763 // Check that the object is a boolean. |
762 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); | 764 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); |
763 __ j(equal, &fast); | 765 __ j(equal, &fast); |
764 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); | 766 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); |
765 __ j(not_equal, &miss); | 767 __ j(not_equal, &miss); |
766 __ bind(&fast); | 768 __ bind(&fast); |
767 // Check that the maps starting from the prototype haven't changed. | 769 // Check that the maps starting from the prototype haven't changed. |
768 GenerateLoadGlobalFunctionPrototype(masm(), | 770 GenerateLoadGlobalFunctionPrototype(masm(), |
769 Context::BOOLEAN_FUNCTION_INDEX, | 771 Context::BOOLEAN_FUNCTION_INDEX, |
770 rcx); | 772 rax); |
771 CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, | 773 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
772 rbx, rdx, name, &miss); | 774 rbx, rdx, name, &miss); |
773 } | 775 } |
774 break; | 776 break; |
775 } | 777 } |
776 | 778 |
777 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: | 779 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: |
778 CheckPrototypes(JSObject::cast(object), rdx, holder, | 780 CheckPrototypes(JSObject::cast(object), rdx, holder, |
779 rbx, rcx, name, &miss); | 781 rbx, rax, name, &miss); |
780 // Make sure object->HasFastElements(). | 782 // Make sure object->HasFastElements(). |
781 // Get the elements array of the object. | 783 // Get the elements array of the object. |
782 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 784 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
783 // Check that the object is in fast mode (not dictionary). | 785 // Check that the object is in fast mode (not dictionary). |
784 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | 786 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), |
785 Factory::fixed_array_map()); | 787 Factory::fixed_array_map()); |
786 __ j(not_equal, &miss); | 788 __ j(not_equal, &miss); |
787 break; | 789 break; |
788 | 790 |
789 default: | 791 default: |
(...skipping 23 matching lines...) Expand all Loading... |
813 } | 815 } |
814 return GetCode(CONSTANT_FUNCTION, function_name); | 816 return GetCode(CONSTANT_FUNCTION, function_name); |
815 } | 817 } |
816 | 818 |
817 | 819 |
818 Object* CallStubCompiler::CompileCallField(Object* object, | 820 Object* CallStubCompiler::CompileCallField(Object* object, |
819 JSObject* holder, | 821 JSObject* holder, |
820 int index, | 822 int index, |
821 String* name) { | 823 String* name) { |
822 // ----------- S t a t e ------------- | 824 // ----------- S t a t e ------------- |
| 825 // rcx : function name |
| 826 // rsp[0] : return address |
| 827 // rsp[8] : argument argc |
| 828 // rsp[16] : argument argc - 1 |
| 829 // ... |
| 830 // rsp[argc * 8] : argument 1 |
| 831 // rsp[(argc + 1) * 8] : argument 0 = receiver |
823 // ----------------------------------- | 832 // ----------------------------------- |
824 // rsp[0] return address | |
825 // rsp[8] argument argc | |
826 // rsp[16] argument argc - 1 | |
827 // ... | |
828 // rsp[argc * 8] argument 1 | |
829 // rsp[(argc + 1) * 8] argument 0 = receiver | |
830 // rsp[(argc + 2) * 8] function name | |
831 Label miss; | 833 Label miss; |
832 | 834 |
833 // Get the receiver from the stack. | 835 // Get the receiver from the stack. |
834 const int argc = arguments().immediate(); | 836 const int argc = arguments().immediate(); |
835 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 837 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
836 | 838 |
837 // Check that the receiver isn't a smi. | 839 // Check that the receiver isn't a smi. |
838 __ JumpIfSmi(rdx, &miss); | 840 __ JumpIfSmi(rdx, &miss); |
839 | 841 |
840 // Do the right check and compute the holder register. | 842 // Do the right check and compute the holder register. |
841 Register reg = | 843 Register reg = |
842 CheckPrototypes(JSObject::cast(object), rdx, holder, | 844 CheckPrototypes(JSObject::cast(object), rdx, holder, |
843 rbx, rcx, name, &miss); | 845 rbx, rax, name, &miss); |
844 | 846 |
845 GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); | 847 GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); |
846 | 848 |
847 // Check that the function really is a function. | 849 // Check that the function really is a function. |
848 __ JumpIfSmi(rdi, &miss); | 850 __ JumpIfSmi(rdi, &miss); |
849 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | 851 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
850 __ j(not_equal, &miss); | 852 __ j(not_equal, &miss); |
851 | 853 |
852 // Patch the receiver on the stack with the global proxy if | 854 // Patch the receiver on the stack with the global proxy if |
853 // necessary. | 855 // necessary. |
(...skipping 12 matching lines...) Expand all Loading... |
866 | 868 |
867 // Return the generated code. | 869 // Return the generated code. |
868 return GetCode(FIELD, name); | 870 return GetCode(FIELD, name); |
869 } | 871 } |
870 | 872 |
871 | 873 |
872 Object* CallStubCompiler::CompileCallInterceptor(Object* object, | 874 Object* CallStubCompiler::CompileCallInterceptor(Object* object, |
873 JSObject* holder, | 875 JSObject* holder, |
874 String* name) { | 876 String* name) { |
875 // ----------- S t a t e ------------- | 877 // ----------- S t a t e ------------- |
| 878 // rcx : function name |
| 879 // rsp[0] : return address |
| 880 // rsp[8] : argument argc |
| 881 // rsp[16] : argument argc - 1 |
| 882 // ... |
| 883 // rsp[argc * 8] : argument 1 |
| 884 // rsp[(argc + 1) * 8] : argument 0 = receiver |
876 // ----------------------------------- | 885 // ----------------------------------- |
877 Label miss; | 886 Label miss; |
878 | 887 |
879 // Get the number of arguments. | 888 // Get the number of arguments. |
880 const int argc = arguments().immediate(); | 889 const int argc = arguments().immediate(); |
881 | 890 |
882 LookupResult lookup; | 891 LookupResult lookup; |
883 LookupPostInterceptor(holder, name, &lookup); | 892 LookupPostInterceptor(holder, name, &lookup); |
884 | 893 |
885 // Get the receiver from the stack. | 894 // Get the receiver from the stack. |
886 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 895 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
887 | 896 |
888 CallInterceptorCompiler compiler(arguments()); | 897 CallInterceptorCompiler compiler(arguments(), rcx); |
889 CompileLoadInterceptor(&compiler, | 898 CompileLoadInterceptor(&compiler, |
890 this, | 899 this, |
891 masm(), | 900 masm(), |
892 JSObject::cast(object), | 901 JSObject::cast(object), |
893 holder, | 902 holder, |
894 name, | 903 name, |
895 &lookup, | 904 &lookup, |
896 rdx, | 905 rdx, |
897 rbx, | 906 rbx, |
898 rcx, | 907 rdi, |
899 &miss); | 908 &miss); |
900 | 909 |
901 // Restore receiver. | 910 // Restore receiver. |
902 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 911 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
903 | 912 |
904 // Check that the function really is a function. | 913 // Check that the function really is a function. |
905 __ JumpIfSmi(rax, &miss); | 914 __ JumpIfSmi(rax, &miss); |
906 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 915 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
907 __ j(not_equal, &miss); | 916 __ j(not_equal, &miss); |
908 | 917 |
(...skipping 19 matching lines...) Expand all Loading... |
928 | 937 |
929 | 938 |
930 | 939 |
931 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, | 940 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, |
932 GlobalObject* holder, | 941 GlobalObject* holder, |
933 JSGlobalPropertyCell* cell, | 942 JSGlobalPropertyCell* cell, |
934 JSFunction* function, | 943 JSFunction* function, |
935 String* name) { | 944 String* name) { |
936 // ----------- S t a t e ------------- | 945 // ----------- S t a t e ------------- |
937 // ----------------------------------- | 946 // ----------------------------------- |
938 // rsp[0] return address | 947 // rcx : function name |
939 // rsp[8] argument argc | 948 // rsp[0] : return address |
940 // rsp[16] argument argc - 1 | 949 // rsp[8] : argument argc |
| 950 // rsp[16] : argument argc - 1 |
941 // ... | 951 // ... |
942 // rsp[argc * 8] argument 1 | 952 // rsp[argc * 8] : argument 1 |
943 // rsp[(argc + 1) * 8] argument 0 = receiver | 953 // rsp[(argc + 1) * 8] : argument 0 = receiver |
944 // rsp[(argc + 2) * 8] function name | |
945 Label miss; | 954 Label miss; |
946 | 955 |
947 // Get the number of arguments. | 956 // Get the number of arguments. |
948 const int argc = arguments().immediate(); | 957 const int argc = arguments().immediate(); |
949 | 958 |
950 // Get the receiver from the stack. | 959 // Get the receiver from the stack. |
951 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 960 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
952 | 961 |
953 // If the object is the holder then we know that it's a global | 962 // If the object is the holder then we know that it's a global |
954 // object which can only happen for contextual calls. In this case, | 963 // object which can only happen for contextual calls. In this case, |
955 // the receiver cannot be a smi. | 964 // the receiver cannot be a smi. |
956 if (object != holder) { | 965 if (object != holder) { |
957 __ JumpIfSmi(rdx, &miss); | 966 __ JumpIfSmi(rdx, &miss); |
958 } | 967 } |
959 | 968 |
960 // Check that the maps haven't changed. | 969 // Check that the maps haven't changed. |
961 CheckPrototypes(object, rdx, holder, rbx, rcx, name, &miss); | 970 CheckPrototypes(object, rdx, holder, rbx, rax, name, &miss); |
962 | 971 |
963 // Get the value from the cell. | 972 // Get the value from the cell. |
964 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); | 973 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); |
965 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); | 974 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); |
966 | 975 |
967 // Check that the cell contains the same function. | 976 // Check that the cell contains the same function. |
968 if (Heap::InNewSpace(function)) { | 977 if (Heap::InNewSpace(function)) { |
969 // We can't embed a pointer to a function in new space so we have | 978 // We can't embed a pointer to a function in new space so we have |
970 // to verify that the shared function info is unchanged. This has | 979 // to verify that the shared function info is unchanged. This has |
971 // the nice side effect that multiple closures based on the same | 980 // the nice side effect that multiple closures based on the same |
972 // function can all use this call IC. Before we load through the | 981 // function can all use this call IC. Before we load through the |
973 // function, we have to verify that it still is a function. | 982 // function, we have to verify that it still is a function. |
974 __ JumpIfSmi(rdi, &miss); | 983 __ JumpIfSmi(rdi, &miss); |
975 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 984 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); |
976 __ j(not_equal, &miss); | 985 __ j(not_equal, &miss); |
977 | 986 |
978 // Check the shared function info. Make sure it hasn't changed. | 987 // Check the shared function info. Make sure it hasn't changed. |
979 __ Move(rcx, Handle<SharedFunctionInfo>(function->shared())); | 988 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
980 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rcx); | 989 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
981 __ j(not_equal, &miss); | 990 __ j(not_equal, &miss); |
982 } else { | 991 } else { |
983 __ Cmp(rdi, Handle<JSFunction>(function)); | 992 __ Cmp(rdi, Handle<JSFunction>(function)); |
984 __ j(not_equal, &miss); | 993 __ j(not_equal, &miss); |
985 } | 994 } |
986 | 995 |
987 // Patch the receiver on the stack with the global proxy. | 996 // Patch the receiver on the stack with the global proxy. |
988 if (object->IsGlobalObject()) { | 997 if (object->IsGlobalObject()) { |
989 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 998 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
990 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 999 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1873 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 1882 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
1874 | 1883 |
1875 // Return the generated code. | 1884 // Return the generated code. |
1876 return GetCode(); | 1885 return GetCode(); |
1877 } | 1886 } |
1878 | 1887 |
1879 | 1888 |
1880 #undef __ | 1889 #undef __ |
1881 | 1890 |
1882 } } // namespace v8::internal | 1891 } } // namespace v8::internal |
OLD | NEW |