[BigInt] Add ValueBitLShift into DFG
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLCapabilities.cpp
1 /*
2  * Copyright (C) 2013-2017 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 "FTLCapabilities.h"
28
29 #if ENABLE(FTL_JIT)
30
31 namespace JSC { namespace FTL {
32
33 using namespace DFG;
34
35 static bool verboseCapabilities()
36 {
37     return verboseCompilationEnabled() || Options::verboseFTLFailure();
38 }
39
40 inline CapabilityLevel canCompile(Node* node)
41 {
42     // NOTE: If we ever have phantom arguments, we can compile them but we cannot
43     // OSR enter.
44     
45     switch (node->op()) {
46     case JSConstant:
47     case LazyJSConstant:
48     case GetLocal:
49     case SetLocal:
50     case PutStack:
51     case KillStack:
52     case GetStack:
53     case MovHint:
54     case ZombieHint:
55     case ExitOK:
56     case Phantom:
57     case Flush:
58     case PhantomLocal:
59     case SetArgumentDefinitely:
60     case SetArgumentMaybe:
61     case Return:
62     case ArithBitNot:
63     case ArithBitAnd:
64     case ArithBitOr:
65     case ArithBitXor:
66     case BitRShift:
67     case ArithBitLShift:
68     case BitURShift:
69     case CheckStructure:
70     case CheckStructureOrEmpty:
71     case DoubleAsInt32:
72     case Arrayify:
73     case ArrayifyToStructure:
74     case PutStructure:
75     case GetButterfly:
76     case NewObject:
77     case NewStringObject:
78     case NewSymbol:
79     case NewArray:
80     case NewArrayWithSpread:
81     case Spread:
82     case NewArrayBuffer:
83     case NewTypedArray:
84     case GetByOffset:
85     case GetGetterSetterByOffset:
86     case GetGetter:
87     case GetSetter:
88     case PutByOffset:
89     case GetGlobalVar:
90     case GetGlobalLexicalVariable:
91     case PutGlobalVariable:
92     case ValueBitAnd:
93     case ValueBitXor:
94     case ValueBitOr:
95     case ValueBitNot:
96     case ValueBitLShift:
97     case ValueNegate:
98     case ValueAdd:
99     case ValueSub:
100     case ValueMul:
101     case ValueDiv:
102     case ValueMod:
103     case ValuePow:
104     case StrCat:
105     case ArithAdd:
106     case ArithClz32:
107     case ArithSub:
108     case ArithMul:
109     case ArithDiv:
110     case ArithMod:
111     case ArithMin:
112     case ArithMax:
113     case ArithAbs:
114     case ArithPow:
115     case ArithRandom:
116     case ArithRound:
117     case ArithFloor:
118     case ArithCeil:
119     case ArithTrunc:
120     case ArithSqrt:
121     case ArithFRound:
122     case ArithNegate:
123     case ArithUnary:
124     case UInt32ToNumber:
125     case Jump:
126     case ForceOSRExit:
127     case Phi:
128     case Upsilon:
129     case ExtractOSREntryLocal:
130     case ExtractCatchLocal:
131     case ClearCatchLocals:
132     case LoopHint:
133     case SkipScope:
134     case GetGlobalObject:
135     case GetGlobalThis:
136     case CreateActivation:
137     case PushWithScope:
138     case NewFunction:
139     case NewGeneratorFunction:
140     case NewAsyncFunction:
141     case NewAsyncGeneratorFunction:
142     case GetClosureVar:
143     case PutClosureVar:
144     case CreateDirectArguments:
145     case CreateScopedArguments:
146     case CreateClonedArguments:
147     case GetFromArguments:
148     case PutToArguments:
149     case GetArgument:
150     case InvalidationPoint:
151     case StringCharAt:
152     case CheckCell:
153     case CheckBadCell:
154     case CheckNotEmpty:
155     case AssertNotEmpty:
156     case CheckStringIdent:
157     case CheckTraps:
158     case StringCharCodeAt:
159     case StringFromCharCode:
160     case AllocatePropertyStorage:
161     case ReallocatePropertyStorage:
162     case NukeStructureAndSetButterfly:
163     case GetTypedArrayByteOffset:
164     case GetPrototypeOf:
165     case NotifyWrite:
166     case StoreBarrier:
167     case FencedStoreBarrier:
168     case Call:
169     case DirectCall:
170     case TailCall:
171     case DirectTailCall:
172     case TailCallInlinedCaller:
173     case DirectTailCallInlinedCaller:
174     case Construct:
175     case DirectConstruct:
176     case CallVarargs:
177     case CallEval:
178     case TailCallVarargs:
179     case TailCallVarargsInlinedCaller:
180     case ConstructVarargs:
181     case CallForwardVarargs:
182     case TailCallForwardVarargs:
183     case TailCallForwardVarargsInlinedCaller:
184     case ConstructForwardVarargs:
185     case LoadVarargs:
186     case ValueToInt32:
187     case Branch:
188     case LogicalNot:
189     case CheckInBounds:
190     case ConstantStoragePointer:
191     case Check:
192     case CheckVarargs:
193     case CheckArray:
194     case CountExecution:
195     case SuperSamplerBegin:
196     case SuperSamplerEnd:
197     case GetExecutable:
198     case GetScope:
199     case GetCallee:
200     case SetCallee:
201     case GetArgumentCountIncludingThis:
202     case SetArgumentCountIncludingThis:
203     case ToNumber:
204     case ToString:
205     case ToObject:
206     case CallObjectConstructor:
207     case CallStringConstructor:
208     case ObjectCreate:
209     case ObjectKeys:
210     case MakeRope:
211     case NewArrayWithSize:
212     case TryGetById:
213     case GetById:
214     case GetByIdFlush:
215     case GetByIdWithThis:
216     case GetByIdDirect:
217     case GetByIdDirectFlush:
218     case ToThis:
219     case MultiGetByOffset:
220     case MultiPutByOffset:
221     case ToPrimitive:
222     case Throw:
223     case ThrowStaticError:
224     case Unreachable:
225     case InByVal:
226     case InById:
227     case HasOwnProperty:
228     case IsCellWithType:
229     case MapHash:
230     case NormalizeMapKey:
231     case GetMapBucket:
232     case GetMapBucketHead:
233     case GetMapBucketNext:
234     case LoadKeyFromMapBucket:
235     case LoadValueFromMapBucket:
236     case ExtractValueFromWeakMapGet:
237     case SetAdd:
238     case MapSet:
239     case WeakMapGet:
240     case WeakSetAdd:
241     case WeakMapSet:
242     case IsEmpty:
243     case IsUndefined:
244     case IsUndefinedOrNull:
245     case IsBoolean:
246     case IsNumber:
247     case NumberIsInteger:
248     case IsObject:
249     case IsObjectOrNull:
250     case IsFunction:
251     case IsTypedArrayView:
252     case CheckTypeInfoFlags:
253     case OverridesHasInstance:
254     case InstanceOf:
255     case InstanceOfCustom:
256     case DoubleRep:
257     case ValueRep:
258     case Int52Rep:
259     case DoubleConstant:
260     case Int52Constant:
261     case BooleanToNumber:
262     case HasGenericProperty:
263     case HasStructureProperty:
264     case HasIndexedProperty:
265     case GetDirectPname:
266     case GetEnumerableLength:
267     case GetIndexedPropertyStorage:
268     case GetPropertyEnumerator:
269     case GetEnumeratorStructurePname:
270     case GetEnumeratorGenericPname:
271     case ToIndexString:
272     case BottomValue:
273     case PhantomNewObject:
274     case PhantomNewFunction:
275     case PhantomNewGeneratorFunction:
276     case PhantomNewAsyncGeneratorFunction:
277     case PhantomNewAsyncFunction:
278     case PhantomCreateActivation:
279     case PhantomNewRegexp:
280     case PutHint:
281     case CheckStructureImmediate:
282     case MaterializeNewObject:
283     case MaterializeCreateActivation:
284     case PhantomDirectArguments:
285     case PhantomCreateRest:
286     case PhantomSpread:
287     case PhantomNewArrayWithSpread:
288     case PhantomNewArrayBuffer:
289     case PhantomClonedArguments:
290     case GetMyArgumentByVal:
291     case GetMyArgumentByValOutOfBounds:
292     case ForwardVarargs:
293     case EntrySwitch:
294     case Switch:
295     case TypeOf:
296     case PutById:
297     case PutByIdDirect:
298     case PutByIdFlush:
299     case PutByIdWithThis:
300     case PutGetterById:
301     case PutSetterById:
302     case PutGetterSetterById:
303     case PutGetterByVal:
304     case PutSetterByVal:
305     case DeleteById:
306     case DeleteByVal:
307     case CreateRest:
308     case GetRestLength:
309     case RegExpExec:
310     case RegExpExecNonGlobalOrSticky:
311     case RegExpTest:
312     case RegExpMatchFast:
313     case RegExpMatchFastGlobal:
314     case NewRegexp:
315     case StringReplace:
316     case StringReplaceRegExp: 
317     case GetRegExpObjectLastIndex:
318     case SetRegExpObjectLastIndex:
319     case RecordRegExpCachedResult:
320     case SetFunctionName:
321     case LogShadowChickenPrologue:
322     case LogShadowChickenTail:
323     case ResolveScope:
324     case ResolveScopeForHoistingFuncDeclInEval:
325     case GetDynamicVar:
326     case PutDynamicVar:
327     case CompareEq:
328     case CompareEqPtr:
329     case CompareLess:
330     case CompareLessEq:
331     case CompareGreater:
332     case CompareGreaterEq:
333     case CompareBelow:
334     case CompareBelowEq:
335     case CompareStrictEq:
336     case SameValue:
337     case DefineDataProperty:
338     case DefineAccessorProperty:
339     case StringValueOf:
340     case StringSlice:
341     case ToLowerCase:
342     case NumberToStringWithRadix:
343     case NumberToStringWithValidRadixConstant:
344     case CheckSubClass:
345     case CallDOM:
346     case CallDOMGetter:
347     case ArraySlice:
348     case ArrayIndexOf:
349     case ArrayPop:
350     case ArrayPush:
351     case ParseInt:
352     case AtomicsAdd:
353     case AtomicsAnd:
354     case AtomicsCompareExchange:
355     case AtomicsExchange:
356     case AtomicsLoad:
357     case AtomicsOr:
358     case AtomicsStore:
359     case AtomicsSub:
360     case AtomicsXor:
361     case AtomicsIsLockFree:
362     case InitializeEntrypointArguments:
363     case CPUIntrinsic:
364     case GetArrayLength:
365     case GetVectorLength:
366     case GetByVal:
367     case GetByValWithThis:
368     case PutByVal:
369     case PutByValAlias:
370     case PutByValDirect:
371     case PutByValWithThis:
372     case MatchStructure:
373     case FilterCallLinkStatus:
374     case FilterGetByIdStatus:
375     case FilterPutByIdStatus:
376     case FilterInByIdStatus:
377     case CreateThis:
378     case DataViewGetInt:
379     case DataViewGetFloat:
380     case DataViewSet:
381         // These are OK.
382         break;
383
384     case Identity:
385         // No backend handles this because it will be optimized out. But we may check
386         // for capabilities before optimization. It would be a deep error to remove this
387         // case because it would prevent us from catching bugs where the FTL backend
388         // pipeline failed to optimize out an Identity.
389         break;
390
391     case IdentityWithProfile:
392     case CheckTierUpInLoop:
393     case CheckTierUpAndOSREnter:
394     case CheckTierUpAtReturn:
395     case FiatInt52:
396     case ArithIMul:
397     case ProfileType:
398     case ProfileControlFlow:
399     case LastNodeType:
400         return CannotCompile;
401     }
402     return CanCompileAndOSREnter;
403 }
404
405 CapabilityLevel canCompile(Graph& graph)
406 {
407     if (graph.m_codeBlock->bytecodeCost() > Options::maximumFTLCandidateBytecodeCost()) {
408         if (verboseCapabilities())
409             dataLog("FTL rejecting ", *graph.m_codeBlock, " because it's too big.\n");
410         return CannotCompile;
411     }
412     
413     if (UNLIKELY(graph.m_codeBlock->ownerExecutable()->neverFTLOptimize())) {
414         if (verboseCapabilities())
415             dataLog("FTL rejecting ", *graph.m_codeBlock, " because it is marked as never FTL compile.\n");
416         return CannotCompile;
417     }
418     
419     CapabilityLevel result = CanCompileAndOSREnter;
420     
421     for (BlockIndex blockIndex = graph.numBlocks(); blockIndex--;) {
422         BasicBlock* block = graph.block(blockIndex);
423         if (!block)
424             continue;
425         
426         // We don't care if we can compile blocks that the CFA hasn't visited.
427         if (!block->cfaHasVisited)
428             continue;
429         
430         for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
431             Node* node = block->at(nodeIndex);
432             
433             for (unsigned childIndex = graph.numChildren(node); childIndex--;) {
434                 Edge edge = graph.child(node, childIndex);
435                 if (!edge)
436                     continue;
437                 switch (edge.useKind()) {
438                 case UntypedUse:
439                 case Int32Use:
440                 case KnownInt32Use:
441                 case Int52RepUse:
442                 case NumberUse:
443                 case RealNumberUse:
444                 case DoubleRepUse:
445                 case DoubleRepRealUse:
446                 case BooleanUse:
447                 case KnownBooleanUse:
448                 case CellUse:
449                 case KnownCellUse:
450                 case CellOrOtherUse:
451                 case ObjectUse:
452                 case ArrayUse:
453                 case FunctionUse:
454                 case ObjectOrOtherUse:
455                 case StringUse:
456                 case StringOrOtherUse:
457                 case KnownStringUse:
458                 case KnownPrimitiveUse:
459                 case StringObjectUse:
460                 case StringOrStringObjectUse:
461                 case SymbolUse:
462                 case BigIntUse:
463                 case MapObjectUse:
464                 case SetObjectUse:
465                 case WeakMapObjectUse:
466                 case WeakSetObjectUse:
467                 case DataViewObjectUse:
468                 case FinalObjectUse:
469                 case RegExpObjectUse:
470                 case ProxyObjectUse:
471                 case DerivedArrayUse:
472                 case NotCellUse:
473                 case OtherUse:
474                 case KnownOtherUse:
475                 case MiscUse:
476                 case StringIdentUse:
477                 case NotStringVarUse:
478                 case NotSymbolUse:
479                 case AnyIntUse:
480                 case DoubleRepAnyIntUse:
481                     // These are OK.
482                     break;
483                 default:
484                     // Don't know how to handle anything else.
485                     if (verboseCapabilities()) {
486                         dataLog("FTL rejecting node in ", *graph.m_codeBlock, " because of bad use kind: ", edge.useKind(), " in node:\n");
487                         graph.dump(WTF::dataFile(), "    ", node);
488                     }
489                     return CannotCompile;
490                 }
491             }
492             
493             switch (canCompile(node)) {
494             case CannotCompile: 
495                 if (verboseCapabilities()) {
496                     dataLog("FTL rejecting node in ", *graph.m_codeBlock, ":\n");
497                     graph.dump(WTF::dataFile(), "    ", node);
498                 }
499                 return CannotCompile;
500                 
501             case CanCompile:
502                 if (result == CanCompileAndOSREnter && verboseCompilationEnabled()) {
503                     dataLog("FTL disabling OSR entry because of node:\n");
504                     graph.dump(WTF::dataFile(), "    ", node);
505                 }
506                 result = CanCompile;
507                 break;
508                 
509             case CanCompileAndOSREnter:
510                 break;
511             }
512             
513             if (node->op() == ForceOSRExit)
514                 break;
515         }
516     }
517     
518     return result;
519 }
520
521 } } // namespace JSC::FTL
522
523 #endif // ENABLE(FTL_JIT)
524