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, ...@@ -2729,37 +2729,23 @@ void MarkCompactCollector::MigrateObject(HeapObject* dst, HeapObject* src,
DCHECK(heap()->AllowedToBeMigrated(src, dest)); DCHECK(heap()->AllowedToBeMigrated(src, dest));
DCHECK(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize); DCHECK(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize);
if (dest == OLD_SPACE) { if (dest == OLD_SPACE) {
Address src_slot = src_addr;
Address dst_slot = dst_addr;
DCHECK(IsAligned(size, kPointerSize)); DCHECK(IsAligned(size, kPointerSize));
switch (src->ContentType()) {
case HeapObjectContents::kTaggedValues:
MigrateObjectTagged(dst, src, size);
break;
bool may_contain_raw_values = src->MayContainRawValues(); case HeapObjectContents::kMixedValues:
#if V8_DOUBLE_FIELDS_UNBOXING MigrateObjectMixed(dst, src, size);
LayoutDescriptorHelper helper(src->map()); break;
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);
}
src_slot += kPointerSize; case HeapObjectContents::kRawValues:
dst_slot += kPointerSize; MigrateObjectRaw(dst, src, size);
break;
} }
if (compacting_ && dst->IsJSFunction()) { 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); Address code_entry = Memory::Address_at(code_entry_slot);
if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) { if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
...@@ -2784,6 +2770,54 @@ void MarkCompactCollector::MigrateObject(HeapObject* dst, HeapObject* src, ...@@ -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. // Visitor for updating pointers from live objects in old spaces to new space.
// It does not expect to encounter pointers to dead objects. // It does not expect to encounter pointers to dead objects.
class PointersUpdatingVisitor : public ObjectVisitor { class PointersUpdatingVisitor : public ObjectVisitor {
...@@ -3152,22 +3186,31 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { ...@@ -3152,22 +3186,31 @@ bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
// We don't need to check large objects' layout descriptor since it can't // We don't need to check large objects' layout descriptor since it can't
// contain in-object fields anyway. // contain in-object fields anyway.
if (object != NULL) { if (object != NULL) {
// TODO(ishell): This is a workaround for crbug/454297. We must not have switch (object->ContentType()) {
// slots in data objects at all. Remove this once we found the root cause. case HeapObjectContents::kTaggedValues:
return true;
case HeapObjectContents::kRawValues: {
InstanceType type = object->map()->instance_type(); InstanceType type = object->map()->instance_type();
// Slots in maps and code can't be invalid because they are never shrunk. // Slots in maps and code can't be invalid because they are never
// shrunk.
if (type == MAP_TYPE || type == CODE_TYPE) return true; if (type == MAP_TYPE || type == CODE_TYPE) return true;
// Consider slots in objects that contain ONLY raw data as invalid. // Consider slots in objects that contain ONLY raw data as invalid.
if (object->MayContainRawValues()) return false; return false;
}
case HeapObjectContents::kMixedValues: {
if (FLAG_unbox_double_fields) { if (FLAG_unbox_double_fields) {
// Filter out slots that happen to point to unboxed double fields. // Filter out slots that happen to point to unboxed double fields.
LayoutDescriptorHelper helper(object->map()); LayoutDescriptorHelper helper(object->map());
bool has_only_tagged_fields = helper.all_fields_tagged(); DCHECK(!helper.all_fields_tagged());
if (!has_only_tagged_fields && return helper.IsTagged(static_cast<int>(slot - object->address()));
!helper.IsTagged(static_cast<int>(slot - object->address()))) { }
return false; break;
} }
} }
UNREACHABLE();
} }
return true; return true;
......
...@@ -666,6 +666,10 @@ class MarkCompactCollector { ...@@ -666,6 +666,10 @@ class MarkCompactCollector {
void MigrateObject(HeapObject* dst, HeapObject* src, int size, void MigrateObject(HeapObject* dst, HeapObject* src, int size,
AllocationSpace to_old_space); 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); bool TryPromoteObject(HeapObject* object, int object_size);
void InvalidateCode(Code* code); void InvalidateCode(Code* code);
......
...@@ -483,16 +483,24 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) { ...@@ -483,16 +483,24 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
for (HeapObject* heap_object = iterator.Next(); heap_object != NULL; for (HeapObject* heap_object = iterator.Next(); heap_object != NULL;
heap_object = iterator.Next()) { heap_object = iterator.Next()) {
// We iterate over objects that contain new space pointers only. // 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(); Address obj_address = heap_object->address();
const int start_offset = HeapObject::kHeaderSize; const int start_offset = HeapObject::kHeaderSize;
const int end_offset = heap_object->Size(); 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) { 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);
break;
}
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;) { for (int offset = start_offset; offset < end_offset;) {
int end_of_region_offset; int end_of_region_offset;
if (helper.IsTagged(offset, end_offset, if (helper.IsTagged(offset, end_offset,
...@@ -504,15 +512,13 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) { ...@@ -504,15 +512,13 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
offset = end_of_region_offset; offset = end_of_region_offset;
} }
} else { } else {
#endif UNREACHABLE();
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
} }
#endif break;
}
case HeapObjectContents::kRawValues:
break;
} }
} }
} }
......
...@@ -1529,20 +1529,36 @@ int HeapObject::Size() { ...@@ -1529,20 +1529,36 @@ int HeapObject::Size() {
} }
bool HeapObject::MayContainRawValues() { HeapObjectContents HeapObject::ContentType() {
InstanceType type = map()->instance_type(); InstanceType type = map()->instance_type();
if (type <= LAST_NAME_TYPE) { if (type <= LAST_NAME_TYPE) {
if (type == SYMBOL_TYPE) { if (type == SYMBOL_TYPE) {
return false; return HeapObjectContents::kTaggedValues;
} }
DCHECK(type < FIRST_NONSTRING_TYPE); DCHECK(type < FIRST_NONSTRING_TYPE);
// There are four string representations: sequential strings, external // There are four string representations: sequential strings, external
// strings, cons strings, and sliced strings. // strings, cons strings, and sliced strings.
// Only the former two contain raw values and no heap pointers (besides the // Only the former two contain raw values and no heap pointers (besides the
// map-word). // 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 { ...@@ -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 // HeapObject is the superclass for all classes describing heap allocated
// objects. // objects.
class HeapObject: public Object { class HeapObject: public Object {
...@@ -1450,9 +1457,8 @@ class HeapObject: public Object { ...@@ -1450,9 +1457,8 @@ class HeapObject: public Object {
// Returns the heap object's size in bytes // Returns the heap object's size in bytes
inline int Size(); inline int Size();
// Returns true if this heap object may contain raw values, i.e., values that // Indicates what type of values this heap object may contain.
// look like pointers to heap objects. inline HeapObjectContents ContentType();
inline bool MayContainRawValues();
// Given a heap object's map pointer, returns the heap size in bytes // Given a heap object's map pointer, returns the heap size in bytes
// Useful when the map pointer field is used for other purposes. // 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