OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 Register receiver, | 362 Register receiver, |
363 Register scratch1, | 363 Register scratch1, |
364 Register scratch2, | 364 Register scratch2, |
365 Label* miss_label) { | 365 Label* miss_label) { |
366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
367 __ mov(eax, scratch1); | 367 __ mov(eax, scratch1); |
368 __ ret(0); | 368 __ ret(0); |
369 } | 369 } |
370 | 370 |
371 | 371 |
372 // Load a fast property out of a holder object (src). In-object properties | |
373 // are loaded directly otherwise the property is loaded from the properties | |
374 // fixed array. | |
375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
376 Register dst, | |
377 Register src, | |
378 Handle<JSObject> holder, | |
379 PropertyIndex index) { | |
380 DoGenerateFastPropertyLoad( | |
381 masm, dst, src, index.is_inobject(holder), index.translate(holder)); | |
382 } | |
383 | |
384 | |
385 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, | 372 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
386 Register dst, | 373 Register dst, |
387 Register src, | 374 Register src, |
388 bool inobject, | 375 bool inobject, |
389 int index) { | 376 int index) { |
390 int offset = index * kPointerSize; | 377 int offset = index * kPointerSize; |
391 if (!inobject) { | 378 if (!inobject) { |
392 // Calculate the offset into the properties array. | 379 // Calculate the offset into the properties array. |
393 offset = offset + FixedArray::kHeaderSize; | 380 offset = offset + FixedArray::kHeaderSize; |
394 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 381 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 __ j(not_equal, interceptor_succeeded); | 709 __ j(not_equal, interceptor_succeeded); |
723 } | 710 } |
724 | 711 |
725 StubCompiler* stub_compiler_; | 712 StubCompiler* stub_compiler_; |
726 const ParameterCount& arguments_; | 713 const ParameterCount& arguments_; |
727 Register name_; | 714 Register name_; |
728 Code::ExtraICState extra_state_; | 715 Code::ExtraICState extra_state_; |
729 }; | 716 }; |
730 | 717 |
731 | 718 |
732 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 719 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
733 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 720 Label* label, |
734 Handle<Code> code = (kind == Code::LOAD_IC) | 721 Handle<Name> name) { |
735 ? masm->isolate()->builtins()->LoadIC_Miss() | 722 if (!label->is_unused()) { |
736 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); | 723 __ bind(label); |
737 __ jmp(code, RelocInfo::CODE_TARGET); | 724 __ mov(this->name(), Immediate(name)); |
| 725 } |
738 } | 726 } |
739 | 727 |
740 | 728 |
741 void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) { | |
742 ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC); | |
743 Handle<Code> code = (kind == Code::STORE_IC) | |
744 ? masm->isolate()->builtins()->StoreIC_Miss() | |
745 : masm->isolate()->builtins()->KeyedStoreIC_Miss(); | |
746 __ jmp(code, RelocInfo::CODE_TARGET); | |
747 } | |
748 | |
749 | |
750 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | |
751 Handle<Code> code = | |
752 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
753 __ jmp(code, RelocInfo::CODE_TARGET); | |
754 } | |
755 | |
756 | |
757 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 729 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
758 // but may be destroyed if store is successful. | 730 // but may be destroyed if store is successful. |
759 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 731 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
760 Handle<JSObject> object, | 732 Handle<JSObject> object, |
761 int index, | 733 int index, |
762 Handle<Map> transition, | 734 Handle<Map> transition, |
763 Handle<Name> name, | 735 Handle<Name> name, |
764 Register receiver_reg, | 736 Register receiver_reg, |
765 Register name_reg, | 737 Register name_reg, |
| 738 Register value_reg, |
766 Register scratch1, | 739 Register scratch1, |
767 Register scratch2, | 740 Register scratch2, |
768 Label* miss_label) { | 741 Label* miss_label, |
| 742 Label* miss_restore_name) { |
769 LookupResult lookup(masm->isolate()); | 743 LookupResult lookup(masm->isolate()); |
770 object->Lookup(*name, &lookup); | 744 object->Lookup(*name, &lookup); |
771 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { | 745 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { |
772 // In sloppy mode, we could just return the value and be done. However, we | 746 // In sloppy mode, we could just return the value and be done. However, we |
773 // might be in strict mode, where we have to throw. Since we cannot tell, | 747 // might be in strict mode, where we have to throw. Since we cannot tell, |
774 // go into slow case unconditionally. | 748 // go into slow case unconditionally. |
775 __ jmp(miss_label); | 749 __ jmp(miss_label); |
776 return; | 750 return; |
777 } | 751 } |
778 | 752 |
(...skipping 14 matching lines...) Expand all Loading... |
793 if (lookup.IsFound()) { | 767 if (lookup.IsFound()) { |
794 holder = lookup.holder(); | 768 holder = lookup.holder(); |
795 } else { | 769 } else { |
796 // Find the top object. | 770 // Find the top object. |
797 holder = *object; | 771 holder = *object; |
798 do { | 772 do { |
799 holder = JSObject::cast(holder->GetPrototype()); | 773 holder = JSObject::cast(holder->GetPrototype()); |
800 } while (holder->GetPrototype()->IsJSObject()); | 774 } while (holder->GetPrototype()->IsJSObject()); |
801 } | 775 } |
802 // We need an extra register, push | 776 // We need an extra register, push |
803 __ push(name_reg); | |
804 Label miss_pop, done_check; | |
805 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, | 777 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
806 scratch1, scratch2, name, &miss_pop); | 778 scratch1, scratch2, name, miss_restore_name); |
807 __ jmp(&done_check); | |
808 __ bind(&miss_pop); | |
809 __ pop(name_reg); | |
810 __ jmp(miss_label); | |
811 __ bind(&done_check); | |
812 __ pop(name_reg); | |
813 } | 779 } |
814 | 780 |
815 // Stub never generated for non-global objects that require access | 781 // Stub never generated for non-global objects that require access |
816 // checks. | 782 // checks. |
817 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 783 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
818 | 784 |
819 // Perform map transition for the receiver if necessary. | 785 // Perform map transition for the receiver if necessary. |
820 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { | 786 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
821 // The properties must be extended before we can store the value. | 787 // The properties must be extended before we can store the value. |
822 // We jump to a runtime call that extends the properties array. | 788 // We jump to a runtime call that extends the properties array. |
(...skipping 27 matching lines...) Expand all Loading... |
850 } | 816 } |
851 | 817 |
852 // Adjust for the number of properties stored in the object. Even in the | 818 // Adjust for the number of properties stored in the object. Even in the |
853 // face of a transition we can use the old map here because the size of the | 819 // face of a transition we can use the old map here because the size of the |
854 // object and the number of in-object properties is not going to change. | 820 // object and the number of in-object properties is not going to change. |
855 index -= object->map()->inobject_properties(); | 821 index -= object->map()->inobject_properties(); |
856 | 822 |
857 if (index < 0) { | 823 if (index < 0) { |
858 // Set the property straight into the object. | 824 // Set the property straight into the object. |
859 int offset = object->map()->instance_size() + (index * kPointerSize); | 825 int offset = object->map()->instance_size() + (index * kPointerSize); |
860 __ mov(FieldOperand(receiver_reg, offset), eax); | 826 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
861 | 827 |
862 // Update the write barrier for the array address. | 828 // Update the write barrier for the array address. |
863 // Pass the value being stored in the now unused name_reg. | 829 // Pass the value being stored in the now unused name_reg. |
864 __ mov(name_reg, eax); | 830 __ mov(name_reg, value_reg); |
865 __ RecordWriteField(receiver_reg, | 831 __ RecordWriteField(receiver_reg, |
866 offset, | 832 offset, |
867 name_reg, | 833 name_reg, |
868 scratch1, | 834 scratch1, |
869 kDontSaveFPRegs); | 835 kDontSaveFPRegs); |
870 } else { | 836 } else { |
871 // Write to the properties array. | 837 // Write to the properties array. |
872 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 838 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
873 // Get the properties array (optimistically). | 839 // Get the properties array (optimistically). |
874 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 840 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
875 __ mov(FieldOperand(scratch1, offset), eax); | 841 __ mov(FieldOperand(scratch1, offset), eax); |
876 | 842 |
877 // Update the write barrier for the array address. | 843 // Update the write barrier for the array address. |
878 // Pass the value being stored in the now unused name_reg. | 844 // Pass the value being stored in the now unused name_reg. |
879 __ mov(name_reg, eax); | 845 __ mov(name_reg, value_reg); |
880 __ RecordWriteField(scratch1, | 846 __ RecordWriteField(scratch1, |
881 offset, | 847 offset, |
882 name_reg, | 848 name_reg, |
883 receiver_reg, | 849 receiver_reg, |
884 kDontSaveFPRegs); | 850 kDontSaveFPRegs); |
885 } | 851 } |
886 | 852 |
887 // Return the value (register eax). | 853 // Return the value (register eax). |
| 854 ASSERT(value_reg.is(eax)); |
888 __ ret(0); | 855 __ ret(0); |
889 } | 856 } |
890 | 857 |
891 | 858 |
892 // Generate code to check that a global property cell is empty. Create | 859 // Generate code to check that a global property cell is empty. Create |
893 // the property cell at compilation time if no cell exists for the | 860 // the property cell at compilation time if no cell exists for the |
894 // property. | 861 // property. |
895 static void GenerateCheckPropertyCell(MacroAssembler* masm, | 862 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
896 Handle<GlobalObject> global, | 863 Handle<GlobalObject> global, |
897 Handle<Name> name, | 864 Handle<Name> name, |
(...skipping 28 matching lines...) Expand all Loading... |
926 GenerateCheckPropertyCell(masm, | 893 GenerateCheckPropertyCell(masm, |
927 Handle<GlobalObject>::cast(current), | 894 Handle<GlobalObject>::cast(current), |
928 name, | 895 name, |
929 scratch, | 896 scratch, |
930 miss); | 897 miss); |
931 } | 898 } |
932 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 899 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
933 } | 900 } |
934 } | 901 } |
935 | 902 |
| 903 |
| 904 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 905 __ jmp(code, RelocInfo::CODE_TARGET); |
| 906 } |
| 907 |
| 908 |
936 #undef __ | 909 #undef __ |
937 #define __ ACCESS_MASM(masm()) | 910 #define __ ACCESS_MASM(masm()) |
938 | 911 |
939 | 912 |
940 void StubCompiler::GenerateTailCall(Handle<Code> code) { | |
941 __ jmp(code, RelocInfo::CODE_TARGET); | |
942 } | |
943 | |
944 | |
945 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 913 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
946 Register object_reg, | 914 Register object_reg, |
947 Handle<JSObject> holder, | 915 Handle<JSObject> holder, |
948 Register holder_reg, | 916 Register holder_reg, |
949 Register scratch1, | 917 Register scratch1, |
950 Register scratch2, | 918 Register scratch2, |
951 Handle<Name> name, | 919 Handle<Name> name, |
952 int save_at_depth, | 920 int save_at_depth, |
953 Label* miss, | 921 Label* miss, |
954 PrototypeCheckType check) { | 922 PrototypeCheckType check) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 // Return the register containing the holder. | 1023 // Return the register containing the holder. |
1056 return reg; | 1024 return reg; |
1057 } | 1025 } |
1058 | 1026 |
1059 | 1027 |
1060 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1028 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
1061 Label* miss) { | 1029 Label* miss) { |
1062 if (!miss->is_unused()) { | 1030 if (!miss->is_unused()) { |
1063 __ jmp(success); | 1031 __ jmp(success); |
1064 __ bind(miss); | 1032 __ bind(miss); |
1065 GenerateLoadMiss(masm(), kind()); | 1033 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1066 } | 1034 } |
1067 } | 1035 } |
1068 | 1036 |
1069 | 1037 |
1070 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1038 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
1071 Handle<JSObject> object, | 1039 Handle<JSObject> object, |
1072 Register object_reg, | 1040 Register object_reg, |
1073 Handle<JSObject> holder, | 1041 Handle<JSObject> holder, |
1074 Handle<Name> name, | 1042 Handle<Name> name, |
1075 Label* success, | 1043 Label* success, |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2574 // Handle call cache miss. | 2542 // Handle call cache miss. |
2575 __ bind(&miss); | 2543 __ bind(&miss); |
2576 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2544 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
2577 GenerateMissBranch(); | 2545 GenerateMissBranch(); |
2578 | 2546 |
2579 // Return the generated code. | 2547 // Return the generated code. |
2580 return GetCode(Code::NORMAL, name); | 2548 return GetCode(Code::NORMAL, name); |
2581 } | 2549 } |
2582 | 2550 |
2583 | 2551 |
2584 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | |
2585 int index, | |
2586 Handle<Map> transition, | |
2587 Handle<Name> name) { | |
2588 // ----------- S t a t e ------------- | |
2589 // -- eax : value | |
2590 // -- ecx : name | |
2591 // -- edx : receiver | |
2592 // -- esp[0] : return address | |
2593 // ----------------------------------- | |
2594 Label miss; | |
2595 | |
2596 // Generate store field code. Trashes the name register. | |
2597 GenerateStoreField(masm(), | |
2598 object, | |
2599 index, | |
2600 transition, | |
2601 name, | |
2602 edx, ecx, ebx, edi, | |
2603 &miss); | |
2604 // Handle store cache miss. | |
2605 __ bind(&miss); | |
2606 __ mov(ecx, Immediate(name)); // restore name | |
2607 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | |
2608 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2609 | |
2610 // Return the generated code. | |
2611 return GetCode(transition.is_null() | |
2612 ? Code::FIELD | |
2613 : Code::MAP_TRANSITION, name); | |
2614 } | |
2615 | |
2616 | |
2617 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2552 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2618 Handle<Name> name, | 2553 Handle<Name> name, |
2619 Handle<JSObject> receiver, | 2554 Handle<JSObject> receiver, |
2620 Handle<JSObject> holder, | 2555 Handle<JSObject> holder, |
2621 Handle<ExecutableAccessorInfo> callback) { | 2556 Handle<ExecutableAccessorInfo> callback) { |
2622 // ----------- S t a t e ------------- | 2557 // ----------- S t a t e ------------- |
2623 // -- eax : value | 2558 // -- eax : value |
2624 // -- ecx : name | 2559 // -- ecx : name |
2625 // -- edx : receiver | 2560 // -- edx : receiver |
2626 // -- esp[0] : return address | 2561 // -- esp[0] : return address |
(...skipping 16 matching lines...) Expand all Loading... |
2643 __ push(ebx); // restore return address | 2578 __ push(ebx); // restore return address |
2644 | 2579 |
2645 // Do tail-call to the runtime system. | 2580 // Do tail-call to the runtime system. |
2646 ExternalReference store_callback_property = | 2581 ExternalReference store_callback_property = |
2647 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2582 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
2648 __ TailCallExternalReference(store_callback_property, 4, 1); | 2583 __ TailCallExternalReference(store_callback_property, 4, 1); |
2649 | 2584 |
2650 // Handle store cache miss. | 2585 // Handle store cache miss. |
2651 __ bind(&miss); | 2586 __ bind(&miss); |
2652 __ pop(eax); | 2587 __ pop(eax); |
2653 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2588 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2654 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2655 | 2589 |
2656 // Return the generated code. | 2590 // Return the generated code. |
2657 return GetCode(Code::CALLBACKS, name); | 2591 return GetICCode(kind(), Code::CALLBACKS, name); |
2658 } | 2592 } |
2659 | 2593 |
2660 | 2594 |
2661 #undef __ | 2595 #undef __ |
2662 #define __ ACCESS_MASM(masm) | 2596 #define __ ACCESS_MASM(masm) |
2663 | 2597 |
2664 | 2598 |
2665 void StoreStubCompiler::GenerateStoreViaSetter( | 2599 void StoreStubCompiler::GenerateStoreViaSetter( |
2666 MacroAssembler* masm, | 2600 MacroAssembler* masm, |
2667 Handle<JSFunction> setter) { | 2601 Handle<JSFunction> setter) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2720 // Check that the maps haven't changed, preserving the name register. | 2654 // Check that the maps haven't changed, preserving the name register. |
2721 __ push(ecx); | 2655 __ push(ecx); |
2722 __ JumpIfSmi(edx, &miss); | 2656 __ JumpIfSmi(edx, &miss); |
2723 CheckPrototypes(receiver, edx, holder, ebx, ecx, edi, name, &miss); | 2657 CheckPrototypes(receiver, edx, holder, ebx, ecx, edi, name, &miss); |
2724 __ pop(ecx); | 2658 __ pop(ecx); |
2725 | 2659 |
2726 GenerateStoreViaSetter(masm(), setter); | 2660 GenerateStoreViaSetter(masm(), setter); |
2727 | 2661 |
2728 __ bind(&miss); | 2662 __ bind(&miss); |
2729 __ pop(ecx); | 2663 __ pop(ecx); |
2730 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2664 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2731 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2732 | 2665 |
2733 // Return the generated code. | 2666 // Return the generated code. |
2734 return GetCode(Code::CALLBACKS, name); | 2667 return GetICCode(kind(), Code::CALLBACKS, name); |
2735 } | 2668 } |
2736 | 2669 |
2737 | 2670 |
2738 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 2671 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
2739 Handle<JSObject> receiver, | 2672 Handle<JSObject> receiver, |
2740 Handle<Name> name) { | 2673 Handle<Name> name) { |
2741 // ----------- S t a t e ------------- | 2674 // ----------- S t a t e ------------- |
2742 // -- eax : value | 2675 // -- eax : value |
2743 // -- ecx : name | 2676 // -- ecx : name |
2744 // -- edx : receiver | 2677 // -- edx : receiver |
(...skipping 11 matching lines...) Expand all Loading... |
2756 } | 2689 } |
2757 | 2690 |
2758 // Stub never generated for non-global objects that require access | 2691 // Stub never generated for non-global objects that require access |
2759 // checks. | 2692 // checks. |
2760 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2693 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
2761 | 2694 |
2762 __ pop(ebx); // remove the return address | 2695 __ pop(ebx); // remove the return address |
2763 __ push(edx); // receiver | 2696 __ push(edx); // receiver |
2764 __ push(ecx); // name | 2697 __ push(ecx); // name |
2765 __ push(eax); // value | 2698 __ push(eax); // value |
2766 __ push(Immediate(Smi::FromInt(strict_mode_))); | 2699 __ push(Immediate(Smi::FromInt(strict_mode()))); |
2767 __ push(ebx); // restore return address | 2700 __ push(ebx); // restore return address |
2768 | 2701 |
2769 // Do tail-call to the runtime system. | 2702 // Do tail-call to the runtime system. |
2770 ExternalReference store_ic_property = | 2703 ExternalReference store_ic_property = |
2771 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2704 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
2772 __ TailCallExternalReference(store_ic_property, 4, 1); | 2705 __ TailCallExternalReference(store_ic_property, 4, 1); |
2773 | 2706 |
2774 // Handle store cache miss. | 2707 // Handle store cache miss. |
2775 __ bind(&miss); | 2708 __ bind(&miss); |
2776 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2709 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2777 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2778 | 2710 |
2779 // Return the generated code. | 2711 // Return the generated code. |
2780 return GetCode(Code::INTERCEPTOR, name); | 2712 return GetICCode(kind(), Code::INTERCEPTOR, name); |
2781 } | 2713 } |
2782 | 2714 |
2783 | 2715 |
2784 Handle<Code> StoreStubCompiler::CompileStoreGlobal( | 2716 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
2785 Handle<GlobalObject> object, | 2717 Handle<GlobalObject> object, |
2786 Handle<JSGlobalPropertyCell> cell, | 2718 Handle<JSGlobalPropertyCell> cell, |
2787 Handle<Name> name) { | 2719 Handle<Name> name) { |
2788 // ----------- S t a t e ------------- | 2720 // ----------- S t a t e ------------- |
2789 // -- eax : value | 2721 // -- eax : value |
2790 // -- ecx : name | 2722 // -- ecx : name |
(...skipping 23 matching lines...) Expand all Loading... |
2814 // No write barrier here, because cells are always rescanned. | 2746 // No write barrier here, because cells are always rescanned. |
2815 | 2747 |
2816 // Return the value (register eax). | 2748 // Return the value (register eax). |
2817 Counters* counters = isolate()->counters(); | 2749 Counters* counters = isolate()->counters(); |
2818 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2750 __ IncrementCounter(counters->named_store_global_inline(), 1); |
2819 __ ret(0); | 2751 __ ret(0); |
2820 | 2752 |
2821 // Handle store cache miss. | 2753 // Handle store cache miss. |
2822 __ bind(&miss); | 2754 __ bind(&miss); |
2823 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2755 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
2824 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2756 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2825 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2826 | 2757 |
2827 // Return the generated code. | 2758 // Return the generated code. |
2828 return GetCode(Code::NORMAL, name); | 2759 return GetICCode(kind(), Code::NORMAL, name); |
2829 } | 2760 } |
2830 | 2761 |
2831 | 2762 |
2832 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, | |
2833 int index, | |
2834 Handle<Map> transition, | |
2835 Handle<Name> name) { | |
2836 // ----------- S t a t e ------------- | |
2837 // -- eax : value | |
2838 // -- ecx : key | |
2839 // -- edx : receiver | |
2840 // -- esp[0] : return address | |
2841 // ----------------------------------- | |
2842 Label miss; | |
2843 | |
2844 Counters* counters = isolate()->counters(); | |
2845 __ IncrementCounter(counters->keyed_store_field(), 1); | |
2846 | |
2847 // Check that the name has not changed. | |
2848 __ cmp(ecx, Immediate(name)); | |
2849 __ j(not_equal, &miss); | |
2850 | |
2851 // Generate store field code. Trashes the name register. | |
2852 GenerateStoreField(masm(), | |
2853 object, | |
2854 index, | |
2855 transition, | |
2856 name, | |
2857 edx, ecx, ebx, edi, | |
2858 &miss); | |
2859 | |
2860 // Handle store cache miss. | |
2861 __ bind(&miss); | |
2862 __ DecrementCounter(counters->keyed_store_field(), 1); | |
2863 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | |
2864 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2865 | |
2866 // Return the generated code. | |
2867 return GetCode(transition.is_null() | |
2868 ? Code::FIELD | |
2869 : Code::MAP_TRANSITION, name); | |
2870 } | |
2871 | |
2872 | |
2873 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | 2763 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
2874 Handle<Map> receiver_map) { | 2764 Handle<Map> receiver_map) { |
2875 // ----------- S t a t e ------------- | 2765 // ----------- S t a t e ------------- |
2876 // -- eax : value | 2766 // -- eax : value |
2877 // -- ecx : key | 2767 // -- ecx : key |
2878 // -- edx : receiver | 2768 // -- edx : receiver |
2879 // -- esp[0] : return address | 2769 // -- esp[0] : return address |
2880 // ----------------------------------- | 2770 // ----------------------------------- |
2881 ElementsKind elements_kind = receiver_map->elements_kind(); | 2771 ElementsKind elements_kind = receiver_map->elements_kind(); |
2882 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2772 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
2883 Handle<Code> stub = | 2773 Handle<Code> stub = |
2884 KeyedStoreElementStub(is_jsarray, | 2774 KeyedStoreElementStub(is_jsarray, |
2885 elements_kind, | 2775 elements_kind, |
2886 store_mode_).GetCode(isolate()); | 2776 store_mode_).GetCode(isolate()); |
2887 | 2777 |
2888 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 2778 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
2889 | 2779 |
2890 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2780 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2891 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2892 | 2781 |
2893 // Return the generated code. | 2782 // Return the generated code. |
2894 return GetCode(Code::NORMAL, factory()->empty_string()); | 2783 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
2895 } | 2784 } |
2896 | 2785 |
2897 | 2786 |
2898 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2787 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
2899 MapHandleList* receiver_maps, | 2788 MapHandleList* receiver_maps, |
2900 CodeHandleList* handler_stubs, | 2789 CodeHandleList* handler_stubs, |
2901 MapHandleList* transitioned_maps) { | 2790 MapHandleList* transitioned_maps) { |
2902 // ----------- S t a t e ------------- | 2791 // ----------- S t a t e ------------- |
2903 // -- eax : value | 2792 // -- eax : value |
2904 // -- ecx : key | 2793 // -- ecx : key |
(...skipping 10 matching lines...) Expand all Loading... |
2915 __ j(equal, handler_stubs->at(i)); | 2804 __ j(equal, handler_stubs->at(i)); |
2916 } else { | 2805 } else { |
2917 Label next_map; | 2806 Label next_map; |
2918 __ j(not_equal, &next_map, Label::kNear); | 2807 __ j(not_equal, &next_map, Label::kNear); |
2919 __ mov(ebx, Immediate(transitioned_maps->at(i))); | 2808 __ mov(ebx, Immediate(transitioned_maps->at(i))); |
2920 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 2809 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
2921 __ bind(&next_map); | 2810 __ bind(&next_map); |
2922 } | 2811 } |
2923 } | 2812 } |
2924 __ bind(&miss); | 2813 __ bind(&miss); |
2925 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2814 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2926 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
2927 | 2815 |
2928 // Return the generated code. | 2816 // Return the generated code. |
2929 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 2817 return GetICCode( |
| 2818 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
2930 } | 2819 } |
2931 | 2820 |
2932 | 2821 |
2933 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2822 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
2934 Handle<JSObject> object, | 2823 Handle<JSObject> object, |
2935 Handle<JSObject> last, | 2824 Handle<JSObject> last, |
2936 Handle<Name> name, | 2825 Handle<Name> name, |
2937 Handle<GlobalObject> global) { | 2826 Handle<GlobalObject> global) { |
2938 Label success; | 2827 Label success; |
2939 | 2828 |
(...skipping 17 matching lines...) Expand all Loading... |
2957 } | 2846 } |
2958 | 2847 |
2959 | 2848 |
2960 Register* KeyedLoadStubCompiler::registers() { | 2849 Register* KeyedLoadStubCompiler::registers() { |
2961 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2850 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2962 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; | 2851 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; |
2963 return registers; | 2852 return registers; |
2964 } | 2853 } |
2965 | 2854 |
2966 | 2855 |
| 2856 Register* StoreStubCompiler::registers() { |
| 2857 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2858 static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg }; |
| 2859 return registers; |
| 2860 } |
| 2861 |
| 2862 |
| 2863 Register* KeyedStoreStubCompiler::registers() { |
| 2864 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2865 static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg }; |
| 2866 return registers; |
| 2867 } |
| 2868 |
| 2869 |
2967 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, | 2870 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, |
2968 Register name_reg, | 2871 Register name_reg, |
2969 Label* miss) { | 2872 Label* miss) { |
2970 __ cmp(name_reg, Immediate(name)); | 2873 __ cmp(name_reg, Immediate(name)); |
2971 __ j(not_equal, miss); | 2874 __ j(not_equal, miss); |
2972 } | 2875 } |
2973 | 2876 |
2974 | 2877 |
| 2878 void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name, |
| 2879 Register name_reg, |
| 2880 Label* miss) { |
| 2881 __ cmp(name_reg, Immediate(name)); |
| 2882 __ j(not_equal, miss); |
| 2883 } |
| 2884 |
| 2885 |
2975 #undef __ | 2886 #undef __ |
2976 #define __ ACCESS_MASM(masm) | 2887 #define __ ACCESS_MASM(masm) |
2977 | 2888 |
2978 | 2889 |
2979 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 2890 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
2980 Handle<JSFunction> getter) { | 2891 Handle<JSFunction> getter) { |
2981 // ----------- S t a t e ------------- | 2892 // ----------- S t a t e ------------- |
2982 // -- ecx : name | 2893 // -- ecx : name |
2983 // -- edx : receiver | 2894 // -- edx : receiver |
2984 // -- esp[0] : return address | 2895 // -- esp[0] : return address |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3064 Handle<Code> stub = KeyedLoadFastElementStub( | 2975 Handle<Code> stub = KeyedLoadFastElementStub( |
3065 receiver_map->instance_type() == JS_ARRAY_TYPE, | 2976 receiver_map->instance_type() == JS_ARRAY_TYPE, |
3066 elements_kind).GetCode(isolate()); | 2977 elements_kind).GetCode(isolate()); |
3067 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 2978 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3068 } else { | 2979 } else { |
3069 Handle<Code> stub = | 2980 Handle<Code> stub = |
3070 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 2981 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
3071 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 2982 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3072 } | 2983 } |
3073 | 2984 |
3074 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2985 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); |
3075 | 2986 |
3076 // Return the generated code. | 2987 // Return the generated code. |
3077 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); | 2988 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
3078 } | 2989 } |
3079 | 2990 |
3080 | 2991 |
3081 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( | 2992 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
3082 MapHandleList* receiver_maps, | 2993 MapHandleList* receiver_maps, |
3083 CodeHandleList* handlers, | 2994 CodeHandleList* handlers, |
3084 Handle<Name> name, | 2995 Handle<Name> name, |
3085 Code::StubType type, | 2996 Code::StubType type, |
3086 IcCheckType check) { | 2997 IcCheckType check) { |
3087 Label miss; | 2998 Label miss; |
3088 | 2999 |
3089 if (check == PROPERTY) { | 3000 if (check == PROPERTY) { |
3090 GenerateNameCheck(name, this->name(), &miss); | 3001 GenerateNameCheck(name, this->name(), &miss); |
3091 } | 3002 } |
3092 | 3003 |
3093 __ JumpIfSmi(receiver(), &miss); | 3004 __ JumpIfSmi(receiver(), &miss); |
3094 Register map_reg = scratch1(); | 3005 Register map_reg = scratch1(); |
3095 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 3006 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
3096 int receiver_count = receiver_maps->length(); | 3007 int receiver_count = receiver_maps->length(); |
3097 for (int current = 0; current < receiver_count; ++current) { | 3008 for (int current = 0; current < receiver_count; ++current) { |
3098 __ cmp(map_reg, receiver_maps->at(current)); | 3009 __ cmp(map_reg, receiver_maps->at(current)); |
3099 __ j(equal, handlers->at(current)); | 3010 __ j(equal, handlers->at(current)); |
3100 } | 3011 } |
3101 | 3012 |
3102 __ bind(&miss); | 3013 __ bind(&miss); |
3103 GenerateLoadMiss(masm(), kind()); | 3014 TailCallBuiltin(masm(), MissBuiltin(kind())); |
3104 | 3015 |
3105 // Return the generated code. | 3016 // Return the generated code. |
3106 InlineCacheState state = | 3017 InlineCacheState state = |
3107 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 3018 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
3108 return GetICCode(kind(), type, name, state); | 3019 return GetICCode(kind(), type, name, state); |
3109 } | 3020 } |
3110 | 3021 |
3111 | 3022 |
3112 // Specialized stub for constructing objects from functions which only have only | 3023 // Specialized stub for constructing objects from functions which only have only |
3113 // simple assignments of the form this.x = ...; in their body. | 3024 // simple assignments of the form this.x = ...; in their body. |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3277 __ ret(0); | 3188 __ ret(0); |
3278 | 3189 |
3279 __ bind(&slow); | 3190 __ bind(&slow); |
3280 __ pop(edx); | 3191 __ pop(edx); |
3281 | 3192 |
3282 // ----------- S t a t e ------------- | 3193 // ----------- S t a t e ------------- |
3283 // -- ecx : key | 3194 // -- ecx : key |
3284 // -- edx : receiver | 3195 // -- edx : receiver |
3285 // -- esp[0] : return address | 3196 // -- esp[0] : return address |
3286 // ----------------------------------- | 3197 // ----------------------------------- |
3287 | 3198 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
3288 Handle<Code> slow_ic = | |
3289 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3290 __ jmp(slow_ic, RelocInfo::CODE_TARGET); | |
3291 | 3199 |
3292 __ bind(&miss_force_generic); | 3200 __ bind(&miss_force_generic); |
3293 // ----------- S t a t e ------------- | 3201 // ----------- S t a t e ------------- |
3294 // -- ecx : key | 3202 // -- ecx : key |
3295 // -- edx : receiver | 3203 // -- edx : receiver |
3296 // -- esp[0] : return address | 3204 // -- esp[0] : return address |
3297 // ----------------------------------- | 3205 // ----------------------------------- |
3298 | 3206 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3299 Handle<Code> miss_force_generic_ic = | |
3300 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3301 __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); | |
3302 } | 3207 } |
3303 | 3208 |
3304 | 3209 |
3305 static void GenerateSmiKeyCheck(MacroAssembler* masm, | 3210 static void GenerateSmiKeyCheck(MacroAssembler* masm, |
3306 Register key, | 3211 Register key, |
3307 Register scratch, | 3212 Register scratch, |
3308 XMMRegister xmm_scratch0, | 3213 XMMRegister xmm_scratch0, |
3309 XMMRegister xmm_scratch1, | 3214 XMMRegister xmm_scratch1, |
3310 Label* fail) { | 3215 Label* fail) { |
3311 // Check that key is a smi and if SSE2 is available a heap number | 3216 // Check that key is a smi and if SSE2 is available a heap number |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3509 __ bind(&slow); | 3414 __ bind(&slow); |
3510 Counters* counters = masm->isolate()->counters(); | 3415 Counters* counters = masm->isolate()->counters(); |
3511 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); | 3416 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); |
3512 | 3417 |
3513 // ----------- S t a t e ------------- | 3418 // ----------- S t a t e ------------- |
3514 // -- eax : value | 3419 // -- eax : value |
3515 // -- ecx : key | 3420 // -- ecx : key |
3516 // -- edx : receiver | 3421 // -- edx : receiver |
3517 // -- esp[0] : return address | 3422 // -- esp[0] : return address |
3518 // ----------------------------------- | 3423 // ----------------------------------- |
3519 | 3424 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3520 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | |
3521 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3522 | 3425 |
3523 // ----------- S t a t e ------------- | 3426 // ----------- S t a t e ------------- |
3524 // -- eax : value | 3427 // -- eax : value |
3525 // -- ecx : key | 3428 // -- ecx : key |
3526 // -- edx : receiver | 3429 // -- edx : receiver |
3527 // -- esp[0] : return address | 3430 // -- esp[0] : return address |
3528 // ----------------------------------- | 3431 // ----------------------------------- |
3529 | 3432 |
3530 __ bind(&miss_force_generic); | 3433 __ bind(&miss_force_generic); |
3531 Handle<Code> miss_ic = | 3434 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3532 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3533 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3534 } | 3435 } |
3535 | 3436 |
3536 | 3437 |
3537 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3438 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3538 MacroAssembler* masm, | 3439 MacroAssembler* masm, |
3539 bool is_js_array, | 3440 bool is_js_array, |
3540 ElementsKind elements_kind, | 3441 ElementsKind elements_kind, |
3541 KeyedAccessStoreMode store_mode) { | 3442 KeyedAccessStoreMode store_mode) { |
3542 // ----------- S t a t e ------------- | 3443 // ----------- S t a t e ------------- |
3543 // -- eax : value | 3444 // -- eax : value |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3599 // Make sure to preserve the value in register eax. | 3500 // Make sure to preserve the value in register eax. |
3600 __ mov(ebx, eax); | 3501 __ mov(ebx, eax); |
3601 __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs); | 3502 __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs); |
3602 } | 3503 } |
3603 | 3504 |
3604 // Done. | 3505 // Done. |
3605 __ ret(0); | 3506 __ ret(0); |
3606 | 3507 |
3607 // Handle store cache miss, replacing the ic with the generic stub. | 3508 // Handle store cache miss, replacing the ic with the generic stub. |
3608 __ bind(&miss_force_generic); | 3509 __ bind(&miss_force_generic); |
3609 Handle<Code> ic_force_generic = | 3510 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3610 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3611 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | |
3612 | 3511 |
3613 // Handle transition to other elements kinds without using the generic stub. | 3512 // Handle transition to other elements kinds without using the generic stub. |
3614 __ bind(&transition_elements_kind); | 3513 __ bind(&transition_elements_kind); |
3615 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3514 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss); |
3616 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | |
3617 | 3515 |
3618 if (is_js_array && IsGrowStoreMode(store_mode)) { | 3516 if (is_js_array && IsGrowStoreMode(store_mode)) { |
3619 // Handle transition requiring the array to grow. | 3517 // Handle transition requiring the array to grow. |
3620 __ bind(&grow); | 3518 __ bind(&grow); |
3621 | 3519 |
3622 // Make sure the array is only growing by a single element, anything else | 3520 // Make sure the array is only growing by a single element, anything else |
3623 // must be handled by the runtime. Flags are already set by previous | 3521 // must be handled by the runtime. Flags are already set by previous |
3624 // compare. | 3522 // compare. |
3625 __ j(not_equal, &miss_force_generic); | 3523 __ j(not_equal, &miss_force_generic); |
3626 | 3524 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3677 // Grow the array and finish the store. | 3575 // Grow the array and finish the store. |
3678 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 3576 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
3679 Immediate(Smi::FromInt(1))); | 3577 Immediate(Smi::FromInt(1))); |
3680 __ jmp(&finish_store); | 3578 __ jmp(&finish_store); |
3681 | 3579 |
3682 __ bind(&prepare_slow); | 3580 __ bind(&prepare_slow); |
3683 // Restore the key, which is known to be the array length. | 3581 // Restore the key, which is known to be the array length. |
3684 __ mov(ecx, Immediate(0)); | 3582 __ mov(ecx, Immediate(0)); |
3685 | 3583 |
3686 __ bind(&slow); | 3584 __ bind(&slow); |
3687 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | 3585 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3688 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | |
3689 } | 3586 } |
3690 } | 3587 } |
3691 | 3588 |
3692 | 3589 |
3693 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( | 3590 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
3694 MacroAssembler* masm, | 3591 MacroAssembler* masm, |
3695 bool is_js_array, | 3592 bool is_js_array, |
3696 KeyedAccessStoreMode store_mode) { | 3593 KeyedAccessStoreMode store_mode) { |
3697 // ----------- S t a t e ------------- | 3594 // ----------- S t a t e ------------- |
3698 // -- eax : value | 3595 // -- eax : value |
(...skipping 28 matching lines...) Expand all Loading... |
3727 __ j(above_equal, &miss_force_generic); | 3624 __ j(above_equal, &miss_force_generic); |
3728 } | 3625 } |
3729 | 3626 |
3730 __ bind(&finish_store); | 3627 __ bind(&finish_store); |
3731 __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0, | 3628 __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0, |
3732 &transition_elements_kind, true); | 3629 &transition_elements_kind, true); |
3733 __ ret(0); | 3630 __ ret(0); |
3734 | 3631 |
3735 // Handle store cache miss, replacing the ic with the generic stub. | 3632 // Handle store cache miss, replacing the ic with the generic stub. |
3736 __ bind(&miss_force_generic); | 3633 __ bind(&miss_force_generic); |
3737 Handle<Code> ic_force_generic = | 3634 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3738 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3739 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | |
3740 | 3635 |
3741 // Handle transition to other elements kinds without using the generic stub. | 3636 // Handle transition to other elements kinds without using the generic stub. |
3742 __ bind(&transition_elements_kind); | 3637 __ bind(&transition_elements_kind); |
3743 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3638 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss); |
3744 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | |
3745 | 3639 |
3746 if (is_js_array && IsGrowStoreMode(store_mode)) { | 3640 if (is_js_array && IsGrowStoreMode(store_mode)) { |
3747 // Handle transition requiring the array to grow. | 3641 // Handle transition requiring the array to grow. |
3748 __ bind(&grow); | 3642 __ bind(&grow); |
3749 | 3643 |
3750 // Make sure the array is only growing by a single element, anything else | 3644 // Make sure the array is only growing by a single element, anything else |
3751 // must be handled by the runtime. Flags are already set by previous | 3645 // must be handled by the runtime. Flags are already set by previous |
3752 // compare. | 3646 // compare. |
3753 __ j(not_equal, &miss_force_generic); | 3647 __ j(not_equal, &miss_force_generic); |
3754 | 3648 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3815 // Grow the array and finish the store. | 3709 // Grow the array and finish the store. |
3816 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 3710 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
3817 Immediate(Smi::FromInt(1))); | 3711 Immediate(Smi::FromInt(1))); |
3818 __ jmp(&finish_store); | 3712 __ jmp(&finish_store); |
3819 | 3713 |
3820 __ bind(&prepare_slow); | 3714 __ bind(&prepare_slow); |
3821 // Restore the key, which is known to be the array length. | 3715 // Restore the key, which is known to be the array length. |
3822 __ mov(ecx, Immediate(0)); | 3716 __ mov(ecx, Immediate(0)); |
3823 | 3717 |
3824 __ bind(&slow); | 3718 __ bind(&slow); |
3825 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | 3719 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3826 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | |
3827 } | 3720 } |
3828 } | 3721 } |
3829 | 3722 |
3830 | 3723 |
3831 #undef __ | 3724 #undef __ |
3832 | 3725 |
3833 } } // namespace v8::internal | 3726 } } // namespace v8::internal |
3834 | 3727 |
3835 #endif // V8_TARGET_ARCH_IA32 | 3728 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |