Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2d9540e

Browse files
committedMay 25, 2020
deps: V8: cherry-pick 548f6c81d424
Original commit message: [runtime] Don't track transitions for certainly detached maps Previously such maps were marked as prototype, but that has bad performance / memory characteristics if objects are used as dictionaries. Bug: b:148346655, v8:10339 Change-Id: I287c5664c8b7799a084669aaaffe3affcf73e95f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2179322 Reviewed-by: Igor Sheludko <[email protected]> Commit-Queue: Toon Verwaest <[email protected]> Cr-Commit-Position: refs/heads/master@{#67537} Refs: v8/v8@548f6c8 PR-URL: nodejs#33484 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matheus Marchini <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
1 parent 5c0232a commit 2d9540e

File tree

5 files changed

+30
-22
lines changed

5 files changed

+30
-22
lines changed
 

‎common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
# Reset this number to 0 on major V8 upgrades.
3636
# Increment by one for each non-official patch applied to deps/v8.
37-
'v8_embedder_string': '-node.37',
37+
'v8_embedder_string': '-node.38',
3838

3939
##### V8 defaults for Node.js #####
4040

‎deps/v8/src/json/json-parser.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ MaybeHandle<Object> JsonParser<Char>::ParseJsonValue() {
828828
Map maybe_feedback = JSObject::cast(*element_stack.back()).map();
829829
// Don't consume feedback from objects with a map that's detached
830830
// from the transition tree.
831-
if (!maybe_feedback.GetBackPointer().IsUndefined(isolate_)) {
831+
if (!maybe_feedback.IsDetached(isolate_)) {
832832
feedback = handle(maybe_feedback, isolate_);
833833
}
834834
}

‎deps/v8/src/objects/map-inl.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ bool Map::CanHaveFastTransitionableElementsKind() const {
119119
return CanHaveFastTransitionableElementsKind(instance_type());
120120
}
121121

122+
bool Map::IsDetached(Isolate* isolate) const {
123+
if (is_prototype_map()) return true;
124+
return instance_type() == JS_OBJECT_TYPE && NumberOfOwnDescriptors() > 0 &&
125+
GetBackPointer().IsUndefined(isolate);
126+
}
127+
122128
// static
123129
void Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
124130
Isolate* isolate, InstanceType instance_type,
@@ -697,7 +703,10 @@ void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) {
697703

698704
DEF_GETTER(Map, GetBackPointer, HeapObject) {
699705
Object object = constructor_or_backpointer(isolate);
700-
if (object.IsMap(isolate)) {
706+
// This is the equivalent of IsMap() but avoids reading the instance type so
707+
// it can be used concurrently without acquire load.
708+
if (object.IsHeapObject() && HeapObject::cast(object).map(isolate) ==
709+
GetReadOnlyRoots(isolate).meta_map()) {
701710
return Map::cast(object);
702711
}
703712
// Can't use ReadOnlyRoots(isolate) as this isolate could be produced by

‎deps/v8/src/objects/map.cc

+13-19
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ Map Map::FindRootMap(Isolate* isolate) const {
646646
// Initial map always owns descriptors and doesn't have unused entries
647647
// in the descriptor array.
648648
DCHECK(result.owns_descriptors());
649-
DCHECK_EQ(result.NumberOfOwnDescriptors(),
649+
DCHECK_LE(result.NumberOfOwnDescriptors(),
650650
result.instance_descriptors().number_of_descriptors());
651651
return result;
652652
}
@@ -1192,7 +1192,7 @@ Map Map::FindElementsKindTransitionedMap(Isolate* isolate,
11921192
DisallowHeapAllocation no_allocation;
11931193
DisallowDeoptimization no_deoptimization(isolate);
11941194

1195-
if (is_prototype_map()) return Map();
1195+
if (IsDetached(isolate)) return Map();
11961196

11971197
ElementsKind kind = elements_kind();
11981198
bool packed = IsFastPackedElementsKind(kind);
@@ -1325,7 +1325,7 @@ static Handle<Map> AddMissingElementsTransitions(Isolate* isolate,
13251325

13261326
ElementsKind kind = map->elements_kind();
13271327
TransitionFlag flag;
1328-
if (map->is_prototype_map()) {
1328+
if (map->IsDetached(isolate)) {
13291329
flag = OMIT_TRANSITION;
13301330
} else {
13311331
flag = INSERT_TRANSITION;
@@ -1687,15 +1687,15 @@ void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
16871687
child->may_have_interesting_symbols());
16881688
if (!parent->GetBackPointer().IsUndefined(isolate)) {
16891689
parent->set_owns_descriptors(false);
1690-
} else {
1690+
} else if (!parent->IsDetached(isolate)) {
16911691
// |parent| is initial map and it must keep the ownership, there must be no
16921692
// descriptors in the descriptors array that do not belong to the map.
16931693
DCHECK(parent->owns_descriptors());
16941694
DCHECK_EQ(parent->NumberOfOwnDescriptors(),
16951695
parent->instance_descriptors().number_of_descriptors());
16961696
}
1697-
if (parent->is_prototype_map()) {
1698-
DCHECK(child->is_prototype_map());
1697+
if (parent->IsDetached(isolate)) {
1698+
DCHECK(child->IsDetached(isolate));
16991699
if (FLAG_trace_maps) {
17001700
LOG(isolate, MapEvent("Transition", *parent, *child, "prototype", *name));
17011701
}
@@ -1722,7 +1722,9 @@ Handle<Map> Map::CopyReplaceDescriptors(
17221722
result->set_may_have_interesting_symbols(true);
17231723
}
17241724

1725-
if (!map->is_prototype_map()) {
1725+
if (map->is_prototype_map()) {
1726+
result->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
1727+
} else {
17261728
if (flag == INSERT_TRANSITION &&
17271729
TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
17281730
result->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
@@ -1733,19 +1735,11 @@ Handle<Map> Map::CopyReplaceDescriptors(
17331735
descriptors->GeneralizeAllFields();
17341736
result->InitializeDescriptors(isolate, *descriptors,
17351737
LayoutDescriptor::FastPointerLayout());
1736-
// If we were trying to insert a transition but failed because there are
1737-
// too many transitions already, mark the object as a prototype to avoid
1738-
// tracking transitions from the detached map.
1739-
if (flag == INSERT_TRANSITION) {
1740-
result->set_is_prototype_map(true);
1741-
}
17421738
}
1743-
} else {
1744-
result->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
17451739
}
17461740
if (FLAG_trace_maps &&
17471741
// Mirror conditions above that did not call ConnectTransition().
1748-
(map->is_prototype_map() ||
1742+
(map->IsDetached(isolate) ||
17491743
!(flag == INSERT_TRANSITION &&
17501744
TransitionsAccessor(isolate, map).CanHaveMoreTransitions()))) {
17511745
LOG(isolate, MapEvent("ReplaceDescriptors", *map, *result, reason,
@@ -1926,7 +1920,7 @@ Handle<Map> Map::AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
19261920
}
19271921

19281922
Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) {
1929-
DCHECK(!map->is_prototype_map());
1923+
DCHECK(!map->IsDetached(isolate));
19301924
Handle<Map> new_map = CopyDropDescriptors(isolate, map);
19311925

19321926
if (map->owns_descriptors()) {
@@ -2126,7 +2120,7 @@ Handle<Map> Map::TransitionToDataProperty(Isolate* isolate, Handle<Map> map,
21262120
StoreOrigin store_origin) {
21272121
RuntimeCallTimerScope stats_scope(
21282122
isolate, *map,
2129-
map->is_prototype_map()
2123+
map->IsDetached(isolate)
21302124
? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
21312125
: RuntimeCallCounterId::kMap_TransitionToDataProperty);
21322126

@@ -2238,7 +2232,7 @@ Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
22382232
PropertyAttributes attributes) {
22392233
RuntimeCallTimerScope stats_scope(
22402234
isolate,
2241-
map->is_prototype_map()
2235+
map->IsDetached(isolate)
22422236
? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty
22432237
: RuntimeCallCounterId::kMap_TransitionToAccessorProperty);
22442238

‎deps/v8/src/objects/map.h

+5
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,11 @@ class Map : public HeapObject {
428428
inline bool has_sealed_elements() const;
429429
inline bool has_frozen_elements() const;
430430

431+
// Weakly checks whether a map is detached from all transition trees. If this
432+
// returns true, the map is guaranteed to be detached. If it returns false,
433+
// there is no guarantee it is attached.
434+
inline bool IsDetached(Isolate* isolate) const;
435+
431436
// Returns true if the current map doesn't have DICTIONARY_ELEMENTS but if a
432437
// map with DICTIONARY_ELEMENTS was found in the prototype chain.
433438
bool DictionaryElementsInPrototypeChainOnly(Isolate* isolate);

0 commit comments

Comments
 (0)
Please sign in to comment.