OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 2959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2970 receiver_map, if_handler, var_handler, &miss); | 2970 receiver_map, if_handler, var_handler, &miss); |
2971 } | 2971 } |
2972 | 2972 |
2973 Bind(&miss); | 2973 Bind(&miss); |
2974 { | 2974 { |
2975 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 2975 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
2976 Goto(if_miss); | 2976 Goto(if_miss); |
2977 } | 2977 } |
2978 } | 2978 } |
2979 | 2979 |
2980 void CodeStubAssembler::HaveLoadICHandler(const LoadICParameters* p, | |
2981 Node* handler) { | |
2982 Comment("have_handler"); | |
2983 Label call_handler(this); | |
2984 GotoUnless(WordIsSmi(handler), &call_handler); | |
2985 | |
2986 // |handler| is a Smi. It encodes a field index as obtained by | |
2987 // FieldIndex.GetLoadByFieldOffset(). | |
2988 // TODO(jkummerow): For KeyedLoadICs, extend this scheme to encode | |
2989 // fast *element* loads. | |
2990 { | |
2991 Label inobject_double(this), out_of_object(this), | |
2992 out_of_object_double(this); | |
2993 Variable var_double_value(this, MachineRepresentation::kFloat64); | |
2994 Label rebox_double(this, &var_double_value); | |
2995 | |
2996 Node* handler_word = SmiUntag(handler); | |
2997 // |handler_word| is a field index as obtained by | |
2998 // FieldIndex.GetLoadByFieldOffset(): | |
2999 // (offset << 3) | (is_double << 2) | (is_inobject << 1) | 1. | |
3000 Label inobject_double(this), out_of_object(this), | |
Jakob Kummerow
2016/07/26 14:43:28
Disregard these label redeclarations; editing mist
Igor Sheludko
2016/07/26 16:25:11
Acknowledged.
| |
3001 out_of_object_double(this); | |
3002 Node* inobject_bit = WordAnd(handler_word, IntPtrConstant(1 << 1)); | |
Igor Sheludko
2016/07/26 16:25:11
It would be nice to have respective constants in F
Jakob Kummerow
2016/07/26 17:10:39
Done.
| |
3003 Node* double_bit = WordAnd(handler_word, IntPtrConstant(1 << 2)); | |
3004 Node* offset = WordSar(handler_word, IntPtrConstant(3)); | |
3005 | |
3006 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); | |
3007 | |
3008 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); | |
3009 Return(LoadObjectField(p->receiver, offset)); | |
3010 | |
3011 Bind(&inobject_double); | |
3012 if (FLAG_unbox_double_fields) { | |
3013 var_double_value.Bind( | |
3014 LoadObjectField(p->receiver, offset, MachineType::Float64())); | |
3015 } else { | |
3016 Node* mutable_heap_number = LoadObjectField(p->receiver, offset); | |
3017 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | |
3018 } | |
3019 Goto(&rebox_double); | |
3020 | |
3021 Bind(&out_of_object); | |
3022 Node* properties = LoadProperties(p->receiver); | |
3023 Node* value = LoadObjectField(properties, offset); | |
3024 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); | |
3025 Return(value); | |
3026 | |
3027 Bind(&out_of_object_double); | |
3028 var_double_value.Bind(LoadHeapNumberValue(value)); | |
3029 Goto(&rebox_double); | |
3030 | |
3031 Bind(&rebox_double); | |
3032 Return(AllocateHeapNumberWithValue(var_double_value.value())); | |
3033 } | |
3034 | |
3035 // |handler| is a heap object. Must be code, call it. | |
3036 Bind(&call_handler); | |
3037 LoadWithVectorDescriptor descriptor(isolate()); | |
3038 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot, | |
3039 p->vector); | |
3040 } | |
3041 | |
2980 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { | 3042 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
2981 Variable var_handler(this, MachineRepresentation::kTagged); | 3043 Variable var_handler(this, MachineRepresentation::kTagged); |
2982 // TODO(ishell): defer blocks when it works. | 3044 // TODO(ishell): defer blocks when it works. |
2983 Label if_handler(this, &var_handler), try_polymorphic(this), | 3045 Label if_handler(this, &var_handler), try_polymorphic(this), |
2984 try_megamorphic(this /*, Label::kDeferred*/), | 3046 try_megamorphic(this /*, Label::kDeferred*/), |
2985 miss(this /*, Label::kDeferred*/); | 3047 miss(this /*, Label::kDeferred*/); |
2986 | 3048 |
2987 Node* receiver_map = LoadReceiverMap(p->receiver); | 3049 Node* receiver_map = LoadReceiverMap(p->receiver); |
2988 | 3050 |
2989 // Check monomorphic case. | 3051 // Check monomorphic case. |
2990 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, | 3052 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, |
2991 &var_handler, &try_polymorphic); | 3053 &var_handler, &try_polymorphic); |
2992 Bind(&if_handler); | 3054 Bind(&if_handler); |
2993 { | 3055 { |
2994 Comment("LoadIC_if_handler"); | 3056 HaveLoadICHandler(p, var_handler.value()); |
2995 Label call_handler(this); | |
2996 Node* handler = var_handler.value(); | |
2997 GotoUnless(WordIsSmi(handler), &call_handler); | |
2998 | |
2999 // |handler| is a Smi. It encodes a field index as obtained by | |
3000 // FieldIndex.GetLoadByFieldOffset(). | |
3001 { | |
3002 Label inobject_double(this), out_of_object(this), | |
3003 out_of_object_double(this); | |
3004 Variable var_double_value(this, MachineRepresentation::kFloat64); | |
3005 Label rebox_double(this, &var_double_value); | |
3006 | |
3007 Node* handler_word = SmiToWord32(handler); | |
3008 // handler == (offset << 1) | is_double. | |
3009 Node* double_bit = Word32And(handler_word, Int32Constant(1)); | |
3010 Node* offset = Word32Sar(handler_word, Int32Constant(1)); | |
3011 | |
3012 // Negative index -> out of object. | |
3013 GotoIf(Int32LessThan(offset, Int32Constant(0)), &out_of_object); | |
3014 | |
3015 Node* offset_ptr = ChangeInt32ToIntPtr(offset); | |
3016 GotoUnless(Word32Equal(double_bit, Int32Constant(0)), &inobject_double); | |
3017 Return(LoadObjectField(p->receiver, offset_ptr)); | |
3018 | |
3019 Bind(&inobject_double); | |
3020 if (FLAG_unbox_double_fields) { | |
3021 var_double_value.Bind( | |
3022 LoadObjectField(p->receiver, offset_ptr, MachineType::Float64())); | |
3023 } else { | |
3024 Node* mutable_heap_number = LoadObjectField(p->receiver, offset_ptr); | |
3025 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | |
3026 } | |
3027 Goto(&rebox_double); | |
3028 | |
3029 Bind(&out_of_object); | |
3030 // |offset| == -actual_offset | |
3031 offset_ptr = ChangeInt32ToIntPtr(Int32Sub(Int32Constant(0), offset)); | |
3032 Node* properties = LoadProperties(p->receiver); | |
3033 Node* value = LoadObjectField(properties, offset_ptr); | |
3034 GotoUnless(Word32Equal(double_bit, Int32Constant(0)), | |
3035 &out_of_object_double); | |
3036 Return(value); | |
3037 | |
3038 Bind(&out_of_object_double); | |
3039 var_double_value.Bind(LoadHeapNumberValue(value)); | |
3040 Goto(&rebox_double); | |
3041 | |
3042 Bind(&rebox_double); | |
3043 Return(AllocateHeapNumberWithValue(var_double_value.value())); | |
3044 } | |
3045 | |
3046 // |handler| is a heap object. Must be code, call it. | |
3047 Bind(&call_handler); | |
3048 LoadWithVectorDescriptor descriptor(isolate()); | |
3049 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot, | |
3050 p->vector); | |
3051 } | 3057 } |
3052 | 3058 |
3053 Bind(&try_polymorphic); | 3059 Bind(&try_polymorphic); |
3054 { | 3060 { |
3055 // Check polymorphic case. | 3061 // Check polymorphic case. |
3056 Comment("LoadIC_try_polymorphic"); | 3062 Comment("LoadIC_try_polymorphic"); |
3057 GotoUnless( | 3063 GotoUnless( |
3058 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 3064 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
3059 &try_megamorphic); | 3065 &try_megamorphic); |
3060 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, | 3066 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3178 // For all objects but the receiver, check that the cache is empty. | 3184 // For all objects but the receiver, check that the cache is empty. |
3179 current_map.Bind(LoadMap(current_js_object.value())); | 3185 current_map.Bind(LoadMap(current_js_object.value())); |
3180 Node* enum_length = EnumLength(current_map.value()); | 3186 Node* enum_length = EnumLength(current_map.value()); |
3181 Node* zero_constant = SmiConstant(Smi::FromInt(0)); | 3187 Node* zero_constant = SmiConstant(Smi::FromInt(0)); |
3182 BranchIf(WordEqual(enum_length, zero_constant), &loop, use_runtime); | 3188 BranchIf(WordEqual(enum_length, zero_constant), &loop, use_runtime); |
3183 } | 3189 } |
3184 } | 3190 } |
3185 | 3191 |
3186 } // namespace internal | 3192 } // namespace internal |
3187 } // namespace v8 | 3193 } // namespace v8 |
OLD | NEW |