Commit 0f159f59 authored by ishell's avatar ishell Committed by Commit bot

[runtime] Add MapUpdater class that manages all kinds of map updates.

... including property reconfiguring, elements kind change and migration
of a map to an up-to-date non-deprecated version.

BUG=v8:5495

Review-Url: https://codereview.chromium.org/2601643002
Cr-Commit-Position: refs/heads/master@{#42177}
parent 8dfea24e
......@@ -1539,6 +1539,8 @@ v8_source_set("v8_base") {
"src/machine-type.cc",
"src/machine-type.h",
"src/macro-assembler.h",
"src/map-updater.cc",
"src/map-updater.h",
"src/messages.cc",
"src/messages.h",
"src/msan.h",
......
......@@ -399,8 +399,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
->NowContains(value)) {
Handle<FieldType> value_type(
value->OptimalType(isolate(), expected_representation));
Map::GeneralizeFieldType(target, descriptor,
expected_representation, value_type);
Map::GeneralizeField(target, descriptor, expected_representation,
value_type);
}
DCHECK(target->instance_descriptors()
->GetFieldType(descriptor)
......
This diff is collapsed.
// 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_
......@@ -3040,26 +3040,6 @@ FixedArrayBase* Map::GetInitialElements() {
return result;
}
// static
Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index,
PropertyKind new_kind,
PropertyAttributes new_attributes,
Representation new_representation,
Handle<FieldType> new_field_type,
StoreMode store_mode) {
return Reconfigure(map, map->elements_kind(), modify_index, new_kind,
new_attributes, new_representation, new_field_type,
store_mode);
}
// static
Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map,
ElementsKind new_elements_kind) {
return Reconfigure(map, new_elements_kind, -1, kData, NONE,
Representation::None(), FieldType::None(map->GetIsolate()),
ALLOW_IN_DESCRIPTOR);
}
Object** DescriptorArray::GetKeySlot(int descriptor_number) {
DCHECK(descriptor_number < number_of_descriptors());
return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
......
This diff is collapsed.
......@@ -6059,17 +6059,19 @@ class Map: public HeapObject {
MUST_USE_RESULT static Handle<FieldType> GeneralizeFieldType(
Representation rep1, Handle<FieldType> type1, Representation rep2,
Handle<FieldType> type2, Isolate* isolate);
static void GeneralizeFieldType(Handle<Map> map, int modify_index,
static void GeneralizeField(Handle<Map> map, int modify_index,
Representation new_representation,
Handle<FieldType> new_field_type);
static inline Handle<Map> ReconfigureProperty(
Handle<Map> map, int modify_index, PropertyKind new_kind,
PropertyAttributes new_attributes, Representation new_representation,
Handle<FieldType> new_field_type, StoreMode store_mode);
static Handle<Map> ReconfigureProperty(Handle<Map> map, int modify_index,
PropertyKind new_kind,
PropertyAttributes new_attributes,
Representation new_representation,
Handle<FieldType> new_field_type,
StoreMode store_mode);
static inline Handle<Map> ReconfigureElementsKind(
Handle<Map> map, ElementsKind new_elements_kind);
static Handle<Map> ReconfigureElementsKind(Handle<Map> map,
ElementsKind new_elements_kind);
static Handle<Map> PrepareForDataProperty(Handle<Map> old_map,
int descriptor_number,
......@@ -6192,6 +6194,8 @@ class Map: public HeapObject {
Descriptor* descriptor,
TransitionFlag flag);
static Handle<Object> WrapType(Handle<FieldType> type);
MUST_USE_RESULT static MaybeHandle<Map> CopyWithField(
Handle<Map> map, Handle<Name> name, Handle<FieldType> type,
PropertyAttributes attributes, Representation representation,
......@@ -6504,14 +6508,7 @@ class Map: public HeapObject {
static Handle<Map> CopyNormalized(Handle<Map> map,
PropertyNormalizationMode mode);
static Handle<Map> Reconfigure(Handle<Map> map,
ElementsKind new_elements_kind,
int modify_index, PropertyKind new_kind,
PropertyAttributes new_attributes,
Representation new_representation,
Handle<FieldType> new_field_type,
StoreMode store_mode);
// TODO(ishell): Move to MapUpdater.
static Handle<Map> CopyGeneralizeAllRepresentations(
Handle<Map> map, ElementsKind elements_kind, int modify_index,
StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
......@@ -6528,8 +6525,6 @@ class Map: public HeapObject {
LayoutDescriptor* new_layout_descriptor);
Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors);
// Update field type of the given descriptor to new representation and new
// type. The type must be prepared for storing in descriptor array:
// it must be either a simple type or a map wrapped in a weak cell.
......@@ -6537,8 +6532,10 @@ class Map: public HeapObject {
Representation new_representation,
Handle<Object> new_wrapped_type);
// TODO(ishell): Move to MapUpdater.
void PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
PropertyAttributes attributes);
// TODO(ishell): Move to MapUpdater.
void PrintGeneralization(FILE* file, const char* reason, int modify_index,
int split, int descriptors, bool constant_to_field,
Representation old_representation,
......@@ -6547,10 +6544,11 @@ class Map: public HeapObject {
MaybeHandle<Object> old_value,
MaybeHandle<FieldType> new_field_type,
MaybeHandle<Object> new_value);
static const int kFastPropertiesSoftLimit = 12;
static const int kMaxFastProperties = 128;
friend class MapUpdater;
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};
......
......@@ -254,7 +254,7 @@ class PropertyDetails BASE_EMBEDDED {
| FieldIndexField::encode(field_index);
}
PropertyDetails(PropertyAttributes attributes, PropertyKind kind,
PropertyDetails(PropertyKind kind, PropertyAttributes attributes,
PropertyLocation location, Representation representation,
int field_index = 0) {
value_ = KindField::encode(kind) | LocationField::encode(location) |
......
......@@ -85,6 +85,7 @@ class Descriptor final BASE_EMBEDDED {
friend class DescriptorArray;
friend class Map;
friend class MapUpdater;
};
std::ostream& operator<<(std::ostream& os, const Descriptor& d);
......
......@@ -1060,6 +1060,8 @@
'lookup-cache.h',
'lookup.cc',
'lookup.h',
'map-updater.cc',
'map-updater.h',
'macro-assembler.h',
'machine-type.cc',
'machine-type.h',
......
......@@ -1664,8 +1664,8 @@ Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
->NowContains(value)) {
Handle<FieldType> value_type =
value->OptimalType(isolate_, expected_representation);
Map::GeneralizeFieldType(target, descriptor,
expected_representation, value_type);
Map::GeneralizeField(target, descriptor, expected_representation,
value_type);
}
DCHECK(target->instance_descriptors()
->GetFieldType(descriptor)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment