Avoid fast short-cut in Map::GeneralizeRepresentation() for literals with non-simple transitions.
It started showing after r25253. BUG=v8:3687 LOG=N R=verwaest@chromium.org Review URL: https://codereview.chromium.org/715313003 Cr-Commit-Position: refs/heads/master@{#25324}
This commit is contained in:
parent
d7169a7311
commit
bc8c41c08d
@ -400,7 +400,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
|
||||
descriptor)->NowContains(value)) {
|
||||
Handle<HeapType> value_type(value->OptimalType(
|
||||
isolate(), expected_representation));
|
||||
Map::GeneralizeFieldType(target, descriptor, value_type);
|
||||
Map::GeneralizeFieldType(target, descriptor,
|
||||
expected_representation, value_type);
|
||||
}
|
||||
DCHECK(target->instance_descriptors()->GetFieldType(
|
||||
descriptor)->NowContains(value));
|
||||
|
@ -2354,6 +2354,7 @@ Map* Map::FindFieldOwner(int descriptor) {
|
||||
|
||||
|
||||
void Map::UpdateFieldType(int descriptor, Handle<Name> name,
|
||||
Representation new_representation,
|
||||
Handle<HeapType> new_type) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
|
||||
@ -2361,13 +2362,18 @@ void Map::UpdateFieldType(int descriptor, Handle<Name> name,
|
||||
if (HasTransitionArray()) {
|
||||
TransitionArray* transitions = this->transitions();
|
||||
for (int i = 0; i < transitions->number_of_transitions(); ++i) {
|
||||
transitions->GetTarget(i)->UpdateFieldType(descriptor, name, new_type);
|
||||
transitions->GetTarget(i)
|
||||
->UpdateFieldType(descriptor, name, new_representation, new_type);
|
||||
}
|
||||
}
|
||||
// It is allowed to change representation here only from None to something.
|
||||
DCHECK(details.representation().Equals(new_representation) ||
|
||||
details.representation().IsNone());
|
||||
|
||||
// Skip if already updated the shared descriptor.
|
||||
if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return;
|
||||
FieldDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
|
||||
new_type, details.attributes(), details.representation());
|
||||
new_type, details.attributes(), new_representation);
|
||||
instance_descriptors()->Replace(descriptor, &d);
|
||||
}
|
||||
|
||||
@ -2393,15 +2399,20 @@ Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
|
||||
|
||||
|
||||
// static
|
||||
void Map::GeneralizeFieldType(Handle<Map> map,
|
||||
int modify_index,
|
||||
void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
|
||||
Representation new_representation,
|
||||
Handle<HeapType> new_field_type) {
|
||||
Isolate* isolate = map->GetIsolate();
|
||||
|
||||
// Check if we actually need to generalize the field type at all.
|
||||
Handle<HeapType> old_field_type(
|
||||
map->instance_descriptors()->GetFieldType(modify_index), isolate);
|
||||
if (new_field_type->NowIs(old_field_type)) {
|
||||
Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
|
||||
Representation old_representation =
|
||||
old_descriptors->GetDetails(modify_index).representation();
|
||||
Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
|
||||
isolate);
|
||||
|
||||
if (old_representation.Equals(new_representation) &&
|
||||
new_field_type->NowIs(old_field_type)) {
|
||||
DCHECK(Map::GeneralizeFieldType(old_field_type,
|
||||
new_field_type,
|
||||
isolate)->NowIs(old_field_type));
|
||||
@ -2420,7 +2431,8 @@ void Map::GeneralizeFieldType(Handle<Map> map,
|
||||
|
||||
PropertyDetails details = descriptors->GetDetails(modify_index);
|
||||
Handle<Name> name(descriptors->GetKey(modify_index));
|
||||
field_owner->UpdateFieldType(modify_index, name, new_field_type);
|
||||
field_owner->UpdateFieldType(modify_index, name, new_representation,
|
||||
new_field_type);
|
||||
field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
|
||||
isolate, DependentCode::kFieldTypeGroup);
|
||||
|
||||
@ -2471,12 +2483,9 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
||||
// modification to the object, because the default uninitialized value for
|
||||
// representation None can be overwritten by both smi and tagged values.
|
||||
// Doubles, however, would require a box allocation.
|
||||
if (old_representation.IsNone() &&
|
||||
!new_representation.IsNone() &&
|
||||
if (old_representation.IsNone() && !new_representation.IsNone() &&
|
||||
!new_representation.IsDouble()) {
|
||||
DCHECK(old_details.type() == FIELD);
|
||||
DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(
|
||||
HeapType::None()));
|
||||
if (FLAG_trace_generalization) {
|
||||
old_map->PrintGeneralization(
|
||||
stdout, "uninitialized field",
|
||||
@ -2485,8 +2494,13 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
||||
old_representation, new_representation,
|
||||
old_descriptors->GetFieldType(modify_index), *new_field_type);
|
||||
}
|
||||
old_descriptors->SetRepresentation(modify_index, new_representation);
|
||||
old_descriptors->SetValue(modify_index, *new_field_type);
|
||||
Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
|
||||
|
||||
GeneralizeFieldType(field_owner, modify_index, new_representation,
|
||||
new_field_type);
|
||||
DCHECK(old_descriptors->GetDetails(modify_index).representation().Equals(
|
||||
new_representation));
|
||||
DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
|
||||
return old_map;
|
||||
}
|
||||
|
||||
@ -2547,7 +2561,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
||||
old_field_type = GeneralizeFieldType(
|
||||
new_field_type, old_field_type, isolate);
|
||||
}
|
||||
GeneralizeFieldType(tmp_map, i, old_field_type);
|
||||
GeneralizeFieldType(tmp_map, i, tmp_representation, old_field_type);
|
||||
} else if (tmp_type == CONSTANT) {
|
||||
if (old_type != CONSTANT ||
|
||||
old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) {
|
||||
|
@ -5825,8 +5825,8 @@ class Map: public HeapObject {
|
||||
Handle<HeapType> type1,
|
||||
Handle<HeapType> type2,
|
||||
Isolate* isolate);
|
||||
static void GeneralizeFieldType(Handle<Map> map,
|
||||
int modify_index,
|
||||
static void GeneralizeFieldType(Handle<Map> map, int modify_index,
|
||||
Representation new_representation,
|
||||
Handle<HeapType> new_field_type);
|
||||
static Handle<Map> GeneralizeRepresentation(
|
||||
Handle<Map> map,
|
||||
@ -6377,6 +6377,7 @@ class Map: public HeapObject {
|
||||
Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors);
|
||||
|
||||
void UpdateFieldType(int descriptor_number, Handle<Name> name,
|
||||
Representation new_representation,
|
||||
Handle<HeapType> new_type);
|
||||
|
||||
void PrintGeneralization(FILE* file,
|
||||
|
22
test/mjsunit/regress/regress-3687.js
Normal file
22
test/mjsunit/regress/regress-3687.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var t1 = { f1: 0 };
|
||||
var t2 = { f2: 0 };
|
||||
|
||||
var z = {
|
||||
x: {
|
||||
x: t1,
|
||||
y: {
|
||||
x: {},
|
||||
z1: {
|
||||
x: t2,
|
||||
y: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
z2: 0
|
||||
};
|
Loading…
Reference in New Issue
Block a user