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

Unified Diff: src/objects.cc

Issue 391693002: In-object double fields unboxing (for 64-bit only). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 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 27636585b1c736aac37384ee1d82a5a8e22ef4d3..4d874219aae409e6673e1ac21fd70af9d7224b66 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2220,10 +2220,14 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
}
ASSERT(old_details.type() == CONSTANT ||
old_details.type() == FIELD);
- Object* raw_value = old_details.type() == CONSTANT
- ? old_descriptors->GetValue(i)
- : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i));
- Handle<Object> value(raw_value, isolate);
+ Handle<Object> value;
+ if (old_details.type() == CONSTANT) {
+ value = handle(old_descriptors->GetValue(i), isolate);
+ } else {
+ FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
+ // TODO(ishell): avoid boxing if copying to unboxed double.
+ value = RawFastBoxedPropertyAt(object, index);
+ }
if (!old_details.representation().IsDouble() &&
details.representation().IsDouble()) {
if (old_details.representation().IsNone()) {
@@ -2262,7 +2266,7 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
int limit = Min(inobject, number_of_fields);
for (int i = 0; i < limit; i++) {
FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
- object->FastPropertyAtPut(index, array->get(external + i));
+ object->FastPropertyAtPut(*new_map, index, array->get(external + i));
}
Heap* heap = isolate->heap();
@@ -2396,10 +2400,11 @@ void Map::DeprecateTransitionTree() {
// Invalidates a transition target at |key|, and installs |new_descriptors| over
// the current instance_descriptors to ensure proper sharing of descriptor
// arrays.
-void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
+void Map::DeprecateTarget(Handle<Name> key,
+ Handle<DescriptorArray> new_descriptors) {
if (HasTransitionArray()) {
TransitionArray* transitions = this->transitions();
- int transition = transitions->Search(key);
+ int transition = transitions->Search(*key);
if (transition != TransitionArray::kNotFound) {
transitions->GetTarget(transition)->DeprecateTransitionTree();
}
@@ -2408,12 +2413,14 @@ void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
// Don't overwrite the empty descriptor array.
if (NumberOfOwnDescriptors() == 0) return;
+ Handle<LayoutDescriptor> new_layout_descriptor =
+ LayoutDescriptor::New(new_descriptors);
DescriptorArray* to_replace = instance_descriptors();
Map* current = this;
GetHeap()->incremental_marking()->RecordWrites(to_replace);
while (current->instance_descriptors() == to_replace) {
current->SetEnumLength(kInvalidEnumCacheSentinel);
- current->set_instance_descriptors(new_descriptors);
+ current->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
Object* next = current->GetBackPointer();
if (next->IsUndefined()) break;
current = Map::cast(next);
@@ -2494,7 +2501,7 @@ void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) {
transitions->GetTarget(i)->UpdateDescriptor(descriptor_number, desc);
}
}
- instance_descriptors()->Replace(descriptor_number, desc);;
+ instance_descriptors()->Replace(descriptor_number, desc);
}
@@ -2744,7 +2751,9 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
int current_offset = 0;
for (int i = 0; i < root_nof; ++i) {
PropertyDetails old_details = old_descriptors->GetDetails(i);
- if (old_details.type() == FIELD) current_offset++;
+ if (old_details.type() == FIELD) {
+ current_offset += old_details.field_width_in_words();
+ }
Descriptor d(handle(old_descriptors->GetKey(i), isolate),
handle(old_descriptors->GetValue(i), isolate),
old_details);
@@ -2782,11 +2791,10 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
target_field_type = GeneralizeFieldType(
target_field_type, new_field_type, isolate);
}
- FieldDescriptor d(target_key,
- current_offset++,
- target_field_type,
+ FieldDescriptor d(target_key, current_offset, target_field_type,
target_details.attributes(),
target_details.representation());
+ current_offset += d.GetDetails().field_width_in_words();
new_descriptors->Set(i, &d);
} else {
ASSERT_NE(FIELD, target_details.type());
@@ -2812,23 +2820,20 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
old_field_type = GeneralizeFieldType(
old_field_type, new_field_type, isolate);
}
- FieldDescriptor d(old_key,
- current_offset++,
- old_field_type,
- old_details.attributes(),
- old_details.representation());
+ FieldDescriptor d(old_key, current_offset, old_field_type,
+ old_details.attributes(), old_details.representation());
+ current_offset += d.GetDetails().field_width_in_words();
new_descriptors->Set(i, &d);
} else {
ASSERT(old_details.type() == CONSTANT || old_details.type() == CALLBACKS);
if (modify_index == i && store_mode == FORCE_FIELD) {
- FieldDescriptor d(old_key,
- current_offset++,
- GeneralizeFieldType(
- old_descriptors->GetValue(i)->OptimalType(
- isolate, old_details.representation()),
- new_field_type, isolate),
- old_details.attributes(),
- old_details.representation());
+ FieldDescriptor d(
+ old_key, current_offset,
+ GeneralizeFieldType(old_descriptors->GetValue(i)->OptimalType(
+ isolate, old_details.representation()),
+ new_field_type, isolate),
+ old_details.attributes(), old_details.representation());
+ current_offset += d.GetDetails().field_width_in_words();
new_descriptors->Set(i, &d);
} else {
ASSERT_NE(FIELD, old_details.type());
@@ -2851,7 +2856,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
ASSERT_NE(old_nof, split_nof);
split_map->DeprecateTarget(
- old_descriptors->GetKey(split_nof), *new_descriptors);
+ handle(old_descriptors->GetKey(split_nof), isolate), new_descriptors);
if (FLAG_trace_generalization) {
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
@@ -3129,8 +3134,13 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
descriptors, old_size, slack);
+ Handle<LayoutDescriptor> new_layout_descriptor =
+ LayoutDescriptor::New(new_descriptors);
+
+ DisallowHeapAllocation no_allocation;
+
if (old_size == 0) {
- map->set_instance_descriptors(*new_descriptors);
+ map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
return;
}
@@ -3152,10 +3162,10 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
current = walk_map->GetBackPointer()) {
walk_map = Map::cast(current);
if (walk_map->instance_descriptors() != *descriptors) break;
- walk_map->set_instance_descriptors(*new_descriptors);
+ walk_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
}
- map->set_instance_descriptors(*new_descriptors);
+ map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
}
@@ -3470,10 +3480,12 @@ void JSObject::LookupOwnRealNamedProperty(Handle<Name> name,
(result->holder() == this && result->IsFastPropertyType()));
// Disallow caching for uninitialized constants. These can only
// occur as fields.
- if (result->IsField() &&
- result->IsReadOnly() &&
- RawFastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
- result->DisallowCaching();
+ if (result->IsField() && result->IsReadOnly()) {
+ FieldIndex index = result->GetFieldIndex();
+ if (!map()->IsUnboxedDoubleField(index) &&
Toon Verwaest 2014/07/29 15:02:09 Unnecessary by now
Igor Sheludko 2014/10/30 14:23:44 Done.
+ RawFastPropertyAt(index)->IsTheHole()) {
+ result->DisallowCaching();
+ }
}
return;
}
@@ -3988,9 +4000,13 @@ void JSObject::WriteToField(int descriptor, Object* value) {
if (details.representation().IsDouble()) {
// Nothing more to be done.
if (value->IsUninitialized()) return;
- HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
- ASSERT(box->IsMutableHeapNumber());
- box->set_value(value->Number());
+ if (map()->IsUnboxedDoubleField(index)) {
+ FastDoublePropertyAtPut(index, value->Number());
+ } else {
+ HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
+ ASSERT(box->IsMutableHeapNumber());
+ box->set_value(value->Number());
+ }
} else {
FastPropertyAtPut(index, value);
}
@@ -4656,8 +4672,7 @@ void JSObject::MigrateFastToSlow(Handle<JSObject> object,
case FIELD: {
Handle<Name> key(descs->GetKey(i));
FieldIndex index = FieldIndex::ForDescriptor(*map, i);
- Handle<Object> value(
- object->RawFastPropertyAt(index), isolate);
+ Handle<Object> value(JSObject::RawFastBoxedPropertyAt(object, index));
if (details.representation().IsDouble()) {
ASSERT(value->IsMutableHeapNumber());
Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
@@ -4823,11 +4838,10 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
int offset = current_offset - inobject_props;
fields->set(offset, value);
}
- FieldDescriptor d(key,
- current_offset++,
- details.attributes(),
+ FieldDescriptor d(key, current_offset, details.attributes(),
// TODO(verwaest): value->OptimalRepresentation();
Representation::Tagged());
+ current_offset += d.GetDetails().field_width_in_words();
descriptors->Set(enumeration_index - 1, &d);
} else if (type == CALLBACKS) {
CallbacksDescriptor d(key,
@@ -4843,8 +4857,11 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
descriptors->Sort();
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(descriptors);
+
DisallowHeapAllocation no_gc;
- new_map->InitializeDescriptors(*descriptors);
+ new_map->InitializeOwnDescriptors(*descriptors, *layout_descriptor);
new_map->set_unused_property_fields(unused_property_fields);
// Transform the object.
@@ -5827,7 +5844,8 @@ Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
Representation representation,
FieldIndex index) {
Isolate* isolate = object->GetIsolate();
- Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
+ // TODO(ishell): unboxed double fields will be wrapped twice here.
+ Handle<Object> raw_value(JSObject::RawFastBoxedPropertyAt(object, index));
return Object::WrapForRead(isolate, raw_value, representation);
}
@@ -5917,7 +5935,8 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
PropertyDetails details = descriptors->GetDetails(i);
if (details.type() != FIELD) continue;
FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
- Handle<Object> value(object->RawFastPropertyAt(index), isolate);
+ // TODO(ishell): avoid boxing if copying to unboxed double.
+ Handle<Object> value = JSObject::RawFastBoxedPropertyAt(object, index);
if (value->IsJSObject()) {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value,
@@ -6160,16 +6179,17 @@ int Map::NumberOfDescribedProperties(DescriptorFlag which,
int Map::NextFreePropertyIndex() {
- int max_index = -1;
+ int free_index = 0;
int number_of_own_descriptors = NumberOfOwnDescriptors();
DescriptorArray* descs = instance_descriptors();
for (int i = 0; i < number_of_own_descriptors; i++) {
- if (descs->GetType(i) == FIELD) {
- int current_index = descs->GetFieldIndex(i);
- if (current_index > max_index) max_index = current_index;
+ PropertyDetails details = descs->GetDetails(i);
+ if (details.type() == FIELD) {
+ int candidate = details.field_index() + details.field_width_in_words();
+ if (candidate > free_index) free_index = candidate;
}
}
- return max_index + 1;
+ return free_index;
}
@@ -7008,17 +7028,27 @@ Object* JSObject::SlowReverseLookup(Object* value) {
if (HasFastProperties()) {
int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
DescriptorArray* descs = map()->instance_descriptors();
+ bool value_is_number = value->IsNumber();
for (int i = 0; i < number_of_own_descriptors; i++) {
if (descs->GetType(i) == FIELD) {
- Object* property =
- RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
- if (descs->GetDetails(i).representation().IsDouble()) {
- ASSERT(property->IsMutableHeapNumber());
- if (value->IsNumber() && property->Number() == value->Number()) {
+ FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
+ if (map()->IsUnboxedDoubleField(field_index)) {
+ if (value_is_number) {
+ double property = RawFastDoublePropertyAt(field_index);
+ if (property == value->Number()) {
+ return descs->GetKey(i);
+ }
+ }
+ } else {
+ Object* property = RawFastPropertyAt(field_index);
+ if (field_index.is_double()) {
+ ASSERT(property->IsMutableHeapNumber());
+ if (value_is_number && property->Number() == value->Number()) {
+ return descs->GetKey(i);
+ }
+ } else if (property == value) {
return descs->GetKey(i);
}
- } else if (property == value) {
- return descs->GetKey(i);
}
} else if (descs->GetType(i) == CONSTANT) {
if (descs->GetConstant(i) == value) {
@@ -7169,12 +7199,15 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map,
}
}
+ descriptors->Append(descriptor);
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(descriptors);
+
// Commit the state atomically.
DisallowHeapAllocation no_gc;
- descriptors->Append(descriptor);
result->SetBackPointer(*map);
- result->InitializeDescriptors(*descriptors);
+ result->InitializeOwnDescriptors(*descriptors, *layout_descriptor);
ASSERT(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
@@ -7193,9 +7226,12 @@ Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
ASSERT(descriptors->IsSortedNoDuplicates());
Handle<Map> result = CopyDropDescriptors(map);
- result->InitializeDescriptors(*descriptors);
if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(descriptors);
+ result->InitializeOwnDescriptors(*descriptors, *layout_descriptor);
+
Handle<Name> name;
CHECK(maybe_name.ToHandle(&name));
Handle<TransitionArray> transitions = TransitionArray::CopyInsert(
@@ -7210,6 +7246,8 @@ Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
descriptors->SetValue(i, HeapType::Any());
}
}
+ result->InitializeOwnDescriptors(*descriptors,
+ LayoutDescriptor::FastPointerLayout());
}
return result;
@@ -7225,8 +7263,14 @@ Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
Handle<Map> result = CopyDropDescriptors(map);
- result->InitializeDescriptors(*descriptors);
+ result->set_instance_descriptors(*descriptors);
result->SetNumberOfOwnDescriptors(new_descriptor + 1);
+ if (FLAG_unbox_double_fields) {
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(descriptors);
+ result->set_layout_descriptor(layout_descriptor->OptimizeFor(*result));
+ result->set_visitor_id(StaticVisitorBase::GetVisitorId(*result));
+ }
int unused_property_fields = map->unused_property_fields();
if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
@@ -7273,10 +7317,14 @@ Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
// transfer ownership to the new map.
Handle<Map> new_map = CopyDropDescriptors(map);
+ Handle<DescriptorArray> descriptors(map->instance_descriptors());
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(descriptors);
+
SetElementsTransitionMap(map, new_map);
new_map->set_elements_kind(kind);
- new_map->InitializeDescriptors(map->instance_descriptors());
+ new_map->InitializeOwnDescriptors(*descriptors, *layout_descriptor);
new_map->SetBackPointer(*map);
map->set_owns_descriptors(false);
return new_map;
@@ -7320,7 +7368,10 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) {
new_map->set_is_observed();
if (map->owns_descriptors()) {
- new_map->InitializeDescriptors(map->instance_descriptors());
Toon Verwaest 2014/07/29 15:02:09 This is overkill, set_instance_descriptors should
Igor Sheludko 2014/10/30 14:23:44 Done.
+ Handle<DescriptorArray> descriptors(map->instance_descriptors());
+ Handle<LayoutDescriptor> layout_descriptor =
+ LayoutDescriptor::New(descriptors);
+ new_map->InitializeOwnDescriptors(*descriptors, *layout_descriptor);
map->set_owns_descriptors(false);
}
@@ -8273,6 +8324,9 @@ Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
+ if (FLAG_unbox_double_fields) {
+ result->set(kLayoutDescriptorCacheIndex, *factory->undefined_value());
+ }
result->set(kEnumCacheIndex, Smi::FromInt(0));
return Handle<DescriptorArray>::cast(result);
}
@@ -8304,8 +8358,7 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
}
-void DescriptorArray::CopyFrom(int index,
- DescriptorArray* src,
+void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
const WhitenessWitness& witness) {
Object* value = src->GetValue(index);
PropertyDetails details = src->GetDetails(index);
@@ -8375,6 +8428,66 @@ void DescriptorArray::Sort() {
}
+Handle<LayoutDescriptor> LayoutDescriptor::New(
+ Handle<DescriptorArray> descriptors) {
+ Isolate* isolate = descriptors->GetIsolate();
+ if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate);
+
+ // Check cached layout descriptor in descriptors array.
+ Object* cached = descriptors->cached_layout_descriptor();
+ if (cached != isolate->heap()->undefined_value()) {
+ LayoutDescriptor* layout_descriptor = LayoutDescriptor::cast(cached);
+ return handle(layout_descriptor, isolate);
+ }
+
+ int num_descriptors = descriptors->number_of_descriptors();
+
+ int layout_descriptor_length;
+
+ const int kMaxWordsPerField = kDoubleSize / kPointerSize;
+
+ if (num_descriptors <= kSmiValueSize / kMaxWordsPerField) {
+ // Even in the "worst" case (all fields are doubles) it would fit into
+ // a Smi, so no need to calculate length.
+ layout_descriptor_length = kSmiValueSize;
+
+ } else {
+ layout_descriptor_length = 0;
+
+ for (int i = 0; i < num_descriptors; i++) {
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.type() == FIELD) {
+ if (layout_descriptor_length <= details.field_index()) {
+ layout_descriptor_length =
+ details.field_index() + details.field_width_in_words();
+ }
+ }
+ }
+ }
+
+ Handle<LayoutDescriptor> layout_descriptor_handle =
+ LayoutDescriptor::New(isolate, layout_descriptor_length);
+
+ DisallowHeapAllocation no_allocation;
+ LayoutDescriptor* layout_descriptor = *layout_descriptor_handle;
+
+ for (int i = 0; i < num_descriptors; i++) {
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.type() == FIELD) {
+ int field_index = details.field_index();
+ bool tagged = !details.representation().IsDouble();
+ layout_descriptor = layout_descriptor->SetTagged(field_index, tagged);
+ if (details.field_width_in_words() > 1) {
+ layout_descriptor =
+ layout_descriptor->SetTagged(field_index + 1, tagged);
+ }
+ }
+ }
+ descriptors->set_cached_layout_descriptor(layout_descriptor);
+ return handle(layout_descriptor, isolate);
+}
+
+
Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
copy->set_getter(pair->getter());

Powered by Google App Engine
This is Rietveld 408576698