Skip to content

Commit 3ba21a1

Browse files
LeszekSwirskiisheludko
authored andcommitted
Merged: [map] Try to in-place transition during map update
When searching for a target map during map update, attempt to update field representations in-place to the more general representation, where possible. Bug: chromium:1143772 No-Try: true No-Presubmit: true No-Tree-Checks: true [email protected], [email protected] (cherry picked from commit 8e3ae62) Change-Id: I659890c2f08c14d1cf94242fb875c19837df2dbb Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2509599 Reviewed-by: Francis McCabe <[email protected]> Reviewed-by: Michael Hablich <[email protected]> Reviewed-by: Bill Budge <[email protected]> Reviewed-by: Igor Sheludko <[email protected]> Cr-Commit-Position: refs/branch-heads/8.6@{#44} Cr-Branched-From: a64aed2-refs/heads/8.6.395@{#1} Cr-Branched-From: a626bc0-refs/heads/master@{#69472}
1 parent 974d647 commit 3ba21a1

4 files changed

Lines changed: 124 additions & 27 deletions

File tree

src/objects/map-updater.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,17 @@ MapUpdater::State MapUpdater::FindTargetMap() {
401401
}
402402
Representation tmp_representation = tmp_details.representation();
403403
if (!old_details.representation().fits_into(tmp_representation)) {
404-
break;
404+
// Try updating the field in-place to a generalized type.
405+
Representation generalized =
406+
tmp_representation.generalize(old_details.representation());
407+
if (!tmp_representation.CanBeInPlaceChangedTo(generalized)) {
408+
break;
409+
}
410+
Handle<Map> field_owner(tmp_map->FindFieldOwner(isolate_, i), isolate_);
411+
tmp_representation = generalized;
412+
GeneralizeField(field_owner, i, tmp_details.constness(),
413+
tmp_representation,
414+
handle(tmp_descriptors->GetFieldType(i), isolate_));
405415
}
406416

407417
if (tmp_details.location() == kField) {

src/objects/map.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ void Map::DeprecateTransitionTree(Isolate* isolate) {
613613
transitions.GetTarget(i).DeprecateTransitionTree(isolate);
614614
}
615615
DCHECK(!constructor_or_backpointer().IsFunctionTemplateInfo());
616+
DCHECK(CanBeDeprecated());
616617
set_is_deprecated(true);
617618
if (FLAG_trace_maps) {
618619
LOG(isolate, MapEvent("Deprecate", handle(*this, isolate), Handle<Map>()));

test/cctest/test-field-type-tracking.cc

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,8 @@ namespace {
10381038
// where "p2A" and "p2B" differ only in the attributes.
10391039
//
10401040
void TestReconfigureDataFieldAttribute_GeneralizeField(
1041-
const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
1041+
const CRFTData& from, const CRFTData& to, const CRFTData& expected,
1042+
bool expected_deprecation) {
10421043
Isolate* isolate = CcTest::i_isolate();
10431044

10441045
Expectations expectations(isolate);
@@ -1107,24 +1108,29 @@ void TestReconfigureDataFieldAttribute_GeneralizeField(
11071108
CHECK_NE(*map2, *new_map);
11081109
CHECK(expectations2.Check(*map2));
11091110

1110-
// |map| should be deprecated and |new_map| should match new expectations.
11111111
for (int i = kSplitProp; i < kPropCount; i++) {
11121112
expectations.SetDataField(i, expected.constness, expected.representation,
11131113
expected.type);
11141114
}
1115-
CHECK(map->is_deprecated());
1116-
CHECK(!code_field_type->marked_for_deoptimization());
1117-
CHECK(!code_field_repr->marked_for_deoptimization());
1118-
CHECK(!code_field_const->marked_for_deoptimization());
1119-
CHECK_NE(*map, *new_map);
1115+
if (expected_deprecation) {
1116+
// |map| should be deprecated and |new_map| should match new expectations.
1117+
CHECK(map->is_deprecated());
1118+
CHECK(!code_field_type->marked_for_deoptimization());
1119+
CHECK(!code_field_repr->marked_for_deoptimization());
1120+
CHECK(!code_field_const->marked_for_deoptimization());
1121+
CHECK_NE(*map, *new_map);
11201122

1121-
CHECK(!new_map->is_deprecated());
1122-
CHECK(expectations.Check(*new_map));
1123+
CHECK(!new_map->is_deprecated());
1124+
CHECK(expectations.Check(*new_map));
11231125

1124-
// Update deprecated |map|, it should become |new_map|.
1125-
Handle<Map> updated_map = Map::Update(isolate, map);
1126-
CHECK_EQ(*new_map, *updated_map);
1127-
CheckMigrationTarget(isolate, *map, *updated_map);
1126+
// Update deprecated |map|, it should become |new_map|.
1127+
Handle<Map> updated_map = Map::Update(isolate, map);
1128+
CHECK_EQ(*new_map, *updated_map);
1129+
CheckMigrationTarget(isolate, *map, *updated_map);
1130+
} else {
1131+
CHECK(!map->is_deprecated());
1132+
CHECK(expectations.Check(*map));
1133+
}
11281134
}
11291135

11301136
// This test ensures that trivial field generalization (from HeapObject to
@@ -1240,22 +1246,22 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
12401246
TestReconfigureDataFieldAttribute_GeneralizeField(
12411247
{PropertyConstness::kConst, Representation::Smi(), any_type},
12421248
{PropertyConstness::kConst, Representation::Double(), any_type},
1243-
{PropertyConstness::kConst, Representation::Double(), any_type});
1249+
{PropertyConstness::kConst, Representation::Double(), any_type}, true);
12441250

12451251
TestReconfigureDataFieldAttribute_GeneralizeField(
12461252
{PropertyConstness::kConst, Representation::Smi(), any_type},
12471253
{PropertyConstness::kMutable, Representation::Double(), any_type},
1248-
{PropertyConstness::kMutable, Representation::Double(), any_type});
1254+
{PropertyConstness::kMutable, Representation::Double(), any_type}, true);
12491255

12501256
TestReconfigureDataFieldAttribute_GeneralizeField(
12511257
{PropertyConstness::kMutable, Representation::Smi(), any_type},
12521258
{PropertyConstness::kConst, Representation::Double(), any_type},
1253-
{PropertyConstness::kMutable, Representation::Double(), any_type});
1259+
{PropertyConstness::kMutable, Representation::Double(), any_type}, true);
12541260

12551261
TestReconfigureDataFieldAttribute_GeneralizeField(
12561262
{PropertyConstness::kMutable, Representation::Smi(), any_type},
12571263
{PropertyConstness::kMutable, Representation::Double(), any_type},
1258-
{PropertyConstness::kMutable, Representation::Double(), any_type});
1264+
{PropertyConstness::kMutable, Representation::Double(), any_type}, true);
12591265
}
12601266

