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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/base/platform/platform.h" 9 #include "src/base/platform/platform.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 void Deserializer::FlushICacheForNewCodeObjects() { 628 void Deserializer::FlushICacheForNewCodeObjects() {
629 PageIterator it(isolate_->heap()->code_space()); 629 PageIterator it(isolate_->heap()->code_space());
630 while (it.has_next()) { 630 while (it.has_next()) {
631 Page* p = it.next(); 631 Page* p = it.next();
632 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); 632 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start());
633 } 633 }
634 } 634 }
635 635
636 636
637 bool Deserializer::ReserveSpace() { 637 bool Deserializer::ReserveSpace() {
638 #ifdef DEBUG
639 for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) {
640 CHECK(reservations_[i].length() > 0);
641 }
642 #endif // DEBUG
638 if (!isolate_->heap()->ReserveSpace(reservations_)) return false; 643 if (!isolate_->heap()->ReserveSpace(reservations_)) return false;
639 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { 644 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
640 high_water_[i] = reservations_[i][0].start; 645 high_water_[i] = reservations_[i][0].start;
641 } 646 }
642 return true; 647 return true;
643 } 648 }
644 649
645 650
651 void Deserializer::Initialize(Isolate* isolate) {
652 DCHECK_EQ(NULL, isolate_);
653 DCHECK_NE(NULL, isolate);
654 isolate_ = isolate;
655 DCHECK_EQ(NULL, external_reference_decoder_);
656 external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
657 }
658
659
646 void Deserializer::Deserialize(Isolate* isolate) { 660 void Deserializer::Deserialize(Isolate* isolate) {
647 isolate_ = isolate; 661 Initialize(isolate);
648 DCHECK(isolate_ != NULL);
649 if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context"); 662 if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context");
650 // No active threads. 663 // No active threads.
651 DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); 664 DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
652 // No active handles. 665 // No active handles.
653 DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty()); 666 DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty());
654 DCHECK_EQ(NULL, external_reference_decoder_);
655 external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
656 isolate_->heap()->IterateSmiRoots(this); 667 isolate_->heap()->IterateSmiRoots(this);
657 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); 668 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
658 isolate_->heap()->RepairFreeListsAfterBoot(); 669 isolate_->heap()->RepairFreeListsAfterBoot();
659 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); 670 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
660 671
661 isolate_->heap()->set_native_contexts_list( 672 isolate_->heap()->set_native_contexts_list(
662 isolate_->heap()->undefined_value()); 673 isolate_->heap()->undefined_value());
663 isolate_->heap()->set_array_buffers_list( 674 isolate_->heap()->set_array_buffers_list(
664 isolate_->heap()->undefined_value()); 675 isolate_->heap()->undefined_value());
665 676
(...skipping 15 matching lines...) Expand all
681 } 692 }
682 693
683 FlushICacheForNewCodeObjects(); 694 FlushICacheForNewCodeObjects();
684 695
685 // Issue code events for newly deserialized code objects. 696 // Issue code events for newly deserialized code objects.
686 LOG_CODE_EVENT(isolate_, LogCodeObjects()); 697 LOG_CODE_EVENT(isolate_, LogCodeObjects());
687 LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); 698 LOG_CODE_EVENT(isolate_, LogCompiledFunctions());
688 } 699 }
689 700
690 701
691 void Deserializer::DeserializePartial(Isolate* isolate, Object** root, 702 MaybeHandle<Object> Deserializer::DeserializePartial(
692 OnOOM on_oom) { 703 Isolate* isolate, Handle<FixedArray>* outdated_contexts_out) {
693 isolate_ = isolate; 704 Initialize(isolate);
694 for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
695 DCHECK(reservations_[i].length() > 0);
696 }
697 if (!ReserveSpace()) { 705 if (!ReserveSpace()) {
698 if (on_oom == FATAL_ON_OOM) FatalProcessOutOfMemory("deserialize context"); 706 FatalProcessOutOfMemory("deserialize context");
699 *root = NULL; 707 return MaybeHandle<Object>();
700 return;
701 }
702 if (external_reference_decoder_ == NULL) {
703 external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
704 } 708 }
705 709
706 DisallowHeapAllocation no_gc; 710 DisallowHeapAllocation no_gc;
707
708 // Keep track of the code space start and end pointers in case new 711 // Keep track of the code space start and end pointers in case new
709 // code objects were unserialized 712 // code objects were unserialized
710 OldSpace* code_space = isolate_->heap()->code_space(); 713 OldSpace* code_space = isolate_->heap()->code_space();
711 Address start_address = code_space->top(); 714 Address start_address = code_space->top();
712 VisitPointer(root); 715 Object* root;
716 Object* outdated_contexts;
717 VisitPointer(&root);
718 VisitPointer(&outdated_contexts);
713 719
714 // There's no code deserialized here. If this assert fires 720 // There's no code deserialized here. If this assert fires
715 // then that's changed and logging should be added to notify 721 // then that's changed and logging should be added to notify
716 // the profiler et al of the new code. 722 // the profiler et al of the new code.
717 CHECK_EQ(start_address, code_space->top()); 723 CHECK_EQ(start_address, code_space->top());
724 CHECK(outdated_contexts->IsFixedArray());
725 *outdated_contexts_out =
726 Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate);
727 return Handle<Object>(root, isolate);
718 } 728 }
719 729
720 730
731 MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
732 Isolate* isolate) {
733 Initialize(isolate);
734 if (!ReserveSpace()) {
735 return Handle<SharedFunctionInfo>();
736 } else {
737 DisallowHeapAllocation no_gc;
738 Object* root;
739 VisitPointer(&root);
740 return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root));
741 }
742 }
743
744
721 Deserializer::~Deserializer() { 745 Deserializer::~Deserializer() {
722 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. 746 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed.
723 // DCHECK(source_.AtEOF()); 747 // DCHECK(source_.AtEOF());
724 if (external_reference_decoder_) { 748 if (external_reference_decoder_) {
725 delete external_reference_decoder_; 749 delete external_reference_decoder_;
726 external_reference_decoder_ = NULL; 750 external_reference_decoder_ = NULL;
727 } 751 }
728 if (attached_objects_) attached_objects_->Dispose(); 752 if (attached_objects_) attached_objects_->Dispose();
729 } 753 }
730 754
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 for (int i = 0; i < kPointerSize; i++) { 1388 for (int i = 0; i < kPointerSize; i++) {
1365 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); 1389 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
1366 } 1390 }
1367 } else { 1391 } else {
1368 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); 1392 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0);
1369 } 1393 }
1370 } 1394 }
1371 } 1395 }
1372 1396
1373 1397
1374 void PartialSerializer::Serialize(Object** object) { 1398 void PartialSerializer::Serialize(Object** o) {
1375 this->VisitPointer(object); 1399 if ((*o)->IsContext()) global_object_ = Context::cast(*o)->global_object();
1400 VisitPointer(o);
1401 SerializeOutdatedContextsAsFixedArray();
1376 Pad(); 1402 Pad();
1377 } 1403 }
1378 1404
1379 1405
1406 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() {
1407 int length = outdated_contexts_.length();
1408 if (length == 0) {
1409 FixedArray* empty = isolate_->heap()->empty_fixed_array();
1410 SerializeObject(empty, kPlain, kStartOfObject, 0);
1411 } else {
1412 // Serialize an imaginary fixed array containing outdated contexts.
1413 int size = FixedArray::SizeFor(length);
1414 Allocate(NEW_SPACE, size);
1415 sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray");
1416 sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words");
1417 Map* map = isolate_->heap()->fixed_array_map();
1418 SerializeObject(map, kPlain, kStartOfObject, 0);
1419 Smi* length_smi = Smi::FromInt(length);
1420 sink_->Put(kOnePointerRawData, "Smi");
1421 for (int i = 0; i < kPointerSize; i++) {
1422 sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte");
1423 }
1424 for (int i = 0; i < length; i++) {
1425 BackReference back_ref = outdated_contexts_[i];
1426 sink_->Put(kBackref + back_ref.space(), "BackRef");
1427 sink_->PutInt(back_ref.reference(), "BackRefValue");
1428 }
1429 }
1430 }
1431
1432
1380 bool Serializer::ShouldBeSkipped(Object** current) { 1433 bool Serializer::ShouldBeSkipped(Object** current) {
1381 Object** roots = isolate()->heap()->roots_array_start(); 1434 Object** roots = isolate()->heap()->roots_array_start();
1382 return current == &roots[Heap::kStoreBufferTopRootIndex] 1435 return current == &roots[Heap::kStoreBufferTopRootIndex]
1383 || current == &roots[Heap::kStackLimitRootIndex] 1436 || current == &roots[Heap::kStackLimitRootIndex]
1384 || current == &roots[Heap::kRealStackLimitRootIndex]; 1437 || current == &roots[Heap::kRealStackLimitRootIndex];
1385 } 1438 }
1386 1439
1387 1440
1388 void Serializer::VisitPointers(Object** start, Object** end) { 1441 void Serializer::VisitPointers(Object** start, Object** end) {
1389 for (Object** current = start; current < end; current++) { 1442 for (Object** current = start; current < end; current++) {
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1626 // either in the root table or in the partial snapshot cache. 1679 // either in the root table or in the partial snapshot cache.
1627 DCHECK(!obj->IsInternalizedString()); 1680 DCHECK(!obj->IsInternalizedString());
1628 1681
1629 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; 1682 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
1630 1683
1631 FlushSkip(skip); 1684 FlushSkip(skip);
1632 1685
1633 // Object has not yet been serialized. Serialize it here. 1686 // Object has not yet been serialized. Serialize it here.
1634 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); 1687 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
1635 serializer.Serialize(); 1688 serializer.Serialize();
1689
1690 if (obj->IsContext() &&
1691 Context::cast(obj)->global_object() == global_object_) {
1692 // Context refers to the current global object. This reference will
1693 // become outdated after deserialization.
1694 BackReference back_reference = back_reference_map_.Lookup(obj);
1695 DCHECK(back_reference.is_valid());
1696 outdated_contexts_.Add(back_reference);
1697 }
1636 } 1698 }
1637 1699
1638 1700
1639 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, 1701 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
1640 int size, Map* map) { 1702 int size, Map* map) {
1641 if (serializer_->code_address_map_) { 1703 if (serializer_->code_address_map_) {
1642 const char* code_name = 1704 const char* code_name =
1643 serializer_->code_address_map_->Lookup(object_->address()); 1705 serializer_->code_address_map_->Lookup(object_->address());
1644 LOG(serializer_->isolate_, 1706 LOG(serializer_->isolate_,
1645 CodeNameEvent(object_->address(), sink_->Position(), code_name)); 1707 CodeNameEvent(object_->address(), sink_->Position(), code_name));
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after
2269 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); 2331 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
2270 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); 2332 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex");
2271 } 2333 }
2272 2334
2273 2335
2274 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( 2336 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
2275 Isolate* isolate, ScriptData* cached_data, Handle<String> source) { 2337 Isolate* isolate, ScriptData* cached_data, Handle<String> source) {
2276 base::ElapsedTimer timer; 2338 base::ElapsedTimer timer;
2277 if (FLAG_profile_deserialization) timer.Start(); 2339 if (FLAG_profile_deserialization) timer.Start();
2278 2340
2279 Object* root; 2341 HandleScope scope(isolate);
2280 2342
2281 { 2343 SmartPointer<SerializedCodeData> scd(
2282 HandleScope scope(isolate); 2344 SerializedCodeData::FromCachedData(cached_data, *source));
2345 if (scd.is_empty()) {
2346 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
2347 DCHECK(cached_data->rejected());
2348 return MaybeHandle<SharedFunctionInfo>();
2349 }
2283 2350
2284 SmartPointer<SerializedCodeData> scd( 2351 // Eagerly expand string table to avoid allocations during deserialization.
2285 SerializedCodeData::FromCachedData(cached_data, *source)); 2352 StringTable::EnsureCapacityForDeserialization(isolate,
2286 if (scd.is_empty()) { 2353 scd->NumInternalizedStrings());
2287 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
2288 DCHECK(cached_data->rejected());
2289 return MaybeHandle<SharedFunctionInfo>();
2290 }
2291 2354
2292 // Eagerly expand string table to avoid allocations during deserialization. 2355 // Prepare and register list of attached objects.
2293 StringTable::EnsureCapacityForDeserialization( 2356 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
2294 isolate, scd->NumInternalizedStrings()); 2357 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
2358 code_stub_keys.length() + kCodeStubsBaseIndex);
2359 attached_objects[kSourceObjectIndex] = source;
2360 for (int i = 0; i < code_stub_keys.length(); i++) {
2361 attached_objects[i + kCodeStubsBaseIndex] =
2362 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
2363 }
2295 2364
2296 // Prepare and register list of attached objects. 2365 Deserializer deserializer(scd.get());
2297 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); 2366 deserializer.SetAttachedObjects(&attached_objects);
2298 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
2299 code_stub_keys.length() + kCodeStubsBaseIndex);
2300 attached_objects[kSourceObjectIndex] = source;
2301 for (int i = 0; i < code_stub_keys.length(); i++) {
2302 attached_objects[i + kCodeStubsBaseIndex] =
2303 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
2304 }
2305 2367
2306 Deserializer deserializer(scd.get()); 2368 // Deserialize.
2307 deserializer.SetAttachedObjects(&attached_objects); 2369 Handle<SharedFunctionInfo> result;
2308 2370 if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) {
2309 // Deserialize. 2371 // Deserializing may fail if the reservations cannot be fulfilled.
2310 deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); 2372 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
2311 if (root == NULL) { 2373 return MaybeHandle<SharedFunctionInfo>();
2312 // Deserializing may fail if the reservations cannot be fulfilled.
2313 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
2314 return MaybeHandle<SharedFunctionInfo>();
2315 }
2316 deserializer.FlushICacheForNewCodeObjects();
2317 } 2374 }
2375 deserializer.FlushICacheForNewCodeObjects();
2318 2376
2319 if (FLAG_profile_deserialization) { 2377 if (FLAG_profile_deserialization) {
2320 double ms = timer.Elapsed().InMillisecondsF(); 2378 double ms = timer.Elapsed().InMillisecondsF();
2321 int length = cached_data->length(); 2379 int length = cached_data->length();
2322 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); 2380 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms);
2323 } 2381 }
2324 Handle<SharedFunctionInfo> result(SharedFunctionInfo::cast(root), isolate);
2325 result->set_deserialized(true); 2382 result->set_deserialized(true);
2326 2383
2327 if (isolate->logger()->is_logging_code_events() || 2384 if (isolate->logger()->is_logging_code_events() ||
2328 isolate->cpu_profiler()->is_profiling()) { 2385 isolate->cpu_profiler()->is_profiling()) {
2329 String* name = isolate->heap()->empty_string(); 2386 String* name = isolate->heap()->empty_string();
2330 if (result->script()->IsScript()) { 2387 if (result->script()->IsScript()) {
2331 Script* script = Script::cast(result->script()); 2388 Script* script = Script::cast(result->script());
2332 if (script->name()->IsString()) name = String::cast(script->name()); 2389 if (script->name()->IsString()) name = String::cast(script->name());
2333 } 2390 }
2334 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), 2391 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(),
2335 *result, NULL, name); 2392 *result, NULL, name);
2336 } 2393 }
2337 2394
2338 return result; 2395 return scope.CloseAndEscape(result);
2339 } 2396 }
2340 2397
2341 2398
2342 void SerializedData::AllocateData(int size) { 2399 void SerializedData::AllocateData(int size) {
2343 DCHECK(!owns_data_); 2400 DCHECK(!owns_data_);
2344 data_ = NewArray<byte>(size); 2401 data_ = NewArray<byte>(size);
2345 size_ = size; 2402 size_ = size;
2346 owns_data_ = true; 2403 owns_data_ = true;
2347 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); 2404 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
2348 } 2405 }
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 return GetHeaderValue(kNumInternalizedStringsOffset); 2538 return GetHeaderValue(kNumInternalizedStringsOffset);
2482 } 2539 }
2483 2540
2484 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const { 2541 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const {
2485 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; 2542 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size;
2486 const byte* start = data_ + kHeaderSize + reservations_size; 2543 const byte* start = data_ + kHeaderSize + reservations_size;
2487 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), 2544 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start),
2488 GetHeaderValue(kNumCodeStubKeysOffset)); 2545 GetHeaderValue(kNumCodeStubKeysOffset));
2489 } 2546 }
2490 } } // namespace v8::internal 2547 } } // namespace v8::internal
OLDNEW
« 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