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