| 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 |