Skip to content

Commit

Permalink
Revert of Prevent stack overflow in the serializer/deserializer. (pat…
Browse files Browse the repository at this point in the history
…chset crosswalk-project#6 id:100001 of https://codereview.chromium.org/1125073004/)

Reason for revert:
[Sheriff] Breaks msan:
http://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20arm64%20-%20sim%20-%20MSAN/builds/2266

Original issue's description:
> Prevent stack overflow in the serializer/deserializer.
>
> We keep an eye on the recursion depth. Once it exceeds a limit, we serialize
> only the object header and size, but defer serializing the object body for
> after we have unwound the stack.
>
> [email protected]
>
> Committed: https://crrev.com/36b4a498d6614243454d5a182e4946b0dad24f0a
> Cr-Commit-Position: refs/heads/master@{#28385}

[email protected],[email protected]
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1139113002

Cr-Commit-Position: refs/heads/master@{#28403}
  • Loading branch information
mi-ac authored and Commit bot committed May 14, 2015
1 parent 2a6a87d commit e1b5db6
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 212 deletions.
2 changes: 1 addition & 1 deletion src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ StartupData V8::CreateSnapshotDataBlob(const char* custom_source) {
i::SnapshotByteSink context_sink;
i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
context_ser.Serialize(&raw_context);
ser.SerializeWeakReferencesAndDeferred();
ser.SerializeWeakReferences();

result = i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
}
Expand Down
1 change: 0 additions & 1 deletion src/bootstrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2831,7 +2831,6 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
if (value->IsPropertyCell()) {
value = handle(PropertyCell::cast(*value)->value(), isolate());
}
if (value->IsTheHole()) continue;
PropertyDetails details = properties->DetailsAt(i);
DCHECK_EQ(kData, details.kind());
JSObject::AddProperty(to, key, value, details.attributes());
Expand Down
11 changes: 5 additions & 6 deletions src/objects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14689,12 +14689,11 @@ Handle<Derived> HashTable<Derived, Shape, Key>::New(
PretenureFlag pretenure) {
DCHECK(0 <= at_least_space_for);
DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
int capacity =
(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
? at_least_space_for
: isolate->serializer_enabled() && isolate->bootstrapper()->IsActive()
? ComputeCapacityForSerialization(at_least_space_for)
: ComputeCapacity(at_least_space_for);
int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
? at_least_space_for
: isolate->serializer_enabled()
? ComputeCapacityForSerialization(at_least_space_for)
: ComputeCapacity(at_least_space_for);
if (capacity > HashTable::kMaxCapacity) {
v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
}
Expand Down
147 changes: 30 additions & 117 deletions src/snapshot/serialize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,6 @@ void Deserializer::Deserialize(Isolate* isolate) {
isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
isolate_->heap()->RepairFreeListsAfterDeserialization();
isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
DeserializeDeferredObjects();

isolate_->heap()->set_native_contexts_list(
isolate_->heap()->undefined_value());
Expand Down Expand Up @@ -610,7 +609,6 @@ MaybeHandle<Object> Deserializer::DeserializePartial(
Object* outdated_contexts;
VisitPointer(&root);
VisitPointer(&outdated_contexts);
DeserializeDeferredObjects();

// There's no code deserialized here. If this assert fires
// then that's changed and logging should be added to notify
Expand All @@ -633,7 +631,6 @@ MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
DisallowHeapAllocation no_gc;
Object* root;
VisitPointer(&root);
DeserializeDeferredObjects();
return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root));
}
}
Expand All @@ -655,22 +652,13 @@ void Deserializer::VisitPointers(Object** start, Object** end) {
}


void Deserializer::DeserializeDeferredObjects() {
for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) {
int space = code & kSpaceMask;
DCHECK(space <= kNumberOfSpaces);
DCHECK(code - space == kNewObject);
HeapObject* object = GetBackReferencedObject(space);
int size = source_.GetInt() << kPointerSizeLog2;
Address obj_address = object->address();
Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize);
Object** end = reinterpret_cast<Object**>(obj_address + size);
bool filled = ReadData(start, end, space, obj_address);
CHECK(filled);
if (object->IsAllocationSite()) {
RelinkAllocationSite(AllocationSite::cast(object));
}
void Deserializer::RelinkAllocationSite(AllocationSite* site) {
if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) {
site->set_weak_next(isolate_->heap()->undefined_value());
} else {
site->set_weak_next(isolate_->heap()->allocation_sites_list());
}
isolate_->heap()->set_allocation_sites_list(site);
}


Expand Down Expand Up @@ -705,8 +693,7 @@ class StringTableInsertionKey : public HashTableKey {
};


HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj) {
DCHECK(deserializing_user_code());
HeapObject* Deserializer::ProcessNewObjectFromSerializedCode(HeapObject* obj) {
if (obj->IsString()) {
String* string = String::cast(obj);
// Uninitialize hash field as the hash seed may have changed.
Expand All @@ -721,30 +708,11 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj) {
}
} else if (obj->IsScript()) {
Script::cast(obj)->set_id(isolate_->heap()->NextScriptId());
} else {
DCHECK(CanBeDeferred(obj));
}
return obj;
}


void Deserializer::RelinkAllocationSite(AllocationSite* obj) {
DCHECK(obj->IsAllocationSite());
// Allocation sites are present in the snapshot, and must be linked into
// a list at deserialization time.
AllocationSite* site = AllocationSite::cast(obj);
// TODO(mvstanton): consider treating the heap()->allocation_sites_list()
// as a (weak) root. If this root is relocated correctly,
// RelinkAllocationSite() isn't necessary.
if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) {
site->set_weak_next(isolate_->heap()->undefined_value());
} else {
site->set_weak_next(isolate_->heap()->allocation_sites_list());
}
isolate_->heap()->set_allocation_sites_list(site);
}


