OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 2816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2827 StubFailureTrampolineFrameConstants::kArgumentsLengthOffset; | 2827 StubFailureTrampolineFrameConstants::kArgumentsLengthOffset; |
2828 __ mov(ebx, MemOperand(ebp, parameter_count_offset)); | 2828 __ mov(ebx, MemOperand(ebp, parameter_count_offset)); |
2829 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 2829 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
2830 __ pop(ecx); | 2830 __ pop(ecx); |
2831 int additional_offset = | 2831 int additional_offset = |
2832 function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; | 2832 function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; |
2833 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); | 2833 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); |
2834 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. | 2834 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. |
2835 } | 2835 } |
2836 | 2836 |
2837 static void HandleArrayCases(MacroAssembler* masm, Register receiver, | |
2838 Register key, Register vector, Register slot, | |
2839 Register feedback, bool is_polymorphic, | |
2840 Label* miss) { | |
2841 // feedback initially contains the feedback array | |
2842 Label next, next_loop, prepare_next; | |
2843 Label load_smi_map, compare_map; | |
2844 Label start_polymorphic; | |
2845 | |
2846 __ push(receiver); | |
2847 __ push(vector); | |
2848 | |
2849 Register receiver_map = receiver; | |
2850 Register cached_map = vector; | |
2851 | |
2852 // Receiver might not be a heap object. | |
2853 __ JumpIfSmi(receiver, &load_smi_map); | |
2854 __ mov(receiver_map, FieldOperand(receiver, 0)); | |
2855 __ bind(&compare_map); | |
2856 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); | |
2857 | |
2858 // A named keyed load might have a 2 element array, all other cases can count | |
2859 // on an array with at least 2 {map, handler} pairs, so they can go right | |
2860 // into polymorphic array handling. | |
2861 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | |
2862 __ j(not_equal, is_polymorphic ? &start_polymorphic : &next); | |
2863 | |
2864 // found, now call handler. | |
2865 Register handler = feedback; | |
2866 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); | |
2867 __ pop(vector); | |
2868 __ pop(receiver); | |
2869 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | |
2870 __ jmp(handler); | |
2871 | |
2872 if (!is_polymorphic) { | |
2873 __ bind(&next); | |
2874 __ cmp(FieldOperand(feedback, FixedArray::kLengthOffset), | |
2875 Immediate(Smi::FromInt(2))); | |
2876 __ j(not_equal, &start_polymorphic); | |
2877 __ pop(vector); | |
2878 __ pop(receiver); | |
2879 __ jmp(miss); | |
2880 } | |
2881 | |
2882 // Polymorphic, we have to loop from 2 to N | |
2883 __ bind(&start_polymorphic); | |
2884 __ push(key); | |
2885 Register counter = key; | |
2886 __ mov(counter, Immediate(Smi::FromInt(2))); | |
2887 __ bind(&next_loop); | |
2888 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | |
2889 FixedArray::kHeaderSize)); | |
2890 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | |
2891 __ j(not_equal, &prepare_next); | |
2892 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, | |
2893 FixedArray::kHeaderSize + kPointerSize)); | |
2894 __ pop(key); | |
2895 __ pop(vector); | |
2896 __ pop(receiver); | |
2897 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | |
2898 __ jmp(handler); | |
2899 | |
2900 __ bind(&prepare_next); | |
2901 __ add(counter, Immediate(Smi::FromInt(2))); | |
2902 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | |
2903 __ j(less, &next_loop); | |
2904 | |
2905 // We exhausted our array of map handler pairs. | |
2906 __ pop(key); | |
2907 __ pop(vector); | |
2908 __ pop(receiver); | |
2909 __ jmp(miss); | |
2910 | |
2911 __ bind(&load_smi_map); | |
2912 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | |
2913 __ jmp(&compare_map); | |
2914 } | |
2915 | |
2916 | |
2917 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver, | |
2918 Register key, Register vector, Register slot, | |
2919 Register weak_cell, Label* miss) { | |
2920 // feedback initially contains the feedback array | |
2921 Label compare_smi_map; | |
2922 | |
2923 // Move the weak map into the weak_cell register. | |
2924 Register ic_map = weak_cell; | |
2925 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); | |
2926 | |
2927 // Receiver might not be a heap object. | |
2928 __ JumpIfSmi(receiver, &compare_smi_map); | |
2929 __ cmp(ic_map, FieldOperand(receiver, 0)); | |
2930 __ j(not_equal, miss); | |
2931 Register handler = weak_cell; | |
2932 __ mov(handler, FieldOperand(vector, slot, times_half_pointer_size, | |
2933 FixedArray::kHeaderSize + kPointerSize)); | |
2934 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | |
2935 __ jmp(handler); | |
2936 | |
2937 // In microbenchmarks, it made sense to unroll this code so that the call to | |
2938 // the handler is duplicated for a HeapObject receiver and a Smi receiver. | |
2939 __ bind(&compare_smi_map); | |
2940 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); | |
2941 __ j(not_equal, miss); | |
2942 __ mov(handler, FieldOperand(vector, slot, times_half_pointer_size, | |
2943 FixedArray::kHeaderSize + kPointerSize)); | |
2944 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | |
2945 __ jmp(handler); | |
2946 } | |
2947 | |
2948 void KeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) { | 2837 void KeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) { |
2949 __ EmitLoadTypeFeedbackVector(StoreWithVectorDescriptor::VectorRegister()); | 2838 __ EmitLoadTypeFeedbackVector(StoreWithVectorDescriptor::VectorRegister()); |
2950 KeyedStoreICStub stub(isolate(), state()); | 2839 KeyedStoreICStub stub(isolate(), state()); |
2951 stub.GenerateForTrampoline(masm); | 2840 stub.GenerateForTrampoline(masm); |
2952 } | 2841 } |
2953 | 2842 |
2954 // value is on the stack already. | 2843 // value is on the stack already. |
2955 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, | 2844 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
2956 Register key, Register vector, | 2845 Register key, Register vector, |
2957 Register slot, Register feedback, | 2846 Register slot, Register feedback, |
(...skipping 1705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4663 kStackUnwindSpace, nullptr, return_value_operand, | 4552 kStackUnwindSpace, nullptr, return_value_operand, |
4664 NULL); | 4553 NULL); |
4665 } | 4554 } |
4666 | 4555 |
4667 #undef __ | 4556 #undef __ |
4668 | 4557 |
4669 } // namespace internal | 4558 } // namespace internal |
4670 } // namespace v8 | 4559 } // namespace v8 |
4671 | 4560 |
4672 #endif // V8_TARGET_ARCH_X87 | 4561 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |