| 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 2677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2688 | 2688 |
| 2689 // Return the generated code. | 2689 // Return the generated code. |
| 2690 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); | 2690 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 2691 } | 2691 } |
| 2692 | 2692 |
| 2693 | 2693 |
| 2694 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, | 2694 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, |
| 2695 Handle<JSObject> object, | 2695 Handle<JSObject> object, |
| 2696 Handle<JSObject> last) { | 2696 Handle<JSObject> last) { |
| 2697 // ----------- S t a t e ------------- | 2697 // ----------- S t a t e ------------- |
| 2698 // -- eax : receiver | |
| 2699 // -- ecx : name | 2698 // -- ecx : name |
| 2699 // -- edx : receiver |
| 2700 // -- esp[0] : return address | 2700 // -- esp[0] : return address |
| 2701 // ----------------------------------- | 2701 // ----------------------------------- |
| 2702 Label miss; | 2702 Label miss; |
| 2703 | 2703 |
| 2704 // Check that the receiver isn't a smi. | 2704 // Check that the receiver isn't a smi. |
| 2705 __ JumpIfSmi(eax, &miss); | 2705 __ JumpIfSmi(edx, &miss); |
| 2706 | 2706 |
| 2707 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2707 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
| 2708 | 2708 |
| 2709 // Check the maps of the full prototype chain. Also check that | 2709 // Check the maps of the full prototype chain. Also check that |
| 2710 // global property cells up to (but not including) the last object | 2710 // global property cells up to (but not including) the last object |
| 2711 // in the prototype chain are empty. | 2711 // in the prototype chain are empty. |
| 2712 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 2712 CheckPrototypes(object, edx, last, ebx, eax, edi, name, &miss); |
| 2713 | 2713 |
| 2714 // If the last object in the prototype chain is a global object, | 2714 // If the last object in the prototype chain is a global object, |
| 2715 // check that the global property cell is empty. | 2715 // check that the global property cell is empty. |
| 2716 if (last->IsGlobalObject()) { | 2716 if (last->IsGlobalObject()) { |
| 2717 GenerateCheckPropertyCell( | 2717 GenerateCheckPropertyCell( |
| 2718 masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); | 2718 masm(), Handle<GlobalObject>::cast(last), name, eax, &miss); |
| 2719 } | 2719 } |
| 2720 | 2720 |
| 2721 // Return undefined if maps of the full prototype chain are still the | 2721 // Return undefined if maps of the full prototype chain are still the |
| 2722 // same and no global property with this name contains a value. | 2722 // same and no global property with this name contains a value. |
| 2723 __ mov(eax, isolate()->factory()->undefined_value()); | 2723 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2724 __ ret(0); | 2724 __ ret(0); |
| 2725 | 2725 |
| 2726 __ bind(&miss); | 2726 __ bind(&miss); |
| 2727 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2727 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2728 | 2728 |
| 2729 // Return the generated code. | 2729 // Return the generated code. |
| 2730 return GetCode(NONEXISTENT, factory()->empty_string()); | 2730 return GetCode(NONEXISTENT, factory()->empty_string()); |
| 2731 } | 2731 } |
| 2732 | 2732 |
| 2733 | 2733 |
| 2734 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, | 2734 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
| 2735 Handle<JSObject> holder, | 2735 Handle<JSObject> holder, |
| 2736 int index, | 2736 int index, |
| 2737 Handle<String> name) { | 2737 Handle<String> name) { |
| 2738 // ----------- S t a t e ------------- | 2738 // ----------- S t a t e ------------- |
| 2739 // -- eax : receiver | |
| 2740 // -- ecx : name | 2739 // -- ecx : name |
| 2740 // -- edx : receiver |
| 2741 // -- esp[0] : return address | 2741 // -- esp[0] : return address |
| 2742 // ----------------------------------- | 2742 // ----------------------------------- |
| 2743 Label miss; | 2743 Label miss; |
| 2744 | 2744 |
| 2745 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); | 2745 GenerateLoadField(object, holder, edx, ebx, eax, edi, index, name, &miss); |
| 2746 __ bind(&miss); | 2746 __ bind(&miss); |
| 2747 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2747 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2748 | 2748 |
| 2749 // Return the generated code. | 2749 // Return the generated code. |
| 2750 return GetCode(FIELD, name); | 2750 return GetCode(FIELD, name); |
| 2751 } | 2751 } |
| 2752 | 2752 |
| 2753 | 2753 |
| 2754 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 2754 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 2755 Handle<String> name, | 2755 Handle<String> name, |
| 2756 Handle<JSObject> object, | 2756 Handle<JSObject> object, |
| 2757 Handle<JSObject> holder, | 2757 Handle<JSObject> holder, |
| 2758 Handle<AccessorInfo> callback) { | 2758 Handle<AccessorInfo> callback) { |
| 2759 // ----------- S t a t e ------------- | 2759 // ----------- S t a t e ------------- |
| 2760 // -- eax : receiver | |
| 2761 // -- ecx : name | 2760 // -- ecx : name |
| 2761 // -- edx : receiver |
| 2762 // -- esp[0] : return address | 2762 // -- esp[0] : return address |
| 2763 // ----------------------------------- | 2763 // ----------------------------------- |
| 2764 Label miss; | 2764 Label miss; |
| 2765 | 2765 |
| 2766 GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback, | 2766 GenerateLoadCallback(object, holder, edx, ecx, ebx, eax, edi, callback, |
| 2767 name, &miss); | 2767 name, &miss); |
| 2768 __ bind(&miss); | 2768 __ bind(&miss); |
| 2769 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2769 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2770 | 2770 |
| 2771 // Return the generated code. | 2771 // Return the generated code. |
| 2772 return GetCode(CALLBACKS, name); | 2772 return GetCode(CALLBACKS, name); |
| 2773 } | 2773 } |
| 2774 | 2774 |
| 2775 | 2775 |
| 2776 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, | 2776 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 2777 Handle<JSObject> holder, | 2777 Handle<JSObject> holder, |
| 2778 Handle<JSFunction> value, | 2778 Handle<JSFunction> value, |
| 2779 Handle<String> name) { | 2779 Handle<String> name) { |
| 2780 // ----------- S t a t e ------------- | 2780 // ----------- S t a t e ------------- |
| 2781 // -- eax : receiver | |
| 2782 // -- ecx : name | 2781 // -- ecx : name |
| 2782 // -- edx : receiver |
| 2783 // -- esp[0] : return address | 2783 // -- esp[0] : return address |
| 2784 // ----------------------------------- | 2784 // ----------------------------------- |
| 2785 Label miss; | 2785 Label miss; |
| 2786 | 2786 |
| 2787 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); | 2787 GenerateLoadConstant(object, holder, edx, ebx, eax, edi, value, name, &miss); |
| 2788 __ bind(&miss); | 2788 __ bind(&miss); |
| 2789 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2789 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2790 | 2790 |
| 2791 // Return the generated code. | 2791 // Return the generated code. |
| 2792 return GetCode(CONSTANT_FUNCTION, name); | 2792 return GetCode(CONSTANT_FUNCTION, name); |
| 2793 } | 2793 } |
| 2794 | 2794 |
| 2795 | 2795 |
| 2796 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, | 2796 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, |
| 2797 Handle<JSObject> holder, | 2797 Handle<JSObject> holder, |
| 2798 Handle<String> name) { | 2798 Handle<String> name) { |
| 2799 // ----------- S t a t e ------------- | 2799 // ----------- S t a t e ------------- |
| 2800 // -- eax : receiver | |
| 2801 // -- ecx : name | 2800 // -- ecx : name |
| 2801 // -- edx : receiver |
| 2802 // -- esp[0] : return address | 2802 // -- esp[0] : return address |
| 2803 // ----------------------------------- | 2803 // ----------------------------------- |
| 2804 Label miss; | 2804 Label miss; |
| 2805 | 2805 |
| 2806 LookupResult lookup(isolate()); | 2806 LookupResult lookup(isolate()); |
| 2807 LookupPostInterceptor(holder, name, &lookup); | 2807 LookupPostInterceptor(holder, name, &lookup); |
| 2808 | 2808 |
| 2809 // TODO(368): Compile in the whole chain: all the interceptors in | 2809 // TODO(368): Compile in the whole chain: all the interceptors in |
| 2810 // prototypes and ultimate answer. | 2810 // prototypes and ultimate answer. |
| 2811 GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi, | 2811 GenerateLoadInterceptor(receiver, holder, &lookup, edx, ecx, eax, ebx, edi, |
| 2812 name, &miss); | 2812 name, &miss); |
| 2813 | 2813 |
| 2814 __ bind(&miss); | 2814 __ bind(&miss); |
| 2815 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2815 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2816 | 2816 |
| 2817 // Return the generated code. | 2817 // Return the generated code. |
| 2818 return GetCode(INTERCEPTOR, name); | 2818 return GetCode(INTERCEPTOR, name); |
| 2819 } | 2819 } |
| 2820 | 2820 |
| 2821 | 2821 |
| 2822 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2822 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 2823 Handle<JSObject> object, | 2823 Handle<JSObject> object, |
| 2824 Handle<GlobalObject> holder, | 2824 Handle<GlobalObject> holder, |
| 2825 Handle<JSGlobalPropertyCell> cell, | 2825 Handle<JSGlobalPropertyCell> cell, |
| 2826 Handle<String> name, | 2826 Handle<String> name, |
| 2827 bool is_dont_delete) { | 2827 bool is_dont_delete) { |
| 2828 // ----------- S t a t e ------------- | 2828 // ----------- S t a t e ------------- |
| 2829 // -- eax : receiver | |
| 2830 // -- ecx : name | 2829 // -- ecx : name |
| 2830 // -- edx : receiver |
| 2831 // -- esp[0] : return address | 2831 // -- esp[0] : return address |
| 2832 // ----------------------------------- | 2832 // ----------------------------------- |
| 2833 Label miss; | 2833 Label miss; |
| 2834 | 2834 |
| 2835 // Check that the maps haven't changed. | 2835 // Check that the maps haven't changed. |
| 2836 __ JumpIfSmi(eax, &miss); | 2836 __ JumpIfSmi(edx, &miss); |
| 2837 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 2837 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss); |
| 2838 | 2838 |
| 2839 // Get the value from the cell. | 2839 // Get the value from the cell. |
| 2840 if (Serializer::enabled()) { | 2840 if (Serializer::enabled()) { |
| 2841 __ mov(ebx, Immediate(cell)); | 2841 __ mov(ebx, Immediate(cell)); |
| 2842 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2842 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| 2843 } else { | 2843 } else { |
| 2844 __ mov(ebx, Operand::Cell(cell)); | 2844 __ mov(ebx, Operand::Cell(cell)); |
| 2845 } | 2845 } |
| 2846 | 2846 |
| 2847 // Check for deleted property if property can actually be deleted. | 2847 // Check for deleted property if property can actually be deleted. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2865 // Return the generated code. | 2865 // Return the generated code. |
| 2866 return GetCode(NORMAL, name); | 2866 return GetCode(NORMAL, name); |
| 2867 } | 2867 } |
| 2868 | 2868 |
| 2869 | 2869 |
| 2870 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, | 2870 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
| 2871 Handle<JSObject> receiver, | 2871 Handle<JSObject> receiver, |
| 2872 Handle<JSObject> holder, | 2872 Handle<JSObject> holder, |
| 2873 int index) { | 2873 int index) { |
| 2874 // ----------- S t a t e ------------- | 2874 // ----------- S t a t e ------------- |
| 2875 // -- eax : key | 2875 // -- ecx : key |
| 2876 // -- edx : receiver | 2876 // -- edx : receiver |
| 2877 // -- esp[0] : return address | 2877 // -- esp[0] : return address |
| 2878 // ----------------------------------- | 2878 // ----------------------------------- |
| 2879 Label miss; | 2879 Label miss; |
| 2880 | 2880 |
| 2881 Counters* counters = isolate()->counters(); | 2881 Counters* counters = isolate()->counters(); |
| 2882 __ IncrementCounter(counters->keyed_load_field(), 1); | 2882 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 2883 | 2883 |
| 2884 // Check that the name has not changed. | 2884 // Check that the name has not changed. |
| 2885 __ cmp(eax, Immediate(name)); | 2885 __ cmp(ecx, Immediate(name)); |
| 2886 __ j(not_equal, &miss); | 2886 __ j(not_equal, &miss); |
| 2887 | 2887 |
| 2888 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2888 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 2889 | 2889 |
| 2890 __ bind(&miss); | 2890 __ bind(&miss); |
| 2891 __ DecrementCounter(counters->keyed_load_field(), 1); | 2891 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 2892 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2892 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2893 | 2893 |
| 2894 // Return the generated code. | 2894 // Return the generated code. |
| 2895 return GetCode(FIELD, name); | 2895 return GetCode(FIELD, name); |
| 2896 } | 2896 } |
| 2897 | 2897 |
| 2898 | 2898 |
| 2899 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( | 2899 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
| 2900 Handle<String> name, | 2900 Handle<String> name, |
| 2901 Handle<JSObject> receiver, | 2901 Handle<JSObject> receiver, |
| 2902 Handle<JSObject> holder, | 2902 Handle<JSObject> holder, |
| 2903 Handle<AccessorInfo> callback) { | 2903 Handle<AccessorInfo> callback) { |
| 2904 // ----------- S t a t e ------------- | 2904 // ----------- S t a t e ------------- |
| 2905 // -- eax : key | 2905 // -- ecx : key |
| 2906 // -- edx : receiver | 2906 // -- edx : receiver |
| 2907 // -- esp[0] : return address | 2907 // -- esp[0] : return address |
| 2908 // ----------------------------------- | 2908 // ----------------------------------- |
| 2909 Label miss; | 2909 Label miss; |
| 2910 | 2910 |
| 2911 Counters* counters = isolate()->counters(); | 2911 Counters* counters = isolate()->counters(); |
| 2912 __ IncrementCounter(counters->keyed_load_callback(), 1); | 2912 __ IncrementCounter(counters->keyed_load_callback(), 1); |
| 2913 | 2913 |
| 2914 // Check that the name has not changed. | 2914 // Check that the name has not changed. |
| 2915 __ cmp(eax, Immediate(name)); | 2915 __ cmp(ecx, Immediate(name)); |
| 2916 __ j(not_equal, &miss); | 2916 __ j(not_equal, &miss); |
| 2917 | 2917 |
| 2918 GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback, | 2918 GenerateLoadCallback(receiver, holder, edx, ecx, ebx, eax, edi, callback, |
| 2919 name, &miss); | 2919 name, &miss); |
| 2920 | 2920 |
| 2921 __ bind(&miss); | 2921 __ bind(&miss); |
| 2922 __ DecrementCounter(counters->keyed_load_callback(), 1); | 2922 __ DecrementCounter(counters->keyed_load_callback(), 1); |
| 2923 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2923 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2924 | 2924 |
| 2925 // Return the generated code. | 2925 // Return the generated code. |
| 2926 return GetCode(CALLBACKS, name); | 2926 return GetCode(CALLBACKS, name); |
| 2927 } | 2927 } |
| 2928 | 2928 |
| 2929 | 2929 |
| 2930 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( | 2930 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 2931 Handle<String> name, | 2931 Handle<String> name, |
| 2932 Handle<JSObject> receiver, | 2932 Handle<JSObject> receiver, |
| 2933 Handle<JSObject> holder, | 2933 Handle<JSObject> holder, |
| 2934 Handle<JSFunction> value) { | 2934 Handle<JSFunction> value) { |
| 2935 // ----------- S t a t e ------------- | 2935 // ----------- S t a t e ------------- |
| 2936 // -- eax : key | 2936 // -- ecx : key |
| 2937 // -- edx : receiver | 2937 // -- edx : receiver |
| 2938 // -- esp[0] : return address | 2938 // -- esp[0] : return address |
| 2939 // ----------------------------------- | 2939 // ----------------------------------- |
| 2940 Label miss; | 2940 Label miss; |
| 2941 | 2941 |
| 2942 Counters* counters = isolate()->counters(); | 2942 Counters* counters = isolate()->counters(); |
| 2943 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 2943 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 2944 | 2944 |
| 2945 // Check that the name has not changed. | 2945 // Check that the name has not changed. |
| 2946 __ cmp(eax, Immediate(name)); | 2946 __ cmp(ecx, Immediate(name)); |
| 2947 __ j(not_equal, &miss); | 2947 __ j(not_equal, &miss); |
| 2948 | 2948 |
| 2949 GenerateLoadConstant( | 2949 GenerateLoadConstant( |
| 2950 receiver, holder, edx, ebx, ecx, edi, value, name, &miss); | 2950 receiver, holder, edx, ebx, eax, edi, value, name, &miss); |
| 2951 __ bind(&miss); | 2951 __ bind(&miss); |
| 2952 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 2952 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 2953 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2953 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2954 | 2954 |
| 2955 // Return the generated code. | 2955 // Return the generated code. |
| 2956 return GetCode(CONSTANT_FUNCTION, name); | 2956 return GetCode(CONSTANT_FUNCTION, name); |
| 2957 } | 2957 } |
| 2958 | 2958 |
| 2959 | 2959 |
| 2960 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( | 2960 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
| 2961 Handle<JSObject> receiver, | 2961 Handle<JSObject> receiver, |
| 2962 Handle<JSObject> holder, | 2962 Handle<JSObject> holder, |
| 2963 Handle<String> name) { | 2963 Handle<String> name) { |
| 2964 // ----------- S t a t e ------------- | 2964 // ----------- S t a t e ------------- |
| 2965 // -- eax : key | 2965 // -- ecx : key |
| 2966 // -- edx : receiver | 2966 // -- edx : receiver |
| 2967 // -- esp[0] : return address | 2967 // -- esp[0] : return address |
| 2968 // ----------------------------------- | 2968 // ----------------------------------- |
| 2969 Label miss; | 2969 Label miss; |
| 2970 | 2970 |
| 2971 Counters* counters = isolate()->counters(); | 2971 Counters* counters = isolate()->counters(); |
| 2972 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 2972 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 2973 | 2973 |
| 2974 // Check that the name has not changed. | 2974 // Check that the name has not changed. |
| 2975 __ cmp(eax, Immediate(name)); | 2975 __ cmp(ecx, Immediate(name)); |
| 2976 __ j(not_equal, &miss); | 2976 __ j(not_equal, &miss); |
| 2977 | 2977 |
| 2978 LookupResult lookup(isolate()); | 2978 LookupResult lookup(isolate()); |
| 2979 LookupPostInterceptor(holder, name, &lookup); | 2979 LookupPostInterceptor(holder, name, &lookup); |
| 2980 GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi, | 2980 GenerateLoadInterceptor(receiver, holder, &lookup, edx, ecx, eax, ebx, edi, |
| 2981 name, &miss); | 2981 name, &miss); |
| 2982 __ bind(&miss); | 2982 __ bind(&miss); |
| 2983 __ DecrementCounter(counters->keyed_load_interceptor(), 1); | 2983 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
| 2984 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2984 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2985 | 2985 |
| 2986 // Return the generated code. | 2986 // Return the generated code. |
| 2987 return GetCode(INTERCEPTOR, name); | 2987 return GetCode(INTERCEPTOR, name); |
| 2988 } | 2988 } |
| 2989 | 2989 |
| 2990 | 2990 |
| 2991 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( | 2991 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 2992 Handle<String> name) { | 2992 Handle<String> name) { |
| 2993 // ----------- S t a t e ------------- | 2993 // ----------- S t a t e ------------- |
| 2994 // -- eax : key | 2994 // -- ecx : key |
| 2995 // -- edx : receiver | 2995 // -- edx : receiver |
| 2996 // -- esp[0] : return address | 2996 // -- esp[0] : return address |
| 2997 // ----------------------------------- | 2997 // ----------------------------------- |
| 2998 Label miss; | 2998 Label miss; |
| 2999 | 2999 |
| 3000 Counters* counters = isolate()->counters(); | 3000 Counters* counters = isolate()->counters(); |
| 3001 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3001 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 3002 | 3002 |
| 3003 // Check that the name has not changed. | 3003 // Check that the name has not changed. |
| 3004 __ cmp(eax, Immediate(name)); | 3004 __ cmp(ecx, Immediate(name)); |
| 3005 __ j(not_equal, &miss); | 3005 __ j(not_equal, &miss); |
| 3006 | 3006 |
| 3007 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3007 GenerateLoadArrayLength(masm(), edx, eax, &miss); |
| 3008 __ bind(&miss); | 3008 __ bind(&miss); |
| 3009 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3009 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 3010 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3010 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3011 | 3011 |
| 3012 // Return the generated code. | 3012 // Return the generated code. |
| 3013 return GetCode(CALLBACKS, name); | 3013 return GetCode(CALLBACKS, name); |
| 3014 } | 3014 } |
| 3015 | 3015 |
| 3016 | 3016 |
| 3017 Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( | 3017 Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
| 3018 Handle<String> name) { | 3018 Handle<String> name) { |
| 3019 // ----------- S t a t e ------------- | 3019 // ----------- S t a t e ------------- |
| 3020 // -- eax : key | 3020 // -- ecx : key |
| 3021 // -- edx : receiver | 3021 // -- edx : receiver |
| 3022 // -- esp[0] : return address | 3022 // -- esp[0] : return address |
| 3023 // ----------------------------------- | 3023 // ----------------------------------- |
| 3024 Label miss; | 3024 Label miss; |
| 3025 | 3025 |
| 3026 Counters* counters = isolate()->counters(); | 3026 Counters* counters = isolate()->counters(); |
| 3027 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3027 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3028 | 3028 |
| 3029 // Check that the name has not changed. | 3029 // Check that the name has not changed. |
| 3030 __ cmp(eax, Immediate(name)); | 3030 __ cmp(ecx, Immediate(name)); |
| 3031 __ j(not_equal, &miss); | 3031 __ j(not_equal, &miss); |
| 3032 | 3032 |
| 3033 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3033 GenerateLoadStringLength(masm(), edx, eax, ebx, &miss, true); |
| 3034 __ bind(&miss); | 3034 __ bind(&miss); |
| 3035 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3035 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3036 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3036 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3037 | 3037 |
| 3038 // Return the generated code. | 3038 // Return the generated code. |
| 3039 return GetCode(CALLBACKS, name); | 3039 return GetCode(CALLBACKS, name); |
| 3040 } | 3040 } |
| 3041 | 3041 |
| 3042 | 3042 |
| 3043 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( | 3043 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
| 3044 Handle<String> name) { | 3044 Handle<String> name) { |
| 3045 // ----------- S t a t e ------------- | 3045 // ----------- S t a t e ------------- |
| 3046 // -- eax : key | 3046 // -- ecx : key |
| 3047 // -- edx : receiver | 3047 // -- edx : receiver |
| 3048 // -- esp[0] : return address | 3048 // -- esp[0] : return address |
| 3049 // ----------------------------------- | 3049 // ----------------------------------- |
| 3050 Label miss; | 3050 Label miss; |
| 3051 | 3051 |
| 3052 Counters* counters = isolate()->counters(); | 3052 Counters* counters = isolate()->counters(); |
| 3053 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3053 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3054 | 3054 |
| 3055 // Check that the name has not changed. | 3055 // Check that the name has not changed. |
| 3056 __ cmp(eax, Immediate(name)); | 3056 __ cmp(ecx, Immediate(name)); |
| 3057 __ j(not_equal, &miss); | 3057 __ j(not_equal, &miss); |
| 3058 | 3058 |
| 3059 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3059 GenerateLoadFunctionPrototype(masm(), edx, eax, ebx, &miss); |
| 3060 __ bind(&miss); | 3060 __ bind(&miss); |
| 3061 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3061 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3062 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3062 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3063 | 3063 |
| 3064 // Return the generated code. | 3064 // Return the generated code. |
| 3065 return GetCode(CALLBACKS, name); | 3065 return GetCode(CALLBACKS, name); |
| 3066 } | 3066 } |
| 3067 | 3067 |
| 3068 | 3068 |
| 3069 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3069 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 3070 Handle<Map> receiver_map) { | 3070 Handle<Map> receiver_map) { |
| 3071 // ----------- S t a t e ------------- | 3071 // ----------- S t a t e ------------- |
| 3072 // -- eax : key | 3072 // -- ecx : key |
| 3073 // -- edx : receiver | 3073 // -- edx : receiver |
| 3074 // -- esp[0] : return address | 3074 // -- esp[0] : return address |
| 3075 // ----------------------------------- | 3075 // ----------------------------------- |
| 3076 | 3076 |
| 3077 ElementsKind elements_kind = receiver_map->elements_kind(); | 3077 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3078 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); | 3078 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
| 3079 | 3079 |
| 3080 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3080 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3081 | 3081 |
| 3082 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3082 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3083 | 3083 |
| 3084 // Return the generated code. | 3084 // Return the generated code. |
| 3085 return GetCode(NORMAL, factory()->empty_string()); | 3085 return GetCode(NORMAL, factory()->empty_string()); |
| 3086 } | 3086 } |
| 3087 | 3087 |
| 3088 | 3088 |
| 3089 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3089 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
| 3090 MapHandleList* receiver_maps, | 3090 MapHandleList* receiver_maps, |
| 3091 CodeHandleList* handler_ics) { | 3091 CodeHandleList* handler_ics) { |
| 3092 // ----------- S t a t e ------------- | 3092 // ----------- S t a t e ------------- |
| 3093 // -- eax : key | 3093 // -- ecx : key |
| 3094 // -- edx : receiver | 3094 // -- edx : receiver |
| 3095 // -- esp[0] : return address | 3095 // -- esp[0] : return address |
| 3096 // ----------------------------------- | 3096 // ----------------------------------- |
| 3097 Label miss; | 3097 Label miss; |
| 3098 __ JumpIfSmi(edx, &miss); | 3098 __ JumpIfSmi(edx, &miss); |
| 3099 | 3099 |
| 3100 Register map_reg = ebx; | 3100 Register map_reg = ebx; |
| 3101 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); | 3101 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); |
| 3102 int receiver_count = receiver_maps->length(); | 3102 int receiver_count = receiver_maps->length(); |
| 3103 for (int current = 0; current < receiver_count; ++current) { | 3103 for (int current = 0; current < receiver_count; ++current) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3247 } | 3247 } |
| 3248 | 3248 |
| 3249 | 3249 |
| 3250 #undef __ | 3250 #undef __ |
| 3251 #define __ ACCESS_MASM(masm) | 3251 #define __ ACCESS_MASM(masm) |
| 3252 | 3252 |
| 3253 | 3253 |
| 3254 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 3254 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
| 3255 MacroAssembler* masm) { | 3255 MacroAssembler* masm) { |
| 3256 // ----------- S t a t e ------------- | 3256 // ----------- S t a t e ------------- |
| 3257 // -- eax : key | 3257 // -- ecx : key |
| 3258 // -- edx : receiver | 3258 // -- edx : receiver |
| 3259 // -- esp[0] : return address | 3259 // -- esp[0] : return address |
| 3260 // ----------------------------------- | 3260 // ----------------------------------- |
| 3261 Label slow, miss_force_generic; | 3261 Label slow, miss_force_generic; |
| 3262 | 3262 |
| 3263 // This stub is meant to be tail-jumped to, the receiver must already | 3263 // This stub is meant to be tail-jumped to, the receiver must already |
| 3264 // have been verified by the caller to not be a smi. | 3264 // have been verified by the caller to not be a smi. |
| 3265 __ JumpIfNotSmi(eax, &miss_force_generic); | 3265 __ JumpIfNotSmi(ecx, &miss_force_generic); |
| 3266 __ mov(ebx, eax); | 3266 __ mov(ebx, ecx); |
| 3267 __ SmiUntag(ebx); | 3267 __ SmiUntag(ebx); |
| 3268 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3268 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
| 3269 | 3269 |
| 3270 // Push receiver on the stack to free up a register for the dictionary | 3270 // Push receiver on the stack to free up a register for the dictionary |
| 3271 // probing. | 3271 // probing. |
| 3272 __ push(edx); | 3272 __ push(edx); |
| 3273 __ LoadFromNumberDictionary(&slow, | 3273 __ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax); |
| 3274 ecx, | |
| 3275 eax, | |
| 3276 ebx, | |
| 3277 edx, | |
| 3278 edi, | |
| 3279 eax); | |
| 3280 // Pop receiver before returning. | 3274 // Pop receiver before returning. |
| 3281 __ pop(edx); | 3275 __ pop(edx); |
| 3282 __ ret(0); | 3276 __ ret(0); |
| 3283 | 3277 |
| 3284 __ bind(&slow); | 3278 __ bind(&slow); |
| 3285 __ pop(edx); | 3279 __ pop(edx); |
| 3286 | 3280 |
| 3287 // ----------- S t a t e ------------- | 3281 // ----------- S t a t e ------------- |
| 3288 // -- eax : value | |
| 3289 // -- ecx : key | 3282 // -- ecx : key |
| 3290 // -- edx : receiver | 3283 // -- edx : receiver |
| 3291 // -- esp[0] : return address | 3284 // -- esp[0] : return address |
| 3292 // ----------------------------------- | 3285 // ----------------------------------- |
| 3293 | 3286 |
| 3294 Handle<Code> slow_ic = | 3287 Handle<Code> slow_ic = |
| 3295 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | 3288 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3296 __ jmp(slow_ic, RelocInfo::CODE_TARGET); | 3289 __ jmp(slow_ic, RelocInfo::CODE_TARGET); |
| 3297 | 3290 |
| 3298 __ bind(&miss_force_generic); | 3291 __ bind(&miss_force_generic); |
| 3299 // ----------- S t a t e ------------- | 3292 // ----------- S t a t e ------------- |
| 3300 // -- eax : value | |
| 3301 // -- ecx : key | 3293 // -- ecx : key |
| 3302 // -- edx : receiver | 3294 // -- edx : receiver |
| 3303 // -- esp[0] : return address | 3295 // -- esp[0] : return address |
| 3304 // ----------------------------------- | 3296 // ----------------------------------- |
| 3305 | 3297 |
| 3306 Handle<Code> miss_force_generic_ic = | 3298 Handle<Code> miss_force_generic_ic = |
| 3307 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3299 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3308 __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); | 3300 __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); |
| 3309 } | 3301 } |
| 3310 | 3302 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3339 } else { | 3331 } else { |
| 3340 __ JumpIfNotSmi(key, fail); | 3332 __ JumpIfNotSmi(key, fail); |
| 3341 } | 3333 } |
| 3342 } | 3334 } |
| 3343 | 3335 |
| 3344 | 3336 |
| 3345 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | 3337 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
| 3346 MacroAssembler* masm, | 3338 MacroAssembler* masm, |
| 3347 ElementsKind elements_kind) { | 3339 ElementsKind elements_kind) { |
| 3348 // ----------- S t a t e ------------- | 3340 // ----------- S t a t e ------------- |
| 3349 // -- eax : key | 3341 // -- ecx : key |
| 3350 // -- edx : receiver | 3342 // -- edx : receiver |
| 3351 // -- esp[0] : return address | 3343 // -- esp[0] : return address |
| 3352 // ----------------------------------- | 3344 // ----------------------------------- |
| 3353 Label miss_force_generic, failed_allocation, slow; | 3345 Label miss_force_generic, failed_allocation, slow; |
| 3354 | 3346 |
| 3355 // This stub is meant to be tail-jumped to, the receiver must already | 3347 // This stub is meant to be tail-jumped to, the receiver must already |
| 3356 // have been verified by the caller to not be a smi. | 3348 // have been verified by the caller to not be a smi. |
| 3357 | 3349 |
| 3358 // Check that the key is a smi or a heap number convertible to a smi. | 3350 // Check that the key is a smi or a heap number convertible to a smi. |
| 3359 GenerateSmiKeyCheck(masm, eax, ecx, xmm0, xmm1, &miss_force_generic); | 3351 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); |
| 3360 | 3352 |
| 3361 // Check that the index is in range. | 3353 // Check that the index is in range. |
| 3362 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3354 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
| 3363 __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); | 3355 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
| 3364 // Unsigned comparison catches both negative and too-large values. | 3356 // Unsigned comparison catches both negative and too-large values. |
| 3365 __ j(above_equal, &miss_force_generic); | 3357 __ j(above_equal, &miss_force_generic); |
| 3366 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | 3358 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
| 3367 // ebx: base pointer of external storage | 3359 // ebx: base pointer of external storage |
| 3368 switch (elements_kind) { | 3360 switch (elements_kind) { |
| 3369 case EXTERNAL_BYTE_ELEMENTS: | 3361 case EXTERNAL_BYTE_ELEMENTS: |
| 3370 __ SmiUntag(eax); // Untag the index. | 3362 __ SmiUntag(ecx); // Untag the index. |
| 3371 __ movsx_b(eax, Operand(ebx, eax, times_1, 0)); | 3363 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); |
| 3372 break; | 3364 break; |
| 3373 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3365 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3374 case EXTERNAL_PIXEL_ELEMENTS: | 3366 case EXTERNAL_PIXEL_ELEMENTS: |
| 3375 __ SmiUntag(eax); // Untag the index. | 3367 __ SmiUntag(ecx); // Untag the index. |
| 3376 __ movzx_b(eax, Operand(ebx, eax, times_1, 0)); | 3368 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); |
| 3377 break; | 3369 break; |
| 3378 case EXTERNAL_SHORT_ELEMENTS: | 3370 case EXTERNAL_SHORT_ELEMENTS: |
| 3379 __ movsx_w(eax, Operand(ebx, eax, times_1, 0)); | 3371 __ movsx_w(eax, Operand(ebx, ecx, times_1, 0)); |
| 3380 break; | 3372 break; |
| 3381 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3373 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3382 __ movzx_w(eax, Operand(ebx, eax, times_1, 0)); | 3374 __ movzx_w(eax, Operand(ebx, ecx, times_1, 0)); |
| 3383 break; | 3375 break; |
| 3384 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3376 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3385 case EXTERNAL_INT_ELEMENTS: | 3377 case EXTERNAL_INT_ELEMENTS: |
| 3386 __ mov(ecx, Operand(ebx, eax, times_2, 0)); | 3378 __ mov(eax, Operand(ebx, ecx, times_2, 0)); |
| 3387 break; | 3379 break; |
| 3388 case EXTERNAL_FLOAT_ELEMENTS: | 3380 case EXTERNAL_FLOAT_ELEMENTS: |
| 3389 __ fld_s(Operand(ebx, eax, times_2, 0)); | 3381 __ fld_s(Operand(ebx, ecx, times_2, 0)); |
| 3390 break; | 3382 break; |
| 3391 case EXTERNAL_DOUBLE_ELEMENTS: | 3383 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3392 __ fld_d(Operand(ebx, eax, times_4, 0)); | 3384 __ fld_d(Operand(ebx, ecx, times_4, 0)); |
| 3393 break; | 3385 break; |
| 3394 default: | 3386 default: |
| 3395 UNREACHABLE(); | 3387 UNREACHABLE(); |
| 3396 break; | 3388 break; |
| 3397 } | 3389 } |
| 3398 | 3390 |
| 3399 // For integer array types: | 3391 // For integer array types: |
| 3400 // ecx: value | 3392 // eax: value |
| 3401 // For floating-point array type: | 3393 // For floating-point array type: |
| 3402 // FP(0): value | 3394 // FP(0): value |
| 3403 | 3395 |
| 3404 if (elements_kind == EXTERNAL_INT_ELEMENTS || | 3396 if (elements_kind == EXTERNAL_INT_ELEMENTS || |
| 3405 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 3397 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 3406 // For the Int and UnsignedInt array types, we need to see whether | 3398 // For the Int and UnsignedInt array types, we need to see whether |
| 3407 // the value can be represented in a Smi. If not, we need to convert | 3399 // the value can be represented in a Smi. If not, we need to convert |
| 3408 // it to a HeapNumber. | 3400 // it to a HeapNumber. |
| 3409 Label box_int; | 3401 Label box_int; |
| 3410 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | 3402 if (elements_kind == EXTERNAL_INT_ELEMENTS) { |
| 3411 __ cmp(ecx, 0xc0000000); | 3403 __ cmp(eax, 0xc0000000); |
| 3412 __ j(sign, &box_int); | 3404 __ j(sign, &box_int); |
| 3413 } else { | 3405 } else { |
| 3414 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | 3406 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
| 3415 // The test is different for unsigned int values. Since we need | 3407 // The test is different for unsigned int values. Since we need |
| 3416 // the value to be in the range of a positive smi, we can't | 3408 // the value to be in the range of a positive smi, we can't |
| 3417 // handle either of the top two bits being set in the value. | 3409 // handle either of the top two bits being set in the value. |
| 3418 __ test(ecx, Immediate(0xc0000000)); | 3410 __ test(eax, Immediate(0xc0000000)); |
| 3419 __ j(not_zero, &box_int); | 3411 __ j(not_zero, &box_int); |
| 3420 } | 3412 } |
| 3421 | 3413 |
| 3422 __ mov(eax, ecx); | |
| 3423 __ SmiTag(eax); | 3414 __ SmiTag(eax); |
| 3424 __ ret(0); | 3415 __ ret(0); |
| 3425 | 3416 |
| 3426 __ bind(&box_int); | 3417 __ bind(&box_int); |
| 3427 | 3418 |
| 3428 // Allocate a HeapNumber for the int and perform int-to-double | 3419 // Allocate a HeapNumber for the int and perform int-to-double |
| 3429 // conversion. | 3420 // conversion. |
| 3430 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | 3421 if (elements_kind == EXTERNAL_INT_ELEMENTS) { |
| 3431 __ push(ecx); | 3422 __ push(eax); |
| 3432 __ fild_s(Operand(esp, 0)); | 3423 __ fild_s(Operand(esp, 0)); |
| 3433 __ pop(ecx); | 3424 __ pop(eax); |
| 3434 } else { | 3425 } else { |
| 3435 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | 3426 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
| 3436 // Need to zero-extend the value. | 3427 // Need to zero-extend the value. |
| 3437 // There's no fild variant for unsigned values, so zero-extend | 3428 // There's no fild variant for unsigned values, so zero-extend |
| 3438 // to a 64-bit int manually. | 3429 // to a 64-bit int manually. |
| 3439 __ push(Immediate(0)); | 3430 __ push(Immediate(0)); |
| 3440 __ push(ecx); | 3431 __ push(eax); |
| 3441 __ fild_d(Operand(esp, 0)); | 3432 __ fild_d(Operand(esp, 0)); |
| 3442 __ pop(ecx); | 3433 __ pop(eax); |
| 3443 __ pop(ecx); | 3434 __ pop(eax); |
| 3444 } | 3435 } |
| 3445 // FP(0): value | 3436 // FP(0): value |
| 3446 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); | 3437 __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); |
| 3447 // Set the value. | 3438 // Set the value. |
| 3448 __ mov(eax, ecx); | |
| 3449 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3439 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3450 __ ret(0); | 3440 __ ret(0); |
| 3451 } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3441 } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| 3452 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3442 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 3453 // For the floating-point array type, we need to always allocate a | 3443 // For the floating-point array type, we need to always allocate a |
| 3454 // HeapNumber. | 3444 // HeapNumber. |
| 3455 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); | 3445 __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); |
| 3456 // Set the value. | 3446 // Set the value. |
| 3457 __ mov(eax, ecx); | |
| 3458 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3447 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3459 __ ret(0); | 3448 __ ret(0); |
| 3460 } else { | 3449 } else { |
| 3461 __ SmiTag(eax); | 3450 __ SmiTag(eax); |
| 3462 __ ret(0); | 3451 __ ret(0); |
| 3463 } | 3452 } |
| 3464 | 3453 |
| 3465 // If we fail allocation of the HeapNumber, we still have a value on | 3454 // If we fail allocation of the HeapNumber, we still have a value on |
| 3466 // top of the FPU stack. Remove it. | 3455 // top of the FPU stack. Remove it. |
| 3467 __ bind(&failed_allocation); | 3456 __ bind(&failed_allocation); |
| 3468 __ fstp(0); | 3457 __ fstp(0); |
| 3469 // Fall through to slow case. | 3458 // Fall through to slow case. |
| 3470 | 3459 |
| 3471 // Slow case: Jump to runtime. | 3460 // Slow case: Jump to runtime. |
| 3472 __ bind(&slow); | 3461 __ bind(&slow); |
| 3473 Counters* counters = masm->isolate()->counters(); | 3462 Counters* counters = masm->isolate()->counters(); |
| 3474 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); | 3463 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
| 3475 | 3464 |
| 3476 // ----------- S t a t e ------------- | 3465 // ----------- S t a t e ------------- |
| 3477 // -- eax : key | 3466 // -- ecx : key |
| 3478 // -- edx : receiver | 3467 // -- edx : receiver |
| 3479 // -- esp[0] : return address | 3468 // -- esp[0] : return address |
| 3480 // ----------------------------------- | 3469 // ----------------------------------- |
| 3481 | 3470 |
| 3482 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); | 3471 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3483 __ jmp(ic, RelocInfo::CODE_TARGET); | 3472 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 3484 | 3473 |
| 3485 // ----------- S t a t e ------------- | 3474 // ----------- S t a t e ------------- |
| 3486 // -- eax : key | 3475 // -- ecx : key |
| 3487 // -- edx : receiver | 3476 // -- edx : receiver |
| 3488 // -- esp[0] : return address | 3477 // -- esp[0] : return address |
| 3489 // ----------------------------------- | 3478 // ----------------------------------- |
| 3490 | 3479 |
| 3491 // Miss case: Jump to runtime. | 3480 // Miss case: Jump to runtime. |
| 3492 __ bind(&miss_force_generic); | 3481 __ bind(&miss_force_generic); |
| 3493 Handle<Code> miss_ic = | 3482 Handle<Code> miss_ic = |
| 3494 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3483 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3495 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3484 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3496 } | 3485 } |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3690 | 3679 |
| 3691 __ bind(&miss_force_generic); | 3680 __ bind(&miss_force_generic); |
| 3692 Handle<Code> miss_ic = | 3681 Handle<Code> miss_ic = |
| 3693 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3682 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 3694 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3683 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3695 } | 3684 } |
| 3696 | 3685 |
| 3697 | 3686 |
| 3698 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { | 3687 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { |
| 3699 // ----------- S t a t e ------------- | 3688 // ----------- S t a t e ------------- |
| 3700 // -- eax : key | 3689 // -- ecx : key |
| 3701 // -- edx : receiver | 3690 // -- edx : receiver |
| 3702 // -- esp[0] : return address | 3691 // -- esp[0] : return address |
| 3703 // ----------------------------------- | 3692 // ----------------------------------- |
| 3704 Label miss_force_generic; | 3693 Label miss_force_generic; |
| 3705 | 3694 |
| 3706 // This stub is meant to be tail-jumped to, the receiver must already | 3695 // This stub is meant to be tail-jumped to, the receiver must already |
| 3707 // have been verified by the caller to not be a smi. | 3696 // have been verified by the caller to not be a smi. |
| 3708 | 3697 |
| 3709 // Check that the key is a smi or a heap number convertible to a smi. | 3698 // Check that the key is a smi or a heap number convertible to a smi. |
| 3710 GenerateSmiKeyCheck(masm, eax, ecx, xmm0, xmm1, &miss_force_generic); | 3699 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); |
| 3711 | 3700 |
| 3712 // Get the elements array. | 3701 // Get the elements array. |
| 3713 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3702 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
| 3714 __ AssertFastElements(ecx); | 3703 __ AssertFastElements(eax); |
| 3715 | 3704 |
| 3716 // Check that the key is within bounds. | 3705 // Check that the key is within bounds. |
| 3717 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3706 __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset)); |
| 3718 __ j(above_equal, &miss_force_generic); | 3707 __ j(above_equal, &miss_force_generic); |
| 3719 | 3708 |
| 3720 // Load the result and make sure it's not the hole. | 3709 // Load the result and make sure it's not the hole. |
| 3721 __ mov(ebx, Operand(ecx, eax, times_2, | 3710 __ mov(ebx, Operand(eax, ecx, times_2, |
| 3722 FixedArray::kHeaderSize - kHeapObjectTag)); | 3711 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3723 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); | 3712 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); |
| 3724 __ j(equal, &miss_force_generic); | 3713 __ j(equal, &miss_force_generic); |
| 3725 __ mov(eax, ebx); | 3714 __ mov(eax, ebx); |
| 3726 __ ret(0); | 3715 __ ret(0); |
| 3727 | 3716 |
| 3728 __ bind(&miss_force_generic); | 3717 __ bind(&miss_force_generic); |
| 3729 Handle<Code> miss_ic = | 3718 Handle<Code> miss_ic = |
| 3730 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3719 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3731 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3720 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3732 } | 3721 } |
| 3733 | 3722 |
| 3734 | 3723 |
| 3735 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | 3724 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( |
| 3736 MacroAssembler* masm) { | 3725 MacroAssembler* masm) { |
| 3737 // ----------- S t a t e ------------- | 3726 // ----------- S t a t e ------------- |
| 3738 // -- eax : key | 3727 // -- ecx : key |
| 3739 // -- edx : receiver | 3728 // -- edx : receiver |
| 3740 // -- esp[0] : return address | 3729 // -- esp[0] : return address |
| 3741 // ----------------------------------- | 3730 // ----------------------------------- |
| 3742 Label miss_force_generic, slow_allocate_heapnumber; | 3731 Label miss_force_generic, slow_allocate_heapnumber; |
| 3743 | 3732 |
| 3744 // This stub is meant to be tail-jumped to, the receiver must already | 3733 // This stub is meant to be tail-jumped to, the receiver must already |
| 3745 // have been verified by the caller to not be a smi. | 3734 // have been verified by the caller to not be a smi. |
| 3746 | 3735 |
| 3747 // Check that the key is a smi or a heap number convertible to a smi. | 3736 // Check that the key is a smi or a heap number convertible to a smi. |
| 3748 GenerateSmiKeyCheck(masm, eax, ecx, xmm0, xmm1, &miss_force_generic); | 3737 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); |
| 3749 | 3738 |
| 3750 // Get the elements array. | 3739 // Get the elements array. |
| 3751 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3740 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
| 3752 __ AssertFastElements(ecx); | 3741 __ AssertFastElements(eax); |
| 3753 | 3742 |
| 3754 // Check that the key is within bounds. | 3743 // Check that the key is within bounds. |
| 3755 __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); | 3744 __ cmp(ecx, FieldOperand(eax, FixedDoubleArray::kLengthOffset)); |
| 3756 __ j(above_equal, &miss_force_generic); | 3745 __ j(above_equal, &miss_force_generic); |
| 3757 | 3746 |
| 3758 // Check for the hole | 3747 // Check for the hole |
| 3759 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | 3748 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 3760 __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32)); | 3749 __ cmp(FieldOperand(eax, ecx, times_4, offset), Immediate(kHoleNanUpper32)); |
| 3761 __ j(equal, &miss_force_generic); | 3750 __ j(equal, &miss_force_generic); |
| 3762 | 3751 |
| 3763 // Always allocate a heap number for the result. | 3752 // Always allocate a heap number for the result. |
| 3764 if (CpuFeatures::IsSupported(SSE2)) { | 3753 if (CpuFeatures::IsSupported(SSE2)) { |
| 3765 CpuFeatures::Scope use_sse2(SSE2); | 3754 CpuFeatures::Scope use_sse2(SSE2); |
| 3766 __ movdbl(xmm0, FieldOperand(ecx, eax, times_4, | 3755 __ movdbl(xmm0, FieldOperand(eax, ecx, times_4, |
| 3767 FixedDoubleArray::kHeaderSize)); | 3756 FixedDoubleArray::kHeaderSize)); |
| 3768 } else { | 3757 } else { |
| 3769 __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize)); | 3758 __ fld_d(FieldOperand(eax, ecx, times_4, FixedDoubleArray::kHeaderSize)); |
| 3770 } | 3759 } |
| 3771 __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber); | 3760 __ AllocateHeapNumber(eax, ebx, edi, &slow_allocate_heapnumber); |
| 3772 // Set the value. | 3761 // Set the value. |
| 3773 if (CpuFeatures::IsSupported(SSE2)) { | 3762 if (CpuFeatures::IsSupported(SSE2)) { |
| 3774 CpuFeatures::Scope use_sse2(SSE2); | 3763 CpuFeatures::Scope use_sse2(SSE2); |
| 3775 __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); | 3764 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 3776 } else { | 3765 } else { |
| 3777 __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset)); | 3766 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3778 } | 3767 } |
| 3779 __ mov(eax, ecx); | |
| 3780 __ ret(0); | 3768 __ ret(0); |
| 3781 | 3769 |
| 3782 __ bind(&slow_allocate_heapnumber); | 3770 __ bind(&slow_allocate_heapnumber); |
| 3783 // A value was pushed on the floating point stack before the allocation, if | 3771 // A value was pushed on the floating point stack before the allocation, if |
| 3784 // the allocation fails it needs to be removed. | 3772 // the allocation fails it needs to be removed. |
| 3785 if (!CpuFeatures::IsSupported(SSE2)) { | 3773 if (!CpuFeatures::IsSupported(SSE2)) { |
| 3786 __ fstp(0); | 3774 __ fstp(0); |
| 3787 } | 3775 } |
| 3788 Handle<Code> slow_ic = | 3776 Handle<Code> slow_ic = |
| 3789 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | 3777 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4079 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4067 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
| 4080 } | 4068 } |
| 4081 } | 4069 } |
| 4082 | 4070 |
| 4083 | 4071 |
| 4084 #undef __ | 4072 #undef __ |
| 4085 | 4073 |
| 4086 } } // namespace v8::internal | 4074 } } // namespace v8::internal |
| 4087 | 4075 |
| 4088 #endif // V8_TARGET_ARCH_IA32 | 4076 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |