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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 Label* if_true, Label* if_false) { | 651 Label* if_true, Label* if_false) { |
652 // Bailout if receiver is a Smi. | 652 // Bailout if receiver is a Smi. |
653 GotoIf(TaggedIsSmi(object), if_false); | 653 GotoIf(TaggedIsSmi(object), if_false); |
654 | 654 |
655 Node* map = LoadMap(object); | 655 Node* map = LoadMap(object); |
656 | 656 |
657 // Bailout if instance type is not JS_ARRAY_TYPE. | 657 // Bailout if instance type is not JS_ARRAY_TYPE. |
658 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), | 658 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), |
659 if_false); | 659 if_false); |
660 | 660 |
661 Node* bit_field2 = LoadMapBitField2(map); | 661 Node* elements_kind = LoadMapElementsKind(map); |
662 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); | |
663 | 662 |
664 // Bailout if receiver has slow elements. | 663 // Bailout if receiver has slow elements. |
665 GotoIf( | 664 GotoIf( |
666 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), | 665 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), |
667 if_false); | 666 if_false); |
668 | 667 |
669 // Check prototype chain if receiver does not have packed elements. | 668 // Check prototype chain if receiver does not have packed elements. |
670 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); | 669 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); |
671 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); | 670 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); |
672 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); | 671 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 Node* CodeStubAssembler::LoadMapBitField3(Node* map) { | 1017 Node* CodeStubAssembler::LoadMapBitField3(Node* map) { |
1019 return LoadObjectField(map, Map::kBitField3Offset, MachineType::Uint32()); | 1018 return LoadObjectField(map, Map::kBitField3Offset, MachineType::Uint32()); |
1020 } | 1019 } |
1021 | 1020 |
1022 Node* CodeStubAssembler::LoadMapInstanceType(Node* map) { | 1021 Node* CodeStubAssembler::LoadMapInstanceType(Node* map) { |
1023 return LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint8()); | 1022 return LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint8()); |
1024 } | 1023 } |
1025 | 1024 |
1026 Node* CodeStubAssembler::LoadMapElementsKind(Node* map) { | 1025 Node* CodeStubAssembler::LoadMapElementsKind(Node* map) { |
1027 Node* bit_field2 = LoadMapBitField2(map); | 1026 Node* bit_field2 = LoadMapBitField2(map); |
1028 return BitFieldDecode<Map::ElementsKindBits>(bit_field2); | 1027 return DecodeWord32<Map::ElementsKindBits>(bit_field2); |
1029 } | 1028 } |
1030 | 1029 |
1031 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { | 1030 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { |
1032 return LoadObjectField(map, Map::kDescriptorsOffset); | 1031 return LoadObjectField(map, Map::kDescriptorsOffset); |
1033 } | 1032 } |
1034 | 1033 |
1035 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { | 1034 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { |
1036 return LoadObjectField(map, Map::kPrototypeOffset); | 1035 return LoadObjectField(map, Map::kPrototypeOffset); |
1037 } | 1036 } |
1038 | 1037 |
(...skipping 2273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3312 Label end(this); | 3311 Label end(this); |
3313 | 3312 |
3314 Variable var_result(this, MachineRepresentation::kTagged); | 3313 Variable var_result(this, MachineRepresentation::kTagged); |
3315 | 3314 |
3316 // Check if string has a cached array index. | 3315 // Check if string has a cached array index. |
3317 Node* hash = LoadNameHashField(input); | 3316 Node* hash = LoadNameHashField(input); |
3318 Node* bit = | 3317 Node* bit = |
3319 Word32And(hash, Int32Constant(String::kContainsCachedArrayIndexMask)); | 3318 Word32And(hash, Int32Constant(String::kContainsCachedArrayIndexMask)); |
3320 GotoIf(Word32NotEqual(bit, Int32Constant(0)), &runtime); | 3319 GotoIf(Word32NotEqual(bit, Int32Constant(0)), &runtime); |
3321 | 3320 |
3322 var_result.Bind(SmiTag(BitFieldDecode<String::ArrayIndexValueBits>(hash))); | 3321 var_result.Bind( |
| 3322 SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash))); |
3323 Goto(&end); | 3323 Goto(&end); |
3324 | 3324 |
3325 Bind(&runtime); | 3325 Bind(&runtime); |
3326 { | 3326 { |
3327 var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input)); | 3327 var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input)); |
3328 Goto(&end); | 3328 Goto(&end); |
3329 } | 3329 } |
3330 | 3330 |
3331 Bind(&end); | 3331 Bind(&end); |
3332 return var_result.value(); | 3332 return var_result.value(); |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3704 | 3704 |
3705 Bind(&return_zero); | 3705 Bind(&return_zero); |
3706 var_arg.Bind(SmiConstant(Smi::kZero)); | 3706 var_arg.Bind(SmiConstant(Smi::kZero)); |
3707 Goto(&out); | 3707 Goto(&out); |
3708 } | 3708 } |
3709 | 3709 |
3710 Bind(&out); | 3710 Bind(&out); |
3711 return var_arg.value(); | 3711 return var_arg.value(); |
3712 } | 3712 } |
3713 | 3713 |
3714 Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, | 3714 Node* CodeStubAssembler::DecodeWord32(Node* word32, uint32_t shift, |
3715 uint32_t mask) { | 3715 uint32_t mask) { |
3716 return Word32Shr(Word32And(word32, Int32Constant(mask)), | 3716 return Word32Shr(Word32And(word32, Int32Constant(mask)), |
3717 static_cast<int>(shift)); | 3717 static_cast<int>(shift)); |
3718 } | 3718 } |
3719 | 3719 |
| 3720 Node* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) { |
| 3721 return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift)); |
| 3722 } |
| 3723 |
3720 void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) { | 3724 void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) { |
3721 if (FLAG_native_code_counters && counter->Enabled()) { | 3725 if (FLAG_native_code_counters && counter->Enabled()) { |
3722 Node* counter_address = ExternalConstant(ExternalReference(counter)); | 3726 Node* counter_address = ExternalConstant(ExternalReference(counter)); |
3723 StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, | 3727 StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, |
3724 Int32Constant(value)); | 3728 Int32Constant(value)); |
3725 } | 3729 } |
3726 } | 3730 } |
3727 | 3731 |
3728 void CodeStubAssembler::IncrementCounter(StatsCounter* counter, int delta) { | 3732 void CodeStubAssembler::IncrementCounter(StatsCounter* counter, int delta) { |
3729 DCHECK(delta > 0); | 3733 DCHECK(delta > 0); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3779 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); | 3783 Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask)); |
3780 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); | 3784 GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout); |
3781 // Finally, check if |key| is internalized. | 3785 // Finally, check if |key| is internalized. |
3782 STATIC_ASSERT(kNotInternalizedTag != 0); | 3786 STATIC_ASSERT(kNotInternalizedTag != 0); |
3783 Node* not_internalized = | 3787 Node* not_internalized = |
3784 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); | 3788 Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask)); |
3785 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); | 3789 GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout); |
3786 Goto(if_keyisunique); | 3790 Goto(if_keyisunique); |
3787 | 3791 |
3788 Bind(&if_hascachedindex); | 3792 Bind(&if_hascachedindex); |
3789 var_index->Bind(BitFieldDecodeWord<Name::ArrayIndexValueBits>(hash)); | 3793 var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash)); |
3790 Goto(if_keyisindex); | 3794 Goto(if_keyisindex); |
3791 } | 3795 } |
3792 | 3796 |
3793 template <typename Dictionary> | 3797 template <typename Dictionary> |
3794 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { | 3798 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) { |
3795 Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize)); | 3799 Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize)); |
3796 return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex + | 3800 return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex + |
3797 field_index)); | 3801 field_index)); |
3798 } | 3802 } |
3799 | 3803 |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3992 GotoIf(Int32LessThanOrEqual(instance_type, | 3996 GotoIf(Int32LessThanOrEqual(instance_type, |
3993 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 3997 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
3994 &if_objectisspecial); | 3998 &if_objectisspecial); |
3995 | 3999 |
3996 Node* bit_field = LoadMapBitField(map); | 4000 Node* bit_field = LoadMapBitField(map); |
3997 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | | 4001 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | |
3998 1 << Map::kIsAccessCheckNeeded); | 4002 1 << Map::kIsAccessCheckNeeded); |
3999 CSA_ASSERT(Word32Equal(Word32And(bit_field, mask), Int32Constant(0))); | 4003 CSA_ASSERT(Word32Equal(Word32And(bit_field, mask), Int32Constant(0))); |
4000 | 4004 |
4001 Node* bit_field3 = LoadMapBitField3(map); | 4005 Node* bit_field3 = LoadMapBitField3(map); |
4002 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); | |
4003 Label if_isfastmap(this), if_isslowmap(this); | 4006 Label if_isfastmap(this), if_isslowmap(this); |
4004 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap); | 4007 Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, |
| 4008 &if_isfastmap); |
4005 Bind(&if_isfastmap); | 4009 Bind(&if_isfastmap); |
4006 { | 4010 { |
4007 Comment("DescriptorArrayLookup"); | 4011 Comment("DescriptorArrayLookup"); |
4008 Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bit_field3); | 4012 Node* nof = |
| 4013 DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3); |
4009 // Bail out to the runtime for large numbers of own descriptors. The stub | 4014 // Bail out to the runtime for large numbers of own descriptors. The stub |
4010 // only does linear search, which becomes too expensive in that case. | 4015 // only does linear search, which becomes too expensive in that case. |
4011 { | 4016 { |
4012 static const int32_t kMaxLinear = 210; | 4017 static const int32_t kMaxLinear = 210; |
4013 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), if_bailout); | 4018 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), if_bailout); |
4014 } | 4019 } |
4015 Node* descriptors = LoadMapDescriptors(map); | 4020 Node* descriptors = LoadMapDescriptors(map); |
4016 var_meta_storage->Bind(descriptors); | 4021 var_meta_storage->Bind(descriptors); |
4017 | 4022 |
4018 DescriptorLookupLinear(unique_name, descriptors, nof, if_found_fast, | 4023 DescriptorLookupLinear(unique_name, descriptors, nof, if_found_fast, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4086 (DescriptorArray::kDescriptorDetails - DescriptorArray::kDescriptorKey) * | 4091 (DescriptorArray::kDescriptorDetails - DescriptorArray::kDescriptorKey) * |
4087 kPointerSize; | 4092 kPointerSize; |
4088 const int name_to_value_offset = | 4093 const int name_to_value_offset = |
4089 (DescriptorArray::kDescriptorValue - DescriptorArray::kDescriptorKey) * | 4094 (DescriptorArray::kDescriptorValue - DescriptorArray::kDescriptorKey) * |
4090 kPointerSize; | 4095 kPointerSize; |
4091 | 4096 |
4092 Node* details = LoadAndUntagToWord32FixedArrayElement(descriptors, name_index, | 4097 Node* details = LoadAndUntagToWord32FixedArrayElement(descriptors, name_index, |
4093 name_to_details_offset); | 4098 name_to_details_offset); |
4094 var_details->Bind(details); | 4099 var_details->Bind(details); |
4095 | 4100 |
4096 Node* location = BitFieldDecode<PropertyDetails::LocationField>(details); | 4101 Node* location = DecodeWord32<PropertyDetails::LocationField>(details); |
4097 | 4102 |
4098 Label if_in_field(this), if_in_descriptor(this), done(this); | 4103 Label if_in_field(this), if_in_descriptor(this), done(this); |
4099 Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field, | 4104 Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field, |
4100 &if_in_descriptor); | 4105 &if_in_descriptor); |
4101 Bind(&if_in_field); | 4106 Bind(&if_in_field); |
4102 { | 4107 { |
4103 Node* field_index = | 4108 Node* field_index = |
4104 BitFieldDecodeWord<PropertyDetails::FieldIndexField>(details); | 4109 DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details); |
4105 Node* representation = | 4110 Node* representation = |
4106 BitFieldDecode<PropertyDetails::RepresentationField>(details); | 4111 DecodeWord32<PropertyDetails::RepresentationField>(details); |
4107 | 4112 |
4108 Node* inobject_properties = LoadMapInobjectProperties(map); | 4113 Node* inobject_properties = LoadMapInobjectProperties(map); |
4109 | 4114 |
4110 Label if_inobject(this), if_backing_store(this); | 4115 Label if_inobject(this), if_backing_store(this); |
4111 Variable var_double_value(this, MachineRepresentation::kFloat64); | 4116 Variable var_double_value(this, MachineRepresentation::kFloat64); |
4112 Label rebox_double(this, &var_double_value); | 4117 Label rebox_double(this, &var_double_value); |
4113 Branch(UintPtrLessThan(field_index, inobject_properties), &if_inobject, | 4118 Branch(UintPtrLessThan(field_index, inobject_properties), &if_inobject, |
4114 &if_backing_store); | 4119 &if_backing_store); |
4115 Bind(&if_inobject); | 4120 Bind(&if_inobject); |
4116 { | 4121 { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4235 // |value| is the property backing store's contents, which is either a value | 4240 // |value| is the property backing store's contents, which is either a value |
4236 // or an accessor pair, as specified by |details|. | 4241 // or an accessor pair, as specified by |details|. |
4237 // Returns either the original value, or the result of the getter call. | 4242 // Returns either the original value, or the result of the getter call. |
4238 Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, | 4243 Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, |
4239 Node* context, Node* receiver, | 4244 Node* context, Node* receiver, |
4240 Label* if_bailout) { | 4245 Label* if_bailout) { |
4241 Variable var_value(this, MachineRepresentation::kTagged); | 4246 Variable var_value(this, MachineRepresentation::kTagged); |
4242 var_value.Bind(value); | 4247 var_value.Bind(value); |
4243 Label done(this); | 4248 Label done(this); |
4244 | 4249 |
4245 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details); | 4250 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); |
4246 GotoIf(Word32Equal(kind, Int32Constant(kData)), &done); | 4251 GotoIf(Word32Equal(kind, Int32Constant(kData)), &done); |
4247 | 4252 |
4248 // Accessor case. | 4253 // Accessor case. |
4249 { | 4254 { |
4250 Node* accessor_pair = value; | 4255 Node* accessor_pair = value; |
4251 GotoIf(Word32Equal(LoadInstanceType(accessor_pair), | 4256 GotoIf(Word32Equal(LoadInstanceType(accessor_pair), |
4252 Int32Constant(ACCESSOR_INFO_TYPE)), | 4257 Int32Constant(ACCESSOR_INFO_TYPE)), |
4253 if_bailout); | 4258 if_bailout); |
4254 AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE); | 4259 AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE); |
4255 Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); | 4260 Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); |
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5132 Variable var_entry(this, MachineType::PointerRepresentation()); | 5137 Variable var_entry(this, MachineType::PointerRepresentation()); |
5133 Label if_found(this); | 5138 Label if_found(this); |
5134 NumberDictionaryLookup<SeededNumberDictionary>( | 5139 NumberDictionaryLookup<SeededNumberDictionary>( |
5135 elements, intptr_index, &if_found, &var_entry, if_hole); | 5140 elements, intptr_index, &if_found, &var_entry, if_hole); |
5136 Bind(&if_found); | 5141 Bind(&if_found); |
5137 // Check that the value is a data property. | 5142 // Check that the value is a data property. |
5138 Node* details_index = EntryToIndex<SeededNumberDictionary>( | 5143 Node* details_index = EntryToIndex<SeededNumberDictionary>( |
5139 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); | 5144 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); |
5140 Node* details = SmiToWord32( | 5145 Node* details = SmiToWord32( |
5141 LoadFixedArrayElement(elements, details_index, 0, INTPTR_PARAMETERS)); | 5146 LoadFixedArrayElement(elements, details_index, 0, INTPTR_PARAMETERS)); |
5142 Node* kind = BitFieldDecode<PropertyDetails::KindField>(details); | 5147 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); |
5143 // TODO(jkummerow): Support accessors without missing? | 5148 // TODO(jkummerow): Support accessors without missing? |
5144 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); | 5149 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); |
5145 // Finally, load the value. | 5150 // Finally, load the value. |
5146 Node* value_index = EntryToIndex<SeededNumberDictionary>( | 5151 Node* value_index = EntryToIndex<SeededNumberDictionary>( |
5147 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); | 5152 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); |
5148 Return(LoadFixedArrayElement(elements, value_index, 0, INTPTR_PARAMETERS)); | 5153 Return(LoadFixedArrayElement(elements, value_index, 0, INTPTR_PARAMETERS)); |
5149 } | 5154 } |
5150 | 5155 |
5151 Bind(&if_typed_array); | 5156 Bind(&if_typed_array); |
5152 { | 5157 { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5262 | 5267 |
5263 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 5268 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
5264 // for the encoding format. | 5269 // for the encoding format. |
5265 Bind(&if_smi_handler); | 5270 Bind(&if_smi_handler); |
5266 { | 5271 { |
5267 Variable var_double_value(this, MachineRepresentation::kFloat64); | 5272 Variable var_double_value(this, MachineRepresentation::kFloat64); |
5268 Label rebox_double(this, &var_double_value); | 5273 Label rebox_double(this, &var_double_value); |
5269 | 5274 |
5270 Node* holder = var_holder.value(); | 5275 Node* holder = var_holder.value(); |
5271 Node* handler_word = SmiUntag(var_smi_handler.value()); | 5276 Node* handler_word = SmiUntag(var_smi_handler.value()); |
5272 Node* handler_type = | 5277 Node* handler_type = DecodeWord<LoadHandlerTypeBits>(handler_word); |
5273 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBits::kMask)); | |
5274 if (support_elements == kSupportElements) { | 5278 if (support_elements == kSupportElements) { |
5275 Label property(this); | 5279 Label property(this); |
5276 GotoUnless( | 5280 GotoUnless( |
5277 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), | 5281 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), |
5278 &property); | 5282 &property); |
5279 | 5283 |
5280 Comment("element_load"); | 5284 Comment("element_load"); |
5281 Node* intptr_index = TryToIntptr(p->name, miss); | 5285 Node* intptr_index = TryToIntptr(p->name, miss); |
5282 Node* elements = LoadElements(holder); | 5286 Node* elements = LoadElements(holder); |
5283 Node* is_jsarray = | 5287 Node* is_jsarray_condition = IsSetWord<KeyedLoadIsJsArray>(handler_word); |
5284 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); | 5288 Node* elements_kind = DecodeWord<KeyedLoadElementsKind>(handler_word); |
5285 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); | |
5286 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); | |
5287 Label if_hole(this), unimplemented_elements_kind(this); | 5289 Label if_hole(this), unimplemented_elements_kind(this); |
5288 Label* out_of_bounds = miss; | 5290 Label* out_of_bounds = miss; |
5289 EmitElementLoad(holder, elements, elements_kind, intptr_index, | 5291 EmitElementLoad(holder, elements, elements_kind, intptr_index, |
5290 is_jsarray_condition, &if_hole, &rebox_double, | 5292 is_jsarray_condition, &if_hole, &rebox_double, |
5291 &var_double_value, &unimplemented_elements_kind, | 5293 &var_double_value, &unimplemented_elements_kind, |
5292 out_of_bounds, miss); | 5294 out_of_bounds, miss); |
5293 | 5295 |
5294 Bind(&unimplemented_elements_kind); | 5296 Bind(&unimplemented_elements_kind); |
5295 { | 5297 { |
5296 // Smi handlers should only be installed for supported elements kinds. | 5298 // Smi handlers should only be installed for supported elements kinds. |
5297 // Crash if we get here. | 5299 // Crash if we get here. |
5298 DebugBreak(); | 5300 DebugBreak(); |
5299 Goto(miss); | 5301 Goto(miss); |
5300 } | 5302 } |
5301 | 5303 |
5302 Bind(&if_hole); | 5304 Bind(&if_hole); |
5303 { | 5305 { |
5304 Comment("convert hole"); | 5306 Comment("convert hole"); |
5305 Node* convert_hole = | 5307 GotoUnless(IsSetWord<KeyedLoadConvertHole>(handler_word), miss); |
5306 WordAnd(handler_word, IntPtrConstant(KeyedLoadConvertHole::kMask)); | |
5307 GotoIf(WordEqual(convert_hole, IntPtrConstant(0)), miss); | |
5308 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); | 5308 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); |
5309 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); | 5309 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); |
5310 GotoUnless( | 5310 GotoUnless( |
5311 WordEqual( | 5311 WordEqual( |
5312 LoadObjectField(protector_cell, PropertyCell::kValueOffset), | 5312 LoadObjectField(protector_cell, PropertyCell::kValueOffset), |
5313 SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))), | 5313 SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))), |
5314 miss); | 5314 miss); |
5315 Return(UndefinedConstant()); | 5315 Return(UndefinedConstant()); |
5316 } | 5316 } |
5317 | 5317 |
5318 Bind(&property); | 5318 Bind(&property); |
5319 Comment("property_load"); | 5319 Comment("property_load"); |
5320 } | 5320 } |
5321 | 5321 |
5322 Label constant(this), field(this); | 5322 Label constant(this), field(this); |
5323 Branch(WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForFields)), | 5323 Branch(WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForFields)), |
5324 &field, &constant); | 5324 &field, &constant); |
5325 | 5325 |
5326 Bind(&field); | 5326 Bind(&field); |
5327 { | 5327 { |
5328 Comment("field_load"); | 5328 Comment("field_load"); |
5329 Label inobject_double(this), out_of_object(this), | 5329 Node* offset = DecodeWord<FieldOffsetOffset>(handler_word); |
5330 out_of_object_double(this); | |
5331 Node* inobject_bit = | |
5332 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask)); | |
5333 Node* double_bit = | |
5334 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask)); | |
5335 Node* offset = | |
5336 WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift)); | |
5337 | 5330 |
5338 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); | 5331 Label inobject(this), out_of_object(this); |
| 5332 Branch(IsSetWord<FieldOffsetIsInobject>(handler_word), &inobject, |
| 5333 &out_of_object); |
5339 | 5334 |
5340 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); | 5335 Bind(&inobject); |
5341 Return(LoadObjectField(holder, offset)); | 5336 { |
| 5337 Label is_double(this); |
| 5338 GotoIf(IsSetWord<FieldOffsetIsDouble>(handler_word), &is_double); |
| 5339 Return(LoadObjectField(holder, offset)); |
5342 | 5340 |
5343 Bind(&inobject_double); | 5341 Bind(&is_double); |
5344 if (FLAG_unbox_double_fields) { | 5342 if (FLAG_unbox_double_fields) { |
5345 var_double_value.Bind( | 5343 var_double_value.Bind( |
5346 LoadObjectField(holder, offset, MachineType::Float64())); | 5344 LoadObjectField(holder, offset, MachineType::Float64())); |
5347 } else { | 5345 } else { |
5348 Node* mutable_heap_number = LoadObjectField(holder, offset); | 5346 Node* mutable_heap_number = LoadObjectField(holder, offset); |
5349 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | 5347 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
| 5348 } |
| 5349 Goto(&rebox_double); |
5350 } | 5350 } |
5351 Goto(&rebox_double); | |
5352 | 5351 |
5353 Bind(&out_of_object); | 5352 Bind(&out_of_object); |
5354 Node* properties = LoadProperties(holder); | 5353 { |
5355 Node* value = LoadObjectField(properties, offset); | 5354 Label is_double(this); |
5356 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), | 5355 Node* properties = LoadProperties(holder); |
5357 &out_of_object_double); | 5356 Node* value = LoadObjectField(properties, offset); |
5358 Return(value); | 5357 GotoIf(IsSetWord<FieldOffsetIsDouble>(handler_word), &is_double); |
| 5358 Return(value); |
5359 | 5359 |
5360 Bind(&out_of_object_double); | 5360 Bind(&is_double); |
5361 var_double_value.Bind(LoadHeapNumberValue(value)); | 5361 var_double_value.Bind(LoadHeapNumberValue(value)); |
5362 Goto(&rebox_double); | 5362 Goto(&rebox_double); |
| 5363 } |
5363 | 5364 |
5364 Bind(&rebox_double); | 5365 Bind(&rebox_double); |
5365 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 5366 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
5366 } | 5367 } |
5367 | 5368 |
5368 Bind(&constant); | 5369 Bind(&constant); |
5369 { | 5370 { |
5370 Comment("constant_load"); | 5371 Comment("constant_load"); |
5371 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); | 5372 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); |
5372 Node* descriptor = WordSar( | 5373 Node* descriptor = DecodeWord<ValueIndexInDescriptorArray>(handler_word); |
5373 handler_word, IntPtrConstant(ValueIndexInDescriptorArray::kShift)); | |
5374 #if defined(DEBUG) | 5374 #if defined(DEBUG) |
5375 Assert(UintPtrLessThan(descriptor, | 5375 CSA_ASSERT(UintPtrLessThan( |
5376 LoadAndUntagFixedArrayBaseLength(descriptors))); | 5376 descriptor, LoadAndUntagFixedArrayBaseLength(descriptors))); |
5377 #endif | 5377 #endif |
5378 Return( | 5378 Return( |
5379 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS)); | 5379 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS)); |
5380 } | 5380 } |
5381 } | 5381 } |
5382 | 5382 |
5383 Bind(&try_proto_cell_handler); | 5383 Bind(&try_proto_cell_handler); |
5384 { | 5384 { |
5385 GotoIf(WordNotEqual(LoadMap(handler), LoadRoot(Heap::kTuple3MapRootIndex)), | 5385 GotoIf(WordNotEqual(LoadMap(handler), LoadRoot(Heap::kTuple3MapRootIndex)), |
5386 &call_handler); | 5386 &call_handler); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5600 // Try looking up the property on the receiver; if unsuccessful, look | 5600 // Try looking up the property on the receiver; if unsuccessful, look |
5601 // for a handler in the stub cache. | 5601 // for a handler in the stub cache. |
5602 Comment("DescriptorArray lookup"); | 5602 Comment("DescriptorArray lookup"); |
5603 | 5603 |
5604 // Skip linear search if there are too many descriptors. | 5604 // Skip linear search if there are too many descriptors. |
5605 // TODO(jkummerow): Consider implementing binary search. | 5605 // TODO(jkummerow): Consider implementing binary search. |
5606 // See also TryLookupProperty() which has the same limitation. | 5606 // See also TryLookupProperty() which has the same limitation. |
5607 const int32_t kMaxLinear = 210; | 5607 const int32_t kMaxLinear = 210; |
5608 Label stub_cache(this); | 5608 Label stub_cache(this); |
5609 Node* bitfield3 = LoadMapBitField3(receiver_map); | 5609 Node* bitfield3 = LoadMapBitField3(receiver_map); |
5610 Node* nof = BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bitfield3); | 5610 Node* nof = |
| 5611 DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); |
5611 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), &stub_cache); | 5612 GotoIf(UintPtrGreaterThan(nof, IntPtrConstant(kMaxLinear)), &stub_cache); |
5612 Node* descriptors = LoadMapDescriptors(receiver_map); | 5613 Node* descriptors = LoadMapDescriptors(receiver_map); |
5613 Variable var_name_index(this, MachineType::PointerRepresentation()); | 5614 Variable var_name_index(this, MachineType::PointerRepresentation()); |
5614 Label if_descriptor_found(this); | 5615 Label if_descriptor_found(this); |
5615 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, | 5616 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, |
5616 &var_name_index, &stub_cache); | 5617 &var_name_index, &stub_cache); |
5617 | 5618 |
5618 Bind(&if_descriptor_found); | 5619 Bind(&if_descriptor_found); |
5619 { | 5620 { |
5620 LoadPropertyFromFastObject(receiver, receiver_map, descriptors, | 5621 LoadPropertyFromFastObject(receiver, receiver_map, descriptors, |
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6407 Bind(&no_memento_found); | 6408 Bind(&no_memento_found); |
6408 Comment("] TrapAllocationMemento"); | 6409 Comment("] TrapAllocationMemento"); |
6409 } | 6410 } |
6410 | 6411 |
6411 Node* CodeStubAssembler::PageFromAddress(Node* address) { | 6412 Node* CodeStubAssembler::PageFromAddress(Node* address) { |
6412 return WordAnd(address, IntPtrConstant(~Page::kPageAlignmentMask)); | 6413 return WordAnd(address, IntPtrConstant(~Page::kPageAlignmentMask)); |
6413 } | 6414 } |
6414 | 6415 |
6415 Node* CodeStubAssembler::EnumLength(Node* map) { | 6416 Node* CodeStubAssembler::EnumLength(Node* map) { |
6416 Node* bitfield_3 = LoadMapBitField3(map); | 6417 Node* bitfield_3 = LoadMapBitField3(map); |
6417 Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3); | 6418 Node* enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(bitfield_3); |
6418 return SmiTag(enum_length); | 6419 return SmiTag(enum_length); |
6419 } | 6420 } |
6420 | 6421 |
6421 void CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache, | 6422 void CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache, |
6422 Label* use_runtime) { | 6423 Label* use_runtime) { |
6423 Variable current_js_object(this, MachineRepresentation::kTagged); | 6424 Variable current_js_object(this, MachineRepresentation::kTagged); |
6424 current_js_object.Bind(receiver); | 6425 current_js_object.Bind(receiver); |
6425 | 6426 |
6426 Variable current_map(this, MachineRepresentation::kTagged); | 6427 Variable current_map(this, MachineRepresentation::kTagged); |
6427 current_map.Bind(LoadMap(current_js_object.value())); | 6428 current_map.Bind(LoadMap(current_js_object.value())); |
(...skipping 1879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8307 Node* buffer_bit_field = LoadObjectField( | 8308 Node* buffer_bit_field = LoadObjectField( |
8308 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8309 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8309 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8310 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8310 | 8311 |
8311 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8312 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8312 Int32Constant(0)); | 8313 Int32Constant(0)); |
8313 } | 8314 } |
8314 | 8315 |
8315 } // namespace internal | 8316 } // namespace internal |
8316 } // namespace v8 | 8317 } // namespace v8 |
OLD | NEW |