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