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/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 2855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2866 // See Dictionary::NextProbe(). | 2866 // See Dictionary::NextProbe(). |
2867 count = IntPtrAdd(count, IntPtrConstant(1)); | 2867 count = IntPtrAdd(count, IntPtrConstant(1)); |
2868 entry = WordAnd(IntPtrAdd(entry, count), mask); | 2868 entry = WordAnd(IntPtrAdd(entry, count), mask); |
2869 | 2869 |
2870 var_count.Bind(count); | 2870 var_count.Bind(count); |
2871 var_entry->Bind(entry); | 2871 var_entry->Bind(entry); |
2872 Goto(&loop); | 2872 Goto(&loop); |
2873 } | 2873 } |
2874 } | 2874 } |
2875 | 2875 |
2876 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, | |
Jakob Kummerow
2016/09/22 22:28:55
This is pulled out from below, unchanged.
| |
2877 Node* descriptors, Node* nof, | |
2878 Label* if_found, | |
2879 Variable* var_name_index, | |
2880 Label* if_not_found) { | |
2881 Variable var_descriptor(this, MachineType::PointerRepresentation()); | |
2882 Label loop(this, &var_descriptor); | |
2883 var_descriptor.Bind(IntPtrConstant(0)); | |
2884 Goto(&loop); | |
2885 | |
2886 Bind(&loop); | |
2887 { | |
2888 Node* index = var_descriptor.value(); | |
2889 Node* name_offset = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); | |
2890 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); | |
2891 GotoIf(WordEqual(index, nof), if_not_found); | |
2892 Node* name_index = IntPtrAdd(name_offset, IntPtrMul(index, factor)); | |
2893 Node* candidate_name = | |
2894 LoadFixedArrayElement(descriptors, name_index, 0, INTPTR_PARAMETERS); | |
2895 var_name_index->Bind(name_index); | |
2896 GotoIf(WordEqual(candidate_name, unique_name), if_found); | |
2897 var_descriptor.Bind(IntPtrAdd(index, IntPtrConstant(1))); | |
2898 Goto(&loop); | |
2899 } | |
2900 } | |
2901 | |
2876 void CodeStubAssembler::TryLookupProperty( | 2902 void CodeStubAssembler::TryLookupProperty( |
2877 Node* object, Node* map, Node* instance_type, Node* unique_name, | 2903 Node* object, Node* map, Node* instance_type, Node* unique_name, |
2878 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, | 2904 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, |
2879 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, | 2905 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, |
2880 Label* if_bailout) { | 2906 Label* if_bailout) { |
2881 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); | 2907 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); |
2882 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); | 2908 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); |
2883 | 2909 |
2884 Label if_objectisspecial(this); | 2910 Label if_objectisspecial(this); |
2885 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); | 2911 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
(...skipping 16 matching lines...) Expand all Loading... | |
2902 Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bit_field3); | 2928 Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bit_field3); |
2903 // Bail out to the runtime for large numbers of own descriptors. The stub | 2929 // Bail out to the runtime for large numbers of own descriptors. The stub |
2904 // only does linear search, which becomes too expensive in that case. | 2930 // only does linear search, which becomes too expensive in that case. |
2905 { | 2931 { |
2906 static const int32_t kMaxLinear = 210; | 2932 static const int32_t kMaxLinear = 210; |
2907 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), if_bailout); | 2933 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), if_bailout); |
2908 } | 2934 } |
2909 Node* descriptors = LoadMapDescriptors(map); | 2935 Node* descriptors = LoadMapDescriptors(map); |
2910 var_meta_storage->Bind(descriptors); | 2936 var_meta_storage->Bind(descriptors); |
2911 | 2937 |
2912 Variable var_descriptor(this, MachineType::PointerRepresentation()); | 2938 DescriptorLookupLinear(unique_name, descriptors, nof, if_found_fast, |
2913 Label loop(this, &var_descriptor); | 2939 var_name_index, if_not_found); |
2914 var_descriptor.Bind(IntPtrConstant(0)); | |
2915 Goto(&loop); | |
2916 Bind(&loop); | |
2917 { | |
2918 Node* index = var_descriptor.value(); | |
2919 Node* name_offset = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); | |
2920 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); | |
2921 GotoIf(WordEqual(index, nof), if_not_found); | |
2922 | |
2923 Node* name_index = IntPtrAdd(name_offset, IntPtrMul(index, factor)); | |
2924 Node* name = | |
2925 LoadFixedArrayElement(descriptors, name_index, 0, INTPTR_PARAMETERS); | |
2926 | |
2927 var_name_index->Bind(name_index); | |
2928 GotoIf(WordEqual(name, unique_name), if_found_fast); | |
2929 | |
2930 var_descriptor.Bind(IntPtrAdd(index, IntPtrConstant(1))); | |
2931 Goto(&loop); | |
2932 } | |
2933 } | 2940 } |
2934 Bind(&if_isslowmap); | 2941 Bind(&if_isslowmap); |
2935 { | 2942 { |
2936 Node* dictionary = LoadProperties(object); | 2943 Node* dictionary = LoadProperties(object); |
2937 var_meta_storage->Bind(dictionary); | 2944 var_meta_storage->Bind(dictionary); |
2938 | 2945 |
2939 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, | 2946 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict, |
2940 var_name_index, if_not_found); | 2947 var_name_index, if_not_found); |
2941 } | 2948 } |
2942 Bind(&if_objectisspecial); | 2949 Bind(&if_objectisspecial); |
(...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4320 Bind(&miss); | 4327 Bind(&miss); |
4321 { | 4328 { |
4322 Comment("KeyedLoadIC_miss"); | 4329 Comment("KeyedLoadIC_miss"); |
4323 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 4330 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
4324 p->name, p->slot, p->vector); | 4331 p->name, p->slot, p->vector); |
4325 } | 4332 } |
4326 } | 4333 } |
4327 | 4334 |
4328 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { | 4335 void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { |
4329 Variable var_index(this, MachineType::PointerRepresentation()); | 4336 Variable var_index(this, MachineType::PointerRepresentation()); |
4337 Variable var_details(this, MachineRepresentation::kWord32); | |
4338 Variable var_value(this, MachineRepresentation::kTagged); | |
4330 Label if_index(this), if_unique_name(this), if_element_hole(this), | 4339 Label if_index(this), if_unique_name(this), if_element_hole(this), |
4331 if_oob(this), slow(this), stub_cache_miss(this), | 4340 if_oob(this), slow(this), stub_cache_miss(this), |
4332 if_property_dictionary(this); | 4341 if_property_dictionary(this), if_found_on_receiver(this); |
4333 | 4342 |
4334 Node* receiver = p->receiver; | 4343 Node* receiver = p->receiver; |
4335 GotoIf(WordIsSmi(receiver), &slow); | 4344 GotoIf(WordIsSmi(receiver), &slow); |
4336 Node* receiver_map = LoadMap(receiver); | 4345 Node* receiver_map = LoadMap(receiver); |
4337 Node* instance_type = LoadMapInstanceType(receiver_map); | 4346 Node* instance_type = LoadMapInstanceType(receiver_map); |
4338 // Receivers requiring non-standard element accesses (interceptors, access | 4347 // Receivers requiring non-standard element accesses (interceptors, access |
4339 // checks, strings and string wrappers, proxies) are handled in the runtime. | 4348 // checks, strings and string wrappers, proxies) are handled in the runtime. |
4340 GotoIf(Int32LessThanOrEqual(instance_type, | 4349 GotoIf(Int32LessThanOrEqual(instance_type, |
4341 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 4350 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
4342 &slow); | 4351 &slow); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4391 Node* properties = nullptr; | 4400 Node* properties = nullptr; |
4392 Bind(&if_unique_name); | 4401 Bind(&if_unique_name); |
4393 { | 4402 { |
4394 Comment("key is unique name"); | 4403 Comment("key is unique name"); |
4395 // Check if the receiver has fast or slow properties. | 4404 // Check if the receiver has fast or slow properties. |
4396 properties = LoadProperties(receiver); | 4405 properties = LoadProperties(receiver); |
4397 Node* properties_map = LoadMap(properties); | 4406 Node* properties_map = LoadMap(properties); |
4398 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), | 4407 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), |
4399 &if_property_dictionary); | 4408 &if_property_dictionary); |
4400 | 4409 |
4401 Comment("stub cache probe for fast property load"); | 4410 // Try looking up the property on the receiver; if unsuccessful, look |
Jakob Kummerow
2016/09/22 22:28:55
All this has moved into the "Bind(&stub_cache)" bl
| |
4402 Variable var_handler(this, MachineRepresentation::kTagged); | 4411 // for a handler in the stub cache. |
4403 Label found_handler(this, &var_handler), stub_cache_miss(this); | 4412 Comment("DescriptorArray lookup"); |
4404 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, | |
4405 &found_handler, &var_handler, &stub_cache_miss); | |
4406 Bind(&found_handler); | |
4407 { HandleLoadICHandlerCase(p, var_handler.value(), &slow); } | |
4408 | 4413 |
4409 Bind(&stub_cache_miss); | 4414 // Skip linear search if there are too many descriptors. |
4415 // TODO(jkummerow): Consider implementing binary search. | |
4416 // See also TryLookupProperty() which has the same limitation. | |
4417 const int32_t kMaxLinear = 210; | |
4418 Label stub_cache(this); | |
4419 Node* bitfield3 = LoadMapBitField3(receiver_map); | |
4420 Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bitfield3); | |
4421 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), &stub_cache); | |
4422 Node* descriptors = LoadMapDescriptors(receiver_map); | |
4423 Variable var_name_index(this, MachineType::PointerRepresentation()); | |
4424 Label if_descriptor_found(this); | |
4425 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, | |
4426 &var_name_index, &slow); | |
4427 | |
4428 Bind(&if_descriptor_found); | |
4410 { | 4429 { |
4411 Comment("KeyedLoadGeneric_miss"); | 4430 LoadPropertyFromFastObject(receiver, receiver_map, descriptors, |
4412 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 4431 var_name_index.value(), &var_details, |
4413 p->name, p->slot, p->vector); | 4432 &var_value); |
4433 Goto(&if_found_on_receiver); | |
4434 } | |
4435 | |
4436 Bind(&stub_cache); | |
4437 { | |
4438 Comment("stub cache probe for fast property load"); | |
4439 Variable var_handler(this, MachineRepresentation::kTagged); | |
4440 Label found_handler(this, &var_handler), stub_cache_miss(this); | |
4441 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, | |
4442 &found_handler, &var_handler, &stub_cache_miss); | |
4443 Bind(&found_handler); | |
4444 { HandleLoadICHandlerCase(p, var_handler.value(), &slow); } | |
4445 | |
4446 Bind(&stub_cache_miss); | |
4447 { | |
4448 Comment("KeyedLoadGeneric_miss"); | |
4449 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | |
4450 p->name, p->slot, p->vector); | |
4451 } | |
4414 } | 4452 } |
4415 } | 4453 } |
4416 | 4454 |
4417 Bind(&if_property_dictionary); | 4455 Bind(&if_property_dictionary); |
4418 { | 4456 { |
4419 Comment("dictionary property load"); | 4457 Comment("dictionary property load"); |
4420 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out | 4458 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out |
4421 // seeing global objects here (which would need special handling). | 4459 // seeing global objects here (which would need special handling). |
4422 | 4460 |
4423 Variable var_name_index(this, MachineType::PointerRepresentation()); | 4461 Variable var_name_index(this, MachineType::PointerRepresentation()); |
4424 Label dictionary_found(this, &var_name_index); | 4462 Label dictionary_found(this, &var_name_index); |
4425 NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found, | 4463 NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found, |
4426 &var_name_index, &slow); | 4464 &var_name_index, &slow); |
4427 Bind(&dictionary_found); | 4465 Bind(&dictionary_found); |
4428 { | 4466 { |
4429 Variable var_details(this, MachineRepresentation::kWord32); | |
4430 Variable var_value(this, MachineRepresentation::kTagged); | |
4431 LoadPropertyFromNameDictionary(properties, var_name_index.value(), | 4467 LoadPropertyFromNameDictionary(properties, var_name_index.value(), |
4432 &var_details, &var_value); | 4468 &var_details, &var_value); |
4433 Node* kind = | 4469 Goto(&if_found_on_receiver); |
4434 BitFieldDecode<PropertyDetails::KindField>(var_details.value()); | |
4435 // TODO(jkummerow): Support accessors without missing? | |
4436 GotoUnless(Word32Equal(kind, Int32Constant(kData)), &slow); | |
4437 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), | |
4438 1); | |
4439 Return(var_value.value()); | |
4440 } | 4470 } |
4441 } | 4471 } |
4442 | 4472 |
4473 Bind(&if_found_on_receiver); | |
4474 { | |
4475 Node* kind = | |
4476 BitFieldDecode<PropertyDetails::KindField>(var_details.value()); | |
4477 // TODO(jkummerow): Support accessors without missing? | |
4478 GotoUnless(Word32Equal(kind, Int32Constant(kData)), &slow); | |
4479 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1); | |
4480 Return(var_value.value()); | |
4481 } | |
4482 | |
4443 Bind(&slow); | 4483 Bind(&slow); |
4444 { | 4484 { |
4445 Comment("KeyedLoadGeneric_slow"); | 4485 Comment("KeyedLoadGeneric_slow"); |
4446 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); | 4486 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); |
4447 // TODO(jkummerow): Should we use the GetProperty TF stub instead? | 4487 // TODO(jkummerow): Should we use the GetProperty TF stub instead? |
4448 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, | 4488 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, |
4449 p->name); | 4489 p->name); |
4450 } | 4490 } |
4451 } | 4491 } |
4452 | 4492 |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5174 Heap::kTheHoleValueRootIndex); | 5214 Heap::kTheHoleValueRootIndex); |
5175 | 5215 |
5176 // Store the WeakCell in the feedback vector. | 5216 // Store the WeakCell in the feedback vector. |
5177 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 5217 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
5178 CodeStubAssembler::SMI_PARAMETERS); | 5218 CodeStubAssembler::SMI_PARAMETERS); |
5179 return cell; | 5219 return cell; |
5180 } | 5220 } |
5181 | 5221 |
5182 } // namespace internal | 5222 } // namespace internal |
5183 } // namespace v8 | 5223 } // namespace v8 |
OLD | NEW |