Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Unified Diff: src/objects.cc

Issue 167303005: Track field types. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Support transitions in LookupResult. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 897c52ade6b9003b309307e939e9456267cd8e2e..9a9fa1c8664bac479264f1814fd68b13a34e3fed 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1959,12 +1959,14 @@ static Handle<Object> NewStorageFor(Isolate* isolate,
static MaybeObject* CopyAddFieldDescriptor(Map* map,
Name* name,
- int index,
+ int field_index,
+ HeapType* field_type,
PropertyAttributes attributes,
Representation representation,
TransitionFlag flag) {
Map* new_map;
- FieldDescriptor new_field_desc(name, index, attributes, representation);
+ FieldDescriptor new_field_desc(name, field_index, field_type,
+ attributes, representation);
MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag);
if (!maybe_map->To(&new_map)) return maybe_map;
int unused_property_fields = map->unused_property_fields() - 1;
@@ -1978,13 +1980,15 @@ static MaybeObject* CopyAddFieldDescriptor(Map* map,
static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map,
Handle<Name> name,
- int index,
+ int field_index,
+ Handle<HeapType> field_type,
PropertyAttributes attributes,
Representation representation,
TransitionFlag flag) {
CALL_HEAP_FUNCTION(map->GetIsolate(),
CopyAddFieldDescriptor(
- *map, *name, index, attributes, representation, flag),
+ *map, *name, field_index, *field_type,
+ attributes, representation, flag),
Map);
}
@@ -2013,23 +2017,44 @@ void JSObject::AddFastProperty(Handle<JSObject> object,
}
// Compute the new index for new field.
- int index = object->map()->NextFreePropertyIndex();
+ int field_index = object->map()->NextFreePropertyIndex();
- // Allocate new instance descriptors with (name, index) added
+ // Compute the optimal representation for the new field.
if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
Representation representation = value->OptimalRepresentation(value_type);
+
+ // Compute the type of the new field.
+ Handle<HeapType> field_type = FLAG_track_field_types
+ ? HeapType::OfCurrently(value, isolate)
Toon Verwaest 2014/03/21 14:33:37 If it's FORCE_TAGGED we also shouldn't be tracking
Benedikt Meurer 2014/04/11 11:12:00 Done.
+ : HeapType::Any(isolate);
+ if (FLAG_trace_track_field_types) {
+#ifdef OBJECT_PRINT
+ PrintF("[Adding fast property ");
+ name->Print();
+ PrintF(" to object ");
+ object->ShortPrint();
+ PrintF(" with value ");
+ value->ShortPrint();
+ PrintF(" and field type ");
+ field_type->TypePrint(stdout);
+ PrintF("]\n");
+#endif
+ }
+
+ // Allocate new instance descriptors with (name, index) added
Handle<Map> new_map = CopyAddFieldDescriptor(
- handle(object->map()), name, index, attributes, representation, flag);
+ handle(object->map()), name, field_index,
+ field_type, attributes, representation, flag);
JSObject::MigrateToMap(object, new_map);
if (representation.IsDouble()) {
// Nothing more to be done.
if (value->IsUninitialized()) return;
- HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
+ HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index));
box->set_value(value->Number());
} else {
- object->FastPropertyAtPut(index, *value);
+ object->FastPropertyAtPut(field_index, *value);
}
}
@@ -2460,9 +2485,11 @@ Handle<TransitionArray> Map::AddTransition(Handle<Map> map,
void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
int modify_index,
Representation new_representation,
+ Handle<HeapType> new_field_type,
StoreMode store_mode) {
Handle<Map> new_map = Map::GeneralizeRepresentation(
- handle(object->map()), modify_index, new_representation, store_mode);
+ handle(object->map()), modify_index, new_representation,
+ new_field_type, store_mode);
if (object->map() == *new_map) return;
return MigrateToMap(object, new_map);
}
@@ -2486,13 +2513,20 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
Handle<Map> new_map = Copy(map);
DescriptorArray* descriptors = new_map->instance_descriptors();
- descriptors->InitializeRepresentations(Representation::Tagged());
+ int length = descriptors->number_of_descriptors();
+ for (int i = 0; i < length; i++) {
+ descriptors->SetRepresentation(i, Representation::Tagged());
+ if (descriptors->GetDetails(i).type() == FIELD) {
+ descriptors->SetValue(i, HeapType::Any());
+ }
+ }
// Unless the instance is being migrated, ensure that modify_index is a field.
PropertyDetails details = descriptors->GetDetails(modify_index);
if (store_mode == FORCE_FIELD && details.type() != FIELD) {
FieldDescriptor d(descriptors->GetKey(modify_index),
new_map->NumberOfFields(),
+ HeapType::Any(),
attributes,
Representation::Tagged());
d.SetSortedKeyIndex(details.pointer());
@@ -2623,20 +2657,64 @@ Map* Map::FindLastMatchMap(int verbatim,
Map* next = transitions->GetTarget(transition);
DescriptorArray* next_descriptors = next->instance_descriptors();
- if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
-
PropertyDetails details = descriptors->GetDetails(i);
PropertyDetails next_details = next_descriptors->GetDetails(i);
if (details.type() != next_details.type()) break;
if (details.attributes() != next_details.attributes()) break;
if (!details.representation().Equals(next_details.representation())) break;
+ // TODO(bmeurer): Check descriptors is subtype of next_descriptors.
+ if (next_details.type() != FIELD &&
+ next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
+
current = next;
}
return current;
}
+Map* Map::FindFieldOwner(int descriptor) {
+ ASSERT(instance_descriptors()->GetDetails(descriptor).type() == FIELD);
+ Map* result = this;
+ while (true) {
+ Object* back = result->GetBackPointer();
+ if (back->IsUndefined()) break;
+ Map* parent = Map::cast(back);
+ if (parent->NumberOfOwnDescriptors() <= descriptor) break;
+ result = parent;
+ }
+ return result;
+}
+
+
+void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) {
+ if (HasTransitionArray()) {
+ TransitionArray* transitions = this->transitions();
+ for (int i = 0; i < transitions->number_of_transitions(); ++i) {
+ transitions->GetTarget(i)->UpdateDescriptor(descriptor_number, desc);
+ }
+ }
+ DescriptorArray* descriptors = instance_descriptors();
+ desc->SetSortedKeyIndex(descriptors->GetDetails(descriptor_number).pointer());
+ descriptors->Set(descriptor_number, desc);
+}
+
+
+void Map::UpdateFieldType(int descriptor, HeapType* field_type) {
+ ASSERT(this == FindFieldOwner(descriptor));
+ DescriptorArray* descriptors = instance_descriptors();
+ PropertyDetails details = descriptors->GetDetails(descriptor);
+ FieldDescriptor d(descriptors->GetKey(descriptor),
+ descriptors->GetFieldIndex(descriptor),
+ field_type,
+ details.attributes(),
+ details.representation());
+ UpdateDescriptor(descriptor, &d);
+ dependent_code()->DeoptimizeDependentCodeGroup(
+ GetIsolate(), DependentCode::kFieldTypeGroup);
+}
+
+
// Generalize the representation of the descriptor at |modify_index|.
// This method rewrites the transition tree to reflect the new change. To avoid
// high degrees over polymorphism, and to stabilize quickly, on every rewrite
@@ -2658,6 +2736,7 @@ Map* Map::FindLastMatchMap(int verbatim,
Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
int modify_index,
Representation new_representation,
+ Handle<HeapType> new_field_type,
StoreMode store_mode) {
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
@@ -2671,6 +2750,9 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
!new_representation.IsNone() &&
!new_representation.IsDouble()) {
old_descriptors->SetRepresentation(modify_index, new_representation);
+ if (old_details.type() == FIELD) {
Toon Verwaest 2014/03/21 14:33:37 Only if new_representation is heap_object right?
+ old_descriptors->SetValue(modify_index, *new_field_type);
+ }
return old_map;
}
@@ -2726,6 +2808,16 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
if (!updated_representation.Equals(old_representation)) {
new_descriptors->SetRepresentation(modify_index, updated_representation);
}
+ if (new_descriptors->GetDetails(modify_index).type() == FIELD) {
+ Handle<HeapType> field_type(new_descriptors->GetFieldType(modify_index),
+ new_descriptors->GetIsolate());
+ if (!new_field_type->IsCurrently(field_type)) {
+ if (!field_type->IsCurrently(new_field_type)) {
+ new_field_type = HeapType::Any(updated->GetIsolate());
+ }
+ new_descriptors->SetValue(modify_index, *new_field_type);
Toon Verwaest 2014/03/21 14:33:37 Only if new_representation.IsHeapObject()
Benedikt Meurer 2014/04/11 11:12:00 No, we track types independent of the representati
+ }
+ }
Handle<Map> split_map(root_map->FindLastMatchMap(
verbatim, descriptors, *new_descriptors));
@@ -2760,13 +2852,13 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
// Generalize the representation of all FIELD descriptors.
Handle<Map> Map::GeneralizeAllFieldRepresentations(
- Handle<Map> map,
- Representation new_representation) {
+ Handle<Map> map) {
Handle<DescriptorArray> descriptors(map->instance_descriptors());
- for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.type() == FIELD) {
- map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD);
+ for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
+ if (descriptors->GetDetails(i).type() == FIELD) {
+ map = GeneralizeRepresentation(map, i, Representation::Tagged(),
+ HeapType::Any(map->GetIsolate()),
+ FORCE_FIELD);
}
}
return map;
@@ -3845,7 +3937,9 @@ void JSObject::MigrateInstance(Handle<JSObject> object) {
// transition that matches the object. This achieves what is needed.
Handle<Map> original_map(object->map());
GeneralizeFieldRepresentation(
- object, 0, Representation::None(), ALLOW_AS_CONSTANT);
+ object, 0, Representation::None(),
+ HeapType::None(object->GetIsolate()),
+ ALLOW_AS_CONSTANT);
object->map()->set_migration_target(true);
if (FLAG_trace_migration) {
object->PrintInstanceMigration(stdout, *original_map, object->map());
@@ -3891,11 +3985,39 @@ Handle<Object> JSObject::SetPropertyUsingTransition(
// Keep the target CONSTANT if the same value is stored.
// TODO(verwaest): Also support keeping the placeholder
// (value->IsUninitialized) as constant.
+ Handle<HeapType> value_type = FLAG_track_field_types
+ ? HeapType::OfCurrently(value, lookup->isolate())
+ : HeapType::Any(lookup->isolate());
if (!value->FitsRepresentation(details.representation()) ||
(details.type() == CONSTANT &&
descriptors->GetValue(descriptor) != *value)) {
- transition_map = Map::GeneralizeRepresentation(transition_map,
- descriptor, value->OptimalRepresentation(), FORCE_FIELD);
+ transition_map = Map::GeneralizeRepresentation(
+ transition_map, descriptor,
+ value->OptimalRepresentation(),
+ value_type, FORCE_FIELD);
+ } else if (details.type() == FIELD &&
+ details.representation().IsHeapObject()) {
+ Handle<HeapType> field_type(descriptors->GetFieldType(descriptor),
+ lookup->isolate());
+ if (!value_type->IsCurrently(field_type)) {
+ if (!field_type->IsCurrently(value_type)) {
+ value_type = HeapType::Any(lookup->isolate());
+ }
+ if (FLAG_trace_track_field_types) {
+#ifdef OBJECT_PRINT
+ PrintF("[Updating type of field ");
+ name->Print();
+ PrintF(" in transition map ");
+ transition_map->ShortPrint();
+ PrintF(": ");
+ field_type->TypePrint(stdout);
+ PrintF(" -> ");
+ value_type->TypePrint(stdout);
+ PrintF("]\n");
+#endif
+ }
+ transition_map->UpdateFieldType(descriptor, *value_type);
+ }
}
JSObject::MigrateToMap(object, transition_map);
@@ -3924,15 +4046,40 @@ static void SetPropertyToField(LookupResult* lookup,
Handle<Name> name,
Handle<Object> value) {
Representation representation = lookup->representation();
+ Handle<HeapType> value_type = FLAG_track_field_types
+ ? HeapType::OfCurrently(value, lookup->isolate())
+ : HeapType::Any(lookup->isolate());
if (!value->FitsRepresentation(representation) ||
lookup->type() == CONSTANT) {
JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
lookup->GetDescriptorIndex(),
value->OptimalRepresentation(),
- FORCE_FIELD);
+ value_type, FORCE_FIELD);
DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
int descriptor = lookup->GetDescriptorIndex();
representation = desc->GetDetails(descriptor).representation();
+ } else if (representation.IsHeapObject()) {
+ Handle<HeapType> field_type(lookup->GetFieldType(), lookup->isolate());
+ if (!value_type->IsCurrently(field_type)) {
+ if (!field_type->IsCurrently(value_type)) {
+ value_type = HeapType::Any(lookup->isolate());
+ }
+ if (FLAG_trace_track_field_types) {
+#ifdef OBJECT_PRINT
+ PrintF("[Updating type of field ");
+ name->Print();
+ PrintF(" in map ");
+ lookup->GetFieldOwner()->ShortPrint();
+ PrintF(": ");
+ field_type->TypePrint(stdout);
+ PrintF(" -> ");
+ value_type->TypePrint(stdout);
+ PrintF("]\n");
+#endif
+ }
+ lookup->GetFieldOwner()->UpdateFieldType(
+ lookup->GetDescriptorIndex(), *value_type);
+ }
}
if (representation.IsDouble()) {
@@ -3964,7 +4111,8 @@ static void ConvertAndSetLocalProperty(LookupResult* lookup,
int descriptor_index = lookup->GetDescriptorIndex();
if (lookup->GetAttributes() == attributes) {
JSObject::GeneralizeFieldRepresentation(
- object, descriptor_index, Representation::Tagged(), FORCE_FIELD);
+ object, descriptor_index, Representation::Tagged(),
+ HeapType::Any(lookup->isolate()), FORCE_FIELD);
} else {
Handle<Map> old_map(object->map());
Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
@@ -4960,8 +5108,6 @@ Object* JSObject::GetHiddenPropertiesHashTable() {
if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
sorted_index < map()->NumberOfOwnDescriptors()) {
ASSERT(descriptors->GetType(sorted_index) == FIELD);
- ASSERT(descriptors->GetDetails(sorted_index).representation().
- IsCompatibleForLoad(Representation::Tagged()));
return this->RawFastPropertyAt(
descriptors->GetFieldIndex(sorted_index));
} else {
@@ -6866,7 +7012,13 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
set_transitions(transitions);
result->SetBackPointer(this);
} else {
- descriptors->InitializeRepresentations(Representation::Tagged());
+ int length = descriptors->number_of_descriptors();
+ for (int i = 0; i < length; i++) {
+ descriptors->SetRepresentation(i, Representation::Tagged());
+ if (descriptors->GetDetails(i).type() == FIELD) {
+ descriptors->SetValue(i, HeapType::Any());
+ }
+ }
}
return result;
@@ -7986,6 +8138,12 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
}
+HeapType* DescriptorArray::GetFieldType(int descriptor_number) {
+ ASSERT(GetDetails(descriptor_number).type() == FIELD);
+ return HeapType::cast(GetValue(descriptor_number));
+}
+
+
void DescriptorArray::CopyFrom(int dst_index,
DescriptorArray* src,
int src_index,
@@ -8065,8 +8223,24 @@ MaybeObject* DescriptorArray::Merge(int verbatim,
GetValue(descriptor) != other->GetValue(descriptor))) {
Representation representation =
details.representation().generalize(other_details.representation());
+ // TODO(bmeurer): Cleanup this crap!
+ HeapType* field_type = HeapType::Any();
+ if (representation.IsHeapObject()) {
+ Object* val = GetValue(descriptor);
+ Object* other_val = other->GetValue(descriptor);
+ if (details.type() == FIELD && other_details.type() == FIELD) {
+ HeapType* type = HeapType::cast(val);
+ HeapType* other_type = HeapType::cast(other_val);
+ if (type->Is(other_type)) {
+ field_type = other_type;
+ } else if (other_type->Is(type)) {
+ field_type = type;
+ }
+ }
+ }
FieldDescriptor d(key,
current_offset++,
+ field_type,
other_details.attributes(),
representation);
result->Set(descriptor, &d, witness);
@@ -8083,6 +8257,7 @@ MaybeObject* DescriptorArray::Merge(int verbatim,
Name* key = other->GetKey(descriptor);
FieldDescriptor d(key,
current_offset++,
+ HeapType::cast(other->GetValue(descriptor)),
details.attributes(),
details.representation());
result->Set(descriptor, &d, witness);
@@ -15726,6 +15901,7 @@ MaybeObject* NameDictionary::TransformPropertiesToFastFor(
}
FieldDescriptor d(key,
current_offset++,
+ HeapType::Any(),
details.attributes(),
// TODO(verwaest): value->OptimalRepresentation();
Representation::Tagged());

Powered by Google App Engine
This is Rietveld 408576698