OLD | NEW |
---|---|
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 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
699 | 699 |
700 MaybeHandle<Object> Deserializer::DeserializePartial( | 700 MaybeHandle<Object> Deserializer::DeserializePartial( |
701 Isolate* isolate, Handle<JSGlobalProxy> global_proxy, | 701 Isolate* isolate, Handle<JSGlobalProxy> global_proxy, |
702 Handle<FixedArray>* outdated_contexts_out) { | 702 Handle<FixedArray>* outdated_contexts_out) { |
703 Initialize(isolate); | 703 Initialize(isolate); |
704 if (!ReserveSpace()) { | 704 if (!ReserveSpace()) { |
705 V8::FatalProcessOutOfMemory("deserialize context"); | 705 V8::FatalProcessOutOfMemory("deserialize context"); |
706 return MaybeHandle<Object>(); | 706 return MaybeHandle<Object>(); |
707 } | 707 } |
708 | 708 |
709 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(1); | 709 Handle<Object> global_proxy_object = global_proxy; |
710 attached_objects[kGlobalProxyReference] = global_proxy; | 710 Vector<Handle<Object> > attached_objects(&global_proxy_object, 1); |
711 SetAttachedObjects(attached_objects); | 711 SetAttachedObjects(attached_objects); |
vogelheim
2015/02/25 14:00:19
I don't get this. My understanding is:
- SetAttac
Yang
2015/02/25 16:06:21
You are right. It will indeed go out of scope, tho
| |
712 | 712 |
713 DisallowHeapAllocation no_gc; | 713 DisallowHeapAllocation no_gc; |
714 // Keep track of the code space start and end pointers in case new | 714 // Keep track of the code space start and end pointers in case new |
715 // code objects were unserialized | 715 // code objects were unserialized |
716 OldSpace* code_space = isolate_->heap()->code_space(); | 716 OldSpace* code_space = isolate_->heap()->code_space(); |
717 Address start_address = code_space->top(); | 717 Address start_address = code_space->top(); |
718 Object* root; | 718 Object* root; |
719 Object* outdated_contexts; | 719 Object* outdated_contexts; |
720 VisitPointer(&root); | 720 VisitPointer(&root); |
721 VisitPointer(&outdated_contexts); | 721 VisitPointer(&outdated_contexts); |
(...skipping 24 matching lines...) Expand all Loading... | |
746 } | 746 } |
747 | 747 |
748 | 748 |
749 Deserializer::~Deserializer() { | 749 Deserializer::~Deserializer() { |
750 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. | 750 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. |
751 // DCHECK(source_.AtEOF()); | 751 // DCHECK(source_.AtEOF()); |
752 if (external_reference_decoder_) { | 752 if (external_reference_decoder_) { |
753 delete external_reference_decoder_; | 753 delete external_reference_decoder_; |
754 external_reference_decoder_ = NULL; | 754 external_reference_decoder_ = NULL; |
755 } | 755 } |
756 attached_objects_.Dispose(); | |
757 } | 756 } |
758 | 757 |
759 | 758 |
760 // This is called on the roots. It is the driver of the deserialization | 759 // This is called on the roots. It is the driver of the deserialization |
761 // process. It is also called on the body of each function. | 760 // process. It is also called on the body of each function. |
762 void Deserializer::VisitPointers(Object** start, Object** end) { | 761 void Deserializer::VisitPointers(Object** start, Object** end) { |
763 // The space must be new space. Any other space would cause ReadChunk to try | 762 // The space must be new space. Any other space would cause ReadChunk to try |
764 // to update the remembered using NULL as the address. | 763 // to update the remembered using NULL as the address. |
765 ReadData(start, end, NEW_SPACE, NULL); | 764 ReadData(start, end, NEW_SPACE, NULL); |
766 } | 765 } |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1371 pending_chunk_[i] = 0; | 1370 pending_chunk_[i] = 0; |
1372 max_chunk_size_[i] = static_cast<uint32_t>( | 1371 max_chunk_size_[i] = static_cast<uint32_t>( |
1373 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); | 1372 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); |
1374 } | 1373 } |
1375 } | 1374 } |
1376 | 1375 |
1377 | 1376 |
1378 Serializer::~Serializer() { | 1377 Serializer::~Serializer() { |
1379 delete external_reference_encoder_; | 1378 delete external_reference_encoder_; |
1380 if (code_address_map_ != NULL) delete code_address_map_; | 1379 if (code_address_map_ != NULL) delete code_address_map_; |
1380 code_buffer_.Dispose(); | |
1381 } | 1381 } |
1382 | 1382 |
1383 | 1383 |
1384 void StartupSerializer::SerializeStrongReferences() { | 1384 void StartupSerializer::SerializeStrongReferences() { |
1385 Isolate* isolate = this->isolate(); | 1385 Isolate* isolate = this->isolate(); |
1386 // No active threads. | 1386 // No active threads. |
1387 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); | 1387 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); |
1388 // No active or weak handles. | 1388 // No active or weak handles. |
1389 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); | 1389 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); |
1390 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); | 1390 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2037 return; | 2037 return; |
2038 } | 2038 } |
2039 } | 2039 } |
2040 } | 2040 } |
2041 // One of the strings in the natives cache should match the resource. We | 2041 // One of the strings in the natives cache should match the resource. We |
2042 // don't expect any other kinds of external strings here. | 2042 // don't expect any other kinds of external strings here. |
2043 UNREACHABLE(); | 2043 UNREACHABLE(); |
2044 } | 2044 } |
2045 | 2045 |
2046 | 2046 |
2047 static Code* CloneCodeObject(HeapObject* code) { | 2047 Address Serializer::ObjectSerializer::PrepareCode() { |
2048 Address copy = new byte[code->Size()]; | 2048 // To make snapshots reproducible, we make a copy of the code object |
2049 MemCopy(copy, code->address(), code->Size()); | 2049 // and wipe all pointers in the copy, which we then serialize. |
2050 return Code::cast(HeapObject::FromAddress(copy)); | 2050 Code* original = Code::cast(object_); |
2051 } | 2051 int size = original->CodeSize(); |
2052 | 2052 Address copy = serializer_->GetCodeBuffer(size); |
2053 | 2053 MemCopy(copy, original->address(), size); |
2054 static void WipeOutRelocations(Code* code) { | 2054 Code* code = Code::cast(HeapObject::FromAddress(copy)); |
2055 // Code age headers are not serializable. | |
2056 code->MakeYoung(serializer_->isolate()); | |
2055 int mode_mask = | 2057 int mode_mask = |
2056 RelocInfo::kCodeTargetMask | | 2058 RelocInfo::kCodeTargetMask | |
2057 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 2059 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
2058 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 2060 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
2059 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 2061 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
2060 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 2062 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { |
2061 if (!(FLAG_enable_ool_constant_pool && it.rinfo()->IsInConstantPool())) { | 2063 if (!(FLAG_enable_ool_constant_pool && it.rinfo()->IsInConstantPool())) { |
2062 it.rinfo()->WipeOut(); | 2064 it.rinfo()->WipeOut(); |
2063 } | 2065 } |
2064 } | 2066 } |
2067 // We need to wipe out the header fields *after* wiping out the | |
2068 // relocations, because some of these fields are needed for the latter. | |
2069 code->WipeOutHeader(); | |
2070 return code->address(); | |
2065 } | 2071 } |
2066 | 2072 |
2067 | 2073 |
2068 int Serializer::ObjectSerializer::OutputRawData( | 2074 int Serializer::ObjectSerializer::OutputRawData( |
2069 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { | 2075 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { |
2070 Address object_start = object_->address(); | 2076 Address object_start = object_->address(); |
2071 int base = bytes_processed_so_far_; | 2077 int base = bytes_processed_so_far_; |
2072 int up_to_offset = static_cast<int>(up_to - object_start); | 2078 int up_to_offset = static_cast<int>(up_to - object_start); |
2073 int to_skip = up_to_offset - bytes_processed_so_far_; | 2079 int to_skip = up_to_offset - bytes_processed_so_far_; |
2074 int bytes_to_output = to_skip; | 2080 int bytes_to_output = to_skip; |
(...skipping 17 matching lines...) Expand all Loading... | |
2092 to_skip = 0; /* This insn already skips. */ \ | 2098 to_skip = 0; /* This insn already skips. */ \ |
2093 } else /* NOLINT */ | 2099 } else /* NOLINT */ |
2094 COMMON_RAW_LENGTHS(RAW_CASE) | 2100 COMMON_RAW_LENGTHS(RAW_CASE) |
2095 #undef RAW_CASE | 2101 #undef RAW_CASE |
2096 { /* NOLINT */ | 2102 { /* NOLINT */ |
2097 // We always end up here if we are outputting the code of a code object. | 2103 // We always end up here if we are outputting the code of a code object. |
2098 sink_->Put(kRawData, "RawData"); | 2104 sink_->Put(kRawData, "RawData"); |
2099 sink_->PutInt(bytes_to_output, "length"); | 2105 sink_->PutInt(bytes_to_output, "length"); |
2100 } | 2106 } |
2101 | 2107 |
2102 // To make snapshots reproducible, we need to wipe out all pointers in code. | 2108 if (code_object_) object_start = PrepareCode(); |
2103 if (code_object_) { | |
2104 Code* code = CloneCodeObject(object_); | |
2105 // Code age headers are not serializable. | |
2106 code->MakeYoung(serializer_->isolate()); | |
2107 WipeOutRelocations(code); | |
2108 // We need to wipe out the header fields *after* wiping out the | |
2109 // relocations, because some of these fields are needed for the latter. | |
2110 code->WipeOutHeader(); | |
2111 object_start = code->address(); | |
2112 } | |
2113 | 2109 |
2114 const char* description = code_object_ ? "Code" : "Byte"; | 2110 const char* description = code_object_ ? "Code" : "Byte"; |
2115 #ifdef MEMORY_SANITIZER | 2111 #ifdef MEMORY_SANITIZER |
2116 // Object sizes are usually rounded up with uninitialized padding space. | 2112 // Object sizes are usually rounded up with uninitialized padding space. |
2117 MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output); | 2113 MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output); |
2118 #endif // MEMORY_SANITIZER | 2114 #endif // MEMORY_SANITIZER |
2119 sink_->PutRaw(object_start + base, bytes_to_output, description); | 2115 sink_->PutRaw(object_start + base, bytes_to_output, description); |
2120 if (code_object_) delete[] object_start; | |
2121 } | 2116 } |
2122 if (to_skip != 0 && return_skip == kIgnoringReturn) { | 2117 if (to_skip != 0 && return_skip == kIgnoringReturn) { |
2123 sink_->Put(kSkip, "Skip"); | 2118 sink_->Put(kSkip, "Skip"); |
2124 sink_->PutInt(to_skip, "SkipDistance"); | 2119 sink_->PutInt(to_skip, "SkipDistance"); |
2125 to_skip = 0; | 2120 to_skip = 0; |
2126 } | 2121 } |
2127 return to_skip; | 2122 return to_skip; |
2128 } | 2123 } |
2129 | 2124 |
2130 | 2125 |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2409 attached_objects[kSourceObjectIndex] = source; | 2404 attached_objects[kSourceObjectIndex] = source; |
2410 for (int i = 0; i < code_stub_keys.length(); i++) { | 2405 for (int i = 0; i < code_stub_keys.length(); i++) { |
2411 attached_objects[i + kCodeStubsBaseIndex] = | 2406 attached_objects[i + kCodeStubsBaseIndex] = |
2412 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); | 2407 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); |
2413 } | 2408 } |
2414 | 2409 |
2415 Deserializer deserializer(scd.get()); | 2410 Deserializer deserializer(scd.get()); |
2416 deserializer.SetAttachedObjects(attached_objects); | 2411 deserializer.SetAttachedObjects(attached_objects); |
2417 | 2412 |
2418 // Deserialize. | 2413 // Deserialize. |
2414 MaybeHandle<SharedFunctionInfo> maybe = deserializer.DeserializeCode(isolate); | |
2415 attached_objects.Dispose(); | |
2416 | |
2419 Handle<SharedFunctionInfo> result; | 2417 Handle<SharedFunctionInfo> result; |
2420 if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) { | 2418 if (!maybe.ToHandle(&result)) { |
2421 // Deserializing may fail if the reservations cannot be fulfilled. | 2419 // Deserializing may fail if the reservations cannot be fulfilled. |
2422 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); | 2420 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); |
2423 return MaybeHandle<SharedFunctionInfo>(); | 2421 return MaybeHandle<SharedFunctionInfo>(); |
2424 } | 2422 } |
2425 deserializer.FlushICacheForNewCodeObjects(); | 2423 deserializer.FlushICacheForNewCodeObjects(); |
2426 | 2424 |
2427 if (FLAG_profile_deserialization) { | 2425 if (FLAG_profile_deserialization) { |
2428 double ms = timer.Elapsed().InMillisecondsF(); | 2426 double ms = timer.Elapsed().InMillisecondsF(); |
2429 int length = cached_data->length(); | 2427 int length = cached_data->length(); |
2430 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); | 2428 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2664 DisallowHeapAllocation no_gc; | 2662 DisallowHeapAllocation no_gc; |
2665 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2663 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2666 SanityCheckResult r = scd->SanityCheck(source); | 2664 SanityCheckResult r = scd->SanityCheck(source); |
2667 if (r == CHECK_SUCCESS) return scd; | 2665 if (r == CHECK_SUCCESS) return scd; |
2668 cached_data->Reject(); | 2666 cached_data->Reject(); |
2669 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2667 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2670 delete scd; | 2668 delete scd; |
2671 return NULL; | 2669 return NULL; |
2672 } | 2670 } |
2673 } } // namespace v8::internal | 2671 } } // namespace v8::internal |
OLD | NEW |