[BigInt] Add ValueBitRShift into DFG
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGDoesGC.cpp
1 /*
2  * Copyright (C) 2014-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGDoesGC.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGClobberize.h"
32 #include "DFGGraph.h"
33 #include "DFGNode.h"
34 #include "Operations.h"
35
36 namespace JSC { namespace DFG {
37
38 bool doesGC(Graph& graph, Node* node)
39 {
40     if (clobbersHeap(graph, node))
41         return true;
42     
43     // Now consider nodes that don't clobber the world but that still may GC. This includes all
44     // nodes. By default, we should assume every node can GC and return true. This includes the
45     // world-clobbering nodes. We should only return false if we have proven that the node cannot
46     // GC. Typical examples of how a node can GC is if the code emitted for the node does any of the
47     // following:
48     //     1. Allocates any objects.
49     //     2. Resolves a rope string, which allocates a string.
50     //     3. Produces a string (which allocates the string) except when we can prove that
51     //        the string will always be one of the pre-allcoated SmallStrings.
52     //     4. Triggers a structure transition (which can allocate a new structure)
53     //        unless it is a known transition between previously allocated structures
54     //        such as between Array types.
55     //     5. Calls to a JS function, which can execute arbitrary code including allocating objects.
56     //     6. Calls operations that uses DeferGC, because it may GC in its destructor.
57
58     switch (node->op()) {
59     case JSConstant:
60     case DoubleConstant:
61     case Int52Constant:
62     case LazyJSConstant:
63     case Identity:
64     case IdentityWithProfile:
65     case GetCallee:
66     case SetCallee:
67     case GetArgumentCountIncludingThis:
68     case SetArgumentCountIncludingThis:
69     case GetRestLength:
70     case GetLocal:
71     case SetLocal:
72     case MovHint:
73     case InitializeEntrypointArguments:
74     case ZombieHint:
75     case ExitOK:
76     case Phantom:
77     case Upsilon:
78     case Phi:
79     case Flush:
80     case PhantomLocal:
81     case SetArgumentDefinitely:
82     case SetArgumentMaybe:
83     case ArithBitNot:
84     case ArithBitAnd:
85     case ArithBitOr:
86     case ArithBitXor:
87     case ArithBitLShift:
88     case ArithBitRShift:
89     case BitURShift:
90     case ValueToInt32:
91     case UInt32ToNumber:
92     case DoubleAsInt32:
93     case ArithAdd:
94     case ArithClz32:
95     case ArithSub:
96     case ArithNegate:
97     case ArithMul:
98     case ArithIMul:
99     case ArithDiv:
100     case ArithMod:
101     case ArithAbs:
102     case ArithMin:
103     case ArithMax:
104     case ArithPow:
105     case ArithSqrt:
106     case ArithRandom:
107     case ArithRound:
108     case ArithFloor:
109     case ArithCeil:
110     case ArithTrunc:
111     case ArithFRound:
112     case ArithUnary:
113     case CheckStructure:
114     case CheckStructureOrEmpty:
115     case CheckStructureImmediate:
116     case GetExecutable:
117     case GetButterfly:
118     case CheckSubClass:
119     case CheckArray:
120     case GetScope:
121     case SkipScope:
122     case GetGlobalObject:
123     case GetGlobalThis:
124     case GetClosureVar:
125     case PutClosureVar:
126     case GetInternalField:
127     case PutInternalField:
128     case GetRegExpObjectLastIndex:
129     case SetRegExpObjectLastIndex:
130     case RecordRegExpCachedResult:
131     case GetGlobalVar:
132     case GetGlobalLexicalVariable:
133     case PutGlobalVariable:
134     case CheckCell:
135     case CheckNotEmpty:
136     case AssertNotEmpty:
137     case CheckStringIdent:
138     case CompareBelow:
139     case CompareBelowEq:
140     case CompareEqPtr:
141     case ProfileControlFlow:
142     case OverridesHasInstance:
143     case IsEmpty:
144     case IsUndefined:
145     case IsUndefinedOrNull:
146     case IsBoolean:
147     case IsNumber:
148     case NumberIsInteger:
149     case IsObject:
150     case IsObjectOrNull:
151     case IsFunction:
152     case IsCellWithType:
153     case IsTypedArrayView:
154     case TypeOf:
155     case LogicalNot:
156     case Jump:
157     case Branch:
158     case EntrySwitch:
159     case CountExecution:
160     case SuperSamplerBegin:
161     case SuperSamplerEnd:
162     case CPUIntrinsic:
163     case NormalizeMapKey:
164     case GetMapBucketHead:
165     case GetMapBucketNext:
166     case LoadKeyFromMapBucket:
167     case LoadValueFromMapBucket:
168     case ExtractValueFromWeakMapGet:
169     case WeakMapGet:
170     case WeakSetAdd:
171     case WeakMapSet:
172     case Unreachable:
173     case ExtractOSREntryLocal:
174     case ExtractCatchLocal:
175     case ClearCatchLocals:
176     case LoopHint:
177     case StoreBarrier:
178     case FencedStoreBarrier:
179     case InvalidationPoint:
180     case NotifyWrite:
181     case CheckInBounds:
182     case ConstantStoragePointer:
183     case Check:
184     case CheckVarargs:
185     case CheckTypeInfoFlags:
186     case MultiGetByOffset:
187     case ValueRep:
188     case DoubleRep:
189     case Int52Rep:
190     case GetGetter:
191     case GetSetter:
192     case GetArrayLength:
193     case GetVectorLength:
194     case StringCharCodeAt:
195     case StringCodePointAt:
196     case GetTypedArrayByteOffset:
197     case GetPrototypeOf:
198     case PutStructure:
199     case GetByOffset:
200     case GetGetterSetterByOffset:
201     case GetEnumerableLength:
202     case FiatInt52:
203     case BooleanToNumber:
204     case CheckBadCell:
205     case BottomValue:
206     case PhantomNewObject:
207     case PhantomNewFunction:
208     case PhantomNewGeneratorFunction:
209     case PhantomNewAsyncFunction:
210     case PhantomNewAsyncGeneratorFunction:
211     case PhantomCreateActivation:
212     case PhantomDirectArguments:
213     case PhantomCreateRest:
214     case PhantomNewArrayWithSpread:
215     case PhantomNewArrayBuffer:
216     case PhantomSpread:
217     case PhantomClonedArguments:
218     case PhantomNewRegexp:
219     case GetMyArgumentByVal:
220     case GetMyArgumentByValOutOfBounds:
221     case ForwardVarargs:
222     case PutHint:
223     case KillStack:
224     case GetStack:
225     case GetFromArguments:
226     case GetArgument:
227     case LogShadowChickenPrologue:
228     case LogShadowChickenTail:
229     case NukeStructureAndSetButterfly:
230     case AtomicsAdd:
231     case AtomicsAnd:
232     case AtomicsCompareExchange:
233     case AtomicsExchange:
234     case AtomicsLoad:
235     case AtomicsOr:
236     case AtomicsStore:
237     case AtomicsSub:
238     case AtomicsXor:
239     case AtomicsIsLockFree:
240     case MatchStructure:
241     case FilterCallLinkStatus:
242     case FilterGetByIdStatus:
243     case FilterPutByIdStatus:
244     case FilterInByIdStatus:
245     case DataViewGetInt:
246     case DataViewGetFloat:
247     case DataViewSet:
248         return false;
249
250 #if !ASSERT_DISABLED
251     case ArrayPush:
252     case ArrayPop:
253     case PushWithScope:
254     case CreateActivation:
255     case CreateDirectArguments:
256     case CreateScopedArguments:
257     case CreateClonedArguments:
258     case Call:
259     case CallEval:
260     case CallForwardVarargs:
261     case CallObjectConstructor:
262     case CallVarargs:
263     case CheckTierUpAndOSREnter:
264     case CheckTierUpAtReturn:
265     case CheckTierUpInLoop:
266     case Construct:
267     case ConstructForwardVarargs:
268     case ConstructVarargs:
269     case DefineDataProperty:
270     case DefineAccessorProperty:
271     case DeleteById:
272     case DeleteByVal:
273     case DirectCall:
274     case DirectConstruct:
275     case DirectTailCall:
276     case DirectTailCallInlinedCaller:
277     case ForceOSRExit:
278     case GetById:
279     case GetByIdDirect:
280     case GetByIdDirectFlush:
281     case GetByIdFlush:
282     case GetByIdWithThis:
283     case GetByValWithThis:
284     case GetDirectPname:
285     case GetDynamicVar:
286     case GetMapBucket:
287     case HasGenericProperty:
288     case HasIndexedProperty:
289     case HasOwnProperty:
290     case HasStructureProperty:
291     case InById:
292     case InByVal:
293     case InstanceOf:
294     case InstanceOfCustom:
295     case LoadVarargs:
296     case NumberToStringWithRadix:
297     case NumberToStringWithValidRadixConstant:
298     case ProfileType:
299     case PutById:
300     case PutByIdDirect:
301     case PutByIdFlush:
302     case PutByIdWithThis:
303     case PutByOffset:
304     case PutByValWithThis:
305     case PutDynamicVar:
306     case PutGetterById:
307     case PutGetterByVal:
308     case PutGetterSetterById:
309     case PutSetterById:
310     case PutSetterByVal:
311     case PutStack:
312     case PutToArguments:
313     case RegExpExec:
314     case RegExpExecNonGlobalOrSticky:
315     case RegExpMatchFast:
316     case RegExpMatchFastGlobal:
317     case RegExpTest:
318     case ResolveScope:
319     case ResolveScopeForHoistingFuncDeclInEval:
320     case Return:
321     case StringCharAt:
322     case TailCall:
323     case TailCallForwardVarargs:
324     case TailCallForwardVarargsInlinedCaller:
325     case TailCallInlinedCaller:
326     case TailCallVarargs:
327     case TailCallVarargsInlinedCaller:
328     case Throw:
329     case ToNumber:
330     case ToObject:
331     case ToPrimitive:
332     case ToThis:
333     case TryGetById:
334     case CreateThis:
335     case CreatePromise:
336     case CreateGenerator:
337     case ObjectCreate:
338     case ObjectKeys:
339     case AllocatePropertyStorage:
340     case ReallocatePropertyStorage:
341     case Arrayify:
342     case ArrayifyToStructure:
343     case NewObject:
344     case NewPromise:
345     case NewGenerator:
346     case NewArray:
347     case NewArrayWithSpread:
348     case Spread:
349     case NewArrayWithSize:
350     case NewArrayBuffer:
351     case NewRegexp:
352     case NewStringObject:
353     case NewSymbol:
354     case MakeRope:
355     case NewFunction:
356     case NewGeneratorFunction:
357     case NewAsyncGeneratorFunction:
358     case NewAsyncFunction:
359     case NewTypedArray:
360     case ThrowStaticError:
361     case GetPropertyEnumerator:
362     case GetEnumeratorStructurePname:
363     case GetEnumeratorGenericPname:
364     case ToIndexString:
365     case MaterializeNewObject:
366     case MaterializeCreateActivation:
367     case SetFunctionName:
368     case StrCat:
369     case StringReplace:
370     case StringReplaceRegExp:
371     case StringSlice:
372     case StringValueOf:
373     case CreateRest:
374     case ToLowerCase:
375     case CallDOMGetter:
376     case CallDOM:
377     case ArraySlice:
378     case ArrayIndexOf:
379     case ParseInt: // We might resolve a rope even though we don't clobber anything.
380     case SetAdd:
381     case MapSet:
382     case ValueBitAnd:
383     case ValueBitOr:
384     case ValueBitXor:
385     case ValueBitLShift:
386     case ValueBitRShift:
387     case ValueAdd:
388     case ValueSub:
389     case ValueMul:
390     case ValueDiv:
391     case ValueMod:
392     case ValuePow:
393     case ValueBitNot:
394     case ValueNegate:
395 #else
396     // See comment at the top for why be default for all nodes should be to
397     // return true.
398     default:
399 #endif
400         return true;
401
402     case CallStringConstructor:
403     case ToString:
404         switch (node->child1().useKind()) {
405         case StringObjectUse:
406         case StringOrStringObjectUse:
407             return false;
408         default:
409             break;
410         }
411         return true;
412
413     case CheckTraps:
414         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=194323
415         ASSERT(Options::usePollingTraps());
416         return true;
417
418     case CompareEq:
419     case CompareLess:
420     case CompareLessEq:
421     case CompareGreater:
422     case CompareGreaterEq:
423         if (node->isBinaryUseKind(Int32Use)
424 #if USE(JSVALUE64)
425             || node->isBinaryUseKind(Int52RepUse)
426 #endif
427             || node->isBinaryUseKind(DoubleRepUse)
428             || node->isBinaryUseKind(StringIdentUse)
429             )
430             return false;
431         if (node->op() == CompareEq) {
432             if (node->isBinaryUseKind(BooleanUse)
433                 || node->isBinaryUseKind(SymbolUse)
434                 || node->isBinaryUseKind(ObjectUse)
435                 || node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) || node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse))
436                 return false;
437         }
438         return true;
439
440     case CompareStrictEq:
441         if (node->isBinaryUseKind(BooleanUse)
442             || node->isBinaryUseKind(Int32Use)
443 #if USE(JSVALUE64)
444             || node->isBinaryUseKind(Int52RepUse)
445 #endif
446             || node->isBinaryUseKind(DoubleRepUse)
447             || node->isBinaryUseKind(SymbolUse)
448             || node->isBinaryUseKind(SymbolUse, UntypedUse)
449             || node->isBinaryUseKind(UntypedUse, SymbolUse)
450             || node->isBinaryUseKind(StringIdentUse)
451             || node->isBinaryUseKind(ObjectUse, UntypedUse) || node->isBinaryUseKind(UntypedUse, ObjectUse)
452             || node->isBinaryUseKind(ObjectUse)
453             || node->isBinaryUseKind(MiscUse, UntypedUse) || node->isBinaryUseKind(UntypedUse, MiscUse)
454             || node->isBinaryUseKind(StringIdentUse, NotStringVarUse) || node->isBinaryUseKind(NotStringVarUse, StringIdentUse))
455             return false;
456         return true;
457
458     case GetIndexedPropertyStorage:
459     case GetByVal:
460         if (node->arrayMode().type() == Array::String)
461             return true;
462         return false;
463
464     case PutByValDirect:
465     case PutByVal:
466     case PutByValAlias:
467         if (!graph.m_plan.isFTL()) {
468             switch (node->arrayMode().modeForPut().type()) {
469             case Array::Int8Array:
470             case Array::Int16Array:
471             case Array::Int32Array:
472             case Array::Uint8Array:
473             case Array::Uint8ClampedArray:
474             case Array::Uint16Array:
475             case Array::Uint32Array:
476                 return true;
477             default:
478                 break;
479             }
480         }
481         return false;
482
483     case MapHash:
484         switch (node->child1().useKind()) {
485         case BooleanUse:
486         case Int32Use:
487         case SymbolUse:
488         case ObjectUse:
489             return false;
490         default:
491             // We might resolve a rope.
492             return true;
493         }
494         
495     case MultiPutByOffset:
496         return node->multiPutByOffsetData().reallocatesStorage();
497
498     case SameValue:
499         if (node->isBinaryUseKind(DoubleRepUse))
500             return false;
501         return true;
502
503     case StringFromCharCode:
504         // FIXME: Should we constant fold this case?
505         // https://bugs.webkit.org/show_bug.cgi?id=194308
506         if (node->child1()->isInt32Constant() && (node->child1()->asUInt32() <= maxSingleCharacterString))
507             return false;
508         return true;
509
510     case Switch:
511         switch (node->switchData()->kind) {
512         case SwitchCell:
513             ASSERT(graph.m_plan.isFTL());
514             FALLTHROUGH;
515         case SwitchImm:
516             return false;
517         case SwitchChar:
518             return true;
519         case SwitchString:
520             if (node->child1().useKind() == StringIdentUse)
521                 return false;
522             ASSERT(node->child1().useKind() == StringUse || node->child1().useKind() == UntypedUse);
523             return true;
524         }
525         RELEASE_ASSERT_NOT_REACHED();
526
527     case LastNodeType:
528         RELEASE_ASSERT_NOT_REACHED();
529     }
530     
531     RELEASE_ASSERT_NOT_REACHED();
532 }
533
534 } } // namespace JSC::DFG
535
536 #endif // ENABLE(DFG_JIT)