Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2180273002: [KeyedLoadIC] Support Smi "handlers" for element loads (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@keyed-load-ic-fieldindex
Patch Set: rebased Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/handler-compiler.h"
9 #include "src/ic/stub-cache.h" 10 #include "src/ic/stub-cache.h"
10 11
11 namespace v8 { 12 namespace v8 {
12 namespace internal { 13 namespace internal {
13 14
14 using compiler::Node; 15 using compiler::Node;
15 16
16 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone, 17 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
17 const CallInterfaceDescriptor& descriptor, 18 const CallInterfaceDescriptor& descriptor,
18 Code::Flags flags, const char* name, 19 Code::Flags flags, const char* name,
(...skipping 2951 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 receiver_map, if_handler, var_handler, &miss); 2971 receiver_map, if_handler, var_handler, &miss);
2971 } 2972 }
2972 2973
2973 Bind(&miss); 2974 Bind(&miss);
2974 { 2975 {
2975 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); 2976 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
2976 Goto(if_miss); 2977 Goto(if_miss);
2977 } 2978 }
2978 } 2979 }
2979 2980
2980 void CodeStubAssembler::HandleLoadICHandlerCase(const LoadICParameters* p, 2981 void CodeStubAssembler::HandleLoadICHandlerCase(
2981 Node* handler, Label* miss) { 2982 const LoadICParameters* p, Node* handler, Label* miss,
2983 ElementSupport support_elements) {
2982 Comment("have_handler"); 2984 Comment("have_handler");
2983 Label call_handler(this); 2985 Label call_handler(this);
2984 GotoUnless(WordIsSmi(handler), &call_handler); 2986 GotoUnless(WordIsSmi(handler), &call_handler);
2985 2987
2986 // |handler| is a Smi. It encodes a field index as obtained by 2988 // |handler| is a Smi, encoding what to do. The last bit distinguishes
2987 // FieldIndex.GetLoadByFieldOffset(). 2989 // element and property loads.
2988 // TODO(jkummerow): For KeyedLoadICs, extend this scheme to encode
2989 // fast *element* loads.
2990 { 2990 {
2991 Variable var_double_value(this, MachineRepresentation::kFloat64); 2991 Variable var_double_value(this, MachineRepresentation::kFloat64);
2992 Label rebox_double(this, &var_double_value); 2992 Label rebox_double(this, &var_double_value);
2993 2993
2994 Node* handler_word = SmiUntag(handler); 2994 Node* handler_word = SmiUntag(handler);
2995 if (support_elements == kSupportElements) {
Igor Sheludko 2016/07/28 10:01:11 I think this new code (and maybe the property case
Jakob Kummerow 2016/08/03 11:44:11 Done (did some splitting, though not exactly here)
2996 Variable var_length(this, MachineRepresentation::kTagged);
2997 Label property(this), is_array(this), length_loaded(this, &var_length);
2998 Node* is_element_bit = WordAnd(handler_word, IntPtrConstant(1));
Igor Sheludko 2016/07/28 10:01:11 It would be nice to have such a SmiHandlerIsProper
Jakob Kummerow 2016/08/03 11:44:09 Done.
2999 GotoUnless(WordEqual(is_element_bit, IntPtrConstant(0)), &property);
3000
3001 Comment("element_load");
3002 GotoUnless(WordIsSmi(p->name), miss);
Igor Sheludko 2016/07/28 10:01:11 Future improvement: support "123"-like unique stri
Jakob Kummerow 2016/08/03 11:44:09 Possibly, yes. That change would have to be made i
3003 Node* key = SmiUntag(p->name);
3004 Node* elements = LoadElements(p->receiver);
3005 Node* is_jsarray = WordAnd(
3006 handler_word,
3007 IntPtrConstant(ElementHandlerCompiler::KeyedLoadIsJsarray::kMask));
3008 GotoUnless(WordEqual(is_jsarray, IntPtrConstant(0)), &is_array);
3009 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
3010 Goto(&length_loaded);
3011 Bind(&is_array);
Igor Sheludko 2016/07/28 10:01:11 Consider wrapping blocks in {} for readability.
Jakob Kummerow 2016/08/03 11:44:09 Done.
3012 var_length.Bind(
3013 SmiUntag(LoadObjectField(p->receiver, JSArray::kLengthOffset)));
3014 Goto(&length_loaded);
3015
3016 Bind(&length_loaded);
Igor Sheludko 2016/07/28 10:01:11 Same here.
Jakob Kummerow 2016/08/03 11:44:12 Done.
3017 // Bounds check.
3018 GotoUnless(UintPtrLessThan(key, var_length.value()), miss);
3019 Node* convert_hole = WordAnd(
Igor Sheludko 2016/07/28 10:01:11 You can probably move this to if_hole block althou
Jakob Kummerow 2016/08/03 11:44:11 Done.
3020 handler_word,
3021 IntPtrConstant(ElementHandlerCompiler::KeyedLoadConvertHole::kMask));
3022 Node* elements_kind =
3023 WordShr(handler_word,
3024 IntPtrConstant(
3025 ElementHandlerCompiler::KeyedLoadElementsKind::kShift));
3026
3027 Label typed_array(this), fast_packed(this), fast_holey(this),
Igor Sheludko 2016/07/28 10:01:10 As far as I understand we have a kind of naming co
Jakob Kummerow 2016/08/03 11:44:11 Done.
3028 fast_double(this), fast_holey_double(this), hole(this);
Igor Sheludko 2016/07/28 10:01:11 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYP
Jakob Kummerow 2016/08/03 11:44:11 Done.
3029 GotoIf(IntPtrGreaterThanOrEqual(
3030 elements_kind,
3031 IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
3032 &typed_array);
3033 #define JUMP_IF_KIND(kind, label) \
3034 GotoIf(WordEqual(elements_kind, IntPtrConstant(kind)), label);
Igor Sheludko 2016/07/28 10:01:10 It looks like a switch construct will fit better h
Jakob Kummerow 2016/08/03 11:44:09 Done.
3035
3036 JUMP_IF_KIND(FAST_SMI_ELEMENTS, &fast_packed);
3037 JUMP_IF_KIND(FAST_ELEMENTS, &fast_packed);
3038 JUMP_IF_KIND(FAST_HOLEY_SMI_ELEMENTS, &fast_holey);
3039 JUMP_IF_KIND(FAST_HOLEY_ELEMENTS, &fast_holey);
3040 JUMP_IF_KIND(FAST_DOUBLE_ELEMENTS, &fast_double);
3041 JUMP_IF_KIND(FAST_HOLEY_DOUBLE_ELEMENTS, &fast_holey_double);
3042 // All other kinds are unimplemented.
3043 DebugBreak();
Igor Sheludko 2016/07/28 10:01:11 ?
Jakob Kummerow 2016/08/03 11:44:11 I want to crash if we get here. Think "UNREACHABLE
3044 Goto(miss);
3045 #undef JUMP_IF_KIND
3046
3047 Bind(&fast_packed);
3048 Comment("fast packed elements");
Igor Sheludko 2016/07/28 10:01:11 Consider wrapping blocks in {} for readability.
Jakob Kummerow 2016/08/03 11:44:11 Done.
3049 // TODO(jkummerow): The Load*Element helpers add movsxlq instructions
3050 // on x64 which we don't need here, because |key| is an IntPtr already.
3051 // Do something about that.
Igor Sheludko 2016/07/28 10:01:10 We just need to introduce INTPTR_PARAMETERS mode.
Jakob Kummerow 2016/08/03 11:44:09 Yes, that's what I was thinking too. Follow-up CL.
3052 Return(LoadFixedArrayElement(elements, key));
3053
3054 Bind(&fast_holey);
3055 {
3056 Comment("fast holey elements");
3057 Node* element = LoadFixedArrayElement(elements, key);
3058 GotoIf(WordEqual(element, TheHoleConstant()), &hole);
3059 Return(element);
3060 }
3061
3062 Bind(&fast_double);
3063 Comment("packed double elements");
Igor Sheludko 2016/07/28 10:01:11 Same here.
Jakob Kummerow 2016/08/03 11:44:09 Done.
3064 var_double_value.Bind(
3065 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64()));
3066 Goto(&rebox_double);
3067
3068 Bind(&fast_holey_double);
3069 {
3070 Comment("holey double elements");
3071 if (kPointerSize == kDoubleSize) {
3072 Node* raw_element =
3073 LoadFixedDoubleArrayElement(elements, key, MachineType::Uint64());
3074 Node* the_hole = Int64Constant(kHoleNanInt64);
3075 GotoIf(Word64Equal(raw_element, the_hole), &hole);
3076 } else {
3077 Node* element_upper =
3078 LoadFixedDoubleArrayElement(elements, key, MachineType::Uint32(),
3079 kIeeeDoubleExponentWordOffset);
3080 GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
3081 &hole);
3082 }
3083 var_double_value.Bind(
3084 LoadFixedDoubleArrayElement(elements, key, MachineType::Float64()));
3085 Goto(&rebox_double);
3086 }
3087
3088 Bind(&hole);
3089 {
3090 Comment("convert hole");
3091 GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss);
3092 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
3093 GotoUnless(
3094 WordEqual(LoadObjectField(protector_cell, Cell::kValueOffset),
3095 SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))),
3096 miss);
3097 Return(UndefinedConstant());
3098 }
3099
3100 Bind(&typed_array);
Igor Sheludko 2016/07/28 10:01:11 And here.
Jakob Kummerow 2016/08/03 11:44:09 Done.
3101 Comment("typed elements");
3102 // Check if buffer has been neutered.
3103 Node* buffer =
3104 LoadObjectField(p->receiver, JSArrayBufferView::kBufferOffset);
3105 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset,
3106 MachineType::Uint32());
3107 Node* neutered_bit = Word32And(
3108 bitfield, Int32Constant(1 << JSArrayBuffer::WasNeutered::kShift));
Igor Sheludko 2016/07/28 10:01:11 JSArrayBuffer::WasNeutered::kMask?
Jakob Kummerow 2016/08/03 11:44:09 Done.
3109 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss);
3110 // Backing store = external_pointer + base_pointer.
3111 Node* external_pointer =
3112 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
3113 MachineType::Pointer());
3114 Node* base_pointer =
3115 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
3116 Node* backing_store = IntPtrAdd(external_pointer, base_pointer);
3117
3118 const int kTypedElementsKindCount =
3119 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
3120 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
3121 Label* elements_kind_labels[kTypedElementsKindCount];
3122 int32_t elements_kinds[kTypedElementsKindCount];
3123 for (int i = 0; i < kTypedElementsKindCount; i++) {
3124 elements_kinds[i] = i + FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
3125 elements_kind_labels[i] = new Label(this);
3126 }
3127 Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
3128 static_cast<size_t>(kTypedElementsKindCount));
3129
3130 for (int i = 0; i < kTypedElementsKindCount; i++) {
3131 ElementsKind kind = static_cast<ElementsKind>(elements_kinds[i]);
3132 Bind(elements_kind_labels[i]);
3133 Comment(ElementsKindToString(kind));
3134 switch (kind) {
3135 case UINT8_ELEMENTS:
3136 case UINT8_CLAMPED_ELEMENTS:
3137 Return(SmiTag(Load(MachineType::Uint8(), backing_store, key)));
3138 break;
3139 case INT8_ELEMENTS:
3140 Return(SmiTag(Load(MachineType::Int8(), backing_store, key)));
3141 break;
3142 case UINT16_ELEMENTS: {
3143 Node* index = WordShl(key, IntPtrConstant(1));
3144 Return(SmiTag(Load(MachineType::Uint16(), backing_store, index)));
3145 break;
3146 }
3147 case INT16_ELEMENTS: {
3148 Node* index = WordShl(key, IntPtrConstant(1));
3149 Return(SmiTag(Load(MachineType::Int16(), backing_store, index)));
3150 break;
3151 }
3152 case UINT32_ELEMENTS: {
3153 Node* index = WordShl(key, IntPtrConstant(2));
3154 Node* element = Load(MachineType::Uint32(), backing_store, index);
3155 Return(ChangeUint32ToTagged(element));
3156 break;
3157 }
3158 case INT32_ELEMENTS: {
3159 Node* index = WordShl(key, IntPtrConstant(2));
3160 Node* element = Load(MachineType::Int32(), backing_store, index);
3161 Return(ChangeInt32ToTagged(element));
3162 break;
3163 }
3164 case FLOAT32_ELEMENTS: {
3165 Node* index = WordShl(key, IntPtrConstant(2));
3166 Node* element = Load(MachineType::Float32(), backing_store, index);
3167 var_double_value.Bind(ChangeFloat32ToFloat64(element));
3168 Goto(&rebox_double);
3169 break;
3170 }
3171 case FLOAT64_ELEMENTS: {
3172 Node* index = WordShl(key, IntPtrConstant(3));
3173 Node* element = Load(MachineType::Float64(), backing_store, index);
3174 var_double_value.Bind(element);
3175 Goto(&rebox_double);
3176 break;
3177 }
3178 default:
3179 UNREACHABLE();
3180 }
3181 // Don't forget to clean up.
3182 delete elements_kind_labels[i];
3183 }
3184
3185 Bind(&property);
3186 Comment("property_load");
3187 }
3188
2995 // |handler_word| is a field index as obtained by 3189 // |handler_word| is a field index as obtained by
2996 // FieldIndex.GetLoadByFieldOffset(): 3190 // FieldIndex.GetLoadByFieldOffset():
2997 Label inobject_double(this), out_of_object(this), 3191 Label inobject_double(this), out_of_object(this),
2998 out_of_object_double(this); 3192 out_of_object_double(this);
2999 Node* inobject_bit = WordAnd( 3193 Node* inobject_bit = WordAnd(
3000 handler_word, IntPtrConstant(FieldIndex::FieldOffsetIsInobject::kMask)); 3194 handler_word, IntPtrConstant(FieldIndex::FieldOffsetIsInobject::kMask));
3001 Node* double_bit = WordAnd( 3195 Node* double_bit = WordAnd(
3002 handler_word, IntPtrConstant(FieldIndex::FieldOffsetIsDouble::kMask)); 3196 handler_word, IntPtrConstant(FieldIndex::FieldOffsetIsDouble::kMask));
3003 Node* offset = WordSar( 3197 Node* offset = WordSar(
3004 handler_word, IntPtrConstant(FieldIndex::FieldOffsetOffset::kShift)); 3198 handler_word, IntPtrConstant(FieldIndex::FieldOffsetOffset::kShift));
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
3095 try_polymorphic_name(this /*, Label::kDeferred*/), 3289 try_polymorphic_name(this /*, Label::kDeferred*/),
3096 miss(this /*, Label::kDeferred*/); 3290 miss(this /*, Label::kDeferred*/);
3097 3291
3098 Node* receiver_map = LoadReceiverMap(p->receiver); 3292 Node* receiver_map = LoadReceiverMap(p->receiver);
3099 3293
3100 // Check monomorphic case. 3294 // Check monomorphic case.
3101 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, 3295 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler,
3102 &var_handler, &try_polymorphic); 3296 &var_handler, &try_polymorphic);
3103 Bind(&if_handler); 3297 Bind(&if_handler);
3104 { 3298 {
3105 HandleLoadICHandlerCase(p, var_handler.value(), &miss); 3299 HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements);
3106 } 3300 }
3107 3301
3108 Bind(&try_polymorphic); 3302 Bind(&try_polymorphic);
3109 { 3303 {
3110 // Check polymorphic case. 3304 // Check polymorphic case.
3111 Comment("KeyedLoadIC_try_polymorphic"); 3305 Comment("KeyedLoadIC_try_polymorphic");
3112 GotoUnless( 3306 GotoUnless(
3113 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), 3307 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
3114 &try_megamorphic); 3308 &try_megamorphic);
3115 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, 3309 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler,
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
3249 // For all objects but the receiver, check that the cache is empty. 3443 // For all objects but the receiver, check that the cache is empty.
3250 current_map.Bind(LoadMap(current_js_object.value())); 3444 current_map.Bind(LoadMap(current_js_object.value()));
3251 Node* enum_length = EnumLength(current_map.value()); 3445 Node* enum_length = EnumLength(current_map.value());
3252 Node* zero_constant = SmiConstant(Smi::FromInt(0)); 3446 Node* zero_constant = SmiConstant(Smi::FromInt(0));
3253 BranchIf(WordEqual(enum_length, zero_constant), &loop, use_runtime); 3447 BranchIf(WordEqual(enum_length, zero_constant), &loop, use_runtime);
3254 } 3448 }
3255 } 3449 }
3256 3450
3257 } // namespace internal 3451 } // namespace internal
3258 } // namespace v8 3452 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/handler-compiler.h » ('j') | src/ic/handler-compiler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698