Reviewers: rmcilroy,
Description:
Ensure double alignment when deserializing.
[email protected]
BUG=chromium:436510
LOG=N
TEST=compile with V8_OOL_CONSTANT_POOL=1, run d8 with --verify-heap --test
Please review this at https://codereview.chromium.org/759823006/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+74, -18 lines):
M src/globals.h
M src/heap/heap.h
M src/heap/heap.cc
M src/objects.h
M src/objects-debug.cc
M src/objects-inl.h
M src/serialize.h
M src/serialize.cc
Index: src/globals.h
diff --git a/src/globals.h b/src/globals.h
index
9a071971db347a946143d8d728c1c64600ed0b00..32ef095c2ca195dee2997796c6f3c3b9178a8ca8
100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -68,7 +68,7 @@ namespace internal {
#endif
// Determine whether the architecture uses an out-of-line constant pool.
-#define V8_OOL_CONSTANT_POOL 0
+#define V8_OOL_CONSTANT_POOL 1
#ifdef V8_TARGET_ARCH_ARM
// Set stack limit lower for ARM than for other architectures because
Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index
e38719379b6fced1a9648bf93a2d7c48a1f8db23..22ba7a9f1619cd3b3b1ab6c9bdbf838c41c139ec
100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -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
Index: src/heap/heap.h
diff --git a/src/heap/heap.h b/src/heap/heap.h
index
eeb83228610870b1aed5d041ebf2171b65615a5d..b84ccaa9c2b7ec379701cd7fd264150fa4490260
100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -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
Index: src/objects-debug.cc
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index
0e670993e0d965f2624f6cff9b581bfe5bcacda8..873c0b8bc6b016dc2e39c62839dd46e7ba69eb7a
100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -47,6 +47,9 @@ void HeapObject::HeapObjectVerify() {
return;
}
+ DCHECK(!NeedsToEnsureDoubleAlignment() ||
+ IsAligned(OffsetFrom(address()), kDoubleAlignment));
+
switch (instance_type) {
case SYMBOL_TYPE:
Symbol::cast(this)->SymbolVerify();
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index
03aea64736d818f456c748f76a31d583593dc664..b05de472e9c81f8b1225d0d5f5448e7868779f26
100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -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) {
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
746f88d1c4c0c10083e63263a005f79ec4378b9d..8d6169e18e6d3e8e328c55b0459bf30762ec0125
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -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;
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index
c2dd338b7ec5c3151a4f9e7606a324f72d9aa8d2..b9d19ad0aa22fa0a2f7d0e8966588a7cb065281e
100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -807,11 +807,21 @@ 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) {
+void Deserializer::ReadObject(int space_number, Object** write_back,
+ bool double_align) {
int size = source_->GetInt() << kObjectAlignmentBits;
- Address address = Allocate(space_number, size);
- HeapObject* obj = HeapObject::FromAddress(address);
+ Address address;
+ HeapObject* obj;
+ if (double_align) {
+ DCHECK_NE(LO_SPACE, space_number);
+ address = Allocate(space_number, size + kPointerSize);
+ obj = isolate_->heap()->DoubleAlignForDeserialization(
+ HeapObject::FromAddress(address), size + kPointerSize);
+ address = obj->address();
+ } else {
+ address = Allocate(space_number, size);
+ obj = HeapObject::FromAddress(address);
+ }
isolate_->heap()->OnAllocationEvent(obj, size);
Object** current = reinterpret_cast<Object**>(address);
Object** limit = current + (size >> kPointerSizeLog2);
@@ -894,6 +904,7 @@ void Deserializer::ReadData(Object** current, Object**
limit, int source_space,
source_space != PROPERTY_CELL_SPACE &&
source_space != CODE_SPACE &&
source_space != OLD_DATA_SPACE);
+ bool double_align_next_object = false;
while (current < limit) {
int data = source_->Get();
switch (data) {
@@ -911,13 +922,16 @@ void Deserializer::ReadData(Object** current,
Object** limit, int source_space,
int space_number = space_number_if_any ==
kAnyOldSpace \
? (data &
kSpaceMask) \
:
space_number_if_any; \
+ DCHECK(!double_align_next_object || where ==
kNewObject); \
if (where == kNewObject && how == kPlain && within == kStartOfObject)
{ \
- ReadObject(space_number,
current); \
+ ReadObject(space_number, current,
double_align_next_object); \
+ double_align_next_object =
false; \
emit_write_barrier = (space_number ==
NEW_SPACE); \
} else
{ \
Object* new_object = NULL; /* May not be a real Object pointer.
*/ \
if (where == kNewObject)
{ \
- ReadObject(space_number,
&new_object); \
+ ReadObject(space_number, &new_object,
double_align_next_object); \
+ double_align_next_object =
false; \
} else if (where == kRootArray)
{ \
int root_id =
source_->GetInt(); \
new_object =
isolate->heap()->roots_array_start()[root_id]; \
@@ -1238,6 +1252,14 @@ void Deserializer::ReadData(Object** current,
Object** limit, int source_space,
break;
}
+#ifndef V8_HOST_ARCH_64_BIT
+ case kDoubleAlignPrefix: {
+ DCHECK(!double_align_next_object);
+ double_align_next_object = true;
+ break;
+ }
+#endif
+
case kSynchronize: {
// If we get here then that indicates that you have a mismatch
between
// the number of GC roots when serializing and deserializing.
@@ -1549,6 +1571,14 @@ void PartialSerializer::SerializeObject(HeapObject*
obj, HowToCode how_to_code,
void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
int size, Map* map) {
+ int reserved_size = size;
+ // Objects on the large object space are always double-aligned.
+ if (space != LO_SPACE && object_->NeedsToEnsureDoubleAlignment()) {
+ sink_->Put(kDoubleAlignPrefix, "double align next object");
+ // Add wriggle room for double alignment padding.
+ reserved_size += kPointerSize;
+ }
+
sink_->Put(kNewObject + reference_representation_ + space,
"ObjectSerialization");
sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
@@ -1572,7 +1602,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 +1948,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)) {
Index: src/serialize.h
diff --git a/src/serialize.h b/src/serialize.h
index
1c781139b5a6a0cf1092261bcaff9ffc15247913..94e05eb8cd3d55ebb10152258f118b30f791d604
100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -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,6 +375,9 @@ class SerializerDeserializer: public ObjectVisitor {
return byte_code & 0x1f;
}
+ static const int kNop = 0xf; // Do nothing, used for
padding.
+ static const int kDoubleAlignPrefix = 0x4f; // Double align next object.
+
static const int kAnyOldSpace = -1;
// A bitmask for getting the space out of an instruction.
@@ -437,7 +440,7 @@ class Deserializer: public SerializerDeserializer {
// the heap.
void ReadData(Object** start, Object** end, int space,
Address object_address);
- void ReadObject(int space_number, Object** write_back);
+ void ReadObject(int space_number, Object** write_back, bool
double_align);
Address Allocate(int space_index, int size);
// Special handling for serialized code like hooking up internalized
strings.
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.