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:
yangguo 2014-11-27 01:22:10 -08:00 committed by Commit bot
parent 60af073ad8
commit 4590e4f4d6
7 changed files with 71 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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