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

Side by Side Diff: src/d8.cc

Issue 2662193002: [d8] Fix ArrayBuffer memory leaks in d8 introduced by commit 96635558. (Closed)
Patch Set: comment Created 3 years, 10 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/d8.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 <errno.h> 5 #include <errno.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; 394 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
395 CounterCollection Shell::local_counters_; 395 CounterCollection Shell::local_counters_;
396 CounterCollection* Shell::counters_ = &local_counters_; 396 CounterCollection* Shell::counters_ = &local_counters_;
397 base::LazyMutex Shell::context_mutex_; 397 base::LazyMutex Shell::context_mutex_;
398 const base::TimeTicks Shell::kInitialTicks = 398 const base::TimeTicks Shell::kInitialTicks =
399 base::TimeTicks::HighResolutionNow(); 399 base::TimeTicks::HighResolutionNow();
400 Global<Function> Shell::stringify_function_; 400 Global<Function> Shell::stringify_function_;
401 base::LazyMutex Shell::workers_mutex_; 401 base::LazyMutex Shell::workers_mutex_;
402 bool Shell::allow_new_workers_ = true; 402 bool Shell::allow_new_workers_ = true;
403 i::List<Worker*> Shell::workers_; 403 i::List<Worker*> Shell::workers_;
404 std::unordered_set<SharedArrayBuffer::Contents, 404 std::vector<ExternalizedContents> Shell::externalized_contents_;
405 Shell::SharedArrayBufferContentsHash,
406 Shell::SharedArrayBufferContentsIsEqual>
407 Shell::externalized_shared_contents_;
408 405
409 Global<Context> Shell::evaluation_context_; 406 Global<Context> Shell::evaluation_context_;
410 ArrayBuffer::Allocator* Shell::array_buffer_allocator; 407 ArrayBuffer::Allocator* Shell::array_buffer_allocator;
411 ShellOptions Shell::options; 408 ShellOptions Shell::options;
412 base::OnceType Shell::quit_once_ = V8_ONCE_INIT; 409 base::OnceType Shell::quit_once_ = V8_ONCE_INIT;
413 410
414 bool CounterMap::Match(void* key1, void* key2) { 411 bool CounterMap::Match(void* key1, void* key2) {
415 const char* name1 = reinterpret_cast<const char*>(key1); 412 const char* name1 = reinterpret_cast<const char*>(key1);
416 const char* name2 = reinterpret_cast<const char*>(key2); 413 const char* name2 = reinterpret_cast<const char*>(key2);
417 return strcmp(name1, name2) == 0; 414 return strcmp(name1, name2) == 0;
(...skipping 1690 matching lines...) Expand 10 before | Expand all | Expand 10 after
2108 if (thread_ == NULL) return; 2105 if (thread_ == NULL) return;
2109 done_semaphore_.Wait(); 2106 done_semaphore_.Wait();
2110 } 2107 }
2111 2108
2112 2109
2113 void SourceGroup::JoinThread() { 2110 void SourceGroup::JoinThread() {
2114 if (thread_ == NULL) return; 2111 if (thread_ == NULL) return;
2115 thread_->Join(); 2112 thread_->Join();
2116 } 2113 }
2117 2114
2118 SerializationData::~SerializationData() { 2115 ExternalizedContents::~ExternalizedContents() {
2119 // Any ArrayBuffer::Contents are owned by this SerializationData object if 2116 Shell::array_buffer_allocator->Free(data_, size_);
2120 // ownership hasn't been transferred out.
2121 // SharedArrayBuffer::Contents may be used by multiple threads, so must be
2122 // cleaned up by the main thread in Shell::CleanupWorkers().
2123 for (const auto& contents : array_buffer_contents_) {
2124 if (contents.Data()) {
2125 Shell::array_buffer_allocator->Free(contents.Data(),
2126 contents.ByteLength());
2127 }
2128 }
2129 }
2130
2131 void SerializationData::ClearTransferredArrayBuffers() {
2132 array_buffer_contents_.clear();
2133 } 2117 }
2134 2118
2135 void SerializationDataQueue::Enqueue(std::unique_ptr<SerializationData> data) { 2119 void SerializationDataQueue::Enqueue(std::unique_ptr<SerializationData> data) {
2136 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2120 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2137 data_.push_back(std::move(data)); 2121 data_.push_back(std::move(data));
2138 } 2122 }
2139 2123
2140 bool SerializationDataQueue::Dequeue( 2124 bool SerializationDataQueue::Dequeue(
2141 std::unique_ptr<SerializationData>* out_data) { 2125 std::unique_ptr<SerializationData>* out_data) {
2142 out_data->reset(); 2126 out_data->reset();
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2588 } 2572 }
2589 return Just(true); 2573 return Just(true);
2590 } else if (transfer->IsUndefined()) { 2574 } else if (transfer->IsUndefined()) {
2591 return Just(true); 2575 return Just(true);
2592 } else { 2576 } else {
2593 Throw(isolate_, "Transfer list must be an Array or undefined"); 2577 Throw(isolate_, "Transfer list must be an Array or undefined");
2594 return Nothing<bool>(); 2578 return Nothing<bool>();
2595 } 2579 }
2596 } 2580 }
2597 2581
2582 template <typename T>
2583 typename T::Contents MaybeExternalize(Local<T> array_buffer) {
2584 if (array_buffer->IsExternal()) {
2585 return array_buffer->GetContents();
2586 } else {
2587 typename T::Contents contents = array_buffer->Externalize();
2588 data_->externalized_contents_.emplace_back(contents);
2589 return contents;
2590 }
2591 }
2592
2598 Maybe<bool> FinalizeTransfer() { 2593 Maybe<bool> FinalizeTransfer() {
2599 for (const auto& global_array_buffer : array_buffers_) { 2594 for (const auto& global_array_buffer : array_buffers_) {
2600 Local<ArrayBuffer> array_buffer = 2595 Local<ArrayBuffer> array_buffer =
2601 Local<ArrayBuffer>::New(isolate_, global_array_buffer); 2596 Local<ArrayBuffer>::New(isolate_, global_array_buffer);
2602 if (!array_buffer->IsNeuterable()) { 2597 if (!array_buffer->IsNeuterable()) {
2603 Throw(isolate_, "ArrayBuffer could not be transferred"); 2598 Throw(isolate_, "ArrayBuffer could not be transferred");
2604 return Nothing<bool>(); 2599 return Nothing<bool>();
2605 } 2600 }
2606 2601
2607 if (!array_buffer->IsExternal()) { 2602 ArrayBuffer::Contents contents = MaybeExternalize(array_buffer);
2608 array_buffer->Externalize();
2609 }
2610 ArrayBuffer::Contents contents = array_buffer->GetContents();
2611 array_buffer->Neuter(); 2603 array_buffer->Neuter();
2612 data_->array_buffer_contents_.push_back(contents); 2604 data_->array_buffer_contents_.push_back(contents);
2613 } 2605 }
2614 2606
2615 for (const auto& global_shared_array_buffer : shared_array_buffers_) { 2607 for (const auto& global_shared_array_buffer : shared_array_buffers_) {
2616 Local<SharedArrayBuffer> shared_array_buffer = 2608 Local<SharedArrayBuffer> shared_array_buffer =
2617 Local<SharedArrayBuffer>::New(isolate_, global_shared_array_buffer); 2609 Local<SharedArrayBuffer>::New(isolate_, global_shared_array_buffer);
2618 if (!shared_array_buffer->IsExternal()) {
2619 shared_array_buffer->Externalize();
2620 }
2621 data_->shared_array_buffer_contents_.push_back( 2610 data_->shared_array_buffer_contents_.push_back(
2622 shared_array_buffer->GetContents()); 2611 MaybeExternalize(shared_array_buffer));
2623 } 2612 }
2624 2613
2625 return Just(true); 2614 return Just(true);
2626 } 2615 }
2627 2616
2628 Isolate* isolate_; 2617 Isolate* isolate_;
2629 ValueSerializer serializer_; 2618 ValueSerializer serializer_;
2630 std::unique_ptr<SerializationData> data_; 2619 std::unique_ptr<SerializationData> data_;
2631 std::vector<Global<ArrayBuffer>> array_buffers_; 2620 std::vector<Global<ArrayBuffer>> array_buffers_;
2632 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_; 2621 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_;
(...skipping 23 matching lines...) Expand all
2656 deserializer_.TransferArrayBuffer(index++, array_buffer); 2645 deserializer_.TransferArrayBuffer(index++, array_buffer);
2657 } 2646 }
2658 2647
2659 index = 0; 2648 index = 0;
2660 for (const auto& contents : data_->shared_array_buffer_contents()) { 2649 for (const auto& contents : data_->shared_array_buffer_contents()) {
2661 Local<SharedArrayBuffer> shared_array_buffer = SharedArrayBuffer::New( 2650 Local<SharedArrayBuffer> shared_array_buffer = SharedArrayBuffer::New(
2662 isolate_, contents.Data(), contents.ByteLength()); 2651 isolate_, contents.Data(), contents.ByteLength());
2663 deserializer_.TransferSharedArrayBuffer(index++, shared_array_buffer); 2652 deserializer_.TransferSharedArrayBuffer(index++, shared_array_buffer);
2664 } 2653 }
2665 2654
2666 MaybeLocal<Value> result = deserializer_.ReadValue(context); 2655 return deserializer_.ReadValue(context);
2667 if (!result.IsEmpty()) {
2668 data_->ClearTransferredArrayBuffers();
2669 }
2670 return result;
2671 } 2656 }
2672 2657
2673 private: 2658 private:
2674 Isolate* isolate_; 2659 Isolate* isolate_;
2675 ValueDeserializer deserializer_; 2660 ValueDeserializer deserializer_;
2676 std::unique_ptr<SerializationData> data_; 2661 std::unique_ptr<SerializationData> data_;
2677 2662
2678 DISALLOW_COPY_AND_ASSIGN(Deserializer); 2663 DISALLOW_COPY_AND_ASSIGN(Deserializer);
2679 }; 2664 };
2680 2665
2681 std::unique_ptr<SerializationData> Shell::SerializeValue( 2666 std::unique_ptr<SerializationData> Shell::SerializeValue(
2682 Isolate* isolate, Local<Value> value, Local<Value> transfer) { 2667 Isolate* isolate, Local<Value> value, Local<Value> transfer) {
2683 bool ok; 2668 bool ok;
2684 Local<Context> context = isolate->GetCurrentContext(); 2669 Local<Context> context = isolate->GetCurrentContext();
2685 Serializer serializer(isolate); 2670 Serializer serializer(isolate);
2686 if (serializer.WriteValue(context, value, transfer).To(&ok)) { 2671 if (serializer.WriteValue(context, value, transfer).To(&ok)) {
2687 std::unique_ptr<SerializationData> data = serializer.Release(); 2672 std::unique_ptr<SerializationData> data = serializer.Release();
2688 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 2673 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2689 for (const auto& contents : data->shared_array_buffer_contents()) { 2674 data->AppendExternalizedContentsTo(&externalized_contents_);
2690 externalized_shared_contents_.insert(contents);
2691 }
2692 return data; 2675 return data;
2693 } 2676 }
2694 return nullptr; 2677 return nullptr;
2695 } 2678 }
2696 2679
2697 MaybeLocal<Value> Shell::DeserializeValue( 2680 MaybeLocal<Value> Shell::DeserializeValue(
2698 Isolate* isolate, std::unique_ptr<SerializationData> data) { 2681 Isolate* isolate, std::unique_ptr<SerializationData> data) {
2699 Local<Value> value; 2682 Local<Value> value;
2700 Local<Context> context = isolate->GetCurrentContext(); 2683 Local<Context> context = isolate->GetCurrentContext();
2701 Deserializer deserializer(isolate, std::move(data)); 2684 Deserializer deserializer(isolate, std::move(data));
(...skipping 15 matching lines...) Expand all
2717 2700
2718 for (int i = 0; i < workers_copy.length(); ++i) { 2701 for (int i = 0; i < workers_copy.length(); ++i) {
2719 Worker* worker = workers_copy[i]; 2702 Worker* worker = workers_copy[i];
2720 worker->WaitForThread(); 2703 worker->WaitForThread();
2721 delete worker; 2704 delete worker;
2722 } 2705 }
2723 2706
2724 // Now that all workers are terminated, we can re-enable Worker creation. 2707 // Now that all workers are terminated, we can re-enable Worker creation.
2725 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 2708 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2726 allow_new_workers_ = true; 2709 allow_new_workers_ = true;
2727 2710 externalized_contents_.clear();
2728 for (const auto& contents : externalized_shared_contents_) {
2729 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
2730 }
2731 externalized_shared_contents_.clear();
2732 } 2711 }
2733 2712
2734 2713
2735 static void DumpHeapConstants(i::Isolate* isolate) { 2714 static void DumpHeapConstants(i::Isolate* isolate) {
2736 i::Heap* heap = isolate->heap(); 2715 i::Heap* heap = isolate->heap();
2737 2716
2738 // Dump the INSTANCE_TYPES table to the console. 2717 // Dump the INSTANCE_TYPES table to the console.
2739 printf("# List of known V8 instance types.\n"); 2718 printf("# List of known V8 instance types.\n");
2740 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); 2719 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
2741 printf("INSTANCE_TYPES = {\n"); 2720 printf("INSTANCE_TYPES = {\n");
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2949 } 2928 }
2950 2929
2951 } // namespace v8 2930 } // namespace v8
2952 2931
2953 2932
2954 #ifndef GOOGLE3 2933 #ifndef GOOGLE3
2955 int main(int argc, char* argv[]) { 2934 int main(int argc, char* argv[]) {
2956 return v8::Shell::Main(argc, argv); 2935 return v8::Shell::Main(argc, argv);
2957 } 2936 }
2958 #endif 2937 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698