2 * Copyright (C) 2013, 2014 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
48 case GetMyArgumentsLength
:
66 case StructureTransitionWatchpoint
:
67 case ArrayifyToStructure
:
69 case PhantomPutStructure
:
93 case CompareEqConstant
:
98 case ExtractOSREntryLocal
:
102 case GetClosureRegisters
:
105 case InvalidationPoint
:
108 case StringCharCodeAt
:
109 case AllocatePropertyStorage
:
110 case ReallocatePropertyStorage
:
111 case FunctionReentryWatchpoint
:
112 case TypedArrayWatchpoint
:
113 case GetTypedArrayByteOffset
:
114 case VariableWatchpoint
:
117 case StoreBarrierWithNullCheck
:
124 case ConstantStoragePointer
:
127 case CheckExecutable
:
129 case AllocationProfileWatchpoint
:
130 case CheckArgumentsNotCreated
:
134 case NewArrayWithSize
:
137 case MultiGetByOffset
:
138 case MultiPutByOffset
:
140 case PhantomArguments
:
142 case ThrowReferenceError
:
144 case GetMyArgumentByVal
:
151 case CheckHasInstance
:
158 case BooleanToNumber
:
162 // No backend handles this because it will be optimized out. But we may check
163 // for capabilities before optimization. It would be a deep error to remove this
164 // case because it would prevent us from catching bugs where the FTL backend
165 // pipeline failed to optimize out an Identity.
169 if (node
->child1().useKind() == CellUse
)
171 return CannotCompile
;
172 case GetIndexedPropertyStorage
:
173 if (node
->arrayMode().type() == Array::String
)
175 if (isTypedView(node
->arrayMode().typedArrayType()))
177 return CannotCompile
;
179 switch (node
->arrayMode().type()) {
182 case Array::Contiguous
:
185 if (isTypedView(node
->arrayMode().typedArrayType()))
187 return CannotCompile
;
191 switch (node
->arrayMode().type()) {
194 case Array::Contiguous
:
198 if (isTypedView(node
->arrayMode().typedArrayType()))
200 return CannotCompile
;
204 switch (node
->arrayMode().type()) {
205 case Array::ForceExit
:
210 case Array::Contiguous
:
213 if (isTypedView(node
->arrayMode().typedArrayType()))
214 return CanCompileAndOSREnter
;
215 return CannotCompile
;
221 switch (node
->arrayMode().type()) {
222 case Array::ForceExit
:
226 case Array::Contiguous
:
229 if (isTypedView(node
->arrayMode().typedArrayType()))
230 return CanCompileAndOSREnter
;
231 return CannotCompile
;
236 switch (node
->arrayMode().type()) {
238 case Array::Contiguous
:
242 return CannotCompile
;
246 if (node
->isBinaryUseKind(Int32Use
))
248 if (node
->isBinaryUseKind(Int52RepUse
))
250 if (node
->isBinaryUseKind(DoubleRepUse
))
252 if (node
->isBinaryUseKind(StringIdentUse
))
254 if (node
->isBinaryUseKind(ObjectUse
))
256 if (node
->isBinaryUseKind(UntypedUse
))
258 if (node
->isBinaryUseKind(BooleanUse
))
260 if (node
->isBinaryUseKind(ObjectUse
, ObjectOrOtherUse
))
262 if (node
->isBinaryUseKind(ObjectOrOtherUse
, ObjectUse
))
264 return CannotCompile
;
265 case CompareStrictEq
:
266 if (node
->isBinaryUseKind(Int32Use
))
268 if (node
->isBinaryUseKind(Int52RepUse
))
270 if (node
->isBinaryUseKind(DoubleRepUse
))
272 if (node
->isBinaryUseKind(StringIdentUse
))
274 if (node
->isBinaryUseKind(ObjectUse
))
276 if (node
->isBinaryUseKind(BooleanUse
))
278 if (node
->isBinaryUseKind(MiscUse
, UntypedUse
))
280 if (node
->isBinaryUseKind(UntypedUse
, MiscUse
))
282 if (node
->isBinaryUseKind(StringIdentUse
, NotStringVarUse
))
284 if (node
->isBinaryUseKind(NotStringVarUse
, StringIdentUse
))
286 return CannotCompile
;
290 case CompareGreaterEq
:
291 if (node
->isBinaryUseKind(Int32Use
))
293 if (node
->isBinaryUseKind(Int52RepUse
))
295 if (node
->isBinaryUseKind(DoubleRepUse
))
297 if (node
->isBinaryUseKind(UntypedUse
))
299 return CannotCompile
;
301 switch (node
->switchData()->kind
) {
306 return CannotCompile
;
310 // Don't know how to handle anything else.
311 return CannotCompile
;
313 return CanCompileAndOSREnter
;
316 CapabilityLevel
canCompile(Graph
& graph
)
318 if (graph
.m_codeBlock
->instructionCount() > Options::maximumFTLCandidateInstructionCount()) {
319 if (verboseCapabilities())
320 dataLog("FTL rejecting ", *graph
.m_codeBlock
, " because it's too big.\n");
321 return CannotCompile
;
324 if (graph
.m_codeBlock
->codeType() != FunctionCode
) {
325 if (verboseCapabilities())
326 dataLog("FTL rejecting ", *graph
.m_codeBlock
, " because it doesn't belong to a function.\n");
327 return CannotCompile
;
330 if (graph
.m_codeBlock
->needsActivation()) {
331 // Need this because although we also don't support
332 // CreateActivation/TearOffActivation, we might not see those nodes in case of
334 // FIXME: Support activations.
335 // https://bugs.webkit.org/show_bug.cgi?id=129576
336 if (verboseCapabilities())
337 dataLog("FTL rejecting ", *graph
.m_codeBlock
, " because it uses activations.\n");
338 return CannotCompile
;
341 CapabilityLevel result
= CanCompileAndOSREnter
;
343 for (BlockIndex blockIndex
= graph
.numBlocks(); blockIndex
--;) {
344 BasicBlock
* block
= graph
.block(blockIndex
);
348 // We don't care if we can compile blocks that the CFA hasn't visited.
349 if (!block
->cfaHasVisited
)
352 for (unsigned nodeIndex
= 0; nodeIndex
< block
->size(); ++nodeIndex
) {
353 Node
* node
= block
->at(nodeIndex
);
355 for (unsigned childIndex
= graph
.numChildren(node
); childIndex
--;) {
356 Edge edge
= graph
.child(node
, childIndex
);
359 switch (edge
.useKind()) {
366 case DoubleRepRealUse
:
371 case ObjectOrOtherUse
:
374 case StringObjectUse
:
375 case StringOrStringObjectUse
:
381 case NotStringVarUse
:
383 case DoubleRepMachineIntUse
:
387 // Don't know how to handle anything else.
388 if (verboseCapabilities()) {
389 dataLog("FTL rejecting node in ", *graph
.m_codeBlock
, " because of bad use kind: ", edge
.useKind(), " in node:\n");
390 graph
.dump(WTF::dataFile(), " ", node
);
392 return CannotCompile
;
396 switch (canCompile(node
)) {
398 if (verboseCapabilities()) {
399 dataLog("FTL rejecting node in ", *graph
.m_codeBlock
, ":\n");
400 graph
.dump(WTF::dataFile(), " ", node
);
402 return CannotCompile
;
405 if (result
== CanCompileAndOSREnter
&& verboseCompilationEnabled()) {
406 dataLog("FTL disabling OSR entry because of node:\n");
407 graph
.dump(WTF::dataFile(), " ", node
);
412 case CanCompileAndOSREnter
:
416 if (node
->op() == ForceOSRExit
)
424 } } // namespace JSC::FTL
426 #endif // ENABLE(FTL_JIT)