HeapObject* Deserializer::GetBackReferencedObject(int space) {
HeapObject* obj;
BackReference back_reference(source_.GetInt());
Expand Down Expand Up @@ -800,21 +768,24 @@ void Deserializer::ReadObject(int space_number, Object** write_back) {
if (FLAG_log_snapshot_positions) {
LOG(isolate_, SnapshotPositionEvent(address, source_.position()));
}
ReadData(current, limit, space_number, address);

if (ReadData(current, limit, space_number, address)) {
// Only post process if object content has not been deferred.
if (obj->IsAllocationSite()) {
RelinkAllocationSite(AllocationSite::cast(obj));
}
}
// TODO(mvstanton): consider treating the heap()->allocation_sites_list()
// as a (weak) root. If this root is relocated correctly,
// RelinkAllocationSite() isn't necessary.
if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj));

if (deserializing_user_code()) obj = PostProcessNewObject(obj);
// Fix up strings from serialized user code.
if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj);

Object* write_back_obj = obj;
UnalignedCopy(write_back, &write_back_obj);
#ifdef DEBUG
if (obj->IsCode()) {
DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
#ifdef VERIFY_HEAP
obj->ObjectVerify();
#endif // VERIFY_HEAP
} else {
DCHECK(space_number != CODE_SPACE);
}
Expand Down Expand Up @@ -858,7 +829,7 @@ Address Deserializer::Allocate(int space_index, int size) {
}


bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
void Deserializer::ReadData(Object** current, Object** limit, int source_space,
Address current_object_address) {
Isolate* const isolate = isolate_;
// Write barrier support costs around 1% in startup time. In fact there
Expand Down Expand Up @@ -1115,14 +1086,6 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
break;
}

case kDeferred: {
// Deferred can only occur right after the heap object header.
DCHECK(current == reinterpret_cast<Object**>(current_object_address +
kPointerSize));
current = limit;
return false;
}

case kSynchronize:
// If we get here then that indicates that you have a mismatch between
// the number of GC roots when serializing and deserializing.
Expand Down Expand Up @@ -1229,7 +1192,6 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
}
}
CHECK_EQ(limit, current);
return true;
}


