Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (110517 => 110518)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2012-03-13 01:05:54 UTC (rev 110518)
@@ -58,7 +58,6 @@
bytecompiler/NodesCodegen.cpp
dfg/DFGAbstractState.cpp
- dfg/DFGArithNodeFlagsInferencePhase.cpp
dfg/DFGAssemblyHelpers.cpp
dfg/DFGByteCodeParser.cpp
dfg/DFGCapabilities.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (110517 => 110518)
--- trunk/Source/_javascript_Core/ChangeLog 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-03-13 01:05:54 UTC (rev 110518)
@@ -1,5 +1,34 @@
2012-03-12 Filip Pizlo <[email protected]>
+ Arithmetic use inference should be procedure-global and should run in tandem
+ with type propagation
+ https://bugs.webkit.org/show_bug.cgi?id=80819
+ <rdar://problem/11034006>
+
+ Reviewed by Gavin Barraclough.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * dfg/DFGArithNodeFlagsInferencePhase.cpp: Removed.
+ * dfg/DFGArithNodeFlagsInferencePhase.h: Removed.
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::isNotNegZero):
+ (PredictionPropagationPhase):
+ (JSC::DFG::PredictionPropagationPhase::isNotZero):
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ (JSC::DFG::PredictionPropagationPhase::mergeDefaultArithFlags):
+ * dfg/DFGVariableAccessData.h:
+ (JSC::DFG::VariableAccessData::VariableAccessData):
+ (JSC::DFG::VariableAccessData::flags):
+ (VariableAccessData):
+ (JSC::DFG::VariableAccessData::mergeFlags):
+
+2012-03-12 Filip Pizlo <[email protected]>
+
Node::op and Node::flags should be private
https://bugs.webkit.org/show_bug.cgi?id=80824
<rdar://problem/11033435>
Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (110517 => 110518)
--- trunk/Source/_javascript_Core/GNUmakefile.list.am 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am 2012-03-13 01:05:54 UTC (rev 110518)
@@ -142,8 +142,6 @@
Source/_javascript_Core/dfg/DFGAbstractState.cpp \
Source/_javascript_Core/dfg/DFGAbstractState.h \
Source/_javascript_Core/dfg/DFGAbstractValue.h \
- Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.cpp \
- Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.h \
Source/_javascript_Core/dfg/DFGAssemblyHelpers.cpp \
Source/_javascript_Core/dfg/DFGAssemblyHelpers.h \
Source/_javascript_Core/dfg/DFGBasicBlock.h \
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (110517 => 110518)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2012-03-13 01:05:54 UTC (rev 110518)
@@ -169,8 +169,6 @@
0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
- 0FFFC95514EF909A00C72532 /* DFGArithNodeFlagsInferencePhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */; };
- 0FFFC95614EF909C00C72532 /* DFGArithNodeFlagsInferencePhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; };
0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */; };
@@ -895,8 +893,6 @@
0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; };
0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
- 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArithNodeFlagsInferencePhase.cpp; path = dfg/DFGArithNodeFlagsInferencePhase.cpp; sourceTree = "<group>"; };
- 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArithNodeFlagsInferencePhase.h; path = dfg/DFGArithNodeFlagsInferencePhase.h; sourceTree = "<group>"; };
0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCSEPhase.cpp; path = dfg/DFGCSEPhase.cpp; sourceTree = "<group>"; };
@@ -2510,8 +2506,6 @@
86EC9DB31328DF44002B2AD7 /* dfg */ = {
isa = PBXGroup;
children = (
- 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */,
- 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */,
0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */,
0F62016E143FCD2F0068B77C /* DFGAbstractState.h */,
0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */,
@@ -3086,7 +3080,6 @@
0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */,
0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */,
BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */,
- 0FFFC95614EF909C00C72532 /* DFGArithNodeFlagsInferencePhase.h in Headers */,
0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */,
0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
0FFFC95C14EF90AF00C72532 /* DFGPhase.h in Headers */,
@@ -3716,7 +3709,6 @@
C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */,
0F9FC8D014E612D800D52AE0 /* DataLog.cpp in Sources */,
0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */,
- 0FFFC95514EF909A00C72532 /* DFGArithNodeFlagsInferencePhase.cpp in Sources */,
0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */,
0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
0FFFC95B14EF90AD00C72532 /* DFGPhase.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/Target.pri (110517 => 110518)
--- trunk/Source/_javascript_Core/Target.pri 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/Target.pri 2012-03-13 01:05:54 UTC (rev 110518)
@@ -86,7 +86,6 @@
debugger/Debugger.cpp \
dfg/DFGAbstractState.cpp \
dfg/DFGAssemblyHelpers.cpp \
- dfg/DFGArithNodeFlagsInferencePhase.cpp \
dfg/DFGByteCodeParser.cpp \
dfg/DFGCapabilities.cpp \
dfg/DFGCFAPhase.cpp \
Deleted: trunk/Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.cpp (110517 => 110518)
--- trunk/Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.cpp 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.cpp 2012-03-13 01:05:54 UTC (rev 110518)
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DFGArithNodeFlagsInferencePhase.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGGraph.h"
-#include "DFGPhase.h"
-
-namespace JSC { namespace DFG {
-
-class ArithNodeFlagsInferencePhase : public Phase {
-public:
- ArithNodeFlagsInferencePhase(Graph& graph)
- : Phase(graph, "arithmetic node flags inference")
- {
- }
-
- void run()
- {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- m_count = 0;
-#endif
- do {
- m_changed = false;
-
- // Up here we start with a backward pass because we suspect that to be
- // more profitable.
- propagateBackward();
- if (!m_changed)
- break;
-
- m_changed = false;
- propagateForward();
- } while (m_changed);
- }
-
-private:
- bool isNotNegZero(NodeIndex nodeIndex)
- {
- if (!m_graph.isNumberConstant(nodeIndex))
- return false;
- double value = m_graph.valueOfNumberConstant(nodeIndex);
- return !value && 1.0 / value < 0.0;
- }
-
- bool isNotZero(NodeIndex nodeIndex)
- {
- if (!m_graph.isNumberConstant(nodeIndex))
- return false;
- return !!m_graph.valueOfNumberConstant(nodeIndex);
- }
-
- void propagate(Node& node)
- {
- if (!node.shouldGenerate())
- return;
-
- NodeType op = node.op();
- NodeFlags flags = node.flags();
-
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" %s @%u: %s ", Graph::opName(op), m_compileIndex, arithNodeFlagsAsString(flags));
-#endif
-
- flags &= NodeUsedAsMask;
-
- bool changed = false;
-
- switch (op) {
- case ValueToInt32:
- case BitAnd:
- case BitOr:
- case BitXor:
- case BitLShift:
- case BitRShift:
- case BitURShift: {
- // These operations are perfectly happy with truncated integers,
- // so we don't want to propagate anything.
- break;
- }
-
- case UInt32ToNumber: {
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- break;
- }
-
- case ArithAdd:
- case ValueAdd: {
- if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
- flags &= ~NodeNeedsNegZero;
-
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
- break;
- }
-
- case ArithSub: {
- if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
- flags &= ~NodeNeedsNegZero;
-
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
- break;
- }
-
- case ArithNegate: {
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- break;
- }
-
- case ArithMul:
- case ArithDiv: {
- // As soon as a multiply happens, we can easily end up in the part
- // of the double domain where the point at which you do truncation
- // can change the outcome. So, ArithMul always checks for overflow
- // no matter what, and always forces its inputs to check as well.
-
- flags |= NodeUsedAsNumber | NodeNeedsNegZero;
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
- break;
- }
-
- case ArithMin:
- case ArithMax: {
- flags |= NodeUsedAsNumber;
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
- break;
- }
-
- case ArithAbs: {
- flags &= ~NodeNeedsNegZero;
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- break;
- }
-
- case PutByVal: {
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber);
- changed |= m_graph[node.child3()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
- break;
- }
-
- case GetByVal: {
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber);
- break;
- }
-
- default:
- flags |= NodeUsedAsNumber | NodeNeedsNegZero;
- if (node.flags() & NodeHasVarArgs) {
- for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
- changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags);
- } else {
- if (!node.child1())
- break;
- changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
- if (!node.child2())
- break;
- changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
- if (!node.child3())
- break;
- changed |= m_graph[node.child3()].mergeArithNodeFlags(flags);
- }
- break;
- }
-
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("%s\n", changed ? "CHANGED" : "");
-#endif
-
- m_changed |= changed;
- }
-
- void propagateForward()
- {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("Propagating arithmetic node flags forward [%u]\n", ++m_count);
-#endif
- for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
- propagate(m_graph[m_compileIndex]);
- }
-
- void propagateBackward()
- {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog("Propagating arithmetic node flags backward [%u]\n", ++m_count);
-#endif
- for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
- propagate(m_graph[m_compileIndex]);
- }
-
- NodeIndex m_compileIndex;
- bool m_changed;
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- unsigned m_count;
-#endif
-};
-
-void performArithNodeFlagsInference(Graph& graph)
-{
- runPhase<ArithNodeFlagsInferencePhase>(graph);
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
Deleted: trunk/Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.h (110517 => 110518)
--- trunk/Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.h 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/dfg/DFGArithNodeFlagsInferencePhase.h 2012-03-13 01:05:54 UTC (rev 110518)
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DFGArithNodeFlagsInferencePhase_h
-#define DFGArithNodeFlagsInferencePhase_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
-
-namespace JSC { namespace DFG {
-
-class Graph;
-
-// Determine which arithmetic nodes' results are only used in a context that
-// truncates to integer anyway. This is great for optimizing away checks for
-// overflow and negative zero. NB the way this phase integrates into the rest
-// of the DFG makes it non-optional. Instead of proving that a node is only
-// used in integer context, it actually does the opposite: finds nodes that
-// are used in non-integer contexts. Hence failing to run this phase will make
-// the compiler assume that all nodes are just used as integers!
-
-void performArithNodeFlagsInference(Graph&);
-
-} } // namespace JSC::DFG::Phase
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // DFGArithNodeFlagsInferencePhase_h
Modified: trunk/Source/_javascript_Core/dfg/DFGDriver.cpp (110517 => 110518)
--- trunk/Source/_javascript_Core/dfg/DFGDriver.cpp 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/dfg/DFGDriver.cpp 2012-03-13 01:05:54 UTC (rev 110518)
@@ -28,7 +28,6 @@
#if ENABLE(DFG_JIT)
-#include "DFGArithNodeFlagsInferencePhase.h"
#include "DFGByteCodeParser.h"
#include "DFGCFAPhase.h"
#include "DFGCSEPhase.h"
@@ -60,7 +59,6 @@
dfg.predictArgumentTypes();
performRedundantPhiElimination(dfg);
- performArithNodeFlagsInference(dfg);
performPredictionPropagation(dfg);
performCSE(dfg);
performVirtualRegisterAllocation(dfg);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (110517 => 110518)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2012-03-13 01:05:54 UTC (rev 110518)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -100,17 +100,35 @@
return m_graph[m_compileIndex].predict(prediction);
}
+ bool isNotNegZero(NodeIndex nodeIndex)
+ {
+ if (!m_graph.isNumberConstant(nodeIndex))
+ return false;
+ double value = m_graph.valueOfNumberConstant(nodeIndex);
+ return !value && 1.0 / value < 0.0;
+ }
+
+ bool isNotZero(NodeIndex nodeIndex)
+ {
+ if (!m_graph.isNumberConstant(nodeIndex))
+ return false;
+ return !!m_graph.valueOfNumberConstant(nodeIndex);
+ }
+
void propagate(Node& node)
{
if (!node.shouldGenerate())
return;
NodeType op = node.op();
+ NodeFlags flags = node.flags();
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex);
+ dataLog(" %s @%u: %s ", Graph::opName(op), m_compileIndex, arithNodeFlagsAsString(flags));
#endif
+ flags &= NodeUsedAsMask;
+
bool changed = false;
switch (op) {
@@ -121,17 +139,29 @@
}
case GetLocal: {
- PredictedType prediction = node.variableAccessData()->prediction();
+ VariableAccessData* variableAccessData = node.variableAccessData();
+ PredictedType prediction = variableAccessData->prediction();
if (prediction)
changed |= mergePrediction(prediction);
+
+ changed |= variableAccessData->mergeFlags(flags);
break;
}
case SetLocal: {
- changed |= node.variableAccessData()->predict(m_graph[node.child1()].prediction());
+ VariableAccessData* variableAccessData = node.variableAccessData();
+ changed |= variableAccessData->predict(m_graph[node.child1()].prediction());
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(variableAccessData->flags());
break;
}
+ case Flush: {
+ // Make sure that the analysis knows that flushed locals escape.
+ VariableAccessData* variableAccessData = node.variableAccessData();
+ variableAccessData->mergeFlags(NodeUsedAsNumber | NodeNeedsNegZero);
+ break;
+ }
+
case BitAnd:
case BitOr:
case BitXor:
@@ -143,15 +173,22 @@
break;
}
- case ArrayPop:
+ case ArrayPop: {
+ if (node.getHeapPrediction())
+ changed |= mergePrediction(node.getHeapPrediction());
+ break;
+ }
+
case ArrayPush: {
if (node.getHeapPrediction())
changed |= mergePrediction(node.getHeapPrediction());
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
case StringCharCodeAt: {
changed |= mergePrediction(PredictInt32);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -165,6 +202,8 @@
else
changed |= mergePrediction(PredictDouble);
}
+
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -173,6 +212,8 @@
changed |= setPrediction(PredictInt32);
else
changed |= setPrediction(PredictNumber);
+
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
break;
}
@@ -192,10 +233,34 @@
} else
changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble);
}
+
+ if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
+ flags &= ~NodeNeedsNegZero;
+
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
break;
}
- case ArithAdd:
+ case ArithAdd: {
+ PredictedType left = m_graph[node.child1()].prediction();
+ PredictedType right = m_graph[node.child2()].prediction();
+
+ if (left && right) {
+ if (m_graph.addShouldSpeculateInteger(node))
+ changed |= mergePrediction(PredictInt32);
+ else
+ changed |= mergePrediction(PredictDouble);
+ }
+
+ if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
+ flags &= ~NodeNeedsNegZero;
+
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
+ break;
+ }
+
case ArithSub: {
PredictedType left = m_graph[node.child1()].prediction();
PredictedType right = m_graph[node.child2()].prediction();
@@ -206,6 +271,12 @@
else
changed |= mergePrediction(PredictDouble);
}
+
+ if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
+ flags &= ~NodeNeedsNegZero;
+
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
break;
}
@@ -216,11 +287,29 @@
else
changed |= mergePrediction(PredictDouble);
}
+
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
break;
+ case ArithMin:
+ case ArithMax: {
+ PredictedType left = m_graph[node.child1()].prediction();
+ PredictedType right = m_graph[node.child2()].prediction();
+
+ if (left && right) {
+ if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ changed |= mergePrediction(PredictInt32);
+ else
+ changed |= mergePrediction(PredictDouble);
+ }
+
+ flags |= NodeUsedAsNumber;
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
+ break;
+ }
+
case ArithMul:
- case ArithMin:
- case ArithMax:
case ArithDiv: {
PredictedType left = m_graph[node.child1()].prediction();
PredictedType right = m_graph[node.child2()].prediction();
@@ -231,11 +320,21 @@
else
changed |= mergePrediction(PredictDouble);
}
+
+ // As soon as a multiply happens, we can easily end up in the part
+ // of the double domain where the point at which you do truncation
+ // can change the outcome. So, ArithMul always checks for overflow
+ // no matter what, and always forces its inputs to check as well.
+
+ flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
break;
}
case ArithSqrt: {
changed |= setPrediction(PredictDouble);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -247,6 +346,9 @@
else
changed |= setPrediction(PredictDouble);
}
+
+ flags &= ~NodeNeedsNegZero;
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
break;
}
@@ -259,6 +361,7 @@
case CompareStrictEq:
case InstanceOf: {
changed |= setPrediction(PredictBoolean);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -283,12 +386,14 @@
if (isArray || isString || isByteArray || isInt8Array || isInt16Array || isInt32Array || isUint8Array || isUint8ClampedArray || isUint16Array || isUint32Array || isFloat32Array || isFloat64Array)
changed |= mergePrediction(PredictInt32);
}
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
case GetByIdFlush:
if (node.getHeapPrediction())
changed |= mergePrediction(node.getHeapPrediction());
+ changed |= mergeDefaultArithFlags(node, flags);
break;
case GetByVal: {
@@ -296,18 +401,23 @@
changed |= mergePrediction(PredictDouble);
else if (node.getHeapPrediction())
changed |= mergePrediction(node.getHeapPrediction());
+
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber);
break;
}
case GetPropertyStorage:
case GetIndexedPropertyStorage: {
changed |= setPrediction(PredictOther);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
case GetByOffset: {
if (node.getHeapPrediction())
changed |= mergePrediction(node.getHeapPrediction());
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -315,6 +425,7 @@
case Construct: {
if (node.getHeapPrediction())
changed |= mergePrediction(node.getHeapPrediction());
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -327,6 +438,7 @@
}
changed |= mergePrediction(prediction);
}
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -339,6 +451,7 @@
case PutGlobalVar: {
changed |= m_graph.predictGlobalVar(node.varNumber(), m_graph[node.child1()].prediction());
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -366,12 +479,14 @@
case CreateThis:
case NewObject: {
changed |= setPrediction(PredictFinalObject);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
case NewArray:
case NewArrayBuffer: {
changed |= setPrediction(PredictArray);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -383,6 +498,7 @@
case StringCharAt:
case StrCat: {
changed |= setPrediction(PredictString);
+ changed |= mergeDefaultArithFlags(node, flags);
break;
}
@@ -403,6 +519,7 @@
} else
changed |= mergePrediction(child);
}
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
break;
}
@@ -436,7 +553,10 @@
break;
}
- case Flush:
+ case PutByVal:
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber);
+ changed |= m_graph[node.child3()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero);
break;
#ifndef NDEBUG
@@ -452,7 +572,6 @@
case ThrowReferenceError:
case ForceOSRExit:
case SetArgument:
- case PutByVal:
case PutByValAlias:
case PutById:
case PutByIdDirect:
@@ -461,6 +580,7 @@
case PutStructure:
case PutByOffset:
case TearOffActivation:
+ changed |= mergeDefaultArithFlags(node, flags);
break;
// These gets ignored because it doesn't do anything.
@@ -474,6 +594,7 @@
break;
#else
default:
+ changed |= mergeDefaultArithFlags(node, flags);
break;
#endif
}
@@ -485,6 +606,27 @@
m_changed |= changed;
}
+ bool mergeDefaultArithFlags(Node& node, NodeFlags flags)
+ {
+ bool changed = false;
+ flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+ if (node.flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
+ changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags);
+ } else {
+ if (!node.child1())
+ return changed;
+ changed |= m_graph[node.child1()].mergeArithNodeFlags(flags);
+ if (!node.child2())
+ return changed;
+ changed |= m_graph[node.child2()].mergeArithNodeFlags(flags);
+ if (!node.child3())
+ return changed;
+ changed |= m_graph[node.child3()].mergeArithNodeFlags(flags);
+ }
+ return changed;
+ }
+
void propagateForward()
{
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
Modified: trunk/Source/_javascript_Core/dfg/DFGVariableAccessData.h (110517 => 110518)
--- trunk/Source/_javascript_Core/dfg/DFGVariableAccessData.h 2012-03-13 01:02:59 UTC (rev 110517)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableAccessData.h 2012-03-13 01:05:54 UTC (rev 110518)
@@ -26,6 +26,7 @@
#ifndef DFGVariableAccessData_h
#define DFGVariableAccessData_h
+#include "DFGNodeFlags.h"
#include "DFGOperands.h"
#include "PredictedType.h"
#include "VirtualRegister.h"
@@ -41,6 +42,7 @@
VariableAccessData()
: m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
, m_prediction(PredictNone)
+ , m_flags(0)
, m_shouldUseDoubleFormat(false)
{
clearVotes();
@@ -49,6 +51,7 @@
VariableAccessData(VirtualRegister local)
: m_local(local)
, m_prediction(PredictNone)
+ , m_flags(0)
, m_shouldUseDoubleFormat(false)
{
clearVotes();
@@ -130,6 +133,17 @@
return true;
}
+ NodeFlags flags() const { return m_flags; }
+
+ bool mergeFlags(NodeFlags newFlags)
+ {
+ newFlags |= m_flags;
+ if (newFlags == m_flags)
+ return false;
+ m_flags = newFlags;
+ return true;
+ }
+
private:
// This is slightly space-inefficient, since anything we're unified with
// will have the same operand and should have the same prediction. But
@@ -138,6 +152,7 @@
VirtualRegister m_local;
PredictedType m_prediction;
+ NodeFlags m_flags;
float m_votes[2];
bool m_shouldUseDoubleFormat;