new_code_objects_.Add(Code::cast(obj));
}
}
+ // Check alignment.
+ DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), obj->RequiredAlignment()));
return obj;
}
uint32_t chunk_index = back_reference.chunk_index();
DCHECK_LE(chunk_index, current_chunk_[space]);
uint32_t chunk_offset = back_reference.chunk_offset();
- obj = HeapObject::FromAddress(reservations_[space][chunk_index].start +
- chunk_offset);
+ Address address = reservations_[space][chunk_index].start + chunk_offset;
+ if (next_alignment_ != kWordAligned) {
+ int padding = Heap::GetFillToAlign(address, next_alignment_);
+ next_alignment_ = kWordAligned;
+ DCHECK(padding == 0 || HeapObject::FromAddress(address)->IsFiller());
+ address += padding;
+ }
+ obj = HeapObject::FromAddress(address);
}
if (deserializing_user_code() && obj->IsInternalizedString()) {
obj = String::cast(obj)->GetForwardedInternalizedString();
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);
+ int size = source_.GetInt() << kObjectAlignmentBits;
+
+ if (next_alignment_ != kWordAligned) {
+ int reserved = size + Heap::GetMaximumFillToAlign(next_alignment_);
+ address = Allocate(space_number, reserved);
+ obj = HeapObject::FromAddress(address);
+ // If one of the following assertions fails, then we are deserializing an
+ // aligned object when the filler maps have not been deserialized yet.
+ // We require filler maps as padding to align the object.
+ Heap* heap = isolate_->heap();
+ DCHECK(heap->free_space_map()->IsMap());
+ DCHECK(heap->one_pointer_filler_map()->IsMap());
+ DCHECK(heap->two_pointer_filler_map()->IsMap());
+ obj = heap->AlignWithFiller(obj, size, reserved, next_alignment_);
address = obj->address();
+ next_alignment_ = kWordAligned;
+ } else {
+ address = Allocate(space_number, size);
+ obj = HeapObject::FromAddress(address);
}
isolate_->heap()->OnAllocationEvent(obj, size);
FOUR_CASES(byte_code + 8) \
FOUR_CASES(byte_code + 12)
+#define SINGLE_CASE(where, how, within, space) \
+ CASE_STATEMENT(where, how, within, space) \
+ CASE_BODY(where, how, within, space)
+
// Deserialize a new object and write a pointer to it to the current
// object.
ALL_SPACES(kNewObject, kPlain, kStartOfObject)
// Support for direct instruction pointers in functions. It's an inner
// pointer because it points at the entry point, not at the start of the
// code object.
- CASE_STATEMENT(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
- CASE_BODY(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
+ SINGLE_CASE(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
// Deserialize a new code object and write a pointer to its first
// instruction to the current code object.
ALL_SPACES(kNewObject, kFromCode, kInnerPointer)
ALL_SPACES(kBackrefWithSkip, kPlain, kInnerPointer)
// Find an object in the roots array and write a pointer to it to the
// current object.
- CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
- CASE_BODY(kRootArray, kPlain, kStartOfObject, 0)
+ SINGLE_CASE(kRootArray, kPlain, kStartOfObject, 0)
#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \
defined(V8_TARGET_ARCH_PPC) || V8_EMBEDDED_CONSTANT_POOL
// Find an object in the roots array and write a pointer to it to in code.
- CASE_STATEMENT(kRootArray, kFromCode, kStartOfObject, 0)
- CASE_BODY(kRootArray, kFromCode, kStartOfObject, 0)
+ SINGLE_CASE(kRootArray, kFromCode, kStartOfObject, 0)
#endif
// Find an object in the partial snapshots cache and write a pointer to it
// to the current object.
- CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
- CASE_BODY(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
+ SINGLE_CASE(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
// Find an code entry in the partial snapshots cache and
// write a pointer to it to the current object.
- CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
- CASE_BODY(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
+ SINGLE_CASE(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
// Find an external reference and write a pointer to it to the current
// object.
- CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
- CASE_BODY(kExternalReference, kPlain, kStartOfObject, 0)
+ SINGLE_CASE(kExternalReference, kPlain, kStartOfObject, 0)
// Find an external reference and write a pointer to it in the current
// code object.
- CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0)
- CASE_BODY(kExternalReference, kFromCode, kStartOfObject, 0)
+ SINGLE_CASE(kExternalReference, kFromCode, kStartOfObject, 0)
// Find an object in the attached references and write a pointer to it to
// the current object.
- CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0)
- CASE_BODY(kAttachedReference, kPlain, kStartOfObject, 0)
- CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0)
- CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0)
- CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0)
- CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0)
+ SINGLE_CASE(kAttachedReference, kPlain, kStartOfObject, 0)
+ SINGLE_CASE(kAttachedReference, kPlain, kInnerPointer, 0)
+ SINGLE_CASE(kAttachedReference, kFromCode, kInnerPointer, 0)
// Find a builtin and write a pointer to it to the current object.
- CASE_STATEMENT(kBuiltin, kPlain, kStartOfObject, 0)
- CASE_BODY(kBuiltin, kPlain, kStartOfObject, 0)
- CASE_STATEMENT(kBuiltin, kPlain, kInnerPointer, 0)
- CASE_BODY(kBuiltin, kPlain, kInnerPointer, 0)
- CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0)
- CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0)
+ SINGLE_CASE(kBuiltin, kPlain, kStartOfObject, 0)
+ SINGLE_CASE(kBuiltin, kPlain, kInnerPointer, 0)
+ SINGLE_CASE(kBuiltin, kFromCode, kInnerPointer, 0)
#undef CASE_STATEMENT
#undef CASE_BODY
break;
}
+ case kAlignmentPrefix:
+ case kAlignmentPrefix + 1:
+ case kAlignmentPrefix + 2: {
+ DCHECK_EQ(kWordAligned, next_alignment_);
+ next_alignment_ =
+ static_cast<AllocationAlignment>(data - (kAlignmentPrefix - 1));
+ break;
+ }
+
STATIC_ASSERT(kNumberOfRootArrayConstants == Heap::kOldSpaceRoots);
STATIC_ASSERT(kNumberOfRootArrayConstants == 32);
SIXTEEN_CASES(kRootArrayConstantsWithSkip)
#undef SIXTEEN_CASES
#undef FOUR_CASES
+#undef SINGLE_CASE
default:
CHECK(false);
PrintF("\n");
}
+ PutAlignmentPrefix(obj);
AllocationSpace space = back_reference.space();
if (skip == 0) {
sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef");
}
+int Serializer::PutAlignmentPrefix(HeapObject* object) {
+ AllocationAlignment alignment = object->RequiredAlignment();
+ if (alignment != kWordAligned) {
+ DCHECK(1 <= alignment && alignment <= 3);
+ byte prefix = (kAlignmentPrefix - 1) + alignment;
+ sink_->Put(prefix, "Alignment");
+ return Heap::GetMaximumFillToAlign(alignment);
+ }
+ return 0;
+}
+
+
void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
WhereToPoint where_to_point, int skip) {
if (obj->IsMap()) {
}
back_reference = serializer_->AllocateLargeObject(size);
} else {
- bool needs_double_align = false;
- // TODO(bbudge): Generalize to other alignment constraints.
- if (object_->RequiredAlignment() == kDoubleAligned) {
- // Add wriggle room for double alignment padding.
- back_reference = serializer_->Allocate(space, size + kPointerSize);
- needs_double_align = true;
- } else {
- back_reference = serializer_->Allocate(space, size);
- }
+ int fill = serializer_->PutAlignmentPrefix(object_);
+ back_reference = serializer_->Allocate(space, size + fill);
sink_->Put(kNewObject + reference_representation_ + space, "NewObject");
- if (needs_double_align)
- sink_->PutInt(kDoubleAlignmentSentinel, "DoubleAlignSentinel");
- int encoded_size = size >> kObjectAlignmentBits;
- DCHECK_NE(kDoubleAlignmentSentinel, encoded_size);
- sink_->PutInt(encoded_size, "ObjectSizeInWords");
+ sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords");
}
#ifdef OBJECT_PRINT
// 0x07 Unused (including 0x27, 0x47, 0x67).
// 0x08..0x0c Reference to previous object from space.
kBackref = 0x08,
+ // 0x0d Unused (including 0x2d, 0x4d, 0x6d).
// 0x0e Unused (including 0x2e, 0x4e, 0x6e).
// 0x0f Unused (including 0x2f, 0x4f, 0x6f).
// 0x10..0x14 Reference to previous object from space after skip.
kBackrefWithSkip = 0x10,
+ // 0x15 Unused (including 0x35, 0x55, 0x75).
// 0x16 Unused (including 0x36, 0x56, 0x76).
- // 0x17 Unused (including 0x37, 0x57, 0x77).
+ // 0x17 Misc (including 0x37, 0x57, 0x77).
// 0x18 Root array item.
kRootArray = 0x18,
// 0x19 Object in the partial snapshot cache.
// is an indication that the snapshot and the VM do not fit together.
// Examine the build process for architecture, version or configuration
// mismatches.
- static const int kSynchronize = 0x5d;
+ static const int kSynchronize = 0x17;
// Used for the source code of the natives, which is in the executable, but
// is referred to from external strings in the snapshot.
- static const int kNativesStringResource = 0x5e;
+ static const int kNativesStringResource = 0x37;
// Raw data of variable length.
- static const int kVariableRawData = 0x7d;
+ static const int kVariableRawData = 0x57;
// Repeats of variable length.
- static const int kVariableRepeat = 0x7e;
+ static const int kVariableRepeat = 0x77;
+ // Alignment prefixes 0x7d..0x7f
+ static const int kAlignmentPrefix = 0x7d;
+
+ // 0x5d..0x5f unused
// ---------- byte code range 0x80..0xff ----------
// First 32 root array items.
magic_number_(data->GetMagicNumber()),
external_reference_table_(NULL),
deserialized_large_objects_(0),
- deserializing_user_code_(false) {
+ deserializing_user_code_(false),
+ next_alignment_(kWordAligned) {
DecodeReservation(data->Reservations());
}
bool deserializing_user_code_;
+ AllocationAlignment next_alignment_;
+
DISALLOW_COPY_AND_ASSIGN(Deserializer);
};
void PutBackReference(HeapObject* object, BackReference reference);
+ // Emit alignment prefix if necessary, return required padding space in bytes.
+ int PutAlignmentPrefix(HeapObject* object);
+
// Returns true if the object was successfully serialized.
bool SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
WhereToPoint where_to_point, int skip);