Expand All @@ -1238,7 +1200,6 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
sink_(sink),
external_reference_encoder_(isolate),
root_index_map_(isolate),
recursion_depth_(0),
code_address_map_(NULL),
large_objects_total_size_(0),
seen_large_objects_index_(0) {
Expand Down Expand Up @@ -1314,16 +1275,6 @@ void Serializer::OutputStatistics(const char* name) {
}


void Serializer::SerializeDeferredObjects() {
while (deferred_objects_.length() > 0) {
HeapObject* obj = deferred_objects_.RemoveLast();
ObjectSerializer obj_serializer(this, obj, sink_, kPlain, kStartOfObject);
obj_serializer.SerializeDeferred();
}
sink_->Put(kSynchronize, "Finished with deferred objects");
}


void StartupSerializer::SerializeStrongReferences() {
Isolate* isolate = this->isolate();
// No active threads.
Expand Down Expand Up @@ -1368,7 +1319,6 @@ void PartialSerializer::Serialize(Object** o) {
}
VisitPointer(o);
SerializeOutdatedContextsAsFixedArray();
SerializeDeferredObjects();
Pad();
}

Expand All @@ -1392,10 +1342,10 @@ void PartialSerializer::SerializeOutdatedContextsAsFixedArray() {
sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte");
}
for (int i = 0; i < length; i++) {
Context* context = outdated_contexts_[i];
BackReference back_reference = back_reference_map_.Lookup(context);
sink_->Put(kBackref + back_reference.space(), "BackRef");
PutBackReference(context, back_reference);
BackReference back_ref = outdated_contexts_[i];
DCHECK(BackReferenceIsAlreadyAllocated(back_ref));
sink_->Put(kBackref + back_ref.space(), "BackRef");
sink_->PutInt(back_ref.reference(), "BackRefValue");
}
}
}
Expand Down Expand Up @@ -1558,7 +1508,10 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
"BackRefWithSkip");
sink_->PutInt(skip, "BackRefSkipDistance");
}
PutBackReference(obj, back_reference);
DCHECK(BackReferenceIsAlreadyAllocated(back_reference));
sink_->PutInt(back_reference.reference(), "BackRefValue");

hot_objects_.Add(obj);
}
return true;
}
Expand Down Expand Up @@ -1594,7 +1547,7 @@ void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
}


void StartupSerializer::SerializeWeakReferencesAndDeferred() {
void StartupSerializer::SerializeWeakReferences() {
// This phase comes right after the serialization (of the snapshot).
// After we have done the partial serialization the partial snapshot cache
// will contain some references needed to decode the partial snapshot. We
Expand All @@ -1603,7 +1556,6 @@ void StartupSerializer::SerializeWeakReferencesAndDeferred() {
Object* undefined = isolate()->heap()->undefined_value();
VisitPointer(&undefined);
isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
SerializeDeferredObjects();
Pad();
}

Expand Down Expand Up @@ -1636,13 +1588,6 @@ void Serializer::PutRoot(int root_index,
}


void Serializer::PutBackReference(HeapObject* object, BackReference reference) {
DCHECK(BackReferenceIsAlreadyAllocated(reference));
sink_->PutInt(reference.reference(), "BackRefValue");
hot_objects_.Add(object);
}


void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
WhereToPoint where_to_point, int skip) {
if (obj->IsMap()) {
Expand Down Expand Up @@ -1696,7 +1641,9 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
Context::cast(obj)->global_object() == global_object_) {
// Context refers to the current global object. This reference will
// become outdated after deserialization.
outdated_contexts_.Add(Context::cast(obj));
BackReference back_reference = back_reference_map_.Lookup(obj);
DCHECK(back_reference.is_valid());
outdated_contexts_.Add(back_reference);
}
}

Expand Down Expand Up @@ -1863,39 +1810,6 @@ void Serializer::ObjectSerializer::Serialize() {
CHECK_EQ(0, bytes_processed_so_far_);
bytes_processed_so_far_ = kPointerSize;

RecursionScope recursion(serializer_);
// Objects that are immediately post processed during deserialization
// cannot be deferred, since post processing requires the object content.
if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) {
serializer_->QueueDeferredObject(object_);
sink_->Put(kDeferred, "Deferring object content");
return;
}

object_->IterateBody(map->instance_type(), size, this);
OutputRawData(object_->address() + size);
}


void Serializer::ObjectSerializer::SerializeDeferred() {
if (FLAG_trace_serializer) {
PrintF(" Encoding deferred heap object: ");
object_->ShortPrint();
PrintF("\n");
}

int size = object_->Size();
Map* map = object_->map();
BackReference reference = serializer_->back_reference_map()->Lookup(object_);

// Serialize the rest of the object.
CHECK_EQ(0, bytes_processed_so_far_);
bytes_processed_so_far_ = kPointerSize;

sink_->Put(kNewObject + reference.space(), "deferred object");
serializer_->PutBackReference(object_, reference);
sink_->PutInt(size >> kPointerSizeLog2, "deferred object size");

object_->IterateBody(map->instance_type(), size, this);
OutputRawData(object_->address() + size);
}
Expand Down Expand Up @@ -2220,7 +2134,6 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
DisallowHeapAllocation no_gc;
Object** location = Handle<Object>::cast(info).location();
cs.VisitPointer(location);
cs.SerializeDeferredObjects();
cs.Pad();

SerializedCodeData data(sink.data(), cs);
Expand Down
Loading

0 comments on commit e1b5db6

Please sign in to comment.