12611267
TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
@@ -1270,22 +1276,26 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
12701276
TestReconfigureDataFieldAttribute_GeneralizeField(
12711277
{PropertyConstness::kConst, Representation::Smi(), any_type},
12721278
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
1273-
{PropertyConstness::kConst, Representation::Tagged(), any_type});
1279+
{PropertyConstness::kConst, Representation::Tagged(), any_type},
1280+
!FLAG_modify_field_representation_inplace);
12741281

12751282
TestReconfigureDataFieldAttribute_GeneralizeField(
12761283
{PropertyConstness::kConst, Representation::Smi(), any_type},
12771284
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
1278-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1285+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1286+
!FLAG_modify_field_representation_inplace);
12791287

12801288
TestReconfigureDataFieldAttribute_GeneralizeField(
12811289
{PropertyConstness::kMutable, Representation::Smi(), any_type},
12821290
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
1283-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1291+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1292+
!FLAG_modify_field_representation_inplace);
12841293

12851294
TestReconfigureDataFieldAttribute_GeneralizeField(
12861295
{PropertyConstness::kMutable, Representation::Smi(), any_type},
12871296
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
1288-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1297+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1298+
!FLAG_modify_field_representation_inplace);
12891299
}
12901300

12911301
TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
@@ -1300,22 +1310,26 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
13001310
TestReconfigureDataFieldAttribute_GeneralizeField(
13011311
{PropertyConstness::kConst, Representation::Double(), any_type},
13021312
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
1303-
{PropertyConstness::kConst, Representation::Tagged(), any_type});
1313+
{PropertyConstness::kConst, Representation::Tagged(), any_type},
1314+
FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
13041315

