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

Side by Side Diff: src/serialize.cc

Issue 957703003: Tweak memory management in the serializer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 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') | no next file » | 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 688 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/serialize.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698