• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 "src/execution/isolate.h"
6 #include "src/handles/handles-inl.h"
7 #include "src/handles/handles.h"
8 #include "src/heap/local-heap.h"
9 #include "src/objects/foreign-inl.h"
10 #include "src/objects/managed.h"
11 #include "src/objects/maybe-object.h"
12 #include "src/objects/object-macros.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // ------- Test simple argument evaluation order problems ---------
18 
Safepoint()19 void Safepoint() { LocalHeap::Current()->Safepoint(); }
20 
CauseGC(Handle<Object> obj,Isolate * isolate)21 Handle<Object> CauseGC(Handle<Object> obj, Isolate* isolate) {
22   isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
23 
24   return obj;
25 }
26 
CauseGCRaw(Object obj,Isolate * isolate)27 Object CauseGCRaw(Object obj, Isolate* isolate) {
28   isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
29 
30   return obj;
31 }
32 
CauseGCManaged(int i,Isolate * isolate)33 Managed<Smi> CauseGCManaged(int i, Isolate* isolate) {
34   isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
35 
36   return Managed<Smi>::cast(Smi::FromInt(i));
37 }
38 
TwoArgumentsFunction(Object a,Object b)39 void TwoArgumentsFunction(Object a, Object b) {
40   a.Print();
41   b.Print();
42 }
43 
TestTwoArguments(Isolate * isolate)44 void TestTwoArguments(Isolate* isolate) {
45   Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
46   Handle<JSObject> obj2 = isolate->factory()->NewJSObjectWithNullProto();
47   // Should cause warning.
48   TwoArgumentsFunction(*CauseGC(obj1, isolate), *CauseGC(obj2, isolate));
49 }
50 
TwoSizeTArgumentsFunction(size_t a,size_t b)51 void TwoSizeTArgumentsFunction(size_t a, size_t b) {
52   USE(a);
53   USE(b);
54 }
55 
TestTwoSizeTArguments(Isolate * isolate)56 void TestTwoSizeTArguments(Isolate* isolate) {
57   Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
58   Handle<JSObject> obj2 = isolate->factory()->NewJSObjectWithNullProto();
59   // Should cause warning.
60   TwoSizeTArgumentsFunction(sizeof(*CauseGC(obj1, isolate)),
61                             sizeof(*CauseGC(obj2, isolate)));
62 }
63 
64 // --------- Test problems with method arguments ----------
65 
66 class SomeObject : public Object {
67  public:
Method(Object a)68   void Method(Object a) { a.Print(); }
69 
operator =(const Object & b)70   SomeObject& operator=(const Object& b) {
71     this->Print();
72     return *this;
73   }
74 
75   DECL_CAST(SomeObject)
76 
77   OBJECT_CONSTRUCTORS(SomeObject, Object);
78 };
79 
TestMethodCall(Isolate * isolate)80 void TestMethodCall(Isolate* isolate) {
81   SomeObject obj;
82   Handle<SomeObject> so = handle(obj, isolate);
83   Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
84   // Should cause warning.
85   so->Method(*CauseGC(obj1, isolate));
86   // Should cause warning.
87   so->Method(CauseGCRaw(*obj1, isolate));
88 }
89 
TestOperatorCall(Isolate * isolate)90 void TestOperatorCall(Isolate* isolate) {
91   SomeObject obj;
92   Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
93   // Should not cause warning.
94   obj = *CauseGC(obj1, isolate);
95 }
96 
97 // --------- Test for templated sub-classes of Object ----------
98 
TestFollowingTemplates(Isolate * isolate)99 void TestFollowingTemplates(Isolate* isolate) {
100   // Should cause warning.
101   CauseGCManaged(42, isolate);
102 }
103 
104 // --------- Test for correctly resolving virtual methods ----------
105 
106 class BaseObject {
107  public:
VirtualCauseGC(Handle<Object> obj,Isolate * isolate)108   virtual Handle<Object> VirtualCauseGC(Handle<Object> obj, Isolate* isolate) {
109     return obj;
110   }
111 };
112 
113 class DerivedObject : public BaseObject {
114  public:
VirtualCauseGC(Handle<Object> obj,Isolate * isolate)115   Handle<Object> VirtualCauseGC(Handle<Object> obj, Isolate* isolate) override {
116     isolate->heap()->CollectGarbage(OLD_SPACE,
117                                     GarbageCollectionReason::kTesting);
118 
119     return obj;
120   }
121 };
122 
TestFollowingVirtualFunctions(Isolate * isolate)123 void TestFollowingVirtualFunctions(Isolate* isolate) {
124   DerivedObject derived;
125   BaseObject* base = &derived;
126   Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
127 
128   SomeObject so;
129   Handle<SomeObject> so_handle = handle(so, isolate);
130   // Should cause warning.
131   so_handle->Method(*derived.VirtualCauseGC(obj1, isolate));
132   // Should cause warning.
133   so_handle->Method(*base->VirtualCauseGC(obj1, isolate));
134 }
135 
136 // --------- Test for correctly resolving static methods ----------
137 
138 class SomeClass {
139  public:
StaticCauseGC(Handle<Object> obj,Isolate * isolate)140   static Handle<Object> StaticCauseGC(Handle<Object> obj, Isolate* isolate) {
141     isolate->heap()->CollectGarbage(OLD_SPACE,
142                                     GarbageCollectionReason::kTesting);
143 
144     return obj;
145   }
146 };
147 
TestFollowingStaticFunctions(Isolate * isolate)148 void TestFollowingStaticFunctions(Isolate* isolate) {
149   SomeObject so;
150   Handle<SomeObject> so_handle = handle(so, isolate);
151 
152   Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
153   // Should cause warning.
154   so_handle->Method(*SomeClass::StaticCauseGC(obj1, isolate));
155 }
156 
157 // --------- Test basic dead variable analysis ----------
158 
TestDeadVarAnalysis(Isolate * isolate)159 void TestDeadVarAnalysis(Isolate* isolate) {
160   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
161   CauseGCRaw(raw_obj, isolate);
162 
163   // Should cause warning.
164   raw_obj.Print();
165 }
166 
TestDeadVarBecauseOfSafepointAnalysis(Isolate * isolate)167 void TestDeadVarBecauseOfSafepointAnalysis(Isolate* isolate) {
168   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
169   Safepoint();
170 
171   // Should cause warning.
172   raw_obj.Print();
173 }
174 
TestGuardedDeadVarAnalysis(Isolate * isolate)175 void TestGuardedDeadVarAnalysis(Isolate* isolate) {
176   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
177 
178   // Note: having DisableGCMole with the same function as CauseGC
179   // normally doesn't make sense, but we want to test whether the guards
180   // are recognized by GCMole.
181   DisableGCMole no_gc_mole;
182   CauseGCRaw(raw_obj, isolate);
183 
184   // Shouldn't cause warning.
185   raw_obj.Print();
186 }
187 
TestGuardedDeadVarAnalysis2(Isolate * isolate)188 void TestGuardedDeadVarAnalysis2(Isolate* isolate) {
189   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
190 
191   // Note: having DisallowGarbageCollection with the same function as CauseGC
192   // normally doesn't make sense, but we want to test whether the guards
193   // are recognized by GCMole.
194   DisallowGarbageCollection no_gc;
195   CauseGCRaw(raw_obj, isolate);
196 
197   // Should cause warning.
198   raw_obj.Print();
199 }
200 
TestGuardedAgainstSafepointDeadVarAnalysis(Isolate * isolate)201 void TestGuardedAgainstSafepointDeadVarAnalysis(Isolate* isolate) {
202   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
203 
204   // Note: having DisableGCMole with the same function as CauseGC
205   // normally doesn't make sense, but we want to test whether the guards
206   // are recognized by GCMole.
207   DisableGCMole no_gc_mole;
208   Safepoint();
209 
210   // Shouldn't cause warning.
211   raw_obj.Print();
212 }
213 
TestGuardedAgainstSafepointDeadVarAnalysis2(Isolate * isolate)214 void TestGuardedAgainstSafepointDeadVarAnalysis2(Isolate* isolate) {
215   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
216 
217   // Note: having DisallowGarbageCollection with the same function as CauseGC
218   // normally doesn't make sense, but we want to test whether the guards
219   // are recognized by GCMole.
220   DisallowGarbageCollection no_gc;
221   Safepoint();
222 
223   // Should cause warning.
224   raw_obj.Print();
225 }
226 
TestGuardedAgainstSafepointDeadVarAnalysis3(Isolate * isolate)227 void TestGuardedAgainstSafepointDeadVarAnalysis3(Isolate* isolate) {
228   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
229   // Note: having DisallowGarbageCollection with the same function as CauseGC
230   // normally doesn't make sense, but we want to test whether the guards
231   // are recognized by GCMole.
232   DisallowGarbageCollection no_gc;
233   Safepoint();
234   // Should cause warning.
235   raw_obj.Print();
236   {
237     DisableGCMole no_gc_mole;
238     // Shouldn't cause warning.
239     raw_obj.Print();
240   }
241   // Should cause warning.
242   raw_obj.Print();
243 }
244 
TestOnlyHeapGuardedDeadVarAnalysisInCompound(Isolate * isolate)245 void TestOnlyHeapGuardedDeadVarAnalysisInCompound(Isolate* isolate) {
246   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
247   // {DisallowHeapAccess} has a {DisallowHeapAllocation}, but no
248   // {DisallowSafepoints}, so it could see objects move due to safepoints.
249   DisallowHeapAccess no_gc;
250   CauseGCRaw(raw_obj, isolate);
251   // Should cause warning.
252   raw_obj.Print();
253 }
254 
TestOnlyHeapGuardedDeadVarAnalysisInCompound2(Isolate * isolate)255 void TestOnlyHeapGuardedDeadVarAnalysisInCompound2(Isolate* isolate) {
256   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
257   // {DisallowHeapAccess} has a {DisallowHeapAllocation}, but no
258   // {DisallowSafepoints}, so it could see objects move due to safepoints.
259   DisallowHeapAccess no_gc;
260   CauseGCRaw(raw_obj, isolate);
261   // Should cause warning.
262   raw_obj.Print();
263   DisableGCMole no_gc_mole;
264   // Should cause warning.
265   raw_obj.Print();
266 }
267 
TestGuardedDeadVarAnalysisNested(JSObject raw_obj,Isolate * isolate)268 void TestGuardedDeadVarAnalysisNested(JSObject raw_obj, Isolate* isolate) {
269   CauseGCRaw(raw_obj, isolate);
270   // Should cause warning.
271   raw_obj.Print();
272 }
273 
TestGuardedDeadVarAnalysisCaller(Isolate * isolate)274 void TestGuardedDeadVarAnalysisCaller(Isolate* isolate) {
275   DisableGCMole no_gc_mole;
276   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
277   TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
278   // Shouldn't cause warning.
279   raw_obj.Print();
280 }
281 
TestGuardedDeadVarAnalysisCaller2(Isolate * isolate)282 void TestGuardedDeadVarAnalysisCaller2(Isolate* isolate) {
283   DisallowGarbageCollection no_gc;
284   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
285   TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
286   // Should cause warning.
287   raw_obj.Print();
288 }
289 
TestGuardedDeadVarAnalysisCaller3(Isolate * isolate)290 void TestGuardedDeadVarAnalysisCaller3(Isolate* isolate) {
291   DisallowHeapAccess no_gc;
292   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
293   TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
294   // Should cause warning.
295   raw_obj.Print();
296 }
297 
TestGuardedDeadVarAnalysisCaller4(Isolate * isolate)298 void TestGuardedDeadVarAnalysisCaller4(Isolate* isolate) {
299   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
300   TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
301   // Should cause warning.
302   raw_obj.Print();
303 }
304 
GuardedAllocation(Isolate * isolate)305 JSObject GuardedAllocation(Isolate* isolate) {
306   DisallowGarbageCollection no_gc;
307   return *isolate->factory()->NewJSObjectWithNullProto();
308 }
309 
GuardedAllocation2(Isolate * isolate)310 JSObject GuardedAllocation2(Isolate* isolate) {
311   DisableGCMole no_gc_mole;
312   return *isolate->factory()->NewJSObjectWithNullProto();
313 }
314 
TestNestedDeadVarAnalysis(Isolate * isolate)315 void TestNestedDeadVarAnalysis(Isolate* isolate) {
316   JSObject raw_obj = GuardedAllocation(isolate);
317   CauseGCRaw(raw_obj, isolate);
318   // Should cause warning.
319   raw_obj.Print();
320 }
321 
TestNestedDeadVarAnalysis2(Isolate * isolate)322 void TestNestedDeadVarAnalysis2(Isolate* isolate) {
323   DisableGCMole no_gc_mole;
324   JSObject raw_obj = GuardedAllocation(isolate);
325   CauseGCRaw(raw_obj, isolate);
326   // Shouldn't cause warning.
327   raw_obj.Print();
328 }
329 
330 // Test that putting a guard in the middle of the function doesn't
331 // mistakenly cover the whole scope of the raw variable.
TestGuardedDeadVarAnalysisMidFunction(Isolate * isolate)332 void TestGuardedDeadVarAnalysisMidFunction(Isolate* isolate) {
333   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
334   CauseGCRaw(raw_obj, isolate);
335   // Guarding the rest of the function from triggering a GC.
336   DisallowGarbageCollection no_gc;
337   // Should cause warning.
338   raw_obj.Print();
339 }
340 
341 // Test that putting a guard in the middle of the function doesn't
342 // mistakenly cover the whole scope of the raw variable.
TestGuardedDeadVarAnalysisMidFunction2(Isolate * isolate)343 void TestGuardedDeadVarAnalysisMidFunction2(Isolate* isolate) {
344   JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
345   CauseGCRaw(raw_obj, isolate);
346   // Guarding the rest of the function from triggering a GC.
347   DisableGCMole no_gc_mole;
348   // Should cause warning.
349   raw_obj.Print();
350 }
351 
352 }  // namespace internal
353 }  // namespace v8
354