13051316
TestReconfigureDataFieldAttribute_GeneralizeField(
13061317
{PropertyConstness::kConst, Representation::Double(), any_type},
13071318
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
1308-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1319+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1320+
FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
13091321

13101322
TestReconfigureDataFieldAttribute_GeneralizeField(
13111323
{PropertyConstness::kMutable, Representation::Double(), any_type},
13121324
{PropertyConstness::kConst, Representation::HeapObject(), value_type},
1313-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1325+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1326+
FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
13141327

13151328
TestReconfigureDataFieldAttribute_GeneralizeField(
13161329
{PropertyConstness::kMutable, Representation::Double(), any_type},
13171330
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
1318-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1331+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1332+
FLAG_unbox_double_fields || !FLAG_modify_field_representation_inplace);
13191333
}
13201334

13211335
TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
@@ -1401,7 +1415,8 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
14011415
TestReconfigureDataFieldAttribute_GeneralizeField(
14021416
{PropertyConstness::kMutable, Representation::HeapObject(), value_type},
14031417
{PropertyConstness::kMutable, Representation::Smi(), any_type},
1404-
{PropertyConstness::kMutable, Representation::Tagged(), any_type});
1418+
{PropertyConstness::kMutable, Representation::Tagged(), any_type},
1419+
!FLAG_modify_field_representation_inplace);
14051420
}
14061421

14071422
// Checks that given |map| is deprecated and that it updates to given |new_map|
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2020 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
//
5+
// Flags: --allow-natives-syntax
6+
7+
(function() {
8+
// Only run this test if doubles are transitioned in-place to tagged.
9+
let x = {};
10+
x.a = 0.1;
11+
let y = {};
12+
y.a = {};
13+
if (!%HaveSameMap(x, y)) return;
14+
15+
// m1: {}
16+
let m1 = {};
17+
18+
// m2: {a:d}
19+
let m2 = {};
20+
assertTrue(%HaveSameMap(m2, m1));
21+
m2.a = 13.37;
22+
23+
// m3: {a:d, b:s}
24+
let m3 = {};
25+
m3.a = 13.37;
26+
assertTrue(%HaveSameMap(m3, m2));
27+
m3.b = 1;
28+
29+
// m4: {a:d, b:s, c:h}
30+
let m4 = {};
31+
m4.a = 13.37;
32+
m4.b = 1;
33+
assertTrue(%HaveSameMap(m4, m3));
34+
m4.c = {};
35+
36+
// m4_2 == m4
37+
let m4_2 = {};
38+
m4_2.a = 13.37;
39+
m4_2.b = 1;
40+
m4_2.c = {};
41+
assertTrue(%HaveSameMap(m4_2, m4));
42+
43+
// m5: {a:d, b:d}
44+
let m5 = {};
45+
m5.a = 13.37;
46+
assertTrue(%HaveSameMap(m5, m2));
47+
m5.b = 13.37;
48+
assertFalse(%HaveSameMap(m5, m3));
49+
50+
// At this point, Map3 and Map4 are both deprecated. Map2 transitions to
51+
// Map5. Map5 is the migration target for Map3.
52+
assertFalse(%HaveSameMap(m5, m3));
53+
54+
// m6: {a:d, b:d, c:d}
55+
let m6 = {};
56+
m6.a = 13.37;
57+
assertTrue(%HaveSameMap(m6, m2));
58+
m6.b = 13.37;
59+
assertTrue(%HaveSameMap(m6, m5));
60+
m6.c = 13.37
61+
62+
// Make m7: {a:d, b:d, c:t}
63+
let m7 = m4_2;
64+
assertTrue(%HaveSameMap(m7, m4));
65+
// Map4 is deprecated, so this property access triggers a Map migration.
66+
// With in-place map updates and no double unboxing, this should end up
67+
// migrating to Map6, and updating it in-place.
68+
m7.c;
69+
assertFalse(%HaveSameMap(m7, m4));
70+
assertTrue(%HaveSameMap(m6, m7));
71+
})();

0 commit comments

Comments
 (0)