diff --git a/src/elements-kind.cc b/src/elements-kind.cc index 200fea600a..c669917c42 100644 --- a/src/elements-kind.cc +++ b/src/elements-kind.cc @@ -54,8 +54,14 @@ int ElementsKindToShiftSize(ElementsKind elements_kind) { int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); - return IsExternalArrayElementsKind(elements_kind) - ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag); + + if (IsExternalArrayElementsKind(elements_kind)) { + return 0; + } else if (IsFixedTypedArrayElementsKind(elements_kind)) { + return FixedTypedArrayBase::kDataOffset - kHeapObjectTag; + } else { + return FixedArray::kHeaderSize - kHeapObjectTag; + } } diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 361b4d91d7..ea6c06d68c 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -2421,6 +2421,12 @@ class ScavengingVisitor : public StaticVisitorBase { HeapObject* object) { int object_size = reinterpret_cast(object)->size(); EvacuateObject(map, slot, object, object_size); + + MapWord map_word = object->map_word(); + DCHECK(map_word.IsForwardingAddress()); + FixedTypedArrayBase* target = + reinterpret_cast(map_word.ToForwardingAddress()); + target->set_base_pointer(target, SKIP_WRITE_BARRIER); } @@ -2428,6 +2434,12 @@ class ScavengingVisitor : public StaticVisitorBase { HeapObject* object) { int object_size = reinterpret_cast(object)->size(); EvacuateObject(map, slot, object, object_size); + + MapWord map_word = object->map_word(); + DCHECK(map_word.IsForwardingAddress()); + FixedTypedArrayBase* target = + reinterpret_cast(map_word.ToForwardingAddress()); + target->set_base_pointer(target, SKIP_WRITE_BARRIER); } @@ -3908,6 +3920,7 @@ AllocationResult Heap::AllocateFixedTypedArray(int length, object->set_map(MapForFixedTypedArray(array_type)); FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(object); + elements->set_base_pointer(elements, SKIP_WRITE_BARRIER); elements->set_length(length); if (initialize) memset(elements->DataPtr(), 0, elements->DataSize()); return elements; diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index 0255dfca96..b56af23c49 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc @@ -2779,7 +2779,12 @@ void MarkCompactCollector::MigrateObjectTagged(HeapObject* dst, HeapObject* src, void MarkCompactCollector::MigrateObjectMixed(HeapObject* dst, HeapObject* src, int size) { - if (FLAG_unbox_double_fields) { + if (src->IsFixedTypedArrayBase()) { + heap()->MoveBlock(dst->address(), src->address(), size); + Address base_pointer_slot = + dst->address() + FixedTypedArrayBase::kBasePointerOffset; + RecordMigratedSlot(Memory::Object_at(base_pointer_slot), base_pointer_slot); + } else if (FLAG_unbox_double_fields) { Address dst_addr = dst->address(); Address src_addr = src->address(); Address src_slot = src_addr; @@ -3198,7 +3203,10 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { } case HeapObjectContents::kMixedValues: { - if (FLAG_unbox_double_fields) { + if (object->IsFixedTypedArrayBase()) { + return static_cast(slot - object->address()) == + FixedTypedArrayBase::kBasePointerOffset; + } else if (FLAG_unbox_double_fields) { // Filter out slots that happen to point to unboxed double fields. LayoutDescriptorHelper helper(object->map()); DCHECK(!helper.all_fields_tagged()); diff --git a/src/heap/store-buffer.cc b/src/heap/store-buffer.cc index 3c880de531..03f587f215 100644 --- a/src/heap/store-buffer.cc +++ b/src/heap/store-buffer.cc @@ -498,7 +498,12 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) { } case HeapObjectContents::kMixedValues: { - if (FLAG_unbox_double_fields) { + if (heap_object->IsFixedTypedArrayBase()) { + FindPointersToNewSpaceInRegion( + obj_address + FixedTypedArrayBase::kBasePointerOffset, + obj_address + FixedTypedArrayBase::kHeaderSize, + slot_callback); + } else if (FLAG_unbox_double_fields) { LayoutDescriptorHelper helper(heap_object->map()); DCHECK(!helper.all_fields_tagged()); for (int offset = start_offset; offset < end_offset;) { diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 9d48a22333..15aa385851 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -5928,6 +5928,11 @@ class HObjectAccess final { Representation::Smi()); } + static HObjectAccess ForFixedTypedArrayBaseBasePointer() { + return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset, + Representation::Tagged()); + } + static HObjectAccess ForStringHashField() { return HObjectAccess(kInobject, String::kHashFieldOffset, diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 12decb0a23..40e82e9643 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -9916,6 +9916,8 @@ HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray( Add(elements, HObjectAccess::ForFixedArrayLength(), length); + Add( + elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements); HValue* filler = Add(static_cast(0)); diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 635bd6140e..d6765ddb09 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -241,6 +241,7 @@ void FixedTypedArray::FixedTypedArrayVerify() { CHECK(IsHeapObject() && HeapObject::cast(this)->map()->instance_type() == Traits::kInstanceType); + CHECK(base_pointer() == this); } diff --git a/src/objects-inl.h b/src/objects-inl.h index 966954dfda..a10832f30b 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1538,6 +1538,9 @@ HeapObjectContents HeapObject::ContentType() { } else if (type == JS_FUNCTION_TYPE) { return HeapObjectContents::kMixedValues; #endif + } else if (type >= FIRST_FIXED_TYPED_ARRAY_TYPE && + type <= LAST_FIXED_TYPED_ARRAY_TYPE) { + return HeapObjectContents::kMixedValues; } else if (type <= LAST_DATA_TYPE) { // TODO(jochen): Why do we claim that Code and Map contain only raw values? return HeapObjectContents::kRawValues; @@ -3877,6 +3880,9 @@ void ExternalFloat64Array::set(int index, double value) { } +ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset) + + void* FixedTypedArrayBase::DataPtr() { return FIELD_ADDR(this, kDataOffset); } @@ -7161,6 +7167,19 @@ void Foreign::ForeignIterateBody() { } +void FixedTypedArrayBase::FixedTypedArrayBaseIterateBody(ObjectVisitor* v) { + v->VisitPointer( + reinterpret_cast(FIELD_ADDR(this, kBasePointerOffset))); +} + + +template +void FixedTypedArrayBase::FixedTypedArrayBaseIterateBody() { + StaticVisitor::VisitPointer( + reinterpret_cast(FIELD_ADDR(this, kBasePointerOffset))); +} + + void ExternalOneByteString::ExternalOneByteStringIterateBody(ObjectVisitor* v) { typedef v8::String::ExternalOneByteStringResource Resource; v->VisitExternalOneByteString( diff --git a/src/objects.cc b/src/objects.cc index c5ad52011d..bbf582a7b5 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1478,10 +1478,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size, case FREE_SPACE_TYPE: break; -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ - case EXTERNAL_##TYPE##_ARRAY_TYPE: \ - case FIXED_##TYPE##_ARRAY_TYPE: \ - break; +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ + case EXTERNAL_##TYPE##_ARRAY_TYPE: \ + break; \ + \ + case FIXED_##TYPE##_ARRAY_TYPE: \ + reinterpret_cast(this) \ + ->FixedTypedArrayBaseIterateBody(v); \ + break; + TYPED_ARRAYS(TYPED_ARRAY_CASE) #undef TYPED_ARRAY_CASE diff --git a/src/objects.h b/src/objects.h index 79a8fbafbe..7b9796481e 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4593,8 +4593,21 @@ class ExternalFloat64Array: public ExternalArray { class FixedTypedArrayBase: public FixedArrayBase { public: + // [base_pointer]: For now, points to the FixedTypedArrayBase itself. + DECL_ACCESSORS(base_pointer, Object) + + // Dispatched behavior. + inline void FixedTypedArrayBaseIterateBody(ObjectVisitor* v); + + template + inline void FixedTypedArrayBaseIterateBody(); + DECLARE_CAST(FixedTypedArrayBase) + static const int kBasePointerOffset = + FixedArrayBase::kHeaderSize + kPointerSize; + static const int kHeaderSize = kBasePointerOffset + kPointerSize; + static const int kDataOffset = DOUBLE_POINTER_ALIGN(kHeaderSize); inline int size();