OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
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/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 2962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2973 // Return to IC Miss stub, continuation still on stack. | 2973 // Return to IC Miss stub, continuation still on stack. |
2974 __ Ret(); | 2974 __ Ret(); |
2975 } | 2975 } |
2976 | 2976 |
2977 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 2977 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
2978 __ EmitLoadTypeFeedbackVector(x2); | 2978 __ EmitLoadTypeFeedbackVector(x2); |
2979 CallICStub stub(isolate(), state()); | 2979 CallICStub stub(isolate(), state()); |
2980 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 2980 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
2981 } | 2981 } |
2982 | 2982 |
2983 | |
2984 static void HandleArrayCases(MacroAssembler* masm, Register feedback, | |
2985 Register receiver_map, Register scratch1, | |
2986 Register scratch2, bool is_polymorphic, | |
2987 Label* miss) { | |
2988 // feedback initially contains the feedback array | |
2989 Label next_loop, prepare_next; | |
2990 Label load_smi_map, compare_map; | |
2991 Label start_polymorphic; | |
2992 | |
2993 Register cached_map = scratch1; | |
2994 | |
2995 __ Ldr(cached_map, | |
2996 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(0))); | |
2997 __ Ldr(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); | |
2998 __ Cmp(receiver_map, cached_map); | |
2999 __ B(ne, &start_polymorphic); | |
3000 // found, now call handler. | |
3001 Register handler = feedback; | |
3002 __ Ldr(handler, FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(1))); | |
3003 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); | |
3004 __ Jump(feedback); | |
3005 | |
3006 Register length = scratch2; | |
3007 __ Bind(&start_polymorphic); | |
3008 __ Ldr(length, FieldMemOperand(feedback, FixedArray::kLengthOffset)); | |
3009 if (!is_polymorphic) { | |
3010 __ Cmp(length, Operand(Smi::FromInt(2))); | |
3011 __ B(eq, miss); | |
3012 } | |
3013 | |
3014 Register too_far = length; | |
3015 Register pointer_reg = feedback; | |
3016 | |
3017 // +-----+------+------+-----+-----+ ... ----+ | |
3018 // | map | len | wm0 | h0 | wm1 | hN | | |
3019 // +-----+------+------+-----+-----+ ... ----+ | |
3020 // 0 1 2 len-1 | |
3021 // ^ ^ | |
3022 // | | | |
3023 // pointer_reg too_far | |
3024 // aka feedback scratch2 | |
3025 // also need receiver_map | |
3026 // use cached_map (scratch1) to look in the weak map values. | |
3027 __ Add(too_far, feedback, | |
3028 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | |
3029 __ Add(too_far, too_far, FixedArray::kHeaderSize - kHeapObjectTag); | |
3030 __ Add(pointer_reg, feedback, | |
3031 FixedArray::OffsetOfElementAt(2) - kHeapObjectTag); | |
3032 | |
3033 __ Bind(&next_loop); | |
3034 __ Ldr(cached_map, MemOperand(pointer_reg)); | |
3035 __ Ldr(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); | |
3036 __ Cmp(receiver_map, cached_map); | |
3037 __ B(ne, &prepare_next); | |
3038 __ Ldr(handler, MemOperand(pointer_reg, kPointerSize)); | |
3039 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); | |
3040 __ Jump(handler); | |
3041 | |
3042 __ Bind(&prepare_next); | |
3043 __ Add(pointer_reg, pointer_reg, kPointerSize * 2); | |
3044 __ Cmp(pointer_reg, too_far); | |
3045 __ B(lt, &next_loop); | |
3046 | |
3047 // We exhausted our array of map handler pairs. | |
3048 __ jmp(miss); | |
3049 } | |
3050 | |
3051 | |
3052 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver, | |
3053 Register receiver_map, Register feedback, | |
3054 Register vector, Register slot, | |
3055 Register scratch, Label* compare_map, | |
3056 Label* load_smi_map, Label* try_array) { | |
3057 __ JumpIfSmi(receiver, load_smi_map); | |
3058 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
3059 __ bind(compare_map); | |
3060 Register cached_map = scratch; | |
3061 // Move the weak map into the weak_cell register. | |
3062 __ Ldr(cached_map, FieldMemOperand(feedback, WeakCell::kValueOffset)); | |
3063 __ Cmp(cached_map, receiver_map); | |
3064 __ B(ne, try_array); | |
3065 | |
3066 Register handler = feedback; | |
3067 __ Add(handler, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); | |
3068 __ Ldr(handler, | |
3069 FieldMemOperand(handler, FixedArray::kHeaderSize + kPointerSize)); | |
3070 __ Add(handler, handler, Code::kHeaderSize - kHeapObjectTag); | |
3071 __ Jump(handler); | |
3072 } | |
3073 | |
3074 void KeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) { | |
3075 __ EmitLoadTypeFeedbackVector(StoreWithVectorDescriptor::VectorRegister()); | |
3076 KeyedStoreICStub stub(isolate(), state()); | |
3077 stub.GenerateForTrampoline(masm); | |
3078 } | |
3079 | |
3080 void KeyedStoreICStub::Generate(MacroAssembler* masm) { | |
3081 GenerateImpl(masm, false); | |
3082 } | |
3083 | |
3084 void KeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | |
3085 GenerateImpl(masm, true); | |
3086 } | |
3087 | |
3088 | |
3089 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register feedback, | |
3090 Register receiver_map, Register scratch1, | |
3091 Register scratch2, Label* miss) { | |
3092 // feedback initially contains the feedback array | |
3093 Label next_loop, prepare_next; | |
3094 Label start_polymorphic; | |
3095 Label transition_call; | |
3096 | |
3097 Register cached_map = scratch1; | |
3098 Register too_far = scratch2; | |
3099 Register pointer_reg = feedback; | |
3100 | |
3101 __ Ldr(too_far, FieldMemOperand(feedback, FixedArray::kLengthOffset)); | |
3102 | |
3103 // +-----+------+------+-----+-----+-----+ ... ----+ | |
3104 // | map | len | wm0 | wt0 | h0 | wm1 | hN | | |
3105 // +-----+------+------+-----+-----+ ----+ ... ----+ | |
3106 // 0 1 2 len-1 | |
3107 // ^ ^ | |
3108 // | | | |
3109 // pointer_reg too_far | |
3110 // aka feedback scratch2 | |
3111 // also need receiver_map | |
3112 // use cached_map (scratch1) to look in the weak map values. | |
3113 __ Add(too_far, feedback, | |
3114 Operand::UntagSmiAndScale(too_far, kPointerSizeLog2)); | |
3115 __ Add(too_far, too_far, FixedArray::kHeaderSize - kHeapObjectTag); | |
3116 __ Add(pointer_reg, feedback, | |
3117 FixedArray::OffsetOfElementAt(0) - kHeapObjectTag); | |
3118 | |
3119 __ Bind(&next_loop); | |
3120 __ Ldr(cached_map, MemOperand(pointer_reg)); | |
3121 __ Ldr(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); | |
3122 __ Cmp(receiver_map, cached_map); | |
3123 __ B(ne, &prepare_next); | |
3124 // Is it a transitioning store? | |
3125 __ Ldr(too_far, MemOperand(pointer_reg, kPointerSize)); | |
3126 __ CompareRoot(too_far, Heap::kUndefinedValueRootIndex); | |
3127 __ B(ne, &transition_call); | |
3128 | |
3129 __ Ldr(pointer_reg, MemOperand(pointer_reg, kPointerSize * 2)); | |
3130 __ Add(pointer_reg, pointer_reg, Code::kHeaderSize - kHeapObjectTag); | |
3131 __ Jump(pointer_reg); | |
3132 | |
3133 __ Bind(&transition_call); | |
3134 __ Ldr(too_far, FieldMemOperand(too_far, WeakCell::kValueOffset)); | |
3135 __ JumpIfSmi(too_far, miss); | |
3136 | |
3137 __ Ldr(receiver_map, MemOperand(pointer_reg, kPointerSize * 2)); | |
3138 // Load the map into the correct register. | |
3139 DCHECK(feedback.is(StoreTransitionDescriptor::MapRegister())); | |
3140 __ mov(feedback, too_far); | |
3141 __ Add(receiver_map, receiver_map, Code::kHeaderSize - kHeapObjectTag); | |
3142 __ Jump(receiver_map); | |
3143 | |
3144 __ Bind(&prepare_next); | |
3145 __ Add(pointer_reg, pointer_reg, kPointerSize * 3); | |
3146 __ Cmp(pointer_reg, too_far); | |
3147 __ B(lt, &next_loop); | |
3148 | |
3149 // We exhausted our array of map handler pairs. | |
3150 __ jmp(miss); | |
3151 } | |
3152 | |
3153 void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | |
3154 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // x1 | |
3155 Register key = StoreWithVectorDescriptor::NameRegister(); // x2 | |
3156 Register vector = StoreWithVectorDescriptor::VectorRegister(); // x3 | |
3157 Register slot = StoreWithVectorDescriptor::SlotRegister(); // x4 | |
3158 DCHECK(StoreWithVectorDescriptor::ValueRegister().is(x0)); // x0 | |
3159 Register feedback = x5; | |
3160 Register receiver_map = x6; | |
3161 Register scratch1 = x7; | |
3162 | |
3163 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); | |
3164 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); | |
3165 | |
3166 // Try to quickly handle the monomorphic case without knowing for sure | |
3167 // if we have a weak cell in feedback. We do know it's safe to look | |
3168 // at WeakCell::kValueOffset. | |
3169 Label try_array, load_smi_map, compare_map; | |
3170 Label not_array, miss; | |
3171 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, | |
3172 scratch1, &compare_map, &load_smi_map, &try_array); | |
3173 | |
3174 __ Bind(&try_array); | |
3175 // Is it a fixed array? | |
3176 __ Ldr(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); | |
3177 __ JumpIfNotRoot(scratch1, Heap::kFixedArrayMapRootIndex, ¬_array); | |
3178 | |
3179 // We have a polymorphic element handler. | |
3180 Label try_poly_name; | |
3181 HandlePolymorphicStoreCase(masm, feedback, receiver_map, scratch1, x8, &miss); | |
3182 | |
3183 __ Bind(¬_array); | |
3184 // Is it generic? | |
3185 __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, | |
3186 &try_poly_name); | |
3187 Handle<Code> megamorphic_stub = | |
3188 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); | |
3189 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); | |
3190 | |
3191 __ Bind(&try_poly_name); | |
3192 // We might have a name in feedback, and a fixed array in the next slot. | |
3193 __ Cmp(key, feedback); | |
3194 __ B(ne, &miss); | |
3195 // If the name comparison succeeded, we know we have a fixed array with | |
3196 // at least one map/handler pair. | |
3197 __ Add(feedback, vector, Operand::UntagSmiAndScale(slot, kPointerSizeLog2)); | |
3198 __ Ldr(feedback, | |
3199 FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); | |
3200 HandleArrayCases(masm, feedback, receiver_map, scratch1, x8, false, &miss); | |
3201 | |
3202 __ Bind(&miss); | |
3203 KeyedStoreIC::GenerateMiss(masm); | |
3204 | |
3205 __ Bind(&load_smi_map); | |
3206 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | |
3207 __ jmp(&compare_map); | |
3208 } | |
3209 | |
3210 | |
3211 // The entry hook is a "BumpSystemStackPointer" instruction (sub), followed by | 2983 // The entry hook is a "BumpSystemStackPointer" instruction (sub), followed by |
3212 // a "Push lr" instruction, followed by a call. | 2984 // a "Push lr" instruction, followed by a call. |
3213 static const unsigned int kProfileEntryHookCallSize = | 2985 static const unsigned int kProfileEntryHookCallSize = |
3214 Assembler::kCallSizeWithRelocation + (2 * kInstructionSize); | 2986 Assembler::kCallSizeWithRelocation + (2 * kInstructionSize); |
3215 | 2987 |
3216 | 2988 |
3217 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 2989 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
3218 if (masm->isolate()->function_entry_hook() != NULL) { | 2990 if (masm->isolate()->function_entry_hook() != NULL) { |
3219 ProfileEntryHookStub stub(masm->isolate()); | 2991 ProfileEntryHookStub stub(masm->isolate()); |
3220 Assembler::BlockConstPoolScope no_const_pools(masm); | 2992 Assembler::BlockConstPoolScope no_const_pools(masm); |
(...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4912 kStackUnwindSpace, NULL, spill_offset, | 4684 kStackUnwindSpace, NULL, spill_offset, |
4913 return_value_operand, NULL); | 4685 return_value_operand, NULL); |
4914 } | 4686 } |
4915 | 4687 |
4916 #undef __ | 4688 #undef __ |
4917 | 4689 |
4918 } // namespace internal | 4690 } // namespace internal |
4919 } // namespace v8 | 4691 } // namespace v8 |
4920 | 4692 |
4921 #endif // V8_TARGET_ARCH_ARM64 | 4693 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |