Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include <stdint.h>
6 : #include <stdlib.h>
7 : #include <string.h>
8 :
9 : #include "src/objects/managed.h"
10 :
11 : #include "src/objects-inl.h"
12 : #include "test/cctest/cctest.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 : class DeleteCounter {
18 : public:
19 40 : explicit DeleteCounter(int* deleted) : deleted_(deleted) { *deleted_ = 0; }
20 40 : ~DeleteCounter() { (*deleted_)++; }
21 5 : static void Deleter(void* arg) {
22 10 : delete reinterpret_cast<DeleteCounter*>(arg);
23 5 : }
24 :
25 : private:
26 : int* deleted_;
27 : };
28 :
29 28342 : TEST(GCCausesDestruction) {
30 5 : Isolate* isolate = CcTest::InitIsolateOnce();
31 5 : int deleted1 = 0;
32 5 : int deleted2 = 0;
33 5 : DeleteCounter* d1 = new DeleteCounter(&deleted1);
34 5 : DeleteCounter* d2 = new DeleteCounter(&deleted2);
35 : {
36 : HandleScope scope(isolate);
37 : auto handle = Managed<DeleteCounter>::FromRawPtr(isolate, 0, d1);
38 : USE(handle);
39 : }
40 :
41 5 : CcTest::CollectAllAvailableGarbage();
42 :
43 5 : CHECK_EQ(1, deleted1);
44 5 : CHECK_EQ(0, deleted2);
45 10 : delete d2;
46 5 : CHECK_EQ(1, deleted2);
47 5 : }
48 :
49 28342 : TEST(DisposeCausesDestruction1) {
50 : v8::Isolate::CreateParams create_params;
51 : create_params.array_buffer_allocator =
52 5 : CcTest::InitIsolateOnce()->array_buffer_allocator();
53 :
54 5 : v8::Isolate* isolate = v8::Isolate::New(create_params);
55 : Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
56 5 : isolate->Enter();
57 5 : int deleted1 = 0;
58 5 : DeleteCounter* d1 = new DeleteCounter(&deleted1);
59 : {
60 : HandleScope scope(i_isolate);
61 5 : auto handle = Managed<DeleteCounter>::FromRawPtr(i_isolate, 0, d1);
62 : USE(handle);
63 : }
64 5 : isolate->Exit();
65 5 : isolate->Dispose();
66 5 : CHECK_EQ(1, deleted1);
67 5 : }
68 :
69 28342 : TEST(DisposeCausesDestruction2) {
70 : v8::Isolate::CreateParams create_params;
71 : create_params.array_buffer_allocator =
72 5 : CcTest::InitIsolateOnce()->array_buffer_allocator();
73 :
74 5 : v8::Isolate* isolate = v8::Isolate::New(create_params);
75 : Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
76 5 : isolate->Enter();
77 5 : int deleted1 = 0;
78 5 : int deleted2 = 0;
79 5 : DeleteCounter* d1 = new DeleteCounter(&deleted1);
80 5 : DeleteCounter* d2 = new DeleteCounter(&deleted2);
81 : {
82 : HandleScope scope(i_isolate);
83 5 : auto handle = Managed<DeleteCounter>::FromRawPtr(i_isolate, 0, d1);
84 : USE(handle);
85 : }
86 : ManagedPtrDestructor* destructor =
87 5 : new ManagedPtrDestructor(0, d2, DeleteCounter::Deleter);
88 5 : i_isolate->RegisterManagedPtrDestructor(destructor);
89 :
90 5 : isolate->Exit();
91 5 : isolate->Dispose();
92 5 : CHECK_EQ(1, deleted1);
93 5 : CHECK_EQ(1, deleted2);
94 5 : }
95 :
96 28342 : TEST(DisposeWithAnotherSharedPtr) {
97 : v8::Isolate::CreateParams create_params;
98 : create_params.array_buffer_allocator =
99 5 : CcTest::InitIsolateOnce()->array_buffer_allocator();
100 :
101 5 : v8::Isolate* isolate = v8::Isolate::New(create_params);
102 : Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
103 5 : isolate->Enter();
104 5 : int deleted1 = 0;
105 5 : DeleteCounter* d1 = new DeleteCounter(&deleted1);
106 : {
107 : std::shared_ptr<DeleteCounter> shared1(d1);
108 : {
109 : HandleScope scope(i_isolate);
110 : auto handle =
111 10 : Managed<DeleteCounter>::FromSharedPtr(i_isolate, 0, shared1);
112 : USE(handle);
113 : }
114 5 : isolate->Exit();
115 5 : isolate->Dispose();
116 5 : CHECK_EQ(0, deleted1);
117 : }
118 : // Should be deleted after the second shared pointer is destroyed.
119 5 : CHECK_EQ(1, deleted1);
120 5 : }
121 :
122 28342 : TEST(DisposeAcrossIsolates) {
123 : v8::Isolate::CreateParams create_params;
124 : create_params.array_buffer_allocator =
125 5 : CcTest::InitIsolateOnce()->array_buffer_allocator();
126 :
127 5 : int deleted = 0;
128 5 : DeleteCounter* delete_counter = new DeleteCounter(&deleted);
129 :
130 5 : v8::Isolate* isolate1 = v8::Isolate::New(create_params);
131 : Isolate* i_isolate1 = reinterpret_cast<i::Isolate*>(isolate1);
132 5 : isolate1->Enter();
133 : {
134 : HandleScope scope1(i_isolate1);
135 : auto handle1 =
136 5 : Managed<DeleteCounter>::FromRawPtr(i_isolate1, 0, delete_counter);
137 :
138 5 : v8::Isolate* isolate2 = v8::Isolate::New(create_params);
139 : Isolate* i_isolate2 = reinterpret_cast<i::Isolate*>(isolate2);
140 5 : isolate2->Enter();
141 : {
142 : HandleScope scope(i_isolate2);
143 : auto handle2 =
144 15 : Managed<DeleteCounter>::FromSharedPtr(i_isolate2, 0, handle1->get());
145 : USE(handle2);
146 : }
147 5 : isolate2->Exit();
148 5 : isolate2->Dispose();
149 5 : CHECK_EQ(0, deleted);
150 : }
151 : // Should be deleted after the first isolate is destroyed.
152 5 : isolate1->Exit();
153 5 : isolate1->Dispose();
154 5 : CHECK_EQ(1, deleted);
155 5 : }
156 :
157 28342 : TEST(CollectAcrossIsolates) {
158 : v8::Isolate::CreateParams create_params;
159 : create_params.array_buffer_allocator =
160 5 : CcTest::InitIsolateOnce()->array_buffer_allocator();
161 :
162 5 : int deleted = 0;
163 5 : DeleteCounter* delete_counter = new DeleteCounter(&deleted);
164 :
165 5 : v8::Isolate* isolate1 = v8::Isolate::New(create_params);
166 : Isolate* i_isolate1 = reinterpret_cast<i::Isolate*>(isolate1);
167 5 : isolate1->Enter();
168 : {
169 : HandleScope scope1(i_isolate1);
170 : auto handle1 =
171 5 : Managed<DeleteCounter>::FromRawPtr(i_isolate1, 0, delete_counter);
172 :
173 5 : v8::Isolate* isolate2 = v8::Isolate::New(create_params);
174 : Isolate* i_isolate2 = reinterpret_cast<i::Isolate*>(isolate2);
175 5 : isolate2->Enter();
176 : {
177 : HandleScope scope(i_isolate2);
178 : auto handle2 =
179 15 : Managed<DeleteCounter>::FromSharedPtr(i_isolate2, 0, handle1->get());
180 : USE(handle2);
181 : }
182 : i_isolate2->heap()->CollectAllAvailableGarbage(
183 5 : i::GarbageCollectionReason::kTesting);
184 5 : CHECK_EQ(0, deleted);
185 5 : isolate2->Exit();
186 5 : isolate2->Dispose();
187 5 : CHECK_EQ(0, deleted);
188 : }
189 : // Should be deleted after the first isolate is destroyed.
190 : i_isolate1->heap()->CollectAllAvailableGarbage(
191 5 : i::GarbageCollectionReason::kTesting);
192 5 : CHECK_EQ(1, deleted);
193 5 : isolate1->Exit();
194 5 : isolate1->Dispose();
195 5 : CHECK_EQ(1, deleted);
196 5 : }
197 :
198 : } // namespace internal
199 85011 : } // namespace v8
|