Ensure double alignment when deserializing.
R=rmcilroy@chromium.org BUG=chromium:436510 LOG=N TEST=compile with V8_OOL_CONSTANT_POOL=1, run d8 with --verify-heap --test Review URL: https://codereview.chromium.org/759823006 Cr-Commit-Position: refs/heads/master@{#25534}
This commit is contained in:
parent
60af073ad8
commit
4590e4f4d6
@ -1829,6 +1829,11 @@ static HeapObject* EnsureDoubleAligned(Heap* heap, HeapObject* object,
|
||||
}
|
||||
|
||||
|
||||
HeapObject* Heap::DoubleAlignForDeserialization(HeapObject* object, int size) {
|
||||
return EnsureDoubleAligned(this, object, size);
|
||||
}
|
||||
|
||||
|
||||
enum LoggingAndProfiling {
|
||||
LOGGING_AND_PROFILING_ENABLED,
|
||||
LOGGING_AND_PROFILING_DISABLED
|
||||
|
@ -1726,6 +1726,8 @@ class Heap {
|
||||
return (pretenure == TENURED) ? preferred_old_space : NEW_SPACE;
|
||||
}
|
||||
|
||||
HeapObject* DoubleAlignForDeserialization(HeapObject* object, int size);
|
||||
|
||||
// Allocate an uninitialized object. The memory is non-executable if the
|
||||
// hardware and OS allow. This is the single choke-point for allocations
|
||||
// performed by the runtime and should not be bypassed (to extend this to
|
||||
|
@ -47,6 +47,10 @@ void HeapObject::HeapObjectVerify() {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(yangguo): Use this check once crbug/436911 has been fixed.
|
||||
// DCHECK(!NeedsToEnsureDoubleAlignment() ||
|
||||
// IsAligned(OffsetFrom(address()), kDoubleAlignment));
|
||||
|
||||
switch (instance_type) {
|
||||
case SYMBOL_TYPE:
|
||||
Symbol::cast(this)->SymbolVerify();
|
||||
|
@ -2758,6 +2758,17 @@ WriteBarrierMode HeapObject::GetWriteBarrierMode(
|
||||
}
|
||||
|
||||
|
||||
bool HeapObject::NeedsToEnsureDoubleAlignment() {
|
||||
#ifndef V8_HOST_ARCH_64_BIT
|
||||
return (IsFixedFloat64Array() || IsFixedDoubleArray() ||
|
||||
IsConstantPoolArray()) &&
|
||||
FixedArrayBase::cast(this)->length() != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif // V8_HOST_ARCH_64_BIT
|
||||
}
|
||||
|
||||
|
||||
void FixedArray::set(int index,
|
||||
Object* value,
|
||||
WriteBarrierMode mode) {
|
||||
|
@ -1443,6 +1443,8 @@ class HeapObject: public Object {
|
||||
static void VerifyHeapPointer(Object* p);
|
||||
#endif
|
||||
|
||||
inline bool NeedsToEnsureDoubleAlignment();
|
||||
|
||||
// Layout description.
|
||||
// First field in a heap object is map.
|
||||
static const int kMapOffset = Object::kHeaderSize;
|
||||
|
@ -807,11 +807,27 @@ Object* Deserializer::ProcessBackRefInSerializedCode(Object* obj) {
|
||||
// The reason for this strange interface is that otherwise the object is
|
||||
// written very late, which means the FreeSpace map is not set up by the
|
||||
// time we need to use it to mark the space at the end of a page free.
|
||||
void Deserializer::ReadObject(int space_number,
|
||||
Object** write_back) {
|
||||
int size = source_->GetInt() << kObjectAlignmentBits;
|
||||
Address address = Allocate(space_number, size);
|
||||
HeapObject* obj = HeapObject::FromAddress(address);
|
||||
void Deserializer::ReadObject(int space_number, Object** write_back) {
|
||||
Address address;
|
||||
HeapObject* obj;
|
||||
int next_int = source_->GetInt();
|
||||
|
||||
bool double_align = false;
|
||||
#ifndef V8_HOST_ARCH_64_BIT
|
||||
double_align = next_int == kDoubleAlignmentSentinel;
|
||||
if (double_align) next_int = source_->GetInt();
|
||||
#endif
|
||||
|
||||
DCHECK_NE(kDoubleAlignmentSentinel, next_int);
|
||||
int size = next_int << kObjectAlignmentBits;
|
||||
int reserved_size = size + (double_align ? kPointerSize : 0);
|
||||
address = Allocate(space_number, reserved_size);
|
||||
obj = HeapObject::FromAddress(address);
|
||||
if (double_align) {
|
||||
obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size);
|
||||
address = obj->address();
|
||||
}
|
||||
|
||||
isolate_->heap()->OnAllocationEvent(obj, size);
|
||||
Object** current = reinterpret_cast<Object**>(address);
|
||||
Object** limit = current + (size >> kPointerSizeLog2);
|
||||
@ -1549,9 +1565,19 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
|
||||
void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
|
||||
int size, Map* map) {
|
||||
int reserved_size = size;
|
||||
|
||||
sink_->Put(kNewObject + reference_representation_ + space,
|
||||
"ObjectSerialization");
|
||||
sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
|
||||
// Objects on the large object space are always double-aligned.
|
||||
if (space != LO_SPACE && object_->NeedsToEnsureDoubleAlignment()) {
|
||||
sink_->PutInt(kDoubleAlignmentSentinel, "double align next object");
|
||||
// Add wriggle room for double alignment padding.
|
||||
reserved_size += kPointerSize;
|
||||
}
|
||||
int encoded_size = size >> kObjectAlignmentBits;
|
||||
DCHECK_NE(kDoubleAlignmentSentinel, encoded_size);
|
||||
sink_->PutInt(encoded_size, "Size in words");
|
||||
|
||||
if (serializer_->code_address_map_) {
|
||||
const char* code_name =
|
||||
@ -1572,7 +1598,7 @@ void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
|
||||
}
|
||||
back_reference = serializer_->AllocateLargeObject(size);
|
||||
} else {
|
||||
back_reference = serializer_->Allocate(space, size);
|
||||
back_reference = serializer_->Allocate(space, reserved_size);
|
||||
}
|
||||
serializer_->back_reference_map()->Add(object_, back_reference);
|
||||
|
||||
@ -1918,7 +1944,7 @@ BackReference Serializer::AllocateLargeObject(int size) {
|
||||
|
||||
|
||||
BackReference Serializer::Allocate(AllocationSpace space, int size) {
|
||||
CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
|
||||
DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
|
||||
DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space)));
|
||||
uint32_t new_chunk_size = pending_chunk_[space] + size;
|
||||
if (new_chunk_size > max_chunk_size(space)) {
|
||||
|
@ -301,20 +301,20 @@ class SerializerDeserializer: public ObjectVisitor {
|
||||
protected:
|
||||
// Where the pointed-to object can be found:
|
||||
enum Where {
|
||||
kNewObject = 0, // Object is next in snapshot.
|
||||
// 1-7 One per space.
|
||||
kNewObject = 0, // Object is next in snapshot.
|
||||
// 1-7 One per space.
|
||||
kRootArray = 0x9, // Object is found in root array.
|
||||
kPartialSnapshotCache = 0xa, // Object is in the cache.
|
||||
kExternalReference = 0xb, // Pointer to an external reference.
|
||||
kSkip = 0xc, // Skip n bytes.
|
||||
kBuiltin = 0xd, // Builtin code object.
|
||||
kAttachedReference = 0xe, // Object is described in an attached list.
|
||||
kNop = 0xf, // Does nothing, used to pad.
|
||||
kBackref = 0x10, // Object is described relative to end.
|
||||
// 0x11-0x17 One per space.
|
||||
kBackrefWithSkip = 0x18, // Object is described relative to end.
|
||||
// 0x19-0x1f One per space.
|
||||
// 0x20-0x3f Used by misc. tags below.
|
||||
// 0xf Used by misc. See below.
|
||||
kBackref = 0x10, // Object is described relative to end.
|
||||
// 0x11-0x17 One per space.
|
||||
kBackrefWithSkip = 0x18, // Object is described relative to end.
|
||||
// 0x19-0x1f One per space.
|
||||
// 0x20-0x3f Used by misc. See below.
|
||||
kPointedToMask = 0x3f
|
||||
};
|
||||
|
||||
@ -375,11 +375,16 @@ class SerializerDeserializer: public ObjectVisitor {
|
||||
return byte_code & 0x1f;
|
||||
}
|
||||
|
||||
static const int kNop = 0xf; // Do nothing, used for padding.
|
||||
|
||||
static const int kAnyOldSpace = -1;
|
||||
|
||||
// A bitmask for getting the space out of an instruction.
|
||||
static const int kSpaceMask = 7;
|
||||
STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
|
||||
|
||||
// Sentinel after a new object to indicate that double alignment is needed.
|
||||
static const int kDoubleAlignmentSentinel = 0;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user