Introduce a base pointer field in FixedTypedArrayBase and teach GC about it

This is the first step towards unifying external and on-heap typed arrays.

The end-state will be that this base pointer either points to the on-heap values
or to the externally allocated array buffer.

BUG=v8:3996
R=hpayer@chromium.org
LOG=n

Review URL: https://codereview.chromium.org/1176263004

Cr-Commit-Position: refs/heads/master@{#29039}
This commit is contained in:
jochen 2015-06-16 00:37:16 -07:00 committed by Commit bot
parent 75350f1ef0
commit 6cc3eb66a2
10 changed files with 86 additions and 9 deletions

View File

@ -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;
}
}

View File

@ -2421,6 +2421,12 @@ class ScavengingVisitor : public StaticVisitorBase {
HeapObject* object) {
int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size();
EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size);
MapWord map_word = object->map_word();
DCHECK(map_word.IsForwardingAddress());
FixedTypedArrayBase* target =
reinterpret_cast<FixedTypedArrayBase*>(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<FixedFloat64Array*>(object)->size();
EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size);
MapWord map_word = object->map_word();
DCHECK(map_word.IsForwardingAddress());
FixedTypedArrayBase* target =
reinterpret_cast<FixedTypedArrayBase*>(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;

View File

@ -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<int>(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());

View File

@ -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;) {

View File

@ -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,

View File

@ -9916,6 +9916,8 @@ HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
Add<HStoreNamedField>(elements,
HObjectAccess::ForFixedArrayLength(),
length);
Add<HStoreNamedField>(
elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
HValue* filler = Add<HConstant>(static_cast<int32_t>(0));

View File

@ -241,6 +241,7 @@ void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
CHECK(IsHeapObject() &&
HeapObject::cast(this)->map()->instance_type() ==
Traits::kInstanceType);
CHECK(base_pointer() == this);
}

View File

@ -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<Object**>(FIELD_ADDR(this, kBasePointerOffset)));
}
template <typename StaticVisitor>
void FixedTypedArrayBase::FixedTypedArrayBaseIterateBody() {
StaticVisitor::VisitPointer(
reinterpret_cast<Object**>(FIELD_ADDR(this, kBasePointerOffset)));
}
void ExternalOneByteString::ExternalOneByteStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalOneByteStringResource Resource;
v->VisitExternalOneByteString(

View File

@ -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<FixedTypedArrayBase*>(this) \
->FixedTypedArrayBaseIterateBody(v); \
break;
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

View File

@ -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 <typename StaticVisitor>
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();