| Index: src/map-updater.h
|
| diff --git a/src/map-updater.h b/src/map-updater.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9b192f2c6d34a829b756aacd6e94f8aa0b00b2c5
|
| --- /dev/null
|
| +++ b/src/map-updater.h
|
| @@ -0,0 +1,173 @@
|
| +// Copyright 2017 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef V8_MAP_RECONFIGURER_H_
|
| +#define V8_MAP_RECONFIGURER_H_
|
| +
|
| +#include "src/elements-kind.h"
|
| +#include "src/globals.h"
|
| +#include "src/handles.h"
|
| +#include "src/objects.h"
|
| +#include "src/property-details.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +// The |MapUpdater| class implements all sorts of map reconfigurations
|
| +// including changes of elements kind, property attributes, property kind,
|
| +// property location and field representations/type changes. It ensures that
|
| +// the reconfigured map and all the intermediate maps are properly integrated
|
| +// into the exising transition tree.
|
| +//
|
| +// To avoid high degrees over polymorphism, and to stabilize quickly, on every
|
| +// rewrite the new type is deduced by merging the current type with any
|
| +// potential new (partial) version of the type in the transition tree.
|
| +// To do this, on each rewrite:
|
| +// - Search the root of the transition tree using FindRootMap.
|
| +// - Find/create a |root_map| with requested |new_elements_kind|.
|
| +// - Find |target_map|, the newest matching version of this map using the
|
| +// "updated" |old_map|'s descriptor array (i.e. whose entry at |modify_index|
|
| +// is considered to be of |new_kind| and having |new_attributes|) to walk
|
| +// the transition tree.
|
| +// - Merge/generalize the "updated" descriptor array of the |old_map| and
|
| +// descriptor array of the |target_map|.
|
| +// - Generalize the |modify_index| descriptor using |new_representation| and
|
| +// |new_field_type|.
|
| +// - Walk the tree again starting from the root towards |target_map|. Stop at
|
| +// |split_map|, the first map who's descriptor array does not match the merged
|
| +// descriptor array.
|
| +// - If |target_map| == |split_map|, |target_map| is in the expected state.
|
| +// Return it.
|
| +// - Otherwise, invalidate the outdated transition target from |target_map|, and
|
| +// replace its transition tree with a new branch for the updated descriptors.
|
| +class MapUpdater {
|
| + public:
|
| + MapUpdater(Isolate* isolate, Handle<Map> old_map)
|
| + : isolate_(isolate),
|
| + old_map_(old_map),
|
| + old_descriptors_(old_map->instance_descriptors(), isolate_),
|
| + old_nof_(old_map_->NumberOfOwnDescriptors()),
|
| + new_elements_kind_(old_map_->elements_kind()) {}
|
| +
|
| + // Prepares for reconfiguring of a property at |descriptor| to data field
|
| + // with given |attributes| and |representation|/|field_type| and
|
| + // performs the steps 1-5.
|
| + Handle<Map> ReconfigureToDataField(int descriptor,
|
| + PropertyAttributes attributes,
|
| + Representation representation,
|
| + Handle<FieldType> field_type);
|
| +
|
| + // Prepares for reconfiguring elements kind and performs the steps 1-5.
|
| + Handle<Map> ReconfigureElementsKind(ElementsKind elements_kind);
|
| +
|
| + // Prepares for updating deprecated map to most up-to-date non-deprecated
|
| + // version and performs the steps 1-5.
|
| + Handle<Map> Update();
|
| +
|
| + private:
|
| + enum State { kInitialized, kAtRootMap, kAtTargetMap, kEnd };
|
| +
|
| + // Try to reconfigure property in-place without rebuilding transition tree
|
| + // and creating new maps. See implementation for details.
|
| + State TryRecofigureToDataFieldInplace();
|
| +
|
| + // Step 1.
|
| + // - Search the root of the transition tree using FindRootMap.
|
| + // - Find/create a |root_map_| with requested |new_elements_kind_|.
|
| + State FindRootMap();
|
| +
|
| + // Step 2.
|
| + // - Find |target_map_|, the newest matching version of this map using the
|
| + // "updated" |old_map|'s descriptor array (i.e. whose entry at
|
| + // |modified_descriptor_| is considered to be of |new_kind| and having
|
| + // |new_attributes|) to walk the transition tree.
|
| + State FindTargetMap();
|
| +
|
| + // Step 3.
|
| + // - Merge/generalize the "updated" descriptor array of the |old_map_| and
|
| + // descriptor array of the |target_map_|.
|
| + // - Generalize the |modified_descriptor_| using |new_representation| and
|
| + // |new_field_type_|.
|
| + Handle<DescriptorArray> BuildDescriptorArray();
|
| +
|
| + // Step 4.
|
| + // - Walk the tree again starting from the root towards |target_map|. Stop at
|
| + // |split_map|, the first map who's descriptor array does not match the
|
| + // merged descriptor array.
|
| + Handle<Map> FindSplitMap(Handle<DescriptorArray> descriptors);
|
| +
|
| + // Step 5.
|
| + // - If |target_map| == |split_map|, |target_map| is in the expected state.
|
| + // Return it.
|
| + // - Otherwise, invalidate the outdated transition target from |target_map|,
|
| + // and replace its transition tree with a new branch for the updated
|
| + // descriptors.
|
| + State ConstructNewMap();
|
| +
|
| + // When a requested reconfiguration can not be done the result is a copy
|
| + // of |old_map_| where every field has |Tagged| representation and |Any|
|
| + // field type. This map is disconnected from the transition tree.
|
| + State CopyGeneralizeAllRepresentations(const char* reason);
|
| +
|
| + // Returns name of a |descriptor| property.
|
| + inline Name* GetKey(int descriptor) const;
|
| +
|
| + // Returns property details of a |descriptor| in "updated" |old_descrtiptors_|
|
| + // array.
|
| + inline PropertyDetails GetDetails(int descriptor) const;
|
| +
|
| + // Returns value of a |descriptor| with kDescriptor location in "updated"
|
| + // |old_descrtiptors_| array.
|
| + inline Object* GetValue(int descriptor) const;
|
| +
|
| + // Returns field type for a |descriptor| with kField location in "updated"
|
| + // |old_descrtiptors_| array.
|
| + inline FieldType* GetFieldType(int descriptor) const;
|
| +
|
| + // If a |descriptor| property in "updated" |old_descriptors_| has kField
|
| + // location then returns it's field type otherwise computes optimal field
|
| + // type for the descriptor's value and |representation|. The |location|
|
| + // value must be a pre-fetched location for |descriptor|.
|
| + inline Handle<FieldType> GetOrComputeFieldType(
|
| + int descriptor, PropertyLocation location,
|
| + Representation representation) const;
|
| +
|
| + // If a |descriptor| property in given |descriptors| array has kField
|
| + // location then returns it's field type otherwise computes optimal field
|
| + // type for the descriptor's value and |representation|.
|
| + // The |location| value must be a pre-fetched location for |descriptor|.
|
| + inline Handle<FieldType> GetOrComputeFieldType(
|
| + Handle<DescriptorArray> descriptors, int descriptor,
|
| + PropertyLocation location, Representation representation);
|
| +
|
| + Isolate* isolate_;
|
| + Handle<Map> old_map_;
|
| + Handle<DescriptorArray> old_descriptors_;
|
| + Handle<Map> root_map_;
|
| + Handle<Map> target_map_;
|
| + Handle<Map> result_map_;
|
| + int old_nof_;
|
| +
|
| + State state_ = kInitialized;
|
| + ElementsKind new_elements_kind_;
|
| +
|
| + // If |modified_descriptor_| is not equal to -1 them the fields below form
|
| + // an "update" of the |old_map_|'s descriptors.
|
| + int modified_descriptor_ = -1;
|
| + PropertyKind new_kind_ = kData;
|
| + PropertyAttributes new_attributes_ = NONE;
|
| + PropertyLocation new_location_ = kField;
|
| + Representation new_representation_ = Representation::None();
|
| +
|
| + // Data specific to kField location.
|
| + Handle<FieldType> new_field_type_;
|
| +
|
| + // Data specific to kDescriptor location.
|
| + Handle<Object> new_value_;
|
| +};
|
| +
|
| +} // namespace internal
|
| +} // namespace v8
|
| +
|
| +#endif // V8_MAP_RECONFIGURER_H_
|
|
|