From 33ae0e6762011e80172b84054a0a90e3b0822772 Mon Sep 17 00:00:00 2001 From: machenbach Date: Tue, 16 Jun 2015 03:18:33 -0700 Subject: [PATCH] Revert of Serializer: support all alignment kinds. (patchset #3 id:40001 of https://codereview.chromium.org/1179873003/) Reason for revert: [Sheriff] Breaks arm debug compile: http://build.chromium.org/p/client.v8/builders/V8%20Arm%20-%20debug%20builder/builds/4308 Original issue's description: > Serializer: support all alignment kinds. > > We use an alignment prefix for unusual alignment kinds (not kWordAligned). > This will cause new objects to be aligned in ReadObject, and back references > to be aligned to skip padding. > > The motivation to change the undefined next sentinel in WeakCell is this: > When the deserializer aligns an object, it requires filler maps to already > exist to create filler objects as padding. However, deserializing the > filler map leads to deserializing NaN, which as heap number is aligned: > filler map > meta map > weak cell cache > undefined > NaN > If we use the-hole instead of undefined as sentinel, it works. > > R=jochen@chromium.org,bbudge@chromium.org > BUG=v8:4178 > LOG=N > > Committed: https://crrev.com/2146ab75387d47eef6582bd8c2d0cfc6c42b68b6 > Cr-Commit-Position: refs/heads/master@{#29044} TBR=jochen@chromium.org,bbudge@chromium.org,yangguo@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:4178 Review URL: https://codereview.chromium.org/1173253006 Cr-Commit-Position: refs/heads/master@{#29045} --- src/code-stubs-hydrogen.cc | 2 +- src/heap/heap.cc | 23 +++--- src/heap/mark-compact.cc | 8 +- src/heap/objects-visiting-inl.h | 4 +- src/snapshot/serialize.cc | 126 ++++++++++++++------------------ src/snapshot/serialize.h | 24 ++---- 6 files changed, 81 insertions(+), 106 deletions(-) diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 4573da1512..45303bd146 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -641,7 +641,7 @@ HValue* CodeStubGraphBuilder::BuildCodeStub() { HInstruction* value = GetParameter(CreateWeakCellDescriptor::kValueIndex); Add(object, HObjectAccess::ForWeakCellValue(), value); Add(object, HObjectAccess::ForWeakCellNext(), - graph()->GetConstantHole()); + graph()->GetConstantUndefined()); HInstruction* feedback_vector = GetParameter(CreateWeakCellDescriptor::kVectorIndex); diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 39099fca1a..80eb5620a8 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -3102,7 +3102,7 @@ AllocationResult Heap::AllocateWeakCell(HeapObject* value) { } result->set_map_no_write_barrier(weak_cell_map()); WeakCell::cast(result)->initialize(value); - WeakCell::cast(result)->set_next(the_hole_value(), SKIP_WRITE_BARRIER); + WeakCell::cast(result)->set_next(undefined_value(), SKIP_WRITE_BARRIER); return result; } @@ -3706,18 +3706,19 @@ AllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) { void Heap::CreateFillerObjectAt(Address addr, int size) { if (size == 0) return; HeapObject* filler = HeapObject::FromAddress(addr); - if (size == kPointerSize) { - filler->set_map_no_write_barrier(raw_unchecked_one_pointer_filler_map()); - } else if (size == 2 * kPointerSize) { - filler->set_map_no_write_barrier(raw_unchecked_two_pointer_filler_map()); - } else { - filler->set_map_no_write_barrier(raw_unchecked_free_space_map()); - FreeSpace::cast(filler)->nobarrier_set_size(size); - } // At this point, we may be deserializing the heap from a snapshot, and // none of the maps have been created yet and are NULL. - DCHECK(filler->map() == NULL && !deserialization_complete_ || - filler->map()->IsMap()); + if (size == kPointerSize) { + filler->set_map_no_write_barrier(raw_unchecked_one_pointer_filler_map()); + DCHECK(filler->map() == NULL || filler->map() == one_pointer_filler_map()); + } else if (size == 2 * kPointerSize) { + filler->set_map_no_write_barrier(raw_unchecked_two_pointer_filler_map()); + DCHECK(filler->map() == NULL || filler->map() == two_pointer_filler_map()); + } else { + filler->set_map_no_write_barrier(raw_unchecked_free_space_map()); + DCHECK(filler->map() == NULL || filler->map() == free_space_map()); + FreeSpace::cast(filler)->nobarrier_set_size(size); + } } diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index 90fc13616c..b56af23c49 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc @@ -2637,7 +2637,7 @@ void MarkCompactCollector::AbortWeakCollections() { void MarkCompactCollector::ProcessAndClearWeakCells() { - HeapObject* the_hole = heap()->the_hole_value(); + HeapObject* undefined = heap()->undefined_value(); Object* weak_cell_obj = heap()->encountered_weak_cells(); while (weak_cell_obj != Smi::FromInt(0)) { WeakCell* weak_cell = reinterpret_cast(weak_cell_obj); @@ -2672,19 +2672,19 @@ void MarkCompactCollector::ProcessAndClearWeakCells() { RecordSlot(slot, slot, *slot); } weak_cell_obj = weak_cell->next(); - weak_cell->set_next(the_hole, SKIP_WRITE_BARRIER); + weak_cell->set_next(undefined, SKIP_WRITE_BARRIER); } heap()->set_encountered_weak_cells(Smi::FromInt(0)); } void MarkCompactCollector::AbortWeakCells() { - Object* the_hole = heap()->the_hole_value(); + Object* undefined = heap()->undefined_value(); Object* weak_cell_obj = heap()->encountered_weak_cells(); while (weak_cell_obj != Smi::FromInt(0)) { WeakCell* weak_cell = reinterpret_cast(weak_cell_obj); weak_cell_obj = weak_cell->next(); - weak_cell->set_next(the_hole, SKIP_WRITE_BARRIER); + weak_cell->set_next(undefined, SKIP_WRITE_BARRIER); } heap()->set_encountered_weak_cells(Smi::FromInt(0)); } diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index 433fc6deab..9cd08c0bff 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -329,11 +329,11 @@ void StaticMarkingVisitor::VisitWeakCell(Map* map, HeapObject* object) { Heap* heap = map->GetHeap(); WeakCell* weak_cell = reinterpret_cast(object); - Object* the_hole = heap->the_hole_value(); + Object* undefined = heap->undefined_value(); // Enqueue weak cell in linked list of encountered weak collections. // We can ignore weak cells with cleared values because they will always // contain smi zero. - if (weak_cell->next() == the_hole && !weak_cell->cleared()) { + if (weak_cell->next() == undefined && !weak_cell->cleared()) { weak_cell->set_next(heap->encountered_weak_cells(), UPDATE_WEAK_WRITE_BARRIER); heap->set_encountered_weak_cells(weak_cell); diff --git a/src/snapshot/serialize.cc b/src/snapshot/serialize.cc index 026d60221d..8b382c09fb 100644 --- a/src/snapshot/serialize.cc +++ b/src/snapshot/serialize.cc @@ -753,8 +753,6 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) { new_code_objects_.Add(Code::cast(obj)); } } - // Check alignment. - DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), obj->RequiredAlignment())); return obj; } @@ -771,14 +769,8 @@ HeapObject* Deserializer::GetBackReferencedObject(int space) { uint32_t chunk_index = back_reference.chunk_index(); DCHECK_LE(chunk_index, current_chunk_[space]); uint32_t chunk_offset = back_reference.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); + obj = HeapObject::FromAddress(reservations_[space][chunk_index].start + + chunk_offset); } if (deserializing_user_code() && obj->IsInternalizedString()) { obj = String::cast(obj)->GetForwardedInternalizedString(); @@ -796,25 +788,22 @@ HeapObject* Deserializer::GetBackReferencedObject(int space) { void Deserializer::ReadObject(int space_number, Object** write_back) { Address address; HeapObject* obj; - int size = source_.GetInt() << kObjectAlignmentBits; + int next_int = source_.GetInt(); - 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_); + 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(); - next_alignment_ = kWordAligned; - } else { - address = Allocate(space_number, size); - obj = HeapObject::FromAddress(address); } isolate_->heap()->OnAllocationEvent(obj, size); @@ -1009,17 +998,14 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, 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. - SINGLE_CASE(kNewObject, kPlain, kInnerPointer, CODE_SPACE) + CASE_STATEMENT(kNewObject, kPlain, kInnerPointer, CODE_SPACE) + CASE_BODY(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) @@ -1050,33 +1036,45 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, ALL_SPACES(kBackrefWithSkip, kPlain, kInnerPointer) // Find an object in the roots array and write a pointer to it to the // current object. - SINGLE_CASE(kRootArray, kPlain, kStartOfObject, 0) + CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0) + CASE_BODY(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. - SINGLE_CASE(kRootArray, kFromCode, kStartOfObject, 0) + CASE_STATEMENT(kRootArray, kFromCode, kStartOfObject, 0) + CASE_BODY(kRootArray, kFromCode, kStartOfObject, 0) #endif // Find an object in the partial snapshots cache and write a pointer to it // to the current object. - SINGLE_CASE(kPartialSnapshotCache, kPlain, kStartOfObject, 0) + CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0) + CASE_BODY(kPartialSnapshotCache, kPlain, kStartOfObject, 0) // Find an code entry in the partial snapshots cache and // write a pointer to it to the current object. - SINGLE_CASE(kPartialSnapshotCache, kPlain, kInnerPointer, 0) + CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0) + CASE_BODY(kPartialSnapshotCache, kPlain, kInnerPointer, 0) // Find an external reference and write a pointer to it to the current // object. - SINGLE_CASE(kExternalReference, kPlain, kStartOfObject, 0) + CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0) + CASE_BODY(kExternalReference, kPlain, kStartOfObject, 0) // Find an external reference and write a pointer to it in the current // code object. - SINGLE_CASE(kExternalReference, kFromCode, kStartOfObject, 0) + CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) + CASE_BODY(kExternalReference, kFromCode, kStartOfObject, 0) // Find an object in the attached references and write a pointer to it to // the current object. - SINGLE_CASE(kAttachedReference, kPlain, kStartOfObject, 0) - SINGLE_CASE(kAttachedReference, kPlain, kInnerPointer, 0) - SINGLE_CASE(kAttachedReference, kFromCode, kInnerPointer, 0) + 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) // Find a builtin and write a pointer to it to the current object. - SINGLE_CASE(kBuiltin, kPlain, kStartOfObject, 0) - SINGLE_CASE(kBuiltin, kPlain, kInnerPointer, 0) - SINGLE_CASE(kBuiltin, kFromCode, kInnerPointer, 0) + 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) #undef CASE_STATEMENT #undef CASE_BODY @@ -1171,15 +1169,6 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, break; } - case kAlignmentPrefix: - case kAlignmentPrefix + 1: - case kAlignmentPrefix + 2: { - DCHECK_EQ(kWordAligned, next_alignment_); - next_alignment_ = - static_cast(data - (kAlignmentPrefix - 1)); - break; - } - STATIC_ASSERT(kNumberOfRootArrayConstants == Heap::kOldSpaceRoots); STATIC_ASSERT(kNumberOfRootArrayConstants == 32); SIXTEEN_CASES(kRootArrayConstantsWithSkip) @@ -1246,7 +1235,6 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, #undef SIXTEEN_CASES #undef FOUR_CASES -#undef SINGLE_CASE default: CHECK(false); @@ -1574,7 +1562,6 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code, PrintF("\n"); } - PutAlignmentPrefix(obj); AllocationSpace space = back_reference.space(); if (skip == 0) { sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); @@ -1668,18 +1655,6 @@ void Serializer::PutBackReference(HeapObject* object, BackReference reference) { } -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()) { @@ -1761,10 +1736,21 @@ void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, } back_reference = serializer_->AllocateLargeObject(size); } else { - int fill = serializer_->PutAlignmentPrefix(object_); - back_reference = serializer_->Allocate(space, size + fill); + 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); + } sink_->Put(kNewObject + reference_representation_ + space, "NewObject"); - sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); + if (needs_double_align) + sink_->PutInt(kDoubleAlignmentSentinel, "DoubleAlignSentinel"); + int encoded_size = size >> kObjectAlignmentBits; + DCHECK_NE(kDoubleAlignmentSentinel, encoded_size); + sink_->PutInt(encoded_size, "ObjectSizeInWords"); } #ifdef OBJECT_PRINT diff --git a/src/snapshot/serialize.h b/src/snapshot/serialize.h index 2a426a94f5..089c323b7d 100644 --- a/src/snapshot/serialize.h +++ b/src/snapshot/serialize.h @@ -324,14 +324,12 @@ class SerializerDeserializer: public ObjectVisitor { // 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 Misc (including 0x37, 0x57, 0x77). + // 0x17 Unused (including 0x37, 0x57, 0x77). // 0x18 Root array item. kRootArray = 0x18, // 0x19 Object in the partial snapshot cache. @@ -386,18 +384,14 @@ class SerializerDeserializer: public ObjectVisitor { // 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 = 0x17; + static const int kSynchronize = 0x5d; // 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 = 0x37; + static const int kNativesStringResource = 0x5e; // Raw data of variable length. - static const int kVariableRawData = 0x57; + static const int kVariableRawData = 0x7d; // Repeats of variable length. - static const int kVariableRepeat = 0x77; - // Alignment prefixes 0x7d..0x7f - static const int kAlignmentPrefix = 0x7d; - - // 0x5d..0x5f unused + static const int kVariableRepeat = 0x7e; // ---------- byte code range 0x80..0xff ---------- // First 32 root array items. @@ -521,8 +515,7 @@ class Deserializer: public SerializerDeserializer { magic_number_(data->GetMagicNumber()), external_reference_table_(NULL), deserialized_large_objects_(0), - deserializing_user_code_(false), - next_alignment_(kWordAligned) { + deserializing_user_code_(false) { DecodeReservation(data->Reservations()); } @@ -609,8 +602,6 @@ class Deserializer: public SerializerDeserializer { bool deserializing_user_code_; - AllocationAlignment next_alignment_; - DISALLOW_COPY_AND_ASSIGN(Deserializer); }; @@ -715,9 +706,6 @@ class Serializer : public SerializerDeserializer { 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);