diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-05-02 10:50:00 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-05-06 20:02:35 +0200 |
commit | 60d1aac8d225e844e68ae48e8f3d58802e635fbe (patch) | |
tree | 922f347dd054db18d88666fad7181e5a777f4022 /deps/v8/src/ic/keyed-store-generic.cc | |
parent | 73d9c0f903ae371cd5011af64c3a6f69a1bda978 (diff) | |
download | android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.gz android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.bz2 android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.zip |
deps: update V8 to 5.8.283.38
PR-URL: https://github.com/nodejs/node/pull/12784
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Diffstat (limited to 'deps/v8/src/ic/keyed-store-generic.cc')
-rw-r--r-- | deps/v8/src/ic/keyed-store-generic.cc | 255 |
1 files changed, 208 insertions, 47 deletions
diff --git a/deps/v8/src/ic/keyed-store-generic.cc b/deps/v8/src/ic/keyed-store-generic.cc index 81ce3a6a1f..8962386c93 100644 --- a/deps/v8/src/ic/keyed-store-generic.cc +++ b/deps/v8/src/ic/keyed-store-generic.cc @@ -7,19 +7,20 @@ #include "src/code-factory.h" #include "src/code-stub-assembler.h" #include "src/contexts.h" -#include "src/ic/accessor-assembler-impl.h" +#include "src/ic/accessor-assembler.h" #include "src/interface-descriptors.h" #include "src/isolate.h" +#include "src/objects-inl.h" namespace v8 { namespace internal { using compiler::Node; -class KeyedStoreGenericAssembler : public AccessorAssemblerImpl { +class KeyedStoreGenericAssembler : public AccessorAssembler { public: explicit KeyedStoreGenericAssembler(compiler::CodeAssemblerState* state) - : AccessorAssemblerImpl(state) {} + : AccessorAssembler(state) {} void KeyedStoreGeneric(LanguageMode language_mode); @@ -72,6 +73,13 @@ class KeyedStoreGenericAssembler : public AccessorAssemblerImpl { Variable* var_accessor_pair, Variable* var_accessor_holder, Label* readonly, Label* bailout); + + void CheckFieldType(Node* descriptors, Node* name_index, Node* representation, + Node* value, Label* bailout); + void OverwriteExistingFastProperty(Node* object, Node* object_map, + Node* properties, Node* descriptors, + Node* descriptor_name_index, Node* details, + Node* value, Label* slow); }; void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state, @@ -266,7 +274,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity( // can always be stored. { Label non_smi_value(this); - GotoUnless(TaggedIsSmi(value), &non_smi_value); + GotoIfNot(TaggedIsSmi(value), &non_smi_value); // If we're about to introduce holes, ensure holey elements. if (update_length == kBumpLengthWithGap) { TryChangeToHoleyMapMulti(receiver, receiver_map, elements_kind, context, @@ -461,6 +469,8 @@ void KeyedStoreGenericAssembler::EmitGenericElementStore( // Out-of-capacity accesses (index >= capacity) jump here. Additionally, // an ElementsKind transition might be necessary. + // The index can also be negative at this point! Jump to the runtime in that + // case to convert it to a named property. Bind(&if_grow); { Comment("Grow backing store"); @@ -537,16 +547,12 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( { Node* descriptors = var_meta_storage.value(); Node* name_index = var_entry.value(); - // TODO(jkummerow): Add helper functions for accessing value and - // details by entry. - const int kNameToDetailsOffset = (DescriptorArray::kDescriptorDetails - - DescriptorArray::kDescriptorKey) * - kPointerSize; - Node* details = LoadAndUntagToWord32FixedArrayElement( - descriptors, name_index, kNameToDetailsOffset); + Node* details = + LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); JumpIfDataProperty(details, &ok_to_write, readonly); // Accessor case. + // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject. Variable var_details(this, MachineRepresentation::kWord32); LoadPropertyFromFastObject(holder, holder_map, descriptors, name_index, &var_details, var_accessor_pair); @@ -558,19 +564,13 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( { Node* dictionary = var_meta_storage.value(); Node* entry = var_entry.value(); - const int kNameToDetailsOffset = (NameDictionary::kEntryDetailsIndex - - NameDictionary::kEntryKeyIndex) * - kPointerSize; - Node* details = LoadAndUntagToWord32FixedArrayElement( - dictionary, entry, kNameToDetailsOffset); + Node* details = + LoadDetailsByKeyIndex<NameDictionary>(dictionary, entry); JumpIfDataProperty(details, &ok_to_write, readonly); // Accessor case. - const int kNameToValueOffset = (NameDictionary::kEntryValueIndex - - NameDictionary::kEntryKeyIndex) * - kPointerSize; var_accessor_pair->Bind( - LoadFixedArrayElement(dictionary, entry, kNameToValueOffset)); + LoadValueByKeyIndex<NameDictionary>(dictionary, entry)); var_accessor_holder->Bind(holder); Goto(accessor); } @@ -579,13 +579,8 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( { Node* dictionary = var_meta_storage.value(); Node* entry = var_entry.value(); - const int kNameToValueOffset = (GlobalDictionary::kEntryValueIndex - - GlobalDictionary::kEntryKeyIndex) * - kPointerSize; - Node* property_cell = - LoadFixedArrayElement(dictionary, entry, kNameToValueOffset); - + LoadValueByKeyIndex<GlobalDictionary>(dictionary, entry); Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); GotoIf(WordEqual(value, TheHoleConstant()), &next_proto); @@ -613,6 +608,146 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( Bind(&ok_to_write); } +void KeyedStoreGenericAssembler::CheckFieldType(Node* descriptors, + Node* name_index, + Node* representation, + Node* value, Label* bailout) { + Label r_smi(this), r_double(this), r_heapobject(this), all_fine(this); + // Ignore FLAG_track_fields etc. and always emit code for all checks, + // because this builtin is part of the snapshot and therefore should + // be flag independent. + GotoIf(Word32Equal(representation, Int32Constant(Representation::kSmi)), + &r_smi); + GotoIf(Word32Equal(representation, Int32Constant(Representation::kDouble)), + &r_double); + GotoIf( + Word32Equal(representation, Int32Constant(Representation::kHeapObject)), + &r_heapobject); + GotoIf(Word32Equal(representation, Int32Constant(Representation::kNone)), + bailout); + CSA_ASSERT(this, Word32Equal(representation, + Int32Constant(Representation::kTagged))); + Goto(&all_fine); + + Bind(&r_smi); + { Branch(TaggedIsSmi(value), &all_fine, bailout); } + + Bind(&r_double); + { + GotoIf(TaggedIsSmi(value), &all_fine); + Node* value_map = LoadMap(value); + // While supporting mutable HeapNumbers would be straightforward, such + // objects should not end up here anyway. + CSA_ASSERT(this, + WordNotEqual(value_map, + LoadRoot(Heap::kMutableHeapNumberMapRootIndex))); + Branch(IsHeapNumberMap(value_map), &all_fine, bailout); + } + + Bind(&r_heapobject); + { + GotoIf(TaggedIsSmi(value), bailout); + Node* field_type = + LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index); + intptr_t kNoneType = reinterpret_cast<intptr_t>(FieldType::None()); + intptr_t kAnyType = reinterpret_cast<intptr_t>(FieldType::Any()); + // FieldType::None can't hold any value. + GotoIf(WordEqual(field_type, IntPtrConstant(kNoneType)), bailout); + // FieldType::Any can hold any value. + GotoIf(WordEqual(field_type, IntPtrConstant(kAnyType)), &all_fine); + CSA_ASSERT(this, IsWeakCell(field_type)); + // Cleared WeakCells count as FieldType::None, which can't hold any value. + field_type = LoadWeakCellValue(field_type, bailout); + // FieldType::Class(...) performs a map check. + CSA_ASSERT(this, IsMap(field_type)); + Branch(WordEqual(LoadMap(value), field_type), &all_fine, bailout); + } + + Bind(&all_fine); +} + +void KeyedStoreGenericAssembler::OverwriteExistingFastProperty( + Node* object, Node* object_map, Node* properties, Node* descriptors, + Node* descriptor_name_index, Node* details, Node* value, Label* slow) { + // Properties in descriptors can't be overwritten without map transition. + GotoIf(Word32NotEqual(DecodeWord32<PropertyDetails::LocationField>(details), + Int32Constant(kField)), + slow); + + if (FLAG_track_constant_fields) { + // TODO(ishell): Taking the slow path is not necessary if new and old + // values are identical. + GotoIf(Word32Equal(DecodeWord32<PropertyDetails::ConstnessField>(details), + Int32Constant(kConst)), + slow); + } + + Label done(this); + Node* representation = + DecodeWord32<PropertyDetails::RepresentationField>(details); + + CheckFieldType(descriptors, descriptor_name_index, representation, value, + slow); + Node* field_index = + DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details); + Node* inobject_properties = LoadMapInobjectProperties(object_map); + + Label inobject(this), backing_store(this); + Branch(UintPtrLessThan(field_index, inobject_properties), &inobject, + &backing_store); + + Bind(&inobject); + { + Node* field_offset = + IntPtrMul(IntPtrSub(LoadMapInstanceSize(object_map), + IntPtrSub(inobject_properties, field_index)), + IntPtrConstant(kPointerSize)); + Label tagged_rep(this), double_rep(this); + Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)), + &double_rep, &tagged_rep); + Bind(&double_rep); + { + Node* double_value = ChangeNumberToFloat64(value); + if (FLAG_unbox_double_fields) { + StoreObjectFieldNoWriteBarrier(object, field_offset, double_value, + MachineRepresentation::kFloat64); + } else { + Node* mutable_heap_number = LoadObjectField(object, field_offset); + StoreHeapNumberValue(mutable_heap_number, double_value); + } + Goto(&done); + } + + Bind(&tagged_rep); + { + StoreObjectField(object, field_offset, value); + Goto(&done); + } + } + + Bind(&backing_store); + { + Node* backing_store_index = IntPtrSub(field_index, inobject_properties); + Label tagged_rep(this), double_rep(this); + Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)), + &double_rep, &tagged_rep); + Bind(&double_rep); + { + Node* double_value = ChangeNumberToFloat64(value); + Node* mutable_heap_number = + LoadFixedArrayElement(properties, backing_store_index); + StoreHeapNumberValue(mutable_heap_number, double_value); + Goto(&done); + } + Bind(&tagged_rep); + { + StoreFixedArrayElement(properties, backing_store_index, value); + Goto(&done); + } + } + Bind(&done); +} + void KeyedStoreGenericAssembler::EmitGenericPropertyStore( Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow, LanguageMode language_mode) { @@ -627,10 +762,40 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( Bind(&fast_properties); { - // TODO(jkummerow): Does it make sense to support some cases here inline? - // Maybe overwrite existing writable properties? - // Maybe support map transitions? - Goto(&stub_cache); + Comment("fast property store"); + Node* bitfield3 = LoadMapBitField3(receiver_map); + Node* descriptors = LoadMapDescriptors(receiver_map); + Label descriptor_found(this); + Variable var_name_index(this, MachineType::PointerRepresentation()); + // TODO(jkummerow): Maybe look for existing map transitions? + Label* notfound = &stub_cache; + DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found, + &var_name_index, notfound); + + Bind(&descriptor_found); + { + Node* name_index = var_name_index.value(); + Node* details = + LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); + Label data_property(this); + JumpIfDataProperty(details, &data_property, &readonly); + + // Accessor case. + // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject. + Variable var_details(this, MachineRepresentation::kWord32); + LoadPropertyFromFastObject(receiver, receiver_map, descriptors, + name_index, &var_details, &var_accessor_pair); + var_accessor_holder.Bind(receiver); + Goto(&accessor); + + Bind(&data_property); + { + OverwriteExistingFastProperty(receiver, receiver_map, properties, + descriptors, name_index, details, + p->value, slow); + Return(p->value); + } + } } Bind(&dictionary_properties); @@ -646,26 +811,20 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( Bind(&dictionary_found); { Label overwrite(this); - const int kNameToDetailsOffset = (NameDictionary::kEntryDetailsIndex - - NameDictionary::kEntryKeyIndex) * - kPointerSize; - Node* details = LoadAndUntagToWord32FixedArrayElement( - properties, var_name_index.value(), kNameToDetailsOffset); + Node* details = LoadDetailsByKeyIndex<NameDictionary>( + properties, var_name_index.value()); JumpIfDataProperty(details, &overwrite, &readonly); // Accessor case. - const int kNameToValueOffset = - (NameDictionary::kEntryValueIndex - NameDictionary::kEntryKeyIndex) * - kPointerSize; - var_accessor_pair.Bind(LoadFixedArrayElement( - properties, var_name_index.value(), kNameToValueOffset)); + var_accessor_pair.Bind(LoadValueByKeyIndex<NameDictionary>( + properties, var_name_index.value())); var_accessor_holder.Bind(receiver); Goto(&accessor); Bind(&overwrite); { - StoreFixedArrayElement(properties, var_name_index.value(), p->value, - UPDATE_WRITE_BARRIER, kNameToValueOffset); + StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(), + p->value); Return(p->value); } } @@ -690,7 +849,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( Node* setter_map = LoadMap(setter); // FunctionTemplateInfo setters are not supported yet. GotoIf(IsFunctionTemplateInfoMap(setter_map), slow); - GotoUnless(IsCallableMap(setter_map), ¬_callable); + GotoIfNot(IsCallableMap(setter_map), ¬_callable); Callable callable = CodeFactory::Call(isolate()); CallJS(callable, p->context, setter, receiver, p->value); @@ -734,7 +893,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( Bind(&found_handler); { Comment("KeyedStoreGeneric found handler"); - HandleStoreICHandlerCase(p, var_handler.value(), slow); + HandleStoreICHandlerCase(p, var_handler.value(), &stub_cache_miss); } Bind(&stub_cache_miss); { @@ -756,6 +915,8 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { Node* context = Parameter(Descriptor::kContext); Variable var_index(this, MachineType::PointerRepresentation()); + Variable var_unique(this, MachineRepresentation::kTagged); + var_unique.Bind(name); // Dummy initialization. Label if_index(this), if_unique_name(this), slow(this); GotoIf(TaggedIsSmi(receiver), &slow); @@ -767,7 +928,7 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), &slow); - TryToName(name, &if_index, &var_index, &if_unique_name, &slow); + TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique, &slow); Bind(&if_index); { @@ -779,8 +940,8 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { Bind(&if_unique_name); { Comment("key is unique name"); - KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name, - value, slot, vector); + StoreICParameters p(context, receiver, var_unique.value(), value, slot, + vector); EmitGenericPropertyStore(receiver, receiver_map, &p, &slow, language_mode); } |