Index: src/objects-inl.h |
diff --git a/src/objects-inl.h b/src/objects-inl.h |
index 9564ff0be077f56e1e3abd8361f5c778b4ae0dfb..e7dcd631a85eadf901eb9c36659d067e49f81998 100644 |
--- a/src/objects-inl.h |
+++ b/src/objects-inl.h |
@@ -26,6 +26,7 @@ |
#include "src/heap/spaces.h" |
#include "src/heap/store-buffer.h" |
#include "src/isolate.h" |
+#include "src/layout-descriptor-inl.h" |
#include "src/lookup.h" |
#include "src/objects.h" |
#include "src/property.h" |
@@ -56,6 +57,14 @@ PropertyDetails PropertyDetails::AsDeleted() const { |
} |
+int PropertyDetails::field_width_in_words() const { |
+ DCHECK(type() == FIELD); |
+ if (!FLAG_unbox_double_fields) return 1; |
+ if (kDoubleSize == kPointerSize) return 1; |
+ return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; |
+} |
+ |
+ |
#define TYPE_CHECKER(type, instancetype) \ |
bool Object::Is##type() const { \ |
return Object::IsHeapObject() && \ |
@@ -699,6 +708,11 @@ bool Object::IsDescriptorArray() const { |
} |
+bool Object::IsLayoutDescriptor() const { |
+ return IsSmi() || IsFixedTypedArrayBase(); |
+} |
+ |
+ |
bool Object::IsTransitionArray() const { |
return IsFixedArray(); |
} |
@@ -2065,10 +2079,24 @@ void JSObject::SetInternalField(int index, Smi* value) { |
} |
+bool JSObject::IsUnboxedDoubleField(FieldIndex index) { |
+ if (!FLAG_unbox_double_fields) return false; |
+ return map()->IsUnboxedDoubleField(index); |
+} |
+ |
+ |
+bool Map::IsUnboxedDoubleField(FieldIndex index) { |
+ if (!FLAG_unbox_double_fields) return false; |
+ if (index.is_hidden_field() || !index.is_inobject()) return false; |
+ return !layout_descriptor()->IsTagged(index.property_index()); |
+} |
+ |
+ |
// Access fast-case object properties at index. The use of these routines |
// is needed to correctly distinguish between properties stored in-object and |
// properties stored in the properties array. |
Object* JSObject::RawFastPropertyAt(FieldIndex index) { |
+ DCHECK(!IsUnboxedDoubleField(index)); |
if (index.is_inobject()) { |
return READ_FIELD(this, index.offset()); |
} else { |
@@ -2077,7 +2105,13 @@ Object* JSObject::RawFastPropertyAt(FieldIndex index) { |
} |
-void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { |
+double JSObject::RawFastDoublePropertyAt(FieldIndex index) { |
+ DCHECK(IsUnboxedDoubleField(index)); |
+ return READ_DOUBLE_FIELD(this, index.offset()); |
+} |
+ |
+ |
+void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) { |
if (index.is_inobject()) { |
int offset = index.offset(); |
WRITE_FIELD(this, offset, value); |
@@ -2088,6 +2122,21 @@ void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { |
} |
+void JSObject::RawFastDoublePropertyAtPut(FieldIndex index, double value) { |
+ WRITE_DOUBLE_FIELD(this, index.offset(), value); |
+} |
+ |
+ |
+void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { |
+ if (IsUnboxedDoubleField(index)) { |
+ DCHECK(value->IsMutableHeapNumber()); |
+ RawFastDoublePropertyAtPut(index, HeapNumber::cast(value)->value()); |
+ } else { |
+ RawFastPropertyAtPut(index, value); |
+ } |
+} |
+ |
+ |
int JSObject::GetInObjectPropertyOffset(int index) { |
return map()->GetInObjectPropertyOffset(index); |
} |
@@ -3106,8 +3155,7 @@ void DescriptorArray::Set(int descriptor_number, |
NoIncrementalWriteBarrierSet(this, |
ToValueIndex(descriptor_number), |
*desc->GetValue()); |
- NoIncrementalWriteBarrierSet(this, |
- ToDetailsIndex(descriptor_number), |
+ NoIncrementalWriteBarrierSet(this, ToDetailsIndex(descriptor_number), |
desc->GetDetails().AsSmi()); |
} |
@@ -3282,6 +3330,7 @@ CAST_ACCESSOR(JSTypedArray) |
CAST_ACCESSOR(JSValue) |
CAST_ACCESSOR(JSWeakMap) |
CAST_ACCESSOR(JSWeakSet) |
+CAST_ACCESSOR(LayoutDescriptor) |
CAST_ACCESSOR(Map) |
CAST_ACCESSOR(Name) |
CAST_ACCESSOR(NameDictionary) |
@@ -4323,6 +4372,14 @@ int Map::GetInObjectPropertyOffset(int index) { |
} |
+Handle<Map> Map::CopyInstallDescriptorsForTesting( |
+ Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors, |
+ Handle<LayoutDescriptor> layout_descriptor) { |
+ return CopyInstallDescriptors(map, new_descriptor, descriptors, |
+ layout_descriptor); |
+} |
+ |
+ |
int HeapObject::SizeFromMap(Map* map) { |
int instance_size = map->instance_size(); |
if (instance_size != kVariableSizeSentinel) return instance_size; |
@@ -5168,14 +5225,41 @@ static void EnsureHasTransitionArray(Handle<Map> map) { |
} |
-void Map::InitializeDescriptors(DescriptorArray* descriptors) { |
+LayoutDescriptor* Map::layout_descriptor_gc_safe() { |
+ Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
+ return LayoutDescriptor::cast_gc_safe(layout_desc); |
+} |
+ |
+ |
+void Map::UpdateDescriptors(DescriptorArray* descriptors, |
+ LayoutDescriptor* layout_desc) { |
+ set_instance_descriptors(descriptors); |
+ if (FLAG_unbox_double_fields) { |
+ if (layout_descriptor()->IsSlowLayout()) { |
+ set_layout_descriptor(layout_desc); |
+ } |
+ SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); |
+ DCHECK(visitor_id() == StaticVisitorBase::GetVisitorId(this)); |
+ } |
+} |
+ |
+ |
+void Map::InitializeDescriptors(DescriptorArray* descriptors, |
+ LayoutDescriptor* layout_desc) { |
int len = descriptors->number_of_descriptors(); |
set_instance_descriptors(descriptors); |
SetNumberOfOwnDescriptors(len); |
+ |
+ if (FLAG_unbox_double_fields) { |
+ set_layout_descriptor(layout_desc); |
+ SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); |
+ set_visitor_id(StaticVisitorBase::GetVisitorId(this)); |
+ } |
} |
ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset) |
+ACCESSORS(Map, layout_descriptor, LayoutDescriptor, kLayoutDecriptorOffset) |
void Map::set_bit_field3(uint32_t bits) { |
@@ -5191,12 +5275,25 @@ uint32_t Map::bit_field3() { |
} |
+LayoutDescriptor* Map::GetLayoutDescriptor() { |
+ return FLAG_unbox_double_fields ? layout_descriptor() |
+ : LayoutDescriptor::FastPointerLayout(); |
+} |
+ |
+ |
void Map::AppendDescriptor(Descriptor* desc) { |
DescriptorArray* descriptors = instance_descriptors(); |
int number_of_own_descriptors = NumberOfOwnDescriptors(); |
DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); |
descriptors->Append(desc); |
SetNumberOfOwnDescriptors(number_of_own_descriptors + 1); |
+ |
+// This function does not support appending double field descriptors and |
+// it should never try to (otherwise, layout descriptor must be updated too). |
+#ifdef DEBUG |
+ PropertyDetails details = desc->GetDetails(); |
+ CHECK(details.type() != FIELD || !details.representation().IsDouble()); |
+#endif |
} |
@@ -7273,12 +7370,37 @@ void ExternalTwoByteString::ExternalTwoByteStringIterateBody() { |
} |
+static inline void IterateBodyUsingLayoutDescriptor(HeapObject* object, |
+ int start_offset, |
+ int end_offset, |
+ ObjectVisitor* v) { |
+ DCHECK(FLAG_unbox_double_fields); |
+ DCHECK(IsAligned(start_offset, kPointerSize) && |
+ IsAligned(end_offset, kPointerSize)); |
+ |
+ InobjectPropertiesHelper helper(object->map()); |
+ DCHECK(!helper.all_fields_tagged()); |
+ |
+ for (int offset = start_offset; offset < end_offset; offset += kPointerSize) { |
+ // Visit all tagged fields. |
+ if (helper.IsTagged(offset)) { |
+ v->VisitPointer(HeapObject::RawField(object, offset)); |
+ } |
+ } |
+} |
+ |
+ |
template<int start_offset, int end_offset, int size> |
void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody( |
HeapObject* obj, |
ObjectVisitor* v) { |
+ if (!FLAG_unbox_double_fields || |
+ obj->map()->layout_descriptor()->IsFastPointerLayout()) { |
v->VisitPointers(HeapObject::RawField(obj, start_offset), |
HeapObject::RawField(obj, end_offset)); |
+ } else { |
+ IterateBodyUsingLayoutDescriptor(obj, start_offset, end_offset, v); |
+ } |
} |
@@ -7286,8 +7408,13 @@ template<int start_offset> |
void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj, |
int object_size, |
ObjectVisitor* v) { |
- v->VisitPointers(HeapObject::RawField(obj, start_offset), |
- HeapObject::RawField(obj, object_size)); |
+ if (!FLAG_unbox_double_fields || |
+ obj->map()->layout_descriptor()->IsFastPointerLayout()) { |
+ v->VisitPointers(HeapObject::RawField(obj, start_offset), |
+ HeapObject::RawField(obj, object_size)); |
+ } else { |
+ IterateBodyUsingLayoutDescriptor(obj, start_offset, object_size, v); |
+ } |
} |