Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1216)

Unified Diff: src/serialize.cc

Issue 846023002: Update references to global object after deserializing context. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressed comments Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index 86348aefee917c2c921fb806bf2d8df2f599e024..a01c8b854828c80325c8d53563a8d52e4ab3ba64 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -635,6 +635,11 @@ void Deserializer::FlushICacheForNewCodeObjects() {
bool Deserializer::ReserveSpace() {
+#ifdef DEBUG
+ for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) {
+ CHECK(reservations_[i].length() > 0);
+ }
+#endif // DEBUG
if (!isolate_->heap()->ReserveSpace(reservations_)) return false;
for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
high_water_[i] = reservations_[i][0].start;
@@ -643,16 +648,22 @@ bool Deserializer::ReserveSpace() {
}
-void Deserializer::Deserialize(Isolate* isolate) {
+void Deserializer::Initialize(Isolate* isolate) {
+ DCHECK_EQ(NULL, isolate_);
+ DCHECK_NE(NULL, isolate);
isolate_ = isolate;
- DCHECK(isolate_ != NULL);
+ DCHECK_EQ(NULL, external_reference_decoder_);
+ external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
+}
+
+
+void Deserializer::Deserialize(Isolate* isolate) {
+ Initialize(isolate);
if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context");
// No active threads.
DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
// No active handles.
DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty());
- DCHECK_EQ(NULL, external_reference_decoder_);
- external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
isolate_->heap()->IterateSmiRoots(this);
isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
isolate_->heap()->RepairFreeListsAfterBoot();
@@ -688,33 +699,46 @@ void Deserializer::Deserialize(Isolate* isolate) {
}
-void Deserializer::DeserializePartial(Isolate* isolate, Object** root,
- OnOOM on_oom) {
- isolate_ = isolate;
- for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
- DCHECK(reservations_[i].length() > 0);
- }
+MaybeHandle<Object> Deserializer::DeserializePartial(
+ Isolate* isolate, Handle<FixedArray>* outdated_contexts_out) {
+ Initialize(isolate);
if (!ReserveSpace()) {
- if (on_oom == FATAL_ON_OOM) FatalProcessOutOfMemory("deserialize context");
- *root = NULL;
- return;
- }
- if (external_reference_decoder_ == NULL) {
- external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
+ FatalProcessOutOfMemory("deserialize context");
+ return MaybeHandle<Object>();
}
DisallowHeapAllocation no_gc;
-
// Keep track of the code space start and end pointers in case new
// code objects were unserialized
OldSpace* code_space = isolate_->heap()->code_space();
Address start_address = code_space->top();
- VisitPointer(root);
+ Object* root;
+ Object* outdated_contexts;
+ VisitPointer(&root);
+ VisitPointer(&outdated_contexts);
// There's no code deserialized here. If this assert fires
// then that's changed and logging should be added to notify
// the profiler et al of the new code.
CHECK_EQ(start_address, code_space->top());
+ CHECK(outdated_contexts->IsFixedArray());
+ *outdated_contexts_out =
+ Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate);
+ return Handle<Object>(root, isolate);
+}
+
+
+MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
+ Isolate* isolate) {
+ Initialize(isolate);
+ if (!ReserveSpace()) {
+ return Handle<SharedFunctionInfo>();
+ } else {
+ DisallowHeapAllocation no_gc;
+ Object* root;
+ VisitPointer(&root);
+ return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root));
+ }
}
@@ -1371,12 +1395,41 @@ void StartupSerializer::VisitPointers(Object** start, Object** end) {
}
-void PartialSerializer::Serialize(Object** object) {
- this->VisitPointer(object);
+void PartialSerializer::Serialize(Object** o) {
+ if ((*o)->IsContext()) global_object_ = Context::cast(*o)->global_object();
+ VisitPointer(o);
+ SerializeOutdatedContextsAsFixedArray();
Pad();
}
+void PartialSerializer::SerializeOutdatedContextsAsFixedArray() {
+ int length = outdated_contexts_.length();
+ if (length == 0) {
+ FixedArray* empty = isolate_->heap()->empty_fixed_array();
+ SerializeObject(empty, kPlain, kStartOfObject, 0);
+ } else {
+ // Serialize an imaginary fixed array containing outdated contexts.
+ int size = FixedArray::SizeFor(length);
+ Allocate(NEW_SPACE, size);
+ sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray");
+ sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words");
+ Map* map = isolate_->heap()->fixed_array_map();
+ SerializeObject(map, kPlain, kStartOfObject, 0);
+ Smi* length_smi = Smi::FromInt(length);
+ sink_->Put(kOnePointerRawData, "Smi");
+ for (int i = 0; i < kPointerSize; i++) {
+ sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte");
+ }
+ for (int i = 0; i < length; i++) {
+ BackReference back_ref = outdated_contexts_[i];
+ sink_->Put(kBackref + back_ref.space(), "BackRef");
+ sink_->PutInt(back_ref.reference(), "BackRefValue");
+ }
+ }
+}
+
+
bool Serializer::ShouldBeSkipped(Object** current) {
Object** roots = isolate()->heap()->roots_array_start();
return current == &roots[Heap::kStoreBufferTopRootIndex]
@@ -1633,6 +1686,15 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
// Object has not yet been serialized. Serialize it here.
ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
serializer.Serialize();
+
+ if (obj->IsContext() &&
+ Context::cast(obj)->global_object() == global_object_) {
+ // Context refers to the current global object. This reference will
+ // become outdated after deserialization.
+ BackReference back_reference = back_reference_map_.Lookup(obj);
+ DCHECK(back_reference.is_valid());
+ outdated_contexts_.Add(back_reference);
+ }
}
@@ -2276,52 +2338,47 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
- Object* root;
+ HandleScope scope(isolate);
- {
- HandleScope scope(isolate);
+ SmartPointer<SerializedCodeData> scd(
+ SerializedCodeData::FromCachedData(cached_data, *source));
+ if (scd.is_empty()) {
+ if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
+ DCHECK(cached_data->rejected());
+ return MaybeHandle<SharedFunctionInfo>();
+ }
- SmartPointer<SerializedCodeData> scd(
- SerializedCodeData::FromCachedData(cached_data, *source));
- if (scd.is_empty()) {
- if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
- DCHECK(cached_data->rejected());
- return MaybeHandle<SharedFunctionInfo>();
- }
+ // Eagerly expand string table to avoid allocations during deserialization.
+ StringTable::EnsureCapacityForDeserialization(isolate,
+ scd->NumInternalizedStrings());
- // Eagerly expand string table to avoid allocations during deserialization.
- StringTable::EnsureCapacityForDeserialization(
- isolate, scd->NumInternalizedStrings());
-
- // Prepare and register list of attached objects.
- Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
- Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
- code_stub_keys.length() + kCodeStubsBaseIndex);
- attached_objects[kSourceObjectIndex] = source;
- for (int i = 0; i < code_stub_keys.length(); i++) {
- attached_objects[i + kCodeStubsBaseIndex] =
- CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
- }
+ // Prepare and register list of attached objects.
+ Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
+ Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
+ code_stub_keys.length() + kCodeStubsBaseIndex);
+ attached_objects[kSourceObjectIndex] = source;
+ for (int i = 0; i < code_stub_keys.length(); i++) {
+ attached_objects[i + kCodeStubsBaseIndex] =
+ CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
+ }
- Deserializer deserializer(scd.get());
- deserializer.SetAttachedObjects(&attached_objects);
+ Deserializer deserializer(scd.get());
+ deserializer.SetAttachedObjects(&attached_objects);
- // Deserialize.
- deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM);
- if (root == NULL) {
- // Deserializing may fail if the reservations cannot be fulfilled.
- if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
- return MaybeHandle<SharedFunctionInfo>();
- }
- deserializer.FlushICacheForNewCodeObjects();
+ // Deserialize.
+ Handle<SharedFunctionInfo> result;
+ if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) {
+ // Deserializing may fail if the reservations cannot be fulfilled.
+ if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
+ return MaybeHandle<SharedFunctionInfo>();
}
+ deserializer.FlushICacheForNewCodeObjects();
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
int length = cached_data->length();
PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms);
}
- Handle<SharedFunctionInfo> result(SharedFunctionInfo::cast(root), isolate);
result->set_deserialized(true);
if (isolate->logger()->is_logging_code_events() ||
@@ -2335,7 +2392,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
*result, NULL, name);
}
- return result;
+ return scope.CloseAndEscape(result);
}
« no previous file with comments | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698