2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "FTLCapabilities.h"
31 namespace JSC
{ namespace FTL
{
35 static bool verboseCapabilities()
37 return verboseCompilationEnabled() || Options::verboseFTLFailure();
40 inline CapabilityLevel
canCompile(Node
* node
)
42 // NOTE: If we ever have phantom arguments, we can compile them but we cannot
67 case ArrayifyToStructure
:
74 case GetGetterSetterByOffset
:
99 case CompareEqConstant
:
104 case ExtractOSREntryLocal
:
107 case CreateActivation
:
111 case CreateDirectArguments
:
112 case CreateScopedArguments
:
113 case CreateClonedArguments
:
114 case GetFromArguments
:
116 case InvalidationPoint
:
121 case StringCharCodeAt
:
122 case AllocatePropertyStorage
:
123 case ReallocatePropertyStorage
:
124 case GetTypedArrayByteOffset
:
130 case CallForwardVarargs
:
131 case ConstructVarargs
:
132 case ConstructForwardVarargs
:
135 case NativeConstruct
:
140 case ConstantStoragePointer
:
146 case GetArgumentCount
:
148 case CallStringConstructor
:
150 case NewArrayWithSize
:
153 case MultiGetByOffset
:
154 case MultiPutByOffset
:
157 case ThrowReferenceError
:
166 case CheckHasInstance
:
173 case BooleanToNumber
:
174 case HasGenericProperty
:
175 case HasStructureProperty
:
177 case GetEnumerableLength
:
178 case GetPropertyEnumerator
:
179 case GetEnumeratorStructurePname
:
180 case GetEnumeratorGenericPname
:
183 case PhantomNewObject
:
184 case PhantomNewFunction
:
185 case PhantomCreateActivation
:
187 case CheckStructureImmediate
:
188 case MaterializeNewObject
:
189 case MaterializeCreateActivation
:
190 case PhantomDirectArguments
:
191 case PhantomClonedArguments
:
192 case GetMyArgumentByVal
:
199 // No backend handles this because it will be optimized out. But we may check
200 // for capabilities before optimization. It would be a deep error to remove this
201 // case because it would prevent us from catching bugs where the FTL backend
202 // pipeline failed to optimize out an Identity.
205 if (node
->child2().useKind() == CellUse
)
207 return CannotCompile
;
210 if (node
->child1().useKind() == CellUse
)
212 return CannotCompile
;
213 case GetIndexedPropertyStorage
:
214 if (node
->arrayMode().type() == Array::String
)
216 if (isTypedView(node
->arrayMode().typedArrayType()))
218 return CannotCompile
;
220 switch (node
->arrayMode().type()) {
223 case Array::Contiguous
:
224 case Array::DirectArguments
:
225 case Array::ScopedArguments
:
228 if (isTypedView(node
->arrayMode().typedArrayType()))
230 return CannotCompile
;
234 switch (node
->arrayMode().type()) {
237 case Array::Contiguous
:
239 case Array::DirectArguments
:
240 case Array::ScopedArguments
:
243 if (isTypedView(node
->arrayMode().typedArrayType()))
245 return CannotCompile
;
248 case HasIndexedProperty
:
249 switch (node
->arrayMode().type()) {
250 case Array::ForceExit
:
253 case Array::Contiguous
:
256 return CannotCompile
;
260 switch (node
->arrayMode().type()) {
261 case Array::ForceExit
:
266 case Array::Contiguous
:
267 case Array::DirectArguments
:
268 case Array::ScopedArguments
:
271 if (isTypedView(node
->arrayMode().typedArrayType()))
272 return CanCompileAndOSREnter
;
273 return CannotCompile
;
279 switch (node
->arrayMode().type()) {
280 case Array::ForceExit
:
284 case Array::Contiguous
:
287 if (isTypedView(node
->arrayMode().typedArrayType()))
288 return CanCompileAndOSREnter
;
289 return CannotCompile
;
294 switch (node
->arrayMode().type()) {
296 case Array::Contiguous
:
300 return CannotCompile
;
304 if (node
->isBinaryUseKind(Int32Use
))
306 if (node
->isBinaryUseKind(Int52RepUse
))
308 if (node
->isBinaryUseKind(DoubleRepUse
))
310 if (node
->isBinaryUseKind(StringIdentUse
))
312 if (node
->isBinaryUseKind(ObjectUse
))
314 if (node
->isBinaryUseKind(UntypedUse
))
316 if (node
->isBinaryUseKind(BooleanUse
))
318 if (node
->isBinaryUseKind(ObjectUse
, ObjectOrOtherUse
))
320 if (node
->isBinaryUseKind(ObjectOrOtherUse
, ObjectUse
))
322 return CannotCompile
;
323 case CompareStrictEq
:
324 if (node
->isBinaryUseKind(Int32Use
))
326 if (node
->isBinaryUseKind(Int52RepUse
))
328 if (node
->isBinaryUseKind(DoubleRepUse
))
330 if (node
->isBinaryUseKind(StringIdentUse
))
332 if (node
->isBinaryUseKind(ObjectUse
, UntypedUse
))
334 if (node
->isBinaryUseKind(UntypedUse
, ObjectUse
))
336 if (node
->isBinaryUseKind(ObjectUse
))
338 if (node
->isBinaryUseKind(BooleanUse
))
340 if (node
->isBinaryUseKind(MiscUse
, UntypedUse
))
342 if (node
->isBinaryUseKind(UntypedUse
, MiscUse
))
344 if (node
->isBinaryUseKind(StringIdentUse
, NotStringVarUse
))
346 if (node
->isBinaryUseKind(NotStringVarUse
, StringIdentUse
))
348 return CannotCompile
;
352 case CompareGreaterEq
:
353 if (node
->isBinaryUseKind(Int32Use
))
355 if (node
->isBinaryUseKind(Int52RepUse
))
357 if (node
->isBinaryUseKind(DoubleRepUse
))
359 if (node
->isBinaryUseKind(UntypedUse
))
361 return CannotCompile
;
363 // Don't know how to handle anything else.
364 return CannotCompile
;
366 return CanCompileAndOSREnter
;
369 CapabilityLevel
canCompile(Graph
& graph
)
371 if (graph
.m_codeBlock
->instructionCount() > Options::maximumFTLCandidateInstructionCount()) {
372 if (verboseCapabilities())
373 dataLog("FTL rejecting ", *graph
.m_codeBlock
, " because it's too big.\n");
374 return CannotCompile
;
377 if (graph
.m_codeBlock
->codeType() != FunctionCode
) {
378 if (verboseCapabilities())
379 dataLog("FTL rejecting ", *graph
.m_codeBlock
, " because it doesn't belong to a function.\n");
380 return CannotCompile
;
383 CapabilityLevel result
= CanCompileAndOSREnter
;
385 for (BlockIndex blockIndex
= graph
.numBlocks(); blockIndex
--;) {
386 BasicBlock
* block
= graph
.block(blockIndex
);
390 // We don't care if we can compile blocks that the CFA hasn't visited.
391 if (!block
->cfaHasVisited
)
394 for (unsigned nodeIndex
= 0; nodeIndex
< block
->size(); ++nodeIndex
) {
395 Node
* node
= block
->at(nodeIndex
);
397 for (unsigned childIndex
= graph
.numChildren(node
); childIndex
--;) {
398 Edge edge
= graph
.child(node
, childIndex
);
401 switch (edge
.useKind()) {
409 case DoubleRepRealUse
:
415 case ObjectOrOtherUse
:
418 case StringObjectUse
:
419 case StringOrStringObjectUse
:
425 case NotStringVarUse
:
427 case DoubleRepMachineIntUse
:
431 // Don't know how to handle anything else.
432 if (verboseCapabilities()) {
433 dataLog("FTL rejecting node in ", *graph
.m_codeBlock
, " because of bad use kind: ", edge
.useKind(), " in node:\n");
434 graph
.dump(WTF::dataFile(), " ", node
);
436 return CannotCompile
;
440 switch (canCompile(node
)) {
442 if (verboseCapabilities()) {
443 dataLog("FTL rejecting node in ", *graph
.m_codeBlock
, ":\n");
444 graph
.dump(WTF::dataFile(), " ", node
);
446 return CannotCompile
;
449 if (result
== CanCompileAndOSREnter
&& verboseCompilationEnabled()) {
450 dataLog("FTL disabling OSR entry because of node:\n");
451 graph
.dump(WTF::dataFile(), " ", node
);
456 case CanCompileAndOSREnter
:
460 if (node
->op() == ForceOSRExit
)
468 } } // namespace JSC::FTL
470 #endif // ENABLE(FTL_JIT)