Commit bcab9eac authored by yangguo's avatar yangguo Committed by Commit bot

Update references to global object after deserializing context.

R=jochen@chromium.org
TEST=test-serialize/CustomContext{Des,S}erialization

Also test by
- make ia32.debug embedscript=<full path to mjsunit.js>
- d8 -e "assertDoesNotThrow('print(1)')"

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

Cr-Commit-Position: refs/heads/master@{#26035}
parent c24220c0
...@@ -201,7 +201,8 @@ class Genesis BASE_EMBEDDED { ...@@ -201,7 +201,8 @@ class Genesis BASE_EMBEDDED {
// Similarly, we want to use the global that has been created by the templates // Similarly, we want to use the global that has been created by the templates
// passed through the API. The global from the snapshot is detached from the // passed through the API. The global from the snapshot is detached from the
// other objects in the snapshot. // other objects in the snapshot.
void HookUpGlobalObject(Handle<GlobalObject> global_object); void HookUpGlobalObject(Handle<GlobalObject> global_object,
Handle<FixedArray> outdated_contexts);
// New context initialization. Used for creating a context from scratch. // New context initialization. Used for creating a context from scratch.
void InitializeGlobal(Handle<GlobalObject> global_object, void InitializeGlobal(Handle<GlobalObject> global_object,
Handle<JSFunction> empty_function); Handle<JSFunction> empty_function);
...@@ -871,13 +872,21 @@ void Genesis::HookUpGlobalProxy(Handle<GlobalObject> global_object, ...@@ -871,13 +872,21 @@ void Genesis::HookUpGlobalProxy(Handle<GlobalObject> global_object,
} }
void Genesis::HookUpGlobalObject(Handle<GlobalObject> global_object) { void Genesis::HookUpGlobalObject(Handle<GlobalObject> global_object,
Handle<FixedArray> outdated_contexts) {
Handle<GlobalObject> global_object_from_snapshot( Handle<GlobalObject> global_object_from_snapshot(
GlobalObject::cast(native_context()->extension())); GlobalObject::cast(native_context()->extension()));
Handle<JSBuiltinsObject> builtins_global(native_context()->builtins()); Handle<JSBuiltinsObject> builtins_global(native_context()->builtins());
native_context()->set_extension(*global_object); native_context()->set_extension(*global_object);
native_context()->set_global_object(*global_object);
native_context()->set_security_token(*global_object); native_context()->set_security_token(*global_object);
// Replace outdated global objects in deserialized contexts.
for (int i = 0; i < outdated_contexts->length(); ++i) {
Context* context = Context::cast(outdated_contexts->get(i));
DCHECK_EQ(context->global_object(), *global_object_from_snapshot);
context->set_global_object(*global_object);
}
static const PropertyAttributes attributes = static const PropertyAttributes attributes =
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
Runtime::DefineObjectProperty(builtins_global, factory()->global_string(), Runtime::DefineObjectProperty(builtins_global, factory()->global_string(),
...@@ -2724,9 +2733,10 @@ Genesis::Genesis(Isolate* isolate, ...@@ -2724,9 +2733,10 @@ Genesis::Genesis(Isolate* isolate,
// We can only de-serialize a context if the isolate was initialized from // We can only de-serialize a context if the isolate was initialized from
// a snapshot. Otherwise we have to build the context from scratch. // a snapshot. Otherwise we have to build the context from scratch.
if (isolate->initialized_from_snapshot()) { Handle<FixedArray> outdated_contexts;
native_context_ = Snapshot::NewContextFromSnapshot(isolate); if (!isolate->initialized_from_snapshot() ||
} else { !Snapshot::NewContextFromSnapshot(isolate, &outdated_contexts)
.ToHandle(&native_context_)) {
native_context_ = Handle<Context>(); native_context_ = Handle<Context>();
} }
...@@ -2748,7 +2758,7 @@ Genesis::Genesis(Isolate* isolate, ...@@ -2748,7 +2758,7 @@ Genesis::Genesis(Isolate* isolate,
global_proxy_template, maybe_global_proxy, &global_object); global_proxy_template, maybe_global_proxy, &global_object);
HookUpGlobalProxy(global_object, global_proxy); HookUpGlobalProxy(global_object, global_proxy);
HookUpGlobalObject(global_object); HookUpGlobalObject(global_object, outdated_contexts);
native_context()->builtins()->set_global_proxy( native_context()->builtins()->set_global_proxy(
native_context()->global_proxy()); native_context()->global_proxy());
......
...@@ -635,6 +635,11 @@ void Deserializer::FlushICacheForNewCodeObjects() { ...@@ -635,6 +635,11 @@ void Deserializer::FlushICacheForNewCodeObjects() {
bool Deserializer::ReserveSpace() { 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; if (!isolate_->heap()->ReserveSpace(reservations_)) return false;
for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
high_water_[i] = reservations_[i][0].start; high_water_[i] = reservations_[i][0].start;
...@@ -643,16 +648,22 @@ bool Deserializer::ReserveSpace() { ...@@ -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; 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"); if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context");
// No active threads. // No active threads.
DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
// No active handles. // No active handles.
DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty()); 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()->IterateSmiRoots(this);
isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
isolate_->heap()->RepairFreeListsAfterBoot(); isolate_->heap()->RepairFreeListsAfterBoot();
...@@ -688,33 +699,46 @@ void Deserializer::Deserialize(Isolate* isolate) { ...@@ -688,33 +699,46 @@ void Deserializer::Deserialize(Isolate* isolate) {
} }
void Deserializer::DeserializePartial(Isolate* isolate, Object** root, MaybeHandle<Object> Deserializer::DeserializePartial(
OnOOM on_oom) { Isolate* isolate, Handle<FixedArray>* outdated_contexts_out) {
isolate_ = isolate; Initialize(isolate);
for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
DCHECK(reservations_[i].length() > 0);
}
if (!ReserveSpace()) { if (!ReserveSpace()) {
if (on_oom == FATAL_ON_OOM) FatalProcessOutOfMemory("deserialize context"); FatalProcessOutOfMemory("deserialize context");
*root = NULL; return MaybeHandle<Object>();
return;
}
if (external_reference_decoder_ == NULL) {
external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
} }
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
// Keep track of the code space start and end pointers in case new // Keep track of the code space start and end pointers in case new
// code objects were unserialized // code objects were unserialized
OldSpace* code_space = isolate_->heap()->code_space(); OldSpace* code_space = isolate_->heap()->code_space();
Address start_address = code_space->top(); 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 // There's no code deserialized here. If this assert fires
// then that's changed and logging should be added to notify // then that's changed and logging should be added to notify
// the profiler et al of the new code. // the profiler et al of the new code.
CHECK_EQ(start_address, code_space->top()); 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) { ...@@ -1371,12 +1395,41 @@ void StartupSerializer::VisitPointers(Object** start, Object** end) {
} }
void PartialSerializer::Serialize(Object** object) { void PartialSerializer::Serialize(Object** o) {
this->VisitPointer(object); if ((*o)->IsContext()) global_object_ = Context::cast(*o)->global_object();
VisitPointer(o);
SerializeOutdatedContextsAsFixedArray();
Pad(); 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) { bool Serializer::ShouldBeSkipped(Object** current) {
Object** roots = isolate()->heap()->roots_array_start(); Object** roots = isolate()->heap()->roots_array_start();
return current == &roots[Heap::kStoreBufferTopRootIndex] return current == &roots[Heap::kStoreBufferTopRootIndex]
...@@ -1633,6 +1686,15 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, ...@@ -1633,6 +1686,15 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
// Object has not yet been serialized. Serialize it here. // Object has not yet been serialized. Serialize it here.
ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
serializer.Serialize(); 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( ...@@ -2276,52 +2338,47 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
base::ElapsedTimer timer; base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start(); if (FLAG_profile_deserialization) timer.Start();
Object* root; HandleScope scope(isolate);
{ SmartPointer<SerializedCodeData> scd(
HandleScope scope(isolate); 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( // Eagerly expand string table to avoid allocations during deserialization.
SerializedCodeData::FromCachedData(cached_data, *source)); StringTable::EnsureCapacityForDeserialization(isolate,
if (scd.is_empty()) { scd->NumInternalizedStrings());
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. // Prepare and register list of attached objects.
StringTable::EnsureCapacityForDeserialization( Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
isolate, scd->NumInternalizedStrings()); Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
code_stub_keys.length() + kCodeStubsBaseIndex);
// Prepare and register list of attached objects. attached_objects[kSourceObjectIndex] = source;
Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); for (int i = 0; i < code_stub_keys.length(); i++) {
Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( attached_objects[i + kCodeStubsBaseIndex] =
code_stub_keys.length() + kCodeStubsBaseIndex); CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
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 deserializer(scd.get());
deserializer.SetAttachedObjects(&attached_objects); deserializer.SetAttachedObjects(&attached_objects);
// Deserialize. // Deserialize.
deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); Handle<SharedFunctionInfo> result;
if (root == NULL) { if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) {
// Deserializing may fail if the reservations cannot be fulfilled. // Deserializing may fail if the reservations cannot be fulfilled.
if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
return MaybeHandle<SharedFunctionInfo>(); return MaybeHandle<SharedFunctionInfo>();
}
deserializer.FlushICacheForNewCodeObjects();
} }
deserializer.FlushICacheForNewCodeObjects();
if (FLAG_profile_deserialization) { if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF(); double ms = timer.Elapsed().InMillisecondsF();
int length = cached_data->length(); int length = cached_data->length();
PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms);
} }
Handle<SharedFunctionInfo> result(SharedFunctionInfo::cast(root), isolate);
result->set_deserialized(true); result->set_deserialized(true);
if (isolate->logger()->is_logging_code_events() || if (isolate->logger()->is_logging_code_events() ||
...@@ -2335,7 +2392,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( ...@@ -2335,7 +2392,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
*result, NULL, name); *result, NULL, name);
} }
return result; return scope.CloseAndEscape(result);
} }
......
...@@ -518,12 +518,12 @@ class Deserializer: public SerializerDeserializer { ...@@ -518,12 +518,12 @@ class Deserializer: public SerializerDeserializer {
// Deserialize the snapshot into an empty heap. // Deserialize the snapshot into an empty heap.
void Deserialize(Isolate* isolate); void Deserialize(Isolate* isolate);
enum OnOOM { FATAL_ON_OOM, NULL_ON_OOM };
// Deserialize a single object and the objects reachable from it. // Deserialize a single object and the objects reachable from it.
// We may want to abort gracefully even if deserialization fails. // We may want to abort gracefully even if deserialization fails.
void DeserializePartial(Isolate* isolate, Object** root, MaybeHandle<Object> DeserializePartial(
OnOOM on_oom = FATAL_ON_OOM); Isolate* isolate, Handle<FixedArray>* outdated_contexts_out);
MaybeHandle<SharedFunctionInfo> DeserializeCode(Isolate* isolate);
void FlushICacheForNewCodeObjects(); void FlushICacheForNewCodeObjects();
...@@ -542,6 +542,8 @@ class Deserializer: public SerializerDeserializer { ...@@ -542,6 +542,8 @@ class Deserializer: public SerializerDeserializer {
UNREACHABLE(); UNREACHABLE();
} }
void Initialize(Isolate* isolate);
void DecodeReservation(Vector<const SerializedData::Reservation> res); void DecodeReservation(Vector<const SerializedData::Reservation> res);
bool ReserveSpace(); bool ReserveSpace();
...@@ -738,11 +740,12 @@ class Serializer : public SerializerDeserializer { ...@@ -738,11 +740,12 @@ class Serializer : public SerializerDeserializer {
class PartialSerializer : public Serializer { class PartialSerializer : public Serializer {
public: public:
PartialSerializer(Isolate* isolate, PartialSerializer(Isolate* isolate, Serializer* startup_snapshot_serializer,
Serializer* startup_snapshot_serializer,
SnapshotByteSink* sink) SnapshotByteSink* sink)
: Serializer(isolate, sink), : Serializer(isolate, sink),
startup_serializer_(startup_snapshot_serializer) { startup_serializer_(startup_snapshot_serializer),
outdated_contexts_(0),
global_object_(NULL) {
InitializeCodeAddressMap(); InitializeCodeAddressMap();
} }
...@@ -766,8 +769,11 @@ class PartialSerializer : public Serializer { ...@@ -766,8 +769,11 @@ class PartialSerializer : public Serializer {
startup_serializer_->isolate()->heap()->fixed_cow_array_map(); startup_serializer_->isolate()->heap()->fixed_cow_array_map();
} }
void SerializeOutdatedContextsAsFixedArray();
Serializer* startup_serializer_; Serializer* startup_serializer_;
List<BackReference> outdated_contexts_;
Object* global_object_;
DISALLOW_COPY_AND_ASSIGN(PartialSerializer); DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
}; };
......
...@@ -38,7 +38,8 @@ bool Snapshot::Initialize(Isolate* isolate) { ...@@ -38,7 +38,8 @@ bool Snapshot::Initialize(Isolate* isolate) {
} }
Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) { MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
Isolate* isolate, Handle<FixedArray>* outdated_contexts_out) {
if (!HaveASnapshotToStartFrom()) return Handle<Context>(); if (!HaveASnapshotToStartFrom()) return Handle<Context>();
base::ElapsedTimer timer; base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start(); if (FLAG_profile_deserialization) timer.Start();
...@@ -47,15 +48,18 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) { ...@@ -47,15 +48,18 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
Vector<const byte> context_data = ExtractContextData(&blob); Vector<const byte> context_data = ExtractContextData(&blob);
SnapshotData snapshot_data(context_data); SnapshotData snapshot_data(context_data);
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
Object* root;
deserializer.DeserializePartial(isolate, &root); MaybeHandle<Object> maybe_context =
CHECK(root->IsContext()); deserializer.DeserializePartial(isolate, outdated_contexts_out);
Handle<Object> result;
if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>();
CHECK(result->IsContext());
if (FLAG_profile_deserialization) { if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF(); double ms = timer.Elapsed().InMillisecondsF();
int bytes = context_data.length(); int bytes = context_data.length();
PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms); PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms);
} }
return Handle<Context>(Context::cast(root)); return Handle<Context>::cast(result);
} }
......
...@@ -16,7 +16,8 @@ class Snapshot : public AllStatic { ...@@ -16,7 +16,8 @@ class Snapshot : public AllStatic {
// snapshot could be found. // snapshot could be found.
static bool Initialize(Isolate* isolate); static bool Initialize(Isolate* isolate);
// Create a new context using the internal partial snapshot. // Create a new context using the internal partial snapshot.
static Handle<Context> NewContextFromSnapshot(Isolate* isolate); static MaybeHandle<Context> NewContextFromSnapshot(
Isolate* isolate, Handle<FixedArray>* outdated_contexts_out);
static bool HaveASnapshotToStartFrom(); static bool HaveASnapshotToStartFrom();
......
...@@ -391,24 +391,26 @@ UNINITIALIZED_DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { ...@@ -391,24 +391,26 @@ UNINITIALIZED_DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
byte* snapshot = ReadBytes(file_name, &snapshot_size); byte* snapshot = ReadBytes(file_name, &snapshot_size);
Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate); Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
Object* root; HandleScope handle_scope(isolate);
Handle<Object> root;
Handle<FixedArray> outdated_contexts;
{ {
SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size)); SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
deserializer.DeserializePartial(isolate, &root); root = deserializer.DeserializePartial(isolate, &outdated_contexts)
.ToHandleChecked();
CHECK_EQ(0, outdated_contexts->length());
CHECK(root->IsString()); CHECK(root->IsString());
} }
HandleScope handle_scope(isolate);
Handle<Object> root_handle(root, isolate);
Handle<Object> root2;
Object* root2;
{ {
SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size)); SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
deserializer.DeserializePartial(isolate, &root2); root2 = deserializer.DeserializePartial(isolate, &outdated_contexts)
.ToHandleChecked();
CHECK(root2->IsString()); CHECK(root2->IsString());
CHECK(*root_handle == root2); CHECK(root.is_identical_to(root2));
} }
} }
v8_isolate->Dispose(); v8_isolate->Dispose();
...@@ -501,24 +503,135 @@ UNINITIALIZED_DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { ...@@ -501,24 +503,135 @@ UNINITIALIZED_DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
byte* snapshot = ReadBytes(file_name, &snapshot_size); byte* snapshot = ReadBytes(file_name, &snapshot_size);
Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate); Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
Object* root; HandleScope handle_scope(isolate);
Handle<Object> root;
Handle<FixedArray> outdated_contexts;
{ {
SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size)); SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
deserializer.DeserializePartial(isolate, &root); root = deserializer.DeserializePartial(isolate, &outdated_contexts)
.ToHandleChecked();
CHECK(root->IsContext()); CHECK(root->IsContext());
CHECK_EQ(1, outdated_contexts->length());
} }
HandleScope handle_scope(isolate);
Handle<Object> root_handle(root, isolate);
Object* root2; Handle<Object> root2;
{ {
SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size)); SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
deserializer.DeserializePartial(isolate, &root2); root2 = deserializer.DeserializePartial(isolate, &outdated_contexts)
.ToHandleChecked();
CHECK(root2->IsContext()); CHECK(root2->IsContext());
CHECK(*root_handle != root2); CHECK(!root.is_identical_to(root2));
}
}
v8_isolate->Dispose();
}
}
UNINITIALIZED_TEST(CustomContextSerialization) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
v8::Isolate::CreateParams params;
params.enable_serializer = true;
v8::Isolate* v8_isolate = v8::Isolate::New(params);
Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
Heap* heap = isolate->heap();
{
v8::Isolate::Scope isolate_scope(v8_isolate);
v8::Persistent<v8::Context> env;
{
HandleScope scope(isolate);
env.Reset(v8_isolate, v8::Context::New(v8_isolate));
}
DCHECK(!env.IsEmpty());
{
v8::HandleScope handle_scope(v8_isolate);
v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
// After execution, e's function context refers to the global object.
CompileRun(
"var e;"
"(function() {"
" e = function(s) { eval (s); }"
"})();");
}
// Make sure all builtin scripts are cached.
{
HandleScope scope(isolate);
for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
isolate->bootstrapper()->NativesSourceLookup(i);
}
}
// If we don't do this then we end up with a stray root pointing at the
// context even after we have disposed of env.
heap->CollectAllGarbage(Heap::kNoGCFlags);
int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
{
v8::HandleScope handle_scope(v8_isolate);
v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
}
i::Object* raw_context = *v8::Utils::OpenPersistent(env);
env.Reset();
SnapshotByteSink startup_sink;
StartupSerializer startup_serializer(isolate, &startup_sink);
startup_serializer.SerializeStrongReferences();
SnapshotByteSink partial_sink;
PartialSerializer partial_serializer(isolate, &startup_serializer,
&partial_sink);
partial_serializer.Serialize(&raw_context);
startup_serializer.SerializeWeakReferences();
SnapshotData startup_snapshot(startup_sink, startup_serializer);
SnapshotData partial_snapshot(partial_sink, partial_serializer);
WritePayload(partial_snapshot.RawData(), FLAG_testing_serialization_file);
WritePayload(startup_snapshot.RawData(), startup_name.start());
startup_name.Dispose();
}
v8_isolate->Dispose();
}
}
UNINITIALIZED_DEPENDENT_TEST(CustomContextDeSerialization,
CustomContextSerialization) {
if (!Snapshot::HaveASnapshotToStartFrom()) {
int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
v8::Isolate* v8_isolate = InitializeFromFile(startup_name.start());
CHECK(v8_isolate);
startup_name.Dispose();
{
v8::Isolate::Scope isolate_scope(v8_isolate);
const char* file_name = FLAG_testing_serialization_file;
int snapshot_size = 0;
byte* snapshot = ReadBytes(file_name, &snapshot_size);
Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
HandleScope handle_scope(isolate);
Handle<Object> root;
Handle<FixedArray> outdated_contexts;
{
SnapshotData snapshot_data(Vector<const byte>(snapshot, snapshot_size));
Deserializer deserializer(&snapshot_data);
root = deserializer.DeserializePartial(isolate, &outdated_contexts)
.ToHandleChecked();
CHECK_EQ(2, outdated_contexts->length());
CHECK(root->IsContext());
} }
} }
v8_isolate->Dispose(); v8_isolate->Dispose();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment