Commit 4590e4f4 authored by yangguo's avatar yangguo Committed by Commit bot

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}
parent 60af073a
...@@ -1829,6 +1829,11 @@ static HeapObject* EnsureDoubleAligned(Heap* heap, HeapObject* object, ...@@ -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 { enum LoggingAndProfiling {
LOGGING_AND_PROFILING_ENABLED, LOGGING_AND_PROFILING_ENABLED,
LOGGING_AND_PROFILING_DISABLED LOGGING_AND_PROFILING_DISABLED
......
...@@ -1726,6 +1726,8 @@ class Heap { ...@@ -1726,6 +1726,8 @@ class Heap {
return (pretenure == TENURED) ? preferred_old_space : NEW_SPACE; 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 // Allocate an uninitialized object. The memory is non-executable if the
// hardware and OS allow. This is the single choke-point for allocations // 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 // performed by the runtime and should not be bypassed (to extend this to
......
...@@ -47,6 +47,10 @@ void HeapObject::HeapObjectVerify() { ...@@ -47,6 +47,10 @@ void HeapObject::HeapObjectVerify() {
return; return;
} }
// TODO(yangguo): Use this check once crbug/436911 has been fixed.
// DCHECK(!NeedsToEnsureDoubleAlignment() ||
// IsAligned(OffsetFrom(address()), kDoubleAlignment));
switch (instance_type) { switch (instance_type) {
case SYMBOL_TYPE: case SYMBOL_TYPE:
Symbol::cast(this)->SymbolVerify(); Symbol::cast(this)->SymbolVerify();
......
...@@ -2758,6 +2758,17 @@ WriteBarrierMode HeapObject::GetWriteBarrierMode( ...@@ -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, void FixedArray::set(int index,
Object* value, Object* value,
WriteBarrierMode mode) { WriteBarrierMode mode) {
......
...@@ -1443,6 +1443,8 @@ class HeapObject: public Object { ...@@ -1443,6 +1443,8 @@ class HeapObject: public Object {
static void VerifyHeapPointer(Object* p); static void VerifyHeapPointer(Object* p);
#endif #endif
inline bool NeedsToEnsureDoubleAlignment();
// Layout description. // Layout description.
// First field in a heap object is map. // First field in a heap object is map.
static const int kMapOffset = Object::kHeaderSize; static const int kMapOffset = Object::kHeaderSize;
......
...@@ -807,11 +807,27 @@ Object* Deserializer::ProcessBackRefInSerializedCode(Object* obj) { ...@@ -807,11 +807,27 @@ Object* Deserializer::ProcessBackRefInSerializedCode(Object* obj) {
// The reason for this strange interface is that otherwise the object is // 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 // 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. // time we need to use it to mark the space at the end of a page free.
void Deserializer::ReadObject(int space_number, void Deserializer::ReadObject(int space_number, Object** write_back) {
Object** write_back) { Address address;
int size = source_->GetInt() << kObjectAlignmentBits; HeapObject* obj;
Address address = Allocate(space_number, size); int next_int = source_->GetInt();
HeapObject* obj = HeapObject::FromAddress(address);
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); isolate_->heap()->OnAllocationEvent(obj, size);
Object** current = reinterpret_cast<Object**>(address); Object** current = reinterpret_cast<Object**>(address);
Object** limit = current + (size >> kPointerSizeLog2); Object** limit = current + (size >> kPointerSizeLog2);
...@@ -1549,9 +1565,19 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, ...@@ -1549,9 +1565,19 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
int size, Map* map) { int size, Map* map) {
int reserved_size = size;
sink_->Put(kNewObject + reference_representation_ + space, sink_->Put(kNewObject + reference_representation_ + space,
"ObjectSerialization"); "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_) { if (serializer_->code_address_map_) {
const char* code_name = const char* code_name =
...@@ -1572,7 +1598,7 @@ void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, ...@@ -1572,7 +1598,7 @@ void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
} }
back_reference = serializer_->AllocateLargeObject(size); back_reference = serializer_->AllocateLargeObject(size);
} else { } else {
back_reference = serializer_->Allocate(space, size); back_reference = serializer_->Allocate(space, reserved_size);
} }
serializer_->back_reference_map()->Add(object_, back_reference); serializer_->back_reference_map()->Add(object_, back_reference);
...@@ -1918,7 +1944,7 @@ BackReference Serializer::AllocateLargeObject(int size) { ...@@ -1918,7 +1944,7 @@ BackReference Serializer::AllocateLargeObject(int size) {
BackReference Serializer::Allocate(AllocationSpace space, 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))); DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space)));
uint32_t new_chunk_size = pending_chunk_[space] + size; uint32_t new_chunk_size = pending_chunk_[space] + size;
if (new_chunk_size > max_chunk_size(space)) { if (new_chunk_size > max_chunk_size(space)) {
......
...@@ -301,20 +301,20 @@ class SerializerDeserializer: public ObjectVisitor { ...@@ -301,20 +301,20 @@ class SerializerDeserializer: public ObjectVisitor {
protected: protected:
// Where the pointed-to object can be found: // Where the pointed-to object can be found:
enum Where { enum Where {
kNewObject = 0, // Object is next in snapshot. kNewObject = 0, // Object is next in snapshot.
// 1-7 One per space. // 1-7 One per space.
kRootArray = 0x9, // Object is found in root array. kRootArray = 0x9, // Object is found in root array.
kPartialSnapshotCache = 0xa, // Object is in the cache. kPartialSnapshotCache = 0xa, // Object is in the cache.
kExternalReference = 0xb, // Pointer to an external reference. kExternalReference = 0xb, // Pointer to an external reference.
kSkip = 0xc, // Skip n bytes. kSkip = 0xc, // Skip n bytes.
kBuiltin = 0xd, // Builtin code object. kBuiltin = 0xd, // Builtin code object.
kAttachedReference = 0xe, // Object is described in an attached list. kAttachedReference = 0xe, // Object is described in an attached list.
kNop = 0xf, // Does nothing, used to pad. // 0xf Used by misc. See below.
kBackref = 0x10, // Object is described relative to end. kBackref = 0x10, // Object is described relative to end.
// 0x11-0x17 One per space. // 0x11-0x17 One per space.
kBackrefWithSkip = 0x18, // Object is described relative to end. kBackrefWithSkip = 0x18, // Object is described relative to end.
// 0x19-0x1f One per space. // 0x19-0x1f One per space.
// 0x20-0x3f Used by misc. tags below. // 0x20-0x3f Used by misc. See below.
kPointedToMask = 0x3f kPointedToMask = 0x3f
}; };
...@@ -375,11 +375,16 @@ class SerializerDeserializer: public ObjectVisitor { ...@@ -375,11 +375,16 @@ class SerializerDeserializer: public ObjectVisitor {
return byte_code & 0x1f; return byte_code & 0x1f;
} }
static const int kNop = 0xf; // Do nothing, used for padding.
static const int kAnyOldSpace = -1; static const int kAnyOldSpace = -1;
// A bitmask for getting the space out of an instruction. // A bitmask for getting the space out of an instruction.
static const int kSpaceMask = 7; static const int kSpaceMask = 7;
STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
// Sentinel after a new object to indicate that double alignment is needed.
static const int kDoubleAlignmentSentinel = 0;
}; };
......
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