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

Unified Diff: src/objects.cc

Issue 14850006: Use mutable heapnumbers to store doubles in fields. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 7 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 3fa1a4098f4b870748e13419feecd42be112f015..e1fb7fbab25acc87666badfe3c683eb65e59f3ab 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -819,6 +819,10 @@ MaybeObject* Object::GetProperty(Object* receiver,
value = result->holder()->FastPropertyAt(
result->GetFieldIndex().field_index());
ASSERT(!value->IsTheHole() || result->IsReadOnly());
+ if (FLAG_track_double_fields && result->representation().IsDouble()) {
+ ASSERT(value->IsHeapNumber());
+ return heap->AllocateHeapNumber(value->Number());
danno 2013/05/07 13:04:47 If this happens too frequently (i.e. having to all
Toon Verwaest 2013/05/07 15:08:52 Done.
+ }
return value->IsTheHole() ? heap->undefined_value() : value;
case CONSTANT_FUNCTION:
return result->GetConstantFunction();
@@ -1711,7 +1715,14 @@ String* JSReceiver::constructor_name() {
MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
Name* name,
Object* value,
- int field_index) {
+ int field_index,
+ Representation representation) {
danno 2013/05/07 13:04:47 Perhaps a comment that this is a transition case.
Toon Verwaest 2013/05/07 15:08:52 Done.
+ Object* storage = value;
+ if (FLAG_track_double_fields && representation.IsDouble()) {
danno 2013/05/07 13:04:47 Don't you just have to write into the existing box
Toon Verwaest 2013/05/07 15:08:52 It is the transition case; added comment. On 2013
+ MaybeObject* maybe_storage = GetHeap()->AllocateHeapNumber(value->Number());
+ if (!maybe_storage->To(&storage)) return maybe_storage;
+ }
+
if (map()->unused_property_fields() == 0) {
int new_unused = new_map->unused_property_fields();
FixedArray* values;
@@ -1721,8 +1732,11 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
set_properties(values);
}
+
set_map(new_map);
- return FastPropertyAtPut(field_index, value);
+
+ FastPropertyAtPut(field_index, storage);
+ return value;
}
@@ -1774,8 +1788,8 @@ MaybeObject* JSObject::AddFastProperty(Name* name,
int index = map()->NextFreePropertyIndex();
// Allocate new instance descriptors with (name, index) added
- FieldDescriptor new_field(
- name, index, attributes, value->OptimalRepresentation(), 0);
+ Representation representation = value->OptimalRepresentation();
+ FieldDescriptor new_field(name, index, attributes, representation, 0);
ASSERT(index < map()->inobject_properties() ||
(index - map()->inobject_properties()) < properties()->length() ||
@@ -1792,10 +1806,16 @@ MaybeObject* JSObject::AddFastProperty(Name* name,
TransitionFlag flag = INSERT_TRANSITION;
+ Heap* heap = isolate->heap();
+
Map* new_map;
MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag);
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
+ Object* storage;
+ MaybeObject* maybe_storage = value->StorageFor(heap, representation);
+ if (!maybe_storage->To(&storage)) return maybe_storage;
+
if (map()->unused_property_fields() == 0) {
ASSERT(values != NULL);
set_properties(values);
@@ -1805,7 +1825,9 @@ MaybeObject* JSObject::AddFastProperty(Name* name,
}
set_map(new_map);
- return FastPropertyAtPut(index, value);
+
+ FastPropertyAtPut(index, storage);
+ return value;
}
@@ -2071,9 +2093,9 @@ MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
return ReplaceSlowProperty(name, new_value, attributes);
}
+ Representation representation = new_value->OptimalRepresentation();
int index = map()->NextFreePropertyIndex();
- FieldDescriptor new_field(
- name, index, attributes, new_value->OptimalRepresentation(), 0);
+ FieldDescriptor new_field(name, index, attributes, representation, 0);
// Make a new map for the object.
Map* new_map;
@@ -2091,6 +2113,11 @@ MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties;
}
+ Heap* heap = GetHeap();
+ Object* storage;
+ MaybeObject* maybe_storage = new_value->StorageFor(heap, representation);
+ if (!maybe_storage->To(&storage)) return maybe_storage;
+
// Update pointers to commit changes.
// Object points to the new map.
new_map->set_unused_property_fields(new_unused_property_fields);
@@ -2098,7 +2125,8 @@ MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
if (new_properties != NULL) {
set_properties(new_properties);
}
- return FastPropertyAtPut(index, new_value);
+ FastPropertyAtPut(index, new_value);
+ return new_value;
}
@@ -2166,13 +2194,28 @@ static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
}
-bool Map::InstancesNeedRewriting(int target_number_of_fields,
+bool Map::InstancesNeedRewriting(Map* target,
+ int target_number_of_fields,
int target_inobject,
int target_unused) {
// If fields were added (or removed), rewrite the instance.
int number_of_fields = NumberOfFields();
ASSERT(target_number_of_fields >= number_of_fields);
if (target_number_of_fields != number_of_fields) return true;
+
+ if (FLAG_track_double_fields) {
+ // If smi descriptors were replaced by double descriptors, rewrite.
+ DescriptorArray* old_desc = instance_descriptors();
+ DescriptorArray* new_desc = target->instance_descriptors();
+ int limit = NumberOfOwnDescriptors();
+ for (int i = 0; i < limit; i++) {
+ if (new_desc->GetDetails(i).representation().IsDouble() &&
+ old_desc->GetDetails(i).representation().IsSmi()) {
+ return true;
+ }
+ }
+ }
+
// If no fields were added, and no inobject properties were removed, setting
// the map is sufficient.
if (target_inobject == inobject_properties()) return false;
@@ -2212,7 +2255,8 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) {
int unused = new_map->unused_property_fields();
// Nothing to do if no functions were converted to fields.
- if (!old_map->InstancesNeedRewriting(number_of_fields, inobject, unused)) {
+ if (!old_map->InstancesNeedRewriting(
+ new_map, number_of_fields, inobject, unused)) {
set_map(new_map);
return this;
}
@@ -2236,6 +2280,20 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) {
Object* value = old_details.type() == CONSTANT_FUNCTION
? old_descriptors->GetValue(i)
: FastPropertyAt(old_descriptors->GetFieldIndex(i));
+ if (FLAG_track_double_fields &&
+ old_details.representation().IsSmi() &&
+ details.representation().IsDouble()) {
+ // Objects must be allocated in the old object space, since the
+ // overall number of HeapNumbers needed for the conversion might
+ // exceed the capacity of new space, and we would fail repeatedly
+ // trying to migrate the instance.
+ MaybeObject* maybe_storage =
+ heap->AllocateHeapNumber(Smi::cast(value)->value(), TENURED);
danno 2013/05/07 13:04:47 AllocateNewStorageFor
Toon Verwaest 2013/05/07 15:08:52 Done.
+ if (!maybe_storage->To(&value)) return maybe_storage;
+ }
+ ASSERT(!(FLAG_track_double_fields &&
+ details.representation().IsDouble() &&
+ value->IsSmi()));
int target_index = new_descriptors->GetFieldIndex(i) - inobject;
if (target_index < 0) target_index += total_size;
array->set(target_index, value);
@@ -2300,6 +2358,10 @@ MaybeObject* Map::CopyGeneralizeAllRepresentations() {
new_map->instance_descriptors()->InitializeRepresentations(
Representation::Tagged());
+ if (FLAG_trace_generalization) {
+ PrintF("failed generalization %p -> %p\n",
+ static_cast<void*>(this), static_cast<void*>(new_map));
+ }
return new_map;
}
@@ -2465,7 +2527,13 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
verbatim, valid, descriptors, old_descriptors)) {
Representation updated_representation =
updated_descriptors->GetDetails(modify_index).representation();
- if (new_representation.fits_into(updated_representation)) return updated;
+ if (new_representation.fits_into(updated_representation)) {
+ if (FLAG_trace_generalization) {
+ PrintF("migrating to existing map %p -> %p\n",
+ static_cast<void*>(this), static_cast<void*>(updated));
+ }
+ return updated;
+ }
}
DescriptorArray* new_descriptors;
@@ -2490,6 +2558,13 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
split_map->DeprecateTarget(
old_descriptors->GetKey(descriptor), new_descriptors);
+ if (FLAG_trace_generalization) {
+ PrintF("migrating to new map %p -> %p (%i steps)\n",
+ static_cast<void*>(this),
+ static_cast<void*>(new_descriptors),
+ descriptors - descriptor);
+ }
+
Map* new_map = split_map;
// Add missing transitions.
for (; descriptor < descriptors; descriptor++) {
@@ -3473,6 +3548,11 @@ void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) {
void JSObject::MigrateInstance(Handle<JSObject> object) {
+ if (FLAG_trace_migration) {
+ PrintF("migrating instance %p (%p)\n",
+ static_cast<void*>(*object),
+ static_cast<void*>(object->map()));
+ }
CALL_HEAP_FUNCTION_VOID(
object->GetIsolate(),
object->MigrateInstance());
@@ -3481,10 +3561,10 @@ void JSObject::MigrateInstance(Handle<JSObject> object) {
Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
int modify_index,
- Representation new_representation) {
+ Representation representation) {
CALL_HEAP_FUNCTION(
map->GetIsolate(),
- map->GeneralizeRepresentation(modify_index, new_representation),
+ map->GeneralizeRepresentation(modify_index, representation),
Map);
}
@@ -3584,9 +3664,21 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
lookup->holder()->GeneralizeFieldRepresentation(
lookup->GetDescriptorIndex(), value->OptimalRepresentation());
if (maybe_failure->IsFailure()) return maybe_failure;
+ DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
+ int descriptor = lookup->GetDescriptorIndex();
+ representation = desc->GetDetails(descriptor).representation();
+ }
+ if (FLAG_track_double_fields && representation.IsDouble()) {
+ HeapNumber* storage =
+ HeapNumber::cast(lookup->holder()->FastPropertyAt(
+ lookup->GetFieldIndex().field_index()));
+ storage->set_value(value->Number());
+ result = *value;
+ break;
}
- result = lookup->holder()->FastPropertyAtPut(
+ lookup->holder()->FastPropertyAtPut(
lookup->GetFieldIndex().field_index(), *value);
+ result = *value;
break;
}
case CONSTANT_FUNCTION:
@@ -3615,7 +3707,8 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
if (details.type() == FIELD) {
if (attributes == details.attributes()) {
- if (!value->FitsRepresentation(details.representation())) {
+ Representation representation = details.representation();
+ if (!value->FitsRepresentation(representation)) {
MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
descriptor, value->OptimalRepresentation());
if (!maybe_map->To(&transition_map)) return maybe_map;
@@ -3625,10 +3718,13 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
lookup->holder()->MigrateToMap(Map::cast(back));
if (maybe_failure->IsFailure()) return maybe_failure;
}
+ DescriptorArray* desc = transition_map->instance_descriptors();
+ int descriptor = transition_map->LastAdded();
+ representation = desc->GetDetails(descriptor).representation();
}
int field_index = descriptors->GetFieldIndex(descriptor);
result = lookup->holder()->AddFastPropertyUsingMap(
- transition_map, *name, *value, field_index);
+ transition_map, *name, *value, field_index, representation);
} else {
result = lookup->holder()->ConvertDescriptorToField(
*name, *value, attributes);
@@ -3769,9 +3865,20 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation(
lookup.GetDescriptorIndex(), value->OptimalRepresentation());
if (maybe_failure->IsFailure()) return maybe_failure;
+ DescriptorArray* desc = self->map()->instance_descriptors();
+ int descriptor = lookup.GetDescriptorIndex();
+ representation = desc->GetDetails(descriptor).representation();
+ }
+ if (FLAG_track_double_fields && representation.IsDouble()) {
+ HeapNumber* storage =
+ HeapNumber::cast(self->FastPropertyAt(
+ lookup.GetFieldIndex().field_index()));
+ storage->set_value(value->Number());
+ result = *value;
+ break;
}
- result = self->FastPropertyAtPut(
- lookup.GetFieldIndex().field_index(), *value);
+ self->FastPropertyAtPut(lookup.GetFieldIndex().field_index(), *value);
+ result = *value;
break;
}
case CONSTANT_FUNCTION:
@@ -3796,7 +3903,8 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
if (details.type() == FIELD) {
if (attributes == details.attributes()) {
- if (!value->FitsRepresentation(details.representation())) {
+ Representation representation = details.representation();
+ if (!value->FitsRepresentation(representation)) {
MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
descriptor, value->OptimalRepresentation());
if (!maybe_map->To(&transition_map)) return maybe_map;
@@ -3805,10 +3913,13 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back));
if (maybe_failure->IsFailure()) return maybe_failure;
}
+ DescriptorArray* desc = transition_map->instance_descriptors();
+ int descriptor = transition_map->LastAdded();
+ representation = desc->GetDetails(descriptor).representation();
}
int field_index = descriptors->GetFieldIndex(descriptor);
- result = self->AddFastPropertyUsingMap(
- transition_map, *name, *value, field_index);
+ result = lookup.holder()->AddFastPropertyUsingMap(
danno 2013/05/07 13:04:47 Can you please revert to self?
Toon Verwaest 2013/05/07 15:08:52 Done.
+ transition_map, *name, *value, field_index, representation);
} else {
result = self->ConvertDescriptorToField(*name, *value, attributes);
}
@@ -4616,6 +4727,12 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
ASSERT(descriptors->GetType(sorted_index) == FIELD);
inline_value =
this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index));
+ if (FLAG_track_double_fields &&
+ descriptors->GetDetails(sorted_index).representation().IsDouble() &&
+ init_option == ONLY_RETURN_INLINE_VALUE) {
+ ASSERT(inline_value->IsHeapNumber());
+ return GetHeap()->AllocateHeapNumber(inline_value->Number());
+ }
} else {
inline_value = GetHeap()->undefined_value();
}
@@ -4684,8 +4801,7 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
sorted_index < map()->NumberOfOwnDescriptors()) {
ASSERT(descriptors->GetType(sorted_index) == FIELD);
- this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
- value);
+ FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value);
return this;
}
}
@@ -5161,6 +5277,11 @@ MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
StackLimitCheck check(isolate);
if (check.HasOverflowed()) return isolate->StackOverflow();
+ if (map()->is_deprecated()) {
+ MaybeObject* maybe_failure = MigrateInstance();
+ if (maybe_failure->IsFailure()) return maybe_failure;
+ }
+
Heap* heap = isolate->heap();
Object* result;
{ MaybeObject* maybe_result = heap->CopyJSObject(this);
@@ -5170,27 +5291,25 @@ MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
// Deep copy local properties.
if (copy->HasFastProperties()) {
- FixedArray* properties = copy->properties();
- for (int i = 0; i < properties->length(); i++) {
- Object* value = properties->get(i);
- if (value->IsJSObject()) {
- JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- properties->set(i, result);
- }
- }
- int nof = copy->map()->inobject_properties();
- for (int i = 0; i < nof; i++) {
- Object* value = copy->InObjectPropertyAt(i);
+ DescriptorArray* descriptors = copy->map()->instance_descriptors();
+ int limit = copy->map()->NumberOfOwnDescriptors();
+ for (int i = 0; i < limit; i++) {
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.type() != FIELD) continue;
+ int index = descriptors->GetFieldIndex(i);
+ Object* value = FastPropertyAt(index);
if (value->IsJSObject()) {
JSObject* js_object = JSObject::cast(value);
- { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
- if (!maybe_result->ToObject(&result)) return maybe_result;
+ MaybeObject* maybe_copy = js_object->DeepCopy(isolate);
+ if (!maybe_copy->To(&value)) return maybe_copy;
+ } else {
+ Representation representation = details.representation();
+ if (representation.IsDouble()) {
+ MaybeObject* maybe_number = heap->AllocateHeapNumber(value->Number());
danno 2013/05/07 13:04:47 NewStorageForValue
Toon Verwaest 2013/05/07 15:08:52 Done.
+ if (!maybe_number->To(&value)) return maybe_number;
}
- copy->InObjectPropertyAtPut(i, result);
}
+ copy->FastPropertyAtPut(index, value);
}
} else {
{ MaybeObject* maybe_result =
@@ -6018,7 +6137,14 @@ Object* JSObject::SlowReverseLookup(Object* value) {
DescriptorArray* descs = map()->instance_descriptors();
for (int i = 0; i < number_of_own_descriptors; i++) {
if (descs->GetType(i) == FIELD) {
- if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
+ Object* property = FastPropertyAt(descs->GetFieldIndex(i));
+ if (FLAG_track_double_fields &&
+ descs->GetDetails(i).representation().IsDouble()) {
+ ASSERT(property->IsHeapNumber());
+ if (value->IsNumber() && property->Number() == value->Number()) {
+ return descs->GetKey(i);
+ }
+ } else if (property == value) {
return descs->GetKey(i);
}
} else if (descs->GetType(i) == CONSTANT_FUNCTION) {

Powered by Google App Engine
This is Rietveld 408576698