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.

Reply via email to