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