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

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

Issue 2182103002: [KeyedLoadIC] Support Smi "handlers" for simple field loads (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: change "handler" Smi encoding format 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/stub-cache.h" 9 #include "src/ic/stub-cache.h"
10 10
(...skipping 2959 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/field-index-inl.h » ('j') | src/field-index-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698