Commit bc8c41c0 authored by ishell@chromium.org's avatar ishell@chromium.org

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}
parent d7169a73
...@@ -400,7 +400,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { ...@@ -400,7 +400,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
descriptor)->NowContains(value)) { descriptor)->NowContains(value)) {
Handle<HeapType> value_type(value->OptimalType( Handle<HeapType> value_type(value->OptimalType(
isolate(), expected_representation)); isolate(), expected_representation));
Map::GeneralizeFieldType(target, descriptor, value_type); Map::GeneralizeFieldType(target, descriptor,
expected_representation, value_type);
} }
DCHECK(target->instance_descriptors()->GetFieldType( DCHECK(target->instance_descriptors()->GetFieldType(
descriptor)->NowContains(value)); descriptor)->NowContains(value));
......
...@@ -2354,6 +2354,7 @@ Map* Map::FindFieldOwner(int descriptor) { ...@@ -2354,6 +2354,7 @@ Map* Map::FindFieldOwner(int descriptor) {
void Map::UpdateFieldType(int descriptor, Handle<Name> name, void Map::UpdateFieldType(int descriptor, Handle<Name> name,
Representation new_representation,
Handle<HeapType> new_type) { Handle<HeapType> new_type) {
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
PropertyDetails details = instance_descriptors()->GetDetails(descriptor); PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
...@@ -2361,13 +2362,18 @@ void Map::UpdateFieldType(int descriptor, Handle<Name> name, ...@@ -2361,13 +2362,18 @@ void Map::UpdateFieldType(int descriptor, Handle<Name> name,
if (HasTransitionArray()) { if (HasTransitionArray()) {
TransitionArray* transitions = this->transitions(); TransitionArray* transitions = this->transitions();
for (int i = 0; i < transitions->number_of_transitions(); ++i) { 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. // Skip if already updated the shared descriptor.
if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return; if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return;
FieldDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor), FieldDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
new_type, details.attributes(), details.representation()); new_type, details.attributes(), new_representation);
instance_descriptors()->Replace(descriptor, &d); instance_descriptors()->Replace(descriptor, &d);
} }
...@@ -2393,15 +2399,20 @@ Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1, ...@@ -2393,15 +2399,20 @@ Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
// static // static
void Map::GeneralizeFieldType(Handle<Map> map, void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
int modify_index, Representation new_representation,
Handle<HeapType> new_field_type) { Handle<HeapType> new_field_type) {
Isolate* isolate = map->GetIsolate(); Isolate* isolate = map->GetIsolate();
// Check if we actually need to generalize the field type at all. // Check if we actually need to generalize the field type at all.
Handle<HeapType> old_field_type( Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
map->instance_descriptors()->GetFieldType(modify_index), isolate); Representation old_representation =
if (new_field_type->NowIs(old_field_type)) { 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, DCHECK(Map::GeneralizeFieldType(old_field_type,
new_field_type, new_field_type,
isolate)->NowIs(old_field_type)); isolate)->NowIs(old_field_type));
...@@ -2420,7 +2431,8 @@ void Map::GeneralizeFieldType(Handle<Map> map, ...@@ -2420,7 +2431,8 @@ void Map::GeneralizeFieldType(Handle<Map> map,
PropertyDetails details = descriptors->GetDetails(modify_index); PropertyDetails details = descriptors->GetDetails(modify_index);
Handle<Name> name(descriptors->GetKey(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( field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
isolate, DependentCode::kFieldTypeGroup); isolate, DependentCode::kFieldTypeGroup);
...@@ -2471,12 +2483,9 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, ...@@ -2471,12 +2483,9 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
// modification to the object, because the default uninitialized value for // modification to the object, because the default uninitialized value for
// representation None can be overwritten by both smi and tagged values. // representation None can be overwritten by both smi and tagged values.
// Doubles, however, would require a box allocation. // Doubles, however, would require a box allocation.
if (old_representation.IsNone() && if (old_representation.IsNone() && !new_representation.IsNone() &&
!new_representation.IsNone() &&
!new_representation.IsDouble()) { !new_representation.IsDouble()) {
DCHECK(old_details.type() == FIELD); DCHECK(old_details.type() == FIELD);
DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(
HeapType::None()));
if (FLAG_trace_generalization) { if (FLAG_trace_generalization) {
old_map->PrintGeneralization( old_map->PrintGeneralization(
stdout, "uninitialized field", stdout, "uninitialized field",
...@@ -2485,8 +2494,13 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, ...@@ -2485,8 +2494,13 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
old_representation, new_representation, old_representation, new_representation,
old_descriptors->GetFieldType(modify_index), *new_field_type); old_descriptors->GetFieldType(modify_index), *new_field_type);
} }
old_descriptors->SetRepresentation(modify_index, new_representation); Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
old_descriptors->SetValue(modify_index, *new_field_type);
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; return old_map;
} }
...@@ -2547,7 +2561,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, ...@@ -2547,7 +2561,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
old_field_type = GeneralizeFieldType( old_field_type = GeneralizeFieldType(
new_field_type, old_field_type, isolate); 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) { } else if (tmp_type == CONSTANT) {
if (old_type != CONSTANT || if (old_type != CONSTANT ||
old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) { old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) {
......
...@@ -5825,8 +5825,8 @@ class Map: public HeapObject { ...@@ -5825,8 +5825,8 @@ class Map: public HeapObject {
Handle<HeapType> type1, Handle<HeapType> type1,
Handle<HeapType> type2, Handle<HeapType> type2,
Isolate* isolate); Isolate* isolate);
static void GeneralizeFieldType(Handle<Map> map, static void GeneralizeFieldType(Handle<Map> map, int modify_index,
int modify_index, Representation new_representation,
Handle<HeapType> new_field_type); Handle<HeapType> new_field_type);
static Handle<Map> GeneralizeRepresentation( static Handle<Map> GeneralizeRepresentation(
Handle<Map> map, Handle<Map> map,
...@@ -6377,6 +6377,7 @@ class Map: public HeapObject { ...@@ -6377,6 +6377,7 @@ class Map: public HeapObject {
Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors); Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors);
void UpdateFieldType(int descriptor_number, Handle<Name> name, void UpdateFieldType(int descriptor_number, Handle<Name> name,
Representation new_representation,
Handle<HeapType> new_type); Handle<HeapType> new_type);
void PrintGeneralization(FILE* file, void PrintGeneralization(FILE* file,
......
// 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
};
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