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 "DFGBackwardsPropagationPhase.h"
31 #include "DFGBasicBlockInlines.h"
34 #include "JSCInlines.h"
36 namespace JSC
{ namespace DFG
{
38 class BackwardsPropagationPhase
: public Phase
{
40 BackwardsPropagationPhase(Graph
& graph
)
41 : Phase(graph
, "backwards propagation")
50 for (BlockIndex blockIndex
= m_graph
.numBlocks(); blockIndex
--;) {
51 BasicBlock
* block
= m_graph
.block(blockIndex
);
55 // Prevent a tower of overflowing additions from creating a value that is out of the
57 m_allowNestedOverflowingAdditions
= block
->size() < (1 << 16);
59 for (unsigned indexInBlock
= block
->size(); indexInBlock
--;)
60 propagate(block
->at(indexInBlock
));
68 bool isNotNegZero(Node
* node
)
70 if (!m_graph
.isNumberConstant(node
))
72 double value
= m_graph
.valueOfNumberConstant(node
);
73 return (value
|| 1.0 / value
> 0.0);
76 bool isNotPosZero(Node
* node
)
78 if (!m_graph
.isNumberConstant(node
))
80 double value
= m_graph
.valueOfNumberConstant(node
);
81 return (value
|| 1.0 / value
< 0.0);
84 // Tests if the absolute value is strictly less than the power of two.
86 bool isWithinPowerOfTwoForConstant(Node
* node
)
88 JSValue immediateValue
= node
->valueOfJSConstant(codeBlock());
89 if (!immediateValue
.isNumber())
91 double immediate
= immediateValue
.asNumber();
92 return immediate
> -(static_cast<int64_t>(1) << power
) && immediate
< (static_cast<int64_t>(1) << power
);
96 bool isWithinPowerOfTwoNonRecursive(Node
* node
)
98 if (node
->op() != JSConstant
)
100 return isWithinPowerOfTwoForConstant
<power
>(node
);
104 bool isWithinPowerOfTwo(Node
* node
)
106 switch (node
->op()) {
108 return isWithinPowerOfTwoForConstant
<power
>(node
);
115 return isWithinPowerOfTwoNonRecursive
<power
>(node
->child1().node())
116 || isWithinPowerOfTwoNonRecursive
<power
>(node
->child2().node());
130 Node
* shiftAmount
= node
->child2().node();
131 if (shiftAmount
->op() != JSConstant
)
133 JSValue immediateValue
= shiftAmount
->valueOfJSConstant(codeBlock());
134 if (!immediateValue
.isInt32())
136 return immediateValue
.asInt32() > 32 - power
;
145 bool isWithinPowerOfTwo(Edge edge
)
147 return isWithinPowerOfTwo
<power
>(edge
.node());
150 bool mergeDefaultFlags(Node
* node
)
152 bool changed
= false;
153 if (node
->flags() & NodeHasVarArgs
) {
154 for (unsigned childIdx
= node
->firstChild();
155 childIdx
< node
->firstChild() + node
->numChildren();
157 if (!!m_graph
.m_varArgChildren
[childIdx
])
158 changed
|= m_graph
.m_varArgChildren
[childIdx
]->mergeFlags(NodeBytecodeUsesAsValue
);
163 changed
|= node
->child1()->mergeFlags(NodeBytecodeUsesAsValue
);
166 changed
|= node
->child2()->mergeFlags(NodeBytecodeUsesAsValue
);
169 changed
|= node
->child3()->mergeFlags(NodeBytecodeUsesAsValue
);
174 void propagate(Node
* node
)
176 NodeFlags flags
= node
->flags() & NodeBytecodeBackPropMask
;
178 switch (node
->op()) {
180 VariableAccessData
* variableAccessData
= node
->variableAccessData();
181 flags
&= ~NodeBytecodeUsesAsInt
; // We don't care about cross-block uses-as-int.
182 m_changed
|= variableAccessData
->mergeFlags(flags
);
187 VariableAccessData
* variableAccessData
= node
->variableAccessData();
188 if (!variableAccessData
->isLoadedFrom())
190 flags
= variableAccessData
->flags();
191 RELEASE_ASSERT(!(flags
& ~NodeBytecodeBackPropMask
));
192 flags
|= NodeBytecodeUsesAsNumber
; // Account for the fact that control flow may cause overflows that our modeling can't handle.
193 node
->child1()->mergeFlags(flags
);
198 VariableAccessData
* variableAccessData
= node
->variableAccessData();
199 m_changed
|= variableAccessData
->mergeFlags(NodeBytecodeUsesAsValue
);
214 flags
|= NodeBytecodeUsesAsInt
;
215 flags
&= ~(NodeBytecodeUsesAsNumber
| NodeBytecodeNeedsNegZero
| NodeBytecodeUsesAsOther
);
216 flags
&= ~NodeBytecodeUsesAsArrayIndex
;
217 node
->child1()->mergeFlags(flags
);
218 node
->child2()->mergeFlags(flags
);
222 case StringCharCodeAt
: {
223 node
->child1()->mergeFlags(NodeBytecodeUsesAsValue
);
224 node
->child2()->mergeFlags(NodeBytecodeUsesAsValue
| NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsArrayIndex
);
228 case UInt32ToNumber
: {
229 node
->child1()->mergeFlags(flags
);
234 if (isNotNegZero(node
->child1().node()) || isNotNegZero(node
->child2().node()))
235 flags
&= ~NodeBytecodeNeedsNegZero
;
236 if (node
->child1()->hasNumberResult() || node
->child2()->hasNumberResult())
237 flags
&= ~NodeBytecodeUsesAsOther
;
238 if (!isWithinPowerOfTwo
<32>(node
->child1()) && !isWithinPowerOfTwo
<32>(node
->child2()))
239 flags
|= NodeBytecodeUsesAsNumber
;
240 if (!m_allowNestedOverflowingAdditions
)
241 flags
|= NodeBytecodeUsesAsNumber
;
243 node
->child1()->mergeFlags(flags
);
244 node
->child2()->mergeFlags(flags
);
249 if (isNotNegZero(node
->child1().node()) || isNotNegZero(node
->child2().node()))
250 flags
&= ~NodeBytecodeNeedsNegZero
;
251 if (!isWithinPowerOfTwo
<32>(node
->child1()) && !isWithinPowerOfTwo
<32>(node
->child2()))
252 flags
|= NodeBytecodeUsesAsNumber
;
253 if (!m_allowNestedOverflowingAdditions
)
254 flags
|= NodeBytecodeUsesAsNumber
;
256 node
->child1()->mergeFlags(flags
);
257 node
->child2()->mergeFlags(flags
);
262 if (isNotNegZero(node
->child1().node()) || isNotPosZero(node
->child2().node()))
263 flags
&= ~NodeBytecodeNeedsNegZero
;
264 if (!isWithinPowerOfTwo
<32>(node
->child1()) && !isWithinPowerOfTwo
<32>(node
->child2()))
265 flags
|= NodeBytecodeUsesAsNumber
;
266 if (!m_allowNestedOverflowingAdditions
)
267 flags
|= NodeBytecodeUsesAsNumber
;
269 node
->child1()->mergeFlags(flags
);
270 node
->child2()->mergeFlags(flags
);
275 flags
&= ~NodeBytecodeUsesAsOther
;
277 node
->child1()->mergeFlags(flags
);
282 // As soon as a multiply happens, we can easily end up in the part
283 // of the double domain where the point at which you do truncation
284 // can change the outcome. So, ArithMul always forces its inputs to
285 // check for overflow. Additionally, it will have to check for overflow
286 // itself unless we can prove that there is no way for the values
287 // produced to cause double rounding.
289 if (!isWithinPowerOfTwo
<22>(node
->child1().node())
290 && !isWithinPowerOfTwo
<22>(node
->child2().node()))
291 flags
|= NodeBytecodeUsesAsNumber
;
293 node
->mergeFlags(flags
);
295 flags
|= NodeBytecodeUsesAsNumber
| NodeBytecodeNeedsNegZero
;
296 flags
&= ~NodeBytecodeUsesAsOther
;
298 node
->child1()->mergeFlags(flags
);
299 node
->child2()->mergeFlags(flags
);
304 flags
|= NodeBytecodeUsesAsNumber
| NodeBytecodeNeedsNegZero
;
305 flags
&= ~NodeBytecodeUsesAsOther
;
307 node
->child1()->mergeFlags(flags
);
308 node
->child2()->mergeFlags(flags
);
313 flags
|= NodeBytecodeUsesAsNumber
| NodeBytecodeNeedsNegZero
;
314 flags
&= ~NodeBytecodeUsesAsOther
;
316 node
->child1()->mergeFlags(flags
);
317 node
->child2()->mergeFlags(flags
);
322 node
->child1()->mergeFlags(NodeBytecodeUsesAsValue
);
323 node
->child2()->mergeFlags(NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsOther
| NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsArrayIndex
);
327 case GetMyArgumentByValSafe
: {
328 node
->child1()->mergeFlags(NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsOther
| NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsArrayIndex
);
332 case NewArrayWithSize
: {
333 node
->child1()->mergeFlags(NodeBytecodeUsesAsValue
| NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsArrayIndex
);
337 case NewTypedArray
: {
338 // Negative zero is not observable. NaN versus undefined are only observable
339 // in that you would get a different exception message. So, like, whatever: we
340 // claim here that NaN v. undefined is observable.
341 node
->child1()->mergeFlags(NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsOther
| NodeBytecodeUsesAsArrayIndex
);
346 node
->child1()->mergeFlags(NodeBytecodeUsesAsValue
);
347 node
->child2()->mergeFlags(NodeBytecodeUsesAsValue
| NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsArrayIndex
);
352 node
->child1()->mergeFlags(NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsOther
);
357 node
->child1()->mergeFlags(flags
);
363 m_graph
.varArgChild(node
, 0)->mergeFlags(NodeBytecodeUsesAsValue
);
364 m_graph
.varArgChild(node
, 1)->mergeFlags(NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsOther
| NodeBytecodeUsesAsInt
| NodeBytecodeUsesAsArrayIndex
);
365 m_graph
.varArgChild(node
, 2)->mergeFlags(NodeBytecodeUsesAsValue
);
370 SwitchData
* data
= node
->switchData();
371 switch (data
->kind
) {
373 // We don't need NodeBytecodeNeedsNegZero because if the cases are all integers
374 // then -0 and 0 are treated the same. We don't need NodeBytecodeUsesAsOther
375 // because if all of the cases are integers then NaN and undefined are
376 // treated the same (i.e. they will take default).
377 node
->child1()->mergeFlags(NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsInt
);
380 // We don't need NodeBytecodeNeedsNegZero because if the cases are all strings
381 // then -0 and 0 are treated the same. We don't need NodeBytecodeUsesAsOther
382 // because if all of the cases are single-character strings then NaN
383 // and undefined are treated the same (i.e. they will take default).
384 node
->child1()->mergeFlags(NodeBytecodeUsesAsNumber
);
388 // We don't need NodeBytecodeNeedsNegZero because if the cases are all strings
389 // then -0 and 0 are treated the same.
390 node
->child1()->mergeFlags(NodeBytecodeUsesAsNumber
| NodeBytecodeUsesAsOther
);
397 // This would be trivial to handle but we just assert that we cannot see these yet.
398 RELEASE_ASSERT_NOT_REACHED();
401 // Note: ArithSqrt, ArithSin, and ArithCos and other math intrinsics don't have special
402 // rules in here because they are always followed by Phantoms to signify that if the
403 // method call speculation fails, the bytecode may use the arguments in arbitrary ways.
404 // This corresponds to that possibility of someone doing something like:
405 // Math.sin = function(x) { doArbitraryThingsTo(x); }
408 mergeDefaultFlags(node
);
413 bool m_allowNestedOverflowingAdditions
;
417 bool performBackwardsPropagation(Graph
& graph
)
419 SamplingRegion
samplingRegion("DFG Backwards Propagation Phase");
420 return runPhase
<BackwardsPropagationPhase
>(graph
);
423 } } // namespace JSC::DFG
425 #endif // ENABLE(DFG_JIT)