Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (183400 => 183401)
--- trunk/Source/_javascript_Core/ChangeLog 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-04-27 18:31:26 UTC (rev 183401)
@@ -1,3 +1,84 @@
+2015-04-24 Filip Pizlo <[email protected]>
+
+ Rationalize DFG DCE handling of nodes that perform checks that propagate through AI
+ https://bugs.webkit.org/show_bug.cgi?id=144186
+
+ Reviewed by Geoffrey Garen.
+
+ If I do ArithAdd(Int32Use, Int32Use, CheckOverflow) then AI will prove that this returns
+ Int32. We may later perform code simplifications based on the proof that this is Int32, and
+ we may kill all DFG users of this ArithAdd. Then we may prove that there is no exit site at
+ which the ArithAdd is live. This seems like it is sufficient to then kill the ArithAdd,
+ except that we still need the overflow check!
+
+ Previously we mishandled this:
+
+ - In places where we want the overflow check we need to use MustGenerate(@ArithAdd) as a hack
+ to keep it alive. That's dirty and it's just indicative of a deeper issue.
+
+ - Our MovHint removal doesn't do Phantom canonicalization which essentially makes it
+ powerless. This was sort of hiding the bug.
+
+ - Nodes that have checks that AI leverages should always be NodeMustGenerate. You can't kill
+ something that you are relying on for subsequent simplifications.
+
+ This fixes MovHint removal to also canonicalize Phantoms. This also adds ModeMustGenerate to
+ nodes that may perform checks that are used by AI to guarantee the result type. As a result,
+ we no longer need the weird MustGenerate node.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGArgumentsEliminationPhase.cpp:
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDCEPhase.cpp:
+ (JSC::DFG::DCEPhase::run):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::tryToRelaxRepresentation):
+ * dfg/DFGIntegerCheckCombiningPhase.cpp:
+ (JSC::DFG::IntegerCheckCombiningPhase::handleBlock):
+ (JSC::DFG::IntegerCheckCombiningPhase::insertMustAdd): Deleted.
+ * dfg/DFGMayExit.cpp:
+ (JSC::DFG::mayExit):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::willHaveCodeGenOrOSR):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGObjectAllocationSinkingPhase.cpp:
+ (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
+ * dfg/DFGPhantomCanonicalizationPhase.cpp:
+ (JSC::DFG::PhantomCanonicalizationPhase::run):
+ * dfg/DFGPhantomRemovalPhase.cpp:
+ (JSC::DFG::PhantomRemovalPhase::run):
+ * dfg/DFGPlan.cpp:
+ (JSC::DFG::Plan::compileInThreadImpl):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGTypeCheckHoistingPhase.cpp:
+ (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
+ (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
+ * dfg/DFGVarargsForwardingPhase.cpp:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ * tests/stress/fold-based-on-int32-proof-mul-branch.js: Added.
+ (foo):
+ * tests/stress/fold-based-on-int32-proof-mul.js: Added.
+ (foo):
+ * tests/stress/fold-based-on-int32-proof-or-zero.js: Added.
+ (foo):
+ * tests/stress/fold-based-on-int32-proof.js: Added.
+ (foo):
+
2015-04-26 Ryosuke Niwa <[email protected]>
Class body ending with a semicolon throws a SyntaxError
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-04-27 18:31:26 UTC (rev 183401)
@@ -2080,7 +2080,6 @@
case ProfileType:
case ProfileControlFlow:
case Phantom:
- case MustGenerate:
case CountExecution:
case CheckTierUpInLoop:
case CheckTierUpAtReturn:
Modified: trunk/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -161,7 +161,6 @@
case Phantom:
case Check:
- case MustGenerate:
case MovHint:
case PutHint:
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-04-27 18:31:26 UTC (rev 183401)
@@ -115,7 +115,6 @@
case Identity:
case Phantom:
- case MustGenerate:
case Check:
case ExtractOSREntryLocal:
case CheckStructureImmediate:
Modified: trunk/Source/_javascript_Core/dfg/DFGDCEPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGDCEPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGDCEPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -71,7 +71,7 @@
cleanVariables(m_graph.m_arguments);
}
- // Just do a basic MustGenerate/Phantom/Check clean-up.
+ // Just do a basic Phantom/Check clean-up.
for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
BasicBlock* block = m_graph.block(blockIndex);
if (!block)
@@ -82,7 +82,6 @@
Node* node = block->at(sourceIndex++);
switch (node->op()) {
case Check:
- case MustGenerate:
case Phantom:
if (node->children.isEmpty())
continue;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -55,7 +55,6 @@
case MovHint:
case ZombieHint:
case Phantom:
- case MustGenerate:
case Upsilon:
case Phi:
case Flush:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -1033,7 +1033,6 @@
case ConstantStoragePointer:
case DoubleAsInt32:
case ValueToInt32:
- case MustGenerate: // MustGenerate would be trivial to handle but anyway we assert that we won't see it here yet.
case DoubleRep:
case ValueRep:
case Int52Rep:
@@ -2018,7 +2017,6 @@
case MovHint:
case Phantom:
case Check:
- case MustGenerate:
DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, fixEdgeRepresentation);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGIntegerCheckCombiningPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGIntegerCheckCombiningPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGIntegerCheckCombiningPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -236,12 +236,12 @@
switch (data.m_key.m_kind) {
case Addition: {
if (range.m_minBound < 0) {
- insertMustAdd(
+ insertAdd(
nodeIndex, NodeOrigin(range.m_minOrigin, node->origin.forExit),
data.m_key.m_source, range.m_minBound);
}
if (range.m_maxBound > 0) {
- insertMustAdd(
+ insertAdd(
nodeIndex, NodeOrigin(range.m_maxOrigin, node->origin.forExit),
data.m_key.m_source, range.m_maxBound);
}
@@ -385,15 +385,6 @@
nodeIndex, origin, jsNumber(addend), source.useKind()));
}
- Node* insertMustAdd(
- unsigned nodeIndex, NodeOrigin origin, Edge source, int32_t addend)
- {
- Node* result = insertAdd(nodeIndex, origin, source, addend);
- m_insertionSet.insertNode(
- nodeIndex, SpecNone, MustGenerate, origin, result->defaultEdge());
- return result;
- }
-
typedef std::unordered_map<RangeKey, Range, HashMethod<RangeKey>> RangeMap;
RangeMap m_map;
Modified: trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -85,7 +85,6 @@
case Flush:
case Phantom:
case Check:
- case MustGenerate:
case GetLocal:
case LoopHint:
case Phi:
@@ -105,6 +104,9 @@
case Jump:
case Branch:
case Unreachable:
+ case DoubleRep:
+ case Int52Rep:
+ case ValueRep:
break;
default:
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-04-27 18:31:26 UTC (rev 183401)
@@ -1554,7 +1554,6 @@
case ZombieHint:
return true;
case Phantom:
- case MustGenerate:
return child1().useKindUnchecked() != UntypedUse || child2().useKindUnchecked() != UntypedUse || child3().useKindUnchecked() != UntypedUse;
default:
return shouldGenerate();
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2015-04-27 18:31:26 UTC (rev 183401)
@@ -71,7 +71,6 @@
macro(MovHint, NodeMustGenerate) \
macro(ZombieHint, NodeMustGenerate) \
macro(Phantom, NodeMustGenerate) \
- macro(MustGenerate, NodeMustGenerate) /* Utility node for making soem not-usually-NodeMustGenerate node become like NodeMustGenerate. */ \
macro(Check, NodeMustGenerate) /* Used if we want just a type check but not liveness. Non-checking uses will be removed. */\
macro(Upsilon, NodeRelevantToOSR) \
macro(Phi, NodeRelevantToOSR) \
@@ -130,16 +129,22 @@
/* Bogus type asserting node. Useful for testing, disappears during Fixup. */\
macro(FiatInt52, NodeResultJS) \
\
- /* Nodes for arithmetic operations. */\
- macro(ArithAdd, NodeResultNumber) \
+ /* Nodes for arithmetic operations. Note that if they do checks other than just type checks, */\
+ /* then they are MustGenerate. This is probably stricter than it needs to be - for example */\
+ /* they won't do checks if they are speculated double. Also, we could kill these if we do it */\
+ /* before AI starts eliminating downstream operations based on proofs, for example in the */\
+ /* case of "var tmp = a + b; return (tmp | 0) == tmp;". If a, b are speculated integer then */\
+ /* this is only true if we do the overflow check - hence the need to keep it alive. More */\
+ /* generally, we need to keep alive any operation whose checks cause filtration in AI. */\
+ macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \
macro(ArithClz32, NodeResultInt32) \
- macro(ArithSub, NodeResultNumber) \
- macro(ArithNegate, NodeResultNumber) \
- macro(ArithMul, NodeResultNumber) \
+ macro(ArithSub, NodeResultNumber | NodeMustGenerate) \
+ macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \
+ macro(ArithMul, NodeResultNumber | NodeMustGenerate) \
macro(ArithIMul, NodeResultInt32) \
- macro(ArithDiv, NodeResultNumber) \
- macro(ArithMod, NodeResultNumber) \
- macro(ArithAbs, NodeResultNumber) \
+ macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \
+ macro(ArithMod, NodeResultNumber | NodeMustGenerate) \
+ macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \
macro(ArithMin, NodeResultNumber) \
macro(ArithMax, NodeResultNumber) \
macro(ArithFRound, NodeResultNumber) \
Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -797,7 +797,6 @@
case MovHint:
case Phantom:
case Check:
- case MustGenerate:
case StoreBarrier:
case StoreBarrierWithNullCheck:
case PutHint:
Modified: trunk/Source/_javascript_Core/dfg/DFGPhantomCanonicalizationPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGPhantomCanonicalizationPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGPhantomCanonicalizationPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -38,7 +38,6 @@
namespace JSC { namespace DFG {
static const NodeFlags NodeNeedsPhantom = NodeMiscFlag1;
-static const NodeFlags NodeNeedsMustGenerate = NodeMiscFlag2;
class PhantomCanonicalizationPhase : public Phase {
public:
@@ -51,7 +50,7 @@
{
ASSERT(m_graph.m_form == SSA);
- m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeNeedsMustGenerate | NodeRelevantToOSR);
+ m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeRelevantToOSR);
m_graph.mergeRelevantToOSR();
for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
@@ -63,13 +62,11 @@
unsigned targetIndex = 0;
while (sourceIndex < block->size()) {
Node* node = block->at(sourceIndex++);
- if (node->op() == MustGenerate || node->op() == Phantom || node->op() == Check) {
+ if (node->op() == Phantom || node->op() == Check) {
for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
Edge edge = node->children.child(i);
if (!edge)
break;
- if (node->op() == MustGenerate)
- edge->mergeFlags(NodeNeedsMustGenerate);
if ((edge->flags() & NodeRelevantToOSR) && node->op() == Phantom) {
// A Phantom on a node that is RelevantToOSR means that we need to keep
// a Phantom on this node instead of just having a Check.
@@ -101,11 +98,8 @@
for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
Node* node = block->at(nodeIndex);
- if (node->flags() & NodeNeedsMustGenerate) {
+ if (node->flags() & NodeNeedsPhantom) {
insertionSet.insertNode(
- nodeIndex + 1, SpecNone, MustGenerate, node->origin, node->defaultEdge());
- } else if (node->flags() & NodeNeedsPhantom) {
- insertionSet.insertNode(
nodeIndex + 1, SpecNone, Phantom, node->origin, node->defaultEdge());
}
}
Modified: trunk/Source/_javascript_Core/dfg/DFGPhantomRemovalPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGPhantomRemovalPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGPhantomRemovalPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -147,14 +147,6 @@
break;
}
- case MustGenerate: {
- if (node->children.isEmpty()) {
- m_graph.m_allocator.free(node);
- continue;
- }
- break;
- }
-
default:
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGPlan.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -395,8 +395,10 @@
performCFA(dfg);
if (Options::validateFTLOSRExitLiveness())
performResurrectionForValidation(dfg);
- if (Options::enableMovHintRemoval())
+ if (Options::enableMovHintRemoval()) {
performMovHintRemoval(dfg);
+ performPhantomCanonicalization(dfg);
+ }
performDCE(dfg); // We rely on this to kill dead code that won't be recognized as dead by LLVM.
performStackLayout(dfg);
performLivenessAnalysis(dfg);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -535,7 +535,6 @@
case InvalidationPoint:
case CheckInBounds:
case ValueToInt32:
- case MustGenerate:
case DoubleRep:
case ValueRep:
case Int52Rep:
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-04-27 18:31:26 UTC (rev 183401)
@@ -125,7 +125,6 @@
case MovHint:
case ZombieHint:
case Phantom:
- case MustGenerate:
case Upsilon:
case Phi:
case Flush:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -4621,7 +4621,6 @@
break;
case Phantom:
- case MustGenerate:
case Check:
DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
noResult(node);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -4338,7 +4338,6 @@
break;
case Phantom:
- case MustGenerate:
case Check:
DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
noResult(node);
Modified: trunk/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -244,7 +244,6 @@
case GetIndexedPropertyStorage:
case GetTypedArrayByteOffset:
case Phantom:
- case MustGenerate:
case MovHint:
case MultiGetByOffset:
case MultiPutByOffset:
@@ -337,7 +336,6 @@
case GetArrayLength:
case GetIndexedPropertyStorage:
case Phantom:
- case MustGenerate:
case MovHint:
case MultiGetByOffset:
case MultiPutByOffset:
Modified: trunk/Source/_javascript_Core/dfg/DFGVarargsForwardingPhase.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/dfg/DFGVarargsForwardingPhase.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/dfg/DFGVarargsForwardingPhase.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -92,7 +92,6 @@
switch (node->op()) {
case Phantom:
case Check:
- case MustGenerate:
case MovHint:
case PutHint:
case LoadVarargs:
@@ -214,7 +213,6 @@
switch (node->op()) {
case Phantom:
case Check:
- case MustGenerate:
case MovHint:
case PutHint:
// We don't need to change anything with these.
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -52,7 +52,6 @@
case MovHint:
case ZombieHint:
case Phantom:
- case MustGenerate:
case Flush:
case PhantomLocal:
case SetArgument:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (183400 => 183401)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-04-27 18:19:37 UTC (rev 183400)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-04-27 18:31:26 UTC (rev 183401)
@@ -464,7 +464,6 @@
compilePutStack();
break;
case Phantom:
- case MustGenerate:
case Check:
compilePhantom();
break;
Added: trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-mul-branch.js (0 => 183401)
--- trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-mul-branch.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-mul-branch.js 2015-04-27 18:31:26 UTC (rev 183401)
@@ -0,0 +1,17 @@
+function foo(a, b) {
+ var value = DFGTrue() ? -0 : "foo";
+ if (a * b == value)
+ return [DFGTrue(), true];
+ return [DFGTrue(), false];
+}
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo(1, 1);
+ if (result[1] !== false)
+ throw "Error: bad result: " + result;
+}
+
+var result = foo(-1, 0);
+if (result[1] !== true && result[0])
+ throw "Error: bad result at end: " + result;
Added: trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-mul.js (0 => 183401)
--- trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-mul.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-mul.js 2015-04-27 18:31:26 UTC (rev 183401)
@@ -0,0 +1,14 @@
+function foo(a, b) {
+ return a * b === -0;
+}
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo(1, 1);
+ if (result !== false)
+ throw "Error: bad result: " + result;
+}
+
+var result = foo(-1, 0);
+if (result !== true)
+ throw "Error: bad result at end: " + result;
Added: trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-or-zero.js (0 => 183401)
--- trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-or-zero.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof-or-zero.js 2015-04-27 18:31:26 UTC (rev 183401)
@@ -0,0 +1,15 @@
+function foo(a, b) {
+ var c = a + b;
+ return (c | 0) == c;
+}
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo(1, 1);
+ if (result !== true)
+ throw "Error: bad result: " + result;
+}
+
+var result = foo(1073741824, 1073741824);
+if (result !== false)
+ throw "Error: bad result at end: " + result;
Added: trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof.js (0 => 183401)
--- trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/fold-based-on-int32-proof.js 2015-04-27 18:31:26 UTC (rev 183401)
@@ -0,0 +1,14 @@
+function foo(a, b) {
+ return a + b === 2147483648;
+}
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo(1, 1);
+ if (result !== false)
+ throw "Error: bad result: " + result;
+}
+
+var result = foo(1073741824, 1073741824);
+if (result !== true)
+ throw "Error: bad result at end: " + result;