Commit 54309ebb authored by jochen's avatar jochen Committed by Commit bot

Factor out handling of mixed objects preprocessing after migration

R=hpayer@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#28834}
parent 5aaceefd
......@@ -2729,37 +2729,23 @@ void MarkCompactCollector::MigrateObject(HeapObject* dst, HeapObject* src,
DCHECK(heap()->AllowedToBeMigrated(src, dest));
DCHECK(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize);
if (dest == OLD_SPACE) {
Address src_slot = src_addr;
Address dst_slot = dst_addr;
DCHECK(IsAligned(size, kPointerSize));
switch (src->ContentType()) {
case HeapObjectContents::kTaggedValues:
MigrateObjectTagged(dst, src, size);
break;
bool may_contain_raw_values = src->MayContainRawValues();
#if V8_DOUBLE_FIELDS_UNBOXING
LayoutDescriptorHelper helper(src->map());
bool has_only_tagged_fields = helper.all_fields_tagged();
#endif
for (int remaining = size / kPointerSize; remaining > 0; remaining--) {
Object* value = Memory::Object_at(src_slot);
Memory::Object_at(dst_slot) = value;
#if V8_DOUBLE_FIELDS_UNBOXING
if (!may_contain_raw_values &&
(has_only_tagged_fields ||
helper.IsTagged(static_cast<int>(src_slot - src_addr))))
#else
if (!may_contain_raw_values)
#endif
{
RecordMigratedSlot(value, dst_slot);
}
case HeapObjectContents::kMixedValues:
MigrateObjectMixed(dst, src, size);
break;
src_slot += kPointerSize;
dst_slot += kPointerSize;
case HeapObjectContents::kRawValues:
MigrateObjectRaw(dst, src, size);
break;
}
if (compacting_ && dst->IsJSFunction()) {
Address code_entry_slot = dst_addr + JSFunction::kCodeEntryOffset;
Address code_entry_slot = dst->address() + JSFunction::kCodeEntryOffset;
Address code_entry = Memory::Address_at(code_entry_slot);
if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
......@@ -2784,6 +2770,54 @@ void MarkCompactCollector::MigrateObject(HeapObject* dst, HeapObject* src,
}
void MarkCompactCollector::MigrateObjectTagged(HeapObject* dst, HeapObject* src,
int size) {
Address src_slot = src->address();
Address dst_slot = dst->address();
for (int remaining = size / kPointerSize; remaining > 0; remaining--) {
Object* value = Memory::Object_at(src_slot);
Memory::Object_at(dst_slot) = value;
RecordMigratedSlot(value, dst_slot);
src_slot += kPointerSize;
dst_slot += kPointerSize;
}
}
void MarkCompactCollector::MigrateObjectMixed(HeapObject* dst, HeapObject* src,
int size) {
if (FLAG_unbox_double_fields) {
Address dst_addr = dst->address();
Address src_addr = src->address();
Address src_slot = src_addr;
Address dst_slot = dst_addr;
LayoutDescriptorHelper helper(src->map());
DCHECK(!helper.all_fields_tagged());
for (int remaining = size / kPointerSize; remaining > 0; remaining--) {
Object* value = Memory::Object_at(src_slot);
Memory::Object_at(dst_slot) = value;
if (helper.IsTagged(static_cast<int>(src_slot - src_addr))) {
RecordMigratedSlot(value, dst_slot);
}
src_slot += kPointerSize;
dst_slot += kPointerSize;
}
} else {
UNREACHABLE();
}
}
void MarkCompactCollector::MigrateObjectRaw(HeapObject* dst, HeapObject* src,
int size) {
heap()->MoveBlock(dst->address(), src->address(), size);
}
// Visitor for updating pointers from live objects in old spaces to new space.
// It does not expect to encounter pointers to dead objects.
class PointersUpdatingVisitor : public ObjectVisitor {
......@@ -3152,22 +3186,31 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
// We don't need to check large objects' layout descriptor since it can't
// contain in-object fields anyway.
if (object != NULL) {
// TODO(ishell): This is a workaround for crbug/454297. We must not have
// slots in data objects at all. Remove this once we found the root cause.
InstanceType type = object->map()->instance_type();
// Slots in maps and code can't be invalid because they are never shrunk.
if (type == MAP_TYPE || type == CODE_TYPE) return true;
// Consider slots in objects that contain ONLY raw data as invalid.
if (object->MayContainRawValues()) return false;
if (FLAG_unbox_double_fields) {
// Filter out slots that happen to point to unboxed double fields.
LayoutDescriptorHelper helper(object->map());
bool has_only_tagged_fields = helper.all_fields_tagged();
if (!has_only_tagged_fields &&
!helper.IsTagged(static_cast<int>(slot - object->address()))) {
switch (object->ContentType()) {
case HeapObjectContents::kTaggedValues:
return true;
case HeapObjectContents::kRawValues: {
InstanceType type = object->map()->instance_type();
// Slots in maps and code can't be invalid because they are never
// shrunk.
if (type == MAP_TYPE || type == CODE_TYPE) return true;
// Consider slots in objects that contain ONLY raw data as invalid.
return false;
}
case HeapObjectContents::kMixedValues: {
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());
return helper.IsTagged(static_cast<int>(slot - object->address()));
}
break;
}
}
UNREACHABLE();
}
return true;
......
......@@ -666,6 +666,10 @@ class MarkCompactCollector {
void MigrateObject(HeapObject* dst, HeapObject* src, int size,
AllocationSpace to_old_space);
void MigrateObjectTagged(HeapObject* dst, HeapObject* src, int size);
void MigrateObjectMixed(HeapObject* dst, HeapObject* src, int size);
void MigrateObjectRaw(HeapObject* dst, HeapObject* src, int size);
bool TryPromoteObject(HeapObject* object, int object_size);
void InvalidateCode(Code* code);
......
......@@ -483,36 +483,42 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
for (HeapObject* heap_object = iterator.Next(); heap_object != NULL;
heap_object = iterator.Next()) {
// We iterate over objects that contain new space pointers only.
bool may_contain_raw_values = heap_object->MayContainRawValues();
if (!may_contain_raw_values) {
Address obj_address = heap_object->address();
const int start_offset = HeapObject::kHeaderSize;
const int end_offset = heap_object->Size();
#if V8_DOUBLE_FIELDS_UNBOXING
LayoutDescriptorHelper helper(heap_object->map());
bool has_only_tagged_fields = helper.all_fields_tagged();
if (!has_only_tagged_fields) {
for (int offset = start_offset; offset < end_offset;) {
int end_of_region_offset;
if (helper.IsTagged(offset, end_offset,
&end_of_region_offset)) {
FindPointersToNewSpaceInRegion(
obj_address + offset,
obj_address + end_of_region_offset, slot_callback);
}
offset = end_of_region_offset;
}
} else {
#endif
Address obj_address = heap_object->address();
const int start_offset = HeapObject::kHeaderSize;
const int end_offset = heap_object->Size();
switch (heap_object->ContentType()) {
case HeapObjectContents::kTaggedValues: {
Address start_address = obj_address + start_offset;
Address end_address = obj_address + end_offset;
// Object has only tagged fields.
FindPointersToNewSpaceInRegion(start_address, end_address,
slot_callback);
#if V8_DOUBLE_FIELDS_UNBOXING
break;
}
#endif
case HeapObjectContents::kMixedValues: {
if (FLAG_unbox_double_fields) {
LayoutDescriptorHelper helper(heap_object->map());
DCHECK(!helper.all_fields_tagged());
for (int offset = start_offset; offset < end_offset;) {
int end_of_region_offset;
if (helper.IsTagged(offset, end_offset,
&end_of_region_offset)) {
FindPointersToNewSpaceInRegion(
obj_address + offset,
obj_address + end_of_region_offset, slot_callback);
}
offset = end_of_region_offset;
}
} else {
UNREACHABLE();
}
break;
}
case HeapObjectContents::kRawValues:
break;
}
}
}
......
......@@ -1529,20 +1529,36 @@ int HeapObject::Size() {
}
bool HeapObject::MayContainRawValues() {
HeapObjectContents HeapObject::ContentType() {
InstanceType type = map()->instance_type();
if (type <= LAST_NAME_TYPE) {
if (type == SYMBOL_TYPE) {
return false;
return HeapObjectContents::kTaggedValues;
}
DCHECK(type < FIRST_NONSTRING_TYPE);
// There are four string representations: sequential strings, external
// strings, cons strings, and sliced strings.
// Only the former two contain raw values and no heap pointers (besides the
// map-word).
return ((type & kIsIndirectStringMask) != kIsIndirectStringTag);
if (((type & kIsIndirectStringMask) != kIsIndirectStringTag))
return HeapObjectContents::kRawValues;
else
return HeapObjectContents::kTaggedValues;
#if 0
// TODO(jochen): Enable eventually.
} else if (type == JS_FUNCTION_TYPE) {
return HeapObjectContents::kMixedValues;
#endif
} else if (type <= LAST_DATA_TYPE) {
// TODO(jochen): Why do we claim that Code and Map contain only raw values?
return HeapObjectContents::kRawValues;
} else {
if (FLAG_unbox_double_fields) {
LayoutDescriptorHelper helper(map());
if (!helper.all_fields_tagged()) return HeapObjectContents::kMixedValues;
}
return HeapObjectContents::kTaggedValues;
}
return (type <= LAST_DATA_TYPE);
}
......
......@@ -1399,6 +1399,13 @@ class MapWord BASE_EMBEDDED {
};
// The content of an heap object (except for the map pointer). kTaggedValues
// objects can contain both heap pointers and Smis, kMixedValues can contain
// heap pointers, Smis, and raw values (e.g. doubles or strings), and kRawValues
// objects can contain raw values and Smis.
enum class HeapObjectContents { kTaggedValues, kMixedValues, kRawValues };
// HeapObject is the superclass for all classes describing heap allocated
// objects.
class HeapObject: public Object {
......@@ -1450,9 +1457,8 @@ class HeapObject: public Object {
// Returns the heap object's size in bytes
inline int Size();
// Returns true if this heap object may contain raw values, i.e., values that
// look like pointers to heap objects.
inline bool MayContainRawValues();
// Indicates what type of values this heap object may contain.
inline HeapObjectContents ContentType();
// Given a heap object's map pointer, returns the heap size in bytes
// Useful when the map pointer field is used for other purposes.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment