Unreviewed, rolling out r145299.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Mar 2013 22:48:09 +0000 (22:48 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Mar 2013 22:48:09 +0000 (22:48 +0000)
http://trac.webkit.org/changeset/145299
https://bugs.webkit.org/show_bug.cgi?id=111928

compilation failure with recent clang
(DFGBackwardsPropagationPhase.cpp:132:35: error: comparison of
constant 10 with expression of type 'bool' is always false)
(Requested by thorton on #webkit).

Patch by Sheriff Bot <webkit.review.bot@gmail.com> on 2013-03-09

Source/JavaScriptCore:

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::refine):
* dfg/DFGBackwardsPropagationPhase.cpp: Removed.
* dfg/DFGBackwardsPropagationPhase.h: Removed.
* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::run):
(CPSRethreadingPhase):
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
(JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::nodeFlagsAsString):
(DFG):
* dfg/DFGNodeFlags.h:
(DFG):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::isNotNegZero):
(PredictionPropagationPhase):
(JSC::DFG::PredictionPropagationPhase::isNotZero):
(JSC::DFG::PredictionPropagationPhase::isWithinPowerOfTwoForConstant):
(JSC::DFG::PredictionPropagationPhase::isWithinPowerOfTwoNonRecursive):
(JSC::DFG::PredictionPropagationPhase::isWithinPowerOfTwo):
(JSC::DFG::PredictionPropagationPhase::propagate):
(JSC::DFG::PredictionPropagationPhase::mergeDefaultFlags):
* dfg/DFGUnificationPhase.cpp:
(JSC::DFG::UnificationPhase::run):
* dfg/DFGVariableAccessData.h:
(JSC::DFG::VariableAccessData::VariableAccessData):
(VariableAccessData):

LayoutTests:

* fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt: Removed.
* fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html: Removed.
* fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt: Removed.
* fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html: Removed.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js: Removed.
* fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js: Removed.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@145323 268f45cc-cd09-0410-ab3c-d52691b4dbfc

24 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt [deleted file]
LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html [deleted file]
LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt [deleted file]
LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html [deleted file]
LayoutTests/fast/js/jsc-test-list
LayoutTests/fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js [deleted file]
LayoutTests/fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js [deleted file]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/dfg/DFGArrayMode.cpp
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp [deleted file]
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.h [deleted file]
Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
Source/JavaScriptCore/dfg/DFGNodeFlags.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGUnificationPhase.cpp
Source/JavaScriptCore/dfg/DFGVariableAccessData.h

index 14ddeb5..5633804 100644 (file)
@@ -1,3 +1,22 @@
+2013-03-09  Sheriff Bot  <webkit.review.bot@gmail.com>
+
+        Unreviewed, rolling out r145299.
+        http://trac.webkit.org/changeset/145299
+        https://bugs.webkit.org/show_bug.cgi?id=111928
+
+        compilation failure with recent clang
+        (DFGBackwardsPropagationPhase.cpp:132:35: error: comparison of
+        constant 10 with expression of type 'bool' is always false)
+        (Requested by thorton on #webkit).
+
+        * fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt: Removed.
+        * fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html: Removed.
+        * fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt: Removed.
+        * fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html: Removed.
+        * fast/js/jsc-test-list:
+        * fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js: Removed.
+        * fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js: Removed.
+
 2013-03-09  Keishi Hattori  <keishi@webkit.org>
 
         Add tests for opening the picker with the f4 key
diff --git a/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt b/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt
deleted file mode 100644 (file)
index 2665137..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-Tests that when values predicted but not proven int are used in a tower of additions, we don't eliminate the overflow check unsoundly.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(1, 2, {f:3}) is 6
-PASS bar(2147483645, 2147483644, {f:9007199254740990}) is -8
-PASS bar(2147483643, 2147483643, {f:18014398509481980}) is -16
-PASS bar(2147483643, 2147483642, {f:36028797018963960}) is -16
-PASS bar(2147483642, 2147483642, {f:36028797018963960}) is -16
-PASS bar(2147483641, 2147483640, {f:144115188075855840}) is -32
-PASS bar(2147483640, 2147483640, {f:144115188075855840}) is -64
-PASS bar(2147483640, 2147483639, {f:288230376151711680}) is -64
-PASS bar(2147483639, 2147483639, {f:288230376151711680}) is -64
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html b/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html
deleted file mode 100644 (file)
index d829718..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="resources/js-test-pre.js"></script>
-</head>
-<body>
-<script src="script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
diff --git a/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt b/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt
deleted file mode 100644 (file)
index 4ee91ea..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-Tests that if we have a tower of large numerical constants being added to each other, the DFG knows that a sufficiently large tower may produce a large enough value that overflow check elimination must be careful.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(1, 2) is 0
-PASS bar(2147483645, 2147483644) is -10
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html b/LayoutTests/fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html
deleted file mode 100644 (file)
index 6ad20dc..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="resources/js-test-pre.js"></script>
-</head>
-<body>
-<script src="script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
index 1712244..ea95c22 100644 (file)
@@ -82,8 +82,6 @@ fast/js/dfg-arguments-osr-exit-multiple-blocks
 fast/js/dfg-arguments-osr-exit-multiple-blocks-before-exit
 fast/js/dfg-arguments-out-of-bounds
 fast/js/dfg-arguments-unexpected-escape
-fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers
-fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int
 fast/js/dfg-arrayify-elimination
 fast/js/dfg-arrayify-when-late-prevent-extensions
 fast/js/dfg-arrayify-when-prevent-extensions
diff --git a/LayoutTests/fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js b/LayoutTests/fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js
deleted file mode 100644 (file)
index 52bedd9..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-description(
-"Tests that when values predicted but not proven int are used in a tower of additions, we don't eliminate the overflow check unsoundly."
-);
-
-function foo(a, b, o) {
-    return (a + b + o.f) | 0;
-}
-
-function bar(a, b, o) {
-    eval(""); // Prevent this function from being opt compiled.
-    return foo(a, b, o);
-}
-
-var badCases = [
-    {a:2147483645, b:2147483644, c:9007199254740990, expected:-8},
-    {a:2147483643, b:2147483643, c:18014398509481980, expected:-16},
-    {a:2147483643, b:2147483642, c:36028797018963960, expected:-16},
-    {a:2147483642, b:2147483642, c:36028797018963960, expected:-16},
-    {a:2147483641, b:2147483640, c:144115188075855840, expected:-32},
-    {a:2147483640, b:2147483640, c:144115188075855840, expected:-64},
-    {a:2147483640, b:2147483639, c:288230376151711680, expected:-64},
-    {a:2147483639, b:2147483639, c:288230376151711680, expected:-64}
-];
-
-var warmup = 100;
-
-for (var i = 0; i < warmup + badCases.length; ++i) {
-    var a, b, c;
-    var expected;
-    if (i < warmup) {
-        a = 1;
-        b = 2;
-        c = 3;
-        expected = 6;
-    } else {
-        var current = badCases[i - warmup];
-        a = current.a;
-        b = current.b;
-        c = current.c;
-        expected = current.expected;
-    }
-    shouldBe("bar(" + a + ", " + b + ", {f:" + c + "})", "" + expected);
-}
-
diff --git a/LayoutTests/fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js b/LayoutTests/fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js
deleted file mode 100644 (file)
index 4c3656f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-description(
-"Tests that if we have a tower of large numerical constants being added to each other, the DFG knows that a sufficiently large tower may produce a large enough value that overflow check elimination must be careful."
-);
-
-function foo(a, b) {
-    return (a + b + 281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 +
-            281474976710655 + 281474976710655 + 281474976710655 + 281474976710655 + 30) | 0;
-}
-
-function bar(a, b, o) {
-    eval(""); // Prevent this function from being opt compiled.
-    return foo(a, b, o);
-}
-
-var warmup = 200;
-
-for (var i = 0; i < warmup + 1; ++i) {
-    var a, b, c;
-    var expected;
-    if (i < warmup) {
-        a = 1;
-        b = 2;
-        expected = 0;
-    } else {
-        a = 2147483645;
-        b = 2147483644;
-        expected = -10;
-    }
-    shouldBe("bar(" + a + ", " + b + ")", "" + expected);
-}
-
index 964b51b..b573ce1 100644 (file)
@@ -78,7 +78,6 @@ set(JavaScriptCore_SOURCES
     dfg/DFGArgumentsSimplificationPhase.cpp
     dfg/DFGArrayMode.cpp
     dfg/DFGAssemblyHelpers.cpp
-    dfg/DFGBackwardsPropagationPhase.cpp
     dfg/DFGByteCodeParser.cpp
     dfg/DFGCapabilities.cpp
     dfg/DFGCommon.cpp
index fd59d73..220bf51 100644 (file)
@@ -1,3 +1,51 @@
+2013-03-09  Sheriff Bot  <webkit.review.bot@gmail.com>
+
+        Unreviewed, rolling out r145299.
+        http://trac.webkit.org/changeset/145299
+        https://bugs.webkit.org/show_bug.cgi?id=111928
+
+        compilation failure with recent clang
+        (DFGBackwardsPropagationPhase.cpp:132:35: error: comparison of
+        constant 10 with expression of type 'bool' is always false)
+        (Requested by thorton on #webkit).
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::refine):
+        * dfg/DFGBackwardsPropagationPhase.cpp: Removed.
+        * dfg/DFGBackwardsPropagationPhase.h: Removed.
+        * dfg/DFGCPSRethreadingPhase.cpp:
+        (JSC::DFG::CPSRethreadingPhase::run):
+        (CPSRethreadingPhase):
+        (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
+        (JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compile):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGNodeFlags.cpp:
+        (JSC::DFG::nodeFlagsAsString):
+        (DFG):
+        * dfg/DFGNodeFlags.h:
+        (DFG):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::isNotNegZero):
+        (PredictionPropagationPhase):
+        (JSC::DFG::PredictionPropagationPhase::isNotZero):
+        (JSC::DFG::PredictionPropagationPhase::isWithinPowerOfTwoForConstant):
+        (JSC::DFG::PredictionPropagationPhase::isWithinPowerOfTwoNonRecursive):
+        (JSC::DFG::PredictionPropagationPhase::isWithinPowerOfTwo):
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        (JSC::DFG::PredictionPropagationPhase::mergeDefaultFlags):
+        * dfg/DFGUnificationPhase.cpp:
+        (JSC::DFG::UnificationPhase::run):
+        * dfg/DFGVariableAccessData.h:
+        (JSC::DFG::VariableAccessData::VariableAccessData):
+        (VariableAccessData):
+
 2013-03-08  Filip Pizlo  <fpizlo@apple.com>
 
         DFG overflow check elimination is too smart for its own good
index 2312154..08f0cf9 100644 (file)
@@ -184,8 +184,6 @@ javascriptcore_sources += \
        Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h \
        Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp \
        Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h \
-       Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp \
-       Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.h \
        Source/JavaScriptCore/dfg/DFGBasicBlock.h \
        Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h \
        Source/JavaScriptCore/dfg/DFGBranchDirection.h \
index c6d25e0..b8ef06c 100644 (file)
                0F63948515E4811B006A597C /* DFGArrayMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63948215E48114006A597C /* DFGArrayMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */; };
-               0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F73D7AE165A142D00ACAB71 /* ClosureCallStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */; };
                0F73D7AF165A143000ACAB71 /* ClosureCallStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F766D2815A8CC1E008F363E /* JITStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */; };
                0F63948215E48114006A597C /* DFGArrayMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayMode.h; path = dfg/DFGArrayMode.h; sourceTree = "<group>"; };
                0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; };
                0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; };
-               0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBackwardsPropagationPhase.cpp; path = dfg/DFGBackwardsPropagationPhase.cpp; sourceTree = "<group>"; };
-               0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBackwardsPropagationPhase.h; path = dfg/DFGBackwardsPropagationPhase.h; sourceTree = "<group>"; };
                0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClosureCallStubRoutine.cpp; sourceTree = "<group>"; };
                0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClosureCallStubRoutine.h; sourceTree = "<group>"; };
                0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
                                0F63948215E48114006A597C /* DFGArrayMode.h */,
                                0FC0976B1468AB4A00CF2442 /* DFGAssemblyHelpers.cpp */,
                                0FC0976C1468AB4A00CF2442 /* DFGAssemblyHelpers.h */,
-                               0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */,
-                               0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */,
                                0F620170143FCD2F0068B77C /* DFGBasicBlock.h */,
                                0FD5652216AB780A00197653 /* DFGBasicBlockInlines.h */,
                                0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */,
                                0FFB921F16D033050055A5DB /* (null) in Headers */,
                                0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */,
                                0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */,
-                               0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */,
                                0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
                                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
-                               0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 3b062f2..8fefc65 100644 (file)
@@ -114,7 +114,6 @@ SOURCES += \
     dfg/DFGArgumentsSimplificationPhase.cpp \
     dfg/DFGArrayMode.cpp \
     dfg/DFGAssemblyHelpers.cpp \
-    dfg/DFGBackwardsPropagationPhase.cpp \
     dfg/DFGByteCodeParser.cpp \
     dfg/DFGCapabilities.cpp \
     dfg/DFGCommon.cpp \
index 7a6f108..6df637d 100644 (file)
@@ -167,14 +167,14 @@ ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, Speculate
         return withTypeAndConversion(Array::Contiguous, Array::Convert);
         
     case Array::Double:
-        if (flags & NodeUsedAsInt)
+        if (flags & NodeUsedAsIntLocally)
             return withTypeAndConversion(Array::Contiguous, Array::RageConvert);
         if (!value || isNumberSpeculation(value))
             return *this;
         return withTypeAndConversion(Array::Contiguous, Array::Convert);
         
     case Array::Contiguous:
-        if (doesConversion() && (flags & NodeUsedAsInt))
+        if (doesConversion() && (flags & NodeUsedAsIntLocally))
             return withConversion(Array::RageConvert);
         return *this;
         
diff --git a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
deleted file mode 100644 (file)
index 279b93e..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (C) 2013 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 "DFGBackwardsPropagationPhase.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGBasicBlockInlines.h"
-#include "DFGGraph.h"
-#include "DFGPhase.h"
-#include "Operations.h"
-
-namespace JSC { namespace DFG {
-
-class BackwardsPropagationPhase : public Phase {
-public:
-    BackwardsPropagationPhase(Graph& graph)
-        : Phase(graph, "backwards propagation")
-    {
-    }
-    
-    bool run()
-    {
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block)
-                continue;
-            
-            // Prevent a tower of overflowing additions from creating a value that is out of the
-            // safe 2^48 range.
-            m_allowNestedOverflowingAdditions = block->size() < (1 << 16);
-            
-            for (unsigned indexInBlock = block->size(); indexInBlock--;)
-                propagate(block->at(indexInBlock));
-        }
-        
-        return true;
-    }
-
-private:
-    bool isNotNegZero(Node* node)
-    {
-        if (!m_graph.isNumberConstant(node))
-            return false;
-        double value = m_graph.valueOfNumberConstant(node);
-        return !value && 1.0 / value < 0.0;
-    }
-    
-    bool isNotZero(Node* node)
-    {
-        if (!m_graph.isNumberConstant(node))
-            return false;
-        return !!m_graph.valueOfNumberConstant(node);
-    }
-
-    // Tests if the absolute value is strictly less than the power of two.
-    template<int power>
-    bool isWithinPowerOfTwoForConstant(Node* node)
-    {
-        JSValue immediateValue = node->valueOfJSConstant(codeBlock());
-        if (!immediateValue.isNumber())
-            return false;
-        double immediate = immediateValue.asNumber();
-        return immediate > -(static_cast<int64_t>(1) << power) && immediate < (static_cast<int64_t>(1) << power);
-    }
-    
-    template<int power>
-    bool isWithinPowerOfTwoNonRecursive(Node* node)
-    {
-        if (node->op() != JSConstant)
-            return false;
-        return isWithinPowerOfTwoForConstant<power>(node);
-    }
-    
-    template<int power>
-    bool isWithinPowerOfTwo(Node* node)
-    {
-        switch (node->op()) {
-        case JSConstant: {
-            return isWithinPowerOfTwoForConstant<power>(node);
-        }
-            
-        case BitAnd: {
-            if (power > 31)
-                return true;
-            
-            return isWithinPowerOfTwoNonRecursive<power>(node->child1().node())
-                || isWithinPowerOfTwoNonRecursive<power>(node->child2().node());
-        }
-            
-        case BitOr:
-        case BitXor:
-        case BitLShift:
-        case ValueToInt32: {
-            return power > 31;
-        }
-            
-        case BitRShift:
-        case BitURShift: {
-            if (power > 31)
-                return true;
-            
-            Node* shiftAmount = node->child2().node();
-            if (shiftAmount->op() != JSConstant)
-                return false;
-            JSValue immediateValue = shiftAmount->valueOfJSConstant(codeBlock());
-            if (!immediateValue.isInt32())
-                return false;
-            return immediateValue > 32 - power;
-        }
-            
-        default:
-            return false;
-        }
-    }
-
-    template<int power>
-    bool isWithinPowerOfTwo(Edge edge)
-    {
-        return isWithinPowerOfTwo<power>(edge.node());
-    }
-
-    bool mergeDefaultFlags(Node* node)
-    {
-        bool changed = false;
-        if (node->flags() & NodeHasVarArgs) {
-            for (unsigned childIdx = node->firstChild();
-                childIdx < node->firstChild() + node->numChildren();
-                childIdx++) {
-                if (!!m_graph.m_varArgChildren[childIdx])
-                    changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
-            }
-        } else {
-            if (!node->child1())
-                return changed;
-            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
-            if (!node->child2())
-                return changed;
-            changed |= node->child2()->mergeFlags(NodeUsedAsValue);
-            if (!node->child3())
-                return changed;
-            changed |= node->child3()->mergeFlags(NodeUsedAsValue);
-        }
-        return changed;
-    }
-    
-    void propagate(Node* node)
-    {
-        NodeFlags flags = node->flags() & NodeBackPropMask;
-        
-        switch (node->op()) {
-        case GetLocal: {
-            VariableAccessData* variableAccessData = node->variableAccessData();
-            variableAccessData->mergeFlags(flags);
-            break;
-        }
-            
-        case SetLocal: {
-            VariableAccessData* variableAccessData = node->variableAccessData();
-            if (!variableAccessData->isLoadedFrom())
-                break;
-            node->child1()->mergeFlags(NodeUsedAsValue);
-            break;
-        }
-            
-        case BitAnd:
-        case BitOr:
-        case BitXor:
-        case BitRShift:
-        case BitLShift:
-        case BitURShift: {
-            flags |= NodeUsedAsInt;
-            flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case ValueToInt32: {
-            flags |= NodeUsedAsInt;
-            flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
-            node->child1()->mergeFlags(flags);
-            break;
-        }
-            
-        case StringCharCodeAt: {
-            node->child1()->mergeFlags(NodeUsedAsValue);
-            node->child2()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt);
-            break;
-        }
-            
-        case Identity: 
-        case UInt32ToNumber: {
-            node->child1()->mergeFlags(flags);
-            break;
-        }
-
-        case ValueAdd: {
-            if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
-                flags &= ~NodeNeedsNegZero;
-            if (node->child1()->hasNumberResult() || node->child2()->hasNumberResult())
-                flags &= ~NodeUsedAsOther;
-            if (!isWithinPowerOfTwo<32>(node->child1()) && !isWithinPowerOfTwo<32>(node->child2()))
-                flags |= NodeUsedAsNumber;
-            if (!m_allowNestedOverflowingAdditions)
-                flags |= NodeUsedAsNumber;
-            
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case ArithAdd: {
-            if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
-                flags &= ~NodeNeedsNegZero;
-            if (!isWithinPowerOfTwo<32>(node->child1()) && !isWithinPowerOfTwo<32>(node->child2()))
-                flags |= NodeUsedAsNumber;
-            if (!m_allowNestedOverflowingAdditions)
-                flags |= NodeUsedAsNumber;
-            
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case ArithSub: {
-            if (isNotZero(node->child1().node()) || isNotZero(node->child2().node()))
-                flags &= ~NodeNeedsNegZero;
-            if (!isWithinPowerOfTwo<32>(node->child1()) && !isWithinPowerOfTwo<32>(node->child2()))
-                flags |= NodeUsedAsNumber;
-            if (!m_allowNestedOverflowingAdditions)
-                flags |= NodeUsedAsNumber;
-            
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case ArithNegate: {
-            flags &= ~NodeUsedAsOther;
-
-            node->child1()->mergeFlags(flags);
-            break;
-        }
-            
-        case ArithMul: {
-            // 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 forces its inputs to
-            // check for overflow. Additionally, it will have to check for overflow
-            // itself unless we can prove that there is no way for the values
-            // produced to cause double rounding.
-            
-            if (!isWithinPowerOfTwo<22>(node->child1().node())
-                && !isWithinPowerOfTwo<22>(node->child2().node()))
-                flags |= NodeUsedAsNumber;
-            
-            node->mergeFlags(flags);
-            
-            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
-            flags &= ~NodeUsedAsOther;
-
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case ArithDiv: {
-            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
-            flags &= ~NodeUsedAsOther;
-
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case ArithMod: {
-            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
-            flags &= ~NodeUsedAsOther;
-
-            node->child1()->mergeFlags(flags);
-            node->child2()->mergeFlags(flags);
-            break;
-        }
-            
-        case GetByVal: {
-            node->child1()->mergeFlags(NodeUsedAsValue);
-            node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
-            break;
-        }
-            
-        case GetMyArgumentByValSafe: {
-            node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
-            break;
-        }
-            
-        case NewArrayWithSize: {
-            node->child1()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt);
-            break;
-        }
-            
-        case StringCharAt: {
-            node->child1()->mergeFlags(NodeUsedAsValue);
-            node->child2()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt);
-            break;
-        }
-            
-        case StrCat: {
-            for (unsigned childIdx = node->firstChild();
-                childIdx < node->firstChild() + node->numChildren();
-                ++childIdx)
-                m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);
-            break;
-        }
-            
-        case ToPrimitive: {
-            node->child1()->mergeFlags(flags);
-            break;
-        }
-            
-        case PutByVal: {
-            m_graph.varArgChild(node, 0)->mergeFlags(NodeUsedAsValue);
-            m_graph.varArgChild(node, 1)->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt);
-            m_graph.varArgChild(node, 2)->mergeFlags(NodeUsedAsValue);
-            break;
-        }
-            
-        default:
-            mergeDefaultFlags(node);
-            break;
-        }
-    }
-    
-    bool m_allowNestedOverflowingAdditions;
-};
-
-bool performBackwardsPropagation(Graph& graph)
-{
-    SamplingRegion samplingRegion("DFG Backwards Propagation Phase");
-    return runPhase<BackwardsPropagationPhase>(graph);
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
diff --git a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.h b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.h
deleted file mode 100644 (file)
index 4386846..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2013 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 DFGBackwardsPropagationPhase_h
-#define DFGBackwardsPropagationPhase_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGCommon.h"
-
-namespace JSC { namespace DFG {
-
-class Graph;
-
-// Infer basic information about how nodes are used by doing a block-local
-// backwards flow analysis.
-
-bool performBackwardsPropagation(Graph&);
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // DFGBackwardsPropagationPhase_h
-
index a10fbe8..96ce188 100644 (file)
@@ -47,7 +47,6 @@ public:
         if (m_graph.m_form == ThreadedCPS)
             return false;
         
-        clearIsLoadedFrom();
         freeUnnecessaryNodes();
         canonicalizeLocalsInBlocks();
         propagatePhis<LocalOperand>();
@@ -59,12 +58,6 @@ public:
 
 private:
     
-    void clearIsLoadedFrom()
-    {
-        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
-            m_graph.m_variableAccessData[i].setIsLoadedFrom(false);
-    }
-    
     void freeUnnecessaryNodes()
     {
         SamplingRegion samplingRegion("DFG CPS Rethreading: freeUnnecessaryNodes");
@@ -177,14 +170,12 @@ private:
             ASSERT(otherNode->variableAccessData() == variable);
             
             if (otherNode->op() == SetArgument) {
-                variable->setIsLoadedFrom(true);
                 node->children.setChild1(Edge(otherNode));
                 m_block->variablesAtTail.atFor<operandKind>(idx) = node;
                 return;
             }
             
             if (variable->isCaptured()) {
-                variable->setIsLoadedFrom(true);
                 if (otherNode->op() == GetLocal)
                     otherNode = otherNode->child1().node();
                 else
@@ -209,7 +200,6 @@ private:
             return;
         }
         
-        variable->setIsLoadedFrom(true);
         Node* phi = addPhi<operandKind>(node->codeOrigin, variable, idx);
         node->children.setChild1(Edge(phi));
         m_block->variablesAtHead.atFor<operandKind>(idx) = phi;
@@ -266,7 +256,6 @@ private:
                 return;
             }
             
-            variable->setIsLoadedFrom(true);
             // There is nothing wrong with having redundant Flush's. It just needs to
             // be linked appropriately. Note that if there had already been a previous
             // use at tail then we don't override it. It's fine for variablesAtTail to
@@ -277,7 +266,6 @@ private:
             return;
         }
         
-        variable->setIsLoadedFrom(true);
         node->children.setChild1(Edge(addPhi<operandKind>(node->codeOrigin, variable, idx)));
         m_block->variablesAtHead.atFor<operandKind>(idx) = node;
         m_block->variablesAtTail.atFor<operandKind>(idx) = node;
index 7623412..c92da40 100644 (file)
@@ -33,7 +33,6 @@
 #if ENABLE(DFG_JIT)
 
 #include "DFGArgumentsSimplificationPhase.h"
-#include "DFGBackwardsPropagationPhase.h"
 #include "DFGByteCodeParser.h"
 #include "DFGCFAPhase.h"
 #include "DFGCFGSimplificationPhase.h"
@@ -123,7 +122,6 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
     if (validationEnabled())
         validate(dfg);
     
-    performBackwardsPropagation(dfg);
     performPredictionPropagation(dfg);
     performFixup(dfg);
     performStructureCheckHoisting(dfg);
index aaf9f85..7fbb526 100644 (file)
@@ -179,8 +179,8 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node)
             out.print(comma, node->child3());
     }
 
-    if (toCString(NodeFlagsDump(node->flags())) != "<empty>")
-        out.print(comma, NodeFlagsDump(node->flags()));
+    if (strlen(nodeFlagsAsString(node->flags())))
+        out.print(comma, nodeFlagsAsString(node->flags()));
     if (node->hasArrayMode())
         out.print(comma, node->arrayMode());
     if (node->hasVarNumber())
index c5753d2..a605113 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
-#include <wtf/CommaPrinter.h>
+#include <wtf/BoundsCheckedPointer.h>
 
 namespace JSC { namespace DFG {
 
-void dumpNodeFlags(PrintStream& out, NodeFlags flags)
+const char* nodeFlagsAsString(NodeFlags flags)
 {
-    if (!(flags ^ NodeDoesNotExit)) {
-        out.print("<empty>");
-        return;
-    }
+    if (!(flags ^ NodeDoesNotExit))
+        return "<empty>";
 
-    CommaPrinter comma("|");
+    static const int size = 128;
+    static char description[size];
+    BoundsCheckedPointer<char> ptr(description, size);
+    
+    bool hasPrinted = false;
     
     if (flags & NodeResultMask) {
         switch (flags & NodeResultMask) {
         case NodeResultJS:
-            out.print(comma, "JS");
+            ptr.strcat("JS");
             break;
         case NodeResultNumber:
-            out.print(comma, "Number");
+            ptr.strcat("Number");
             break;
         case NodeResultInt32:
-            out.print(comma, "Int32");
+            ptr.strcat("Int32");
             break;
         case NodeResultBoolean:
-            out.print(comma, "Boolean");
+            ptr.strcat("Boolean");
             break;
         case NodeResultStorage:
-            out.print(comma, "Storage");
+            ptr.strcat("Storage");
             break;
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
         }
+        hasPrinted = true;
     }
     
-    if (flags & NodeMustGenerate)
-        out.print(comma, "MustGen");
+    if (flags & NodeMustGenerate) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MustGen");
+        hasPrinted = true;
+    }
     
-    if (flags & NodeHasVarArgs)
-        out.print(comma, "VarArgs");
+    if (flags & NodeHasVarArgs) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("VarArgs");
+        hasPrinted = true;
+    }
     
-    if (flags & NodeClobbersWorld)
-        out.print(comma, "Clobbers");
+    if (flags & NodeClobbersWorld) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("Clobbers");
+        hasPrinted = true;
+    }
     
-    if (flags & NodeMightClobber)
-        out.print(comma, "MightClobber");
+    if (flags & NodeMightClobber) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MightClobber");
+        hasPrinted = true;
+    }
     
     if (flags & NodeResultMask) {
-        if (!(flags & NodeUsedAsNumber) && !(flags & NodeNeedsNegZero))
-            out.print(comma, "PureInt");
-        else if (!(flags & NodeUsedAsNumber))
-            out.print(comma, "PureInt(w/ neg zero)");
-        else if (!(flags & NodeNeedsNegZero))
-            out.print(comma, "PureNum");
-        if (flags & NodeUsedAsOther)
-            out.print(comma, "UseAsOther");
+        if (!(flags & NodeUsedAsNumber) && !(flags & NodeNeedsNegZero)) {
+            if (hasPrinted)
+                ptr.strcat("|");
+            ptr.strcat("PureInt");
+            hasPrinted = true;
+        } else if (!(flags & NodeUsedAsNumber)) {
+            if (hasPrinted)
+                ptr.strcat("|");
+            ptr.strcat("PureInt(w/ neg zero)");
+            hasPrinted = true;
+        } else if (!(flags & NodeNeedsNegZero)) {
+            if (hasPrinted)
+                ptr.strcat("|");
+            ptr.strcat("PureNum");
+            hasPrinted = true;
+        }
+        if (flags & NodeUsedAsOther) {
+            if (hasPrinted)
+                ptr.strcat("|");
+            ptr.strcat("UseAsOther");
+            hasPrinted = true;
+        }
     }
     
-    if (flags & NodeMayOverflow)
-        out.print(comma, "MayOverflow");
+    if (flags & NodeMayOverflow) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MayOverflow");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeMayNegZero) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MayNegZero");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeUsedAsInt) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("UseAsInt");
+        hasPrinted = true;
+    }
     
-    if (flags & NodeMayNegZero)
-        out.print(comma, "MayNegZero");
+    if (!(flags & NodeDoesNotExit)) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("CanExit");
+        hasPrinted = true;
+    }
     
-    if (flags & NodeUsedAsInt)
-        out.print(comma, "UseAsInt");
+    if (flags & NodeExitsForward) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("NodeExitsForward");
+        hasPrinted = true;
+    }
     
-    if (!(flags & NodeDoesNotExit))
-        out.print(comma, "CanExit");
+    *ptr++ = 0;
     
-    if (flags & NodeExitsForward)
-        out.print(comma, "NodeExitsForward");
+    return description;
 }
 
+
 } } // namespace JSC::DFG
 
 #endif // ENABLE(DFG_JIT)
index 926f371..b352d16 100644 (file)
@@ -30,7 +30,6 @@
 
 #if ENABLE(DFG_JIT)
 
-#include <wtf/PrintStream.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC { namespace DFG {
@@ -60,14 +59,15 @@ namespace JSC { namespace DFG {
 #define NodeUsedAsOther          0x0800 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
 #define NodeUsedAsValue          (NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther)
 #define NodeUsedAsInt            0x1000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
+#define NodeUsedAsIntLocally     0x2000 // Same as NodeUsedAsInt, but within the same basic block.
 
 #define NodeArithFlagsMask       (NodeBehaviorMask | NodeBackPropMask)
 
-#define NodeDoesNotExit          0x2000 // This flag is negated to make it natural for the default to be that a node does exit.
+#define NodeDoesNotExit          0x4000 // This flag is negated to make it natural for the default to be that a node does exit.
 
-#define NodeRelevantToOSR        0x4000
+#define NodeRelevantToOSR        0x8000
 
-#define NodeExitsForward         0x8000
+#define NodeExitsForward        0x10000
 
 typedef uint32_t NodeFlags;
 
@@ -102,8 +102,7 @@ static inline bool nodeCanSpeculateInteger(NodeFlags flags)
     return true;
 }
 
-void dumpNodeFlags(PrintStream&, NodeFlags);
-MAKE_PRINT_ADAPTOR(NodeFlagsDump, NodeFlags, dumpNodeFlags);
+const char* nodeFlagsAsString(NodeFlags);
 
 } } // namespace JSC::DFG
 
index c041361..e5b5925 100644 (file)
@@ -106,6 +106,65 @@ private:
         return m_currentNode->predict(prediction);
     }
     
+    bool isNotNegZero(Node* node)
+    {
+        if (!m_graph.isNumberConstant(node))
+            return false;
+        double value = m_graph.valueOfNumberConstant(node);
+        return !value && 1.0 / value < 0.0;
+    }
+    
+    bool isNotZero(Node* node)
+    {
+        if (!m_graph.isNumberConstant(node))
+            return false;
+        return !!m_graph.valueOfNumberConstant(node);
+    }
+    
+    bool isWithinPowerOfTwoForConstant(Node* node, int power)
+    {
+        JSValue immediateValue = node->valueOfJSConstant(codeBlock());
+        if (!immediateValue.isInt32())
+            return false;
+        int32_t intImmediate = immediateValue.asInt32();
+        return intImmediate > -(1 << power) && intImmediate < (1 << power);
+    }
+    
+    bool isWithinPowerOfTwoNonRecursive(Node* node, int power)
+    {
+        if (node->op() != JSConstant)
+            return false;
+        return isWithinPowerOfTwoForConstant(node, power);
+    }
+    
+    bool isWithinPowerOfTwo(Node* node, int power)
+    {
+        switch (node->op()) {
+        case JSConstant: {
+            return isWithinPowerOfTwoForConstant(node, power);
+        }
+            
+        case BitAnd: {
+            return isWithinPowerOfTwoNonRecursive(node->child1().node(), power)
+                || isWithinPowerOfTwoNonRecursive(node->child2().node(), power);
+        }
+            
+        case BitRShift:
+        case BitURShift: {
+            Node* shiftAmount = node->child2().node();
+            if (shiftAmount->op() != JSConstant)
+                return false;
+            JSValue immediateValue = shiftAmount->valueOfJSConstant(codeBlock());
+            if (!immediateValue.isInt32())
+                return false;
+            return immediateValue > 32 - power;
+        }
+            
+        default:
+            return false;
+        }
+    }
+
     SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
     {
         if (!isNumberSpeculation(value))
@@ -123,9 +182,10 @@ private:
     void propagate(Node* node)
     {
         NodeType op = node->op();
+        NodeFlags flags = node->flags() & NodeBackPropMask;
 
 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-        dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", NodeFlagsDump(node->flags()), " ");
+        dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", nodeFlagsAsString(flags), " ");
 #endif
         
         bool changed = false;
@@ -142,12 +202,29 @@ private:
             SpeculatedType prediction = variableAccessData->prediction();
             if (prediction)
                 changed |= mergePrediction(prediction);
+            
+            // Assume conservatively that a SetLocal implies that the value may flow through a loop,
+            // and so we would have overflow leading to the program "observing" numbers even if all
+            // users of the value are doing toInt32. It might be worthwhile to revisit this at some
+            // point and actually check if the data flow involves loops, but right now I don't think
+            // we have evidence that this would be beneficial for benchmarks.
+            
+            changed |= variableAccessData->mergeFlags((flags & ~NodeUsedAsIntLocally) | NodeUsedAsNumber);
             break;
         }
             
         case SetLocal: {
             VariableAccessData* variableAccessData = node->variableAccessData();
             changed |= variableAccessData->predict(node->child1()->prediction());
+
+            changed |= node->child1()->mergeFlags(variableAccessData->flags());
+            break;
+        }
+            
+        case Flush: {
+            // Make sure that the analysis knows that flushed locals escape.
+            VariableAccessData* variableAccessData = node->variableAccessData();
+            changed |= variableAccessData->mergeFlags(NodeUsedAsValue);
             break;
         }
             
@@ -158,36 +235,45 @@ private:
         case BitLShift:
         case BitURShift: {
             changed |= setPrediction(SpecInt32);
+            flags |= NodeUsedAsInt | NodeUsedAsIntLocally;
+            flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
         case ValueToInt32: {
             changed |= setPrediction(SpecInt32);
+            flags |= NodeUsedAsInt | NodeUsedAsIntLocally;
+            flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
+            changed |= node->child1()->mergeFlags(flags);
             break;
         }
             
-        case ArrayPop:
-        case ArrayPush:
+        case ArrayPop: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+
+        case ArrayPush: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child2()->mergeFlags(NodeUsedAsValue);
+            break;
+        }
+
         case RegExpExec:
-        case RegExpTest:
-        case GetById:
-        case GetByIdFlush:
-        case GetMyArgumentByValSafe:
-        case GetByOffset:
-        case Call:
-        case Construct:
-        case GetGlobalVar:
-        case GetScopedVar:
-        case Resolve:
-        case ResolveBase:
-        case ResolveBaseStrictPut:
-        case ResolveGlobal: {
-            changed |= setPrediction(node->getHeapPrediction());
+        case RegExpTest: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
             break;
         }
 
         case StringCharCodeAt: {
-            changed |= setPrediction(SpecInt32);
+            changed |= mergePrediction(SpecInt32);
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
             break;
         }
 
@@ -196,6 +282,8 @@ private:
                 changed |= mergePrediction(SpecInt32);
             else
                 changed |= mergePrediction(SpecNumber);
+            
+            changed |= node->child1()->mergeFlags(flags);
             break;
         }
 
@@ -203,9 +291,11 @@ private:
             SpeculatedType left = node->child1()->prediction();
             SpeculatedType right = node->child2()->prediction();
             
+            AddSpeculationMode mode = DontSpeculateInteger;
+            
             if (left && right) {
                 if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
-                    if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
+                    if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
                         changed |= mergePrediction(SpecInt32);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
@@ -215,6 +305,17 @@ private:
                 } else
                     changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
             }
+            
+            if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
+                flags &= ~NodeNeedsNegZero;
+            if (node->child1()->hasNumberResult() || node->child2()->hasNumberResult())
+                flags &= ~NodeUsedAsOther;
+            
+            if (mode != SpeculateInteger)
+                flags |= NodeUsedAsNumber;
+            
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
@@ -222,12 +323,24 @@ private:
             SpeculatedType left = node->child1()->prediction();
             SpeculatedType right = node->child2()->prediction();
             
+            AddSpeculationMode mode = DontSpeculateInteger;
+            
             if (left && right) {
-                if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
+                if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
                     changed |= mergePrediction(SpecInt32);
                 else
                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
             }
+            
+            if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
+                flags &= ~NodeNeedsNegZero;
+            flags &= ~NodeUsedAsOther;
+            
+            if (mode != SpeculateInteger)
+                flags |= NodeUsedAsNumber;
+            
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
@@ -235,12 +348,24 @@ private:
             SpeculatedType left = node->child1()->prediction();
             SpeculatedType right = node->child2()->prediction();
             
+            AddSpeculationMode mode = DontSpeculateInteger;
+            
             if (left && right) {
-                if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
+                if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
                     changed |= mergePrediction(SpecInt32);
                 else
                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
             }
+
+            if (isNotZero(node->child1().node()) || isNotZero(node->child2().node()))
+                flags &= ~NodeNeedsNegZero;
+            flags &= ~NodeUsedAsOther;
+            
+            if (mode != SpeculateInteger)
+                flags |= NodeUsedAsNumber;
+            
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
@@ -251,6 +376,10 @@ private:
                 else
                     changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
             }
+
+            flags &= ~NodeUsedAsOther;
+
+            changed |= node->child1()->mergeFlags(flags);
             break;
             
         case ArithMin:
@@ -265,6 +394,12 @@ private:
                 else
                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
             }
+
+            flags |= NodeUsedAsNumber;
+            flags &= ~NodeUsedAsOther;
+
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
 
@@ -278,6 +413,25 @@ private:
                 else
                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
             }
+
+            // 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 forces its inputs to
+            // check for overflow. Additionally, it will have to check for overflow
+            // itself unless we can prove that there is no way for the values
+            // produced to cause double rounding.
+            
+            if (!isWithinPowerOfTwo(node->child1().node(), 22)
+                && !isWithinPowerOfTwo(node->child2().node(), 22))
+                flags |= NodeUsedAsNumber;
+            
+            changed |= node->mergeFlags(flags);
+            
+            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+            flags &= ~NodeUsedAsOther;
+
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
@@ -292,6 +446,17 @@ private:
                 else
                     changed |= mergePrediction(SpecDouble);
             }
+
+            // 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, ArithDiv always checks for overflow
+            // no matter what, and always forces its inputs to check as well.
+            
+            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+            flags &= ~NodeUsedAsOther;
+
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
@@ -306,11 +471,20 @@ private:
                 else
                     changed |= mergePrediction(SpecDouble);
             }
+            
+            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+            flags &= ~NodeUsedAsOther;
+
+            changed |= node->child1()->mergeFlags(flags);
+            changed |= node->child2()->mergeFlags(flags);
             break;
         }
             
         case ArithSqrt: {
             changed |= setPrediction(SpecDouble);
+            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+            flags &= ~NodeUsedAsOther;
+            changed |= node->child1()->mergeFlags(flags);
             break;
         }
             
@@ -321,6 +495,8 @@ private:
                 changed |= mergePrediction(SpecInt32);
             else
                 changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
+
+            changed |= node->child1()->mergeFlags(flags);
             break;
         }
             
@@ -341,20 +517,42 @@ private:
         case IsObject:
         case IsFunction: {
             changed |= setPrediction(SpecBoolean);
+            changed |= mergeDefaultFlags(node);
             break;
         }
 
         case TypeOf: {
             changed |= setPrediction(SpecString);
+            changed |= mergeDefaultFlags(node);
             break;
         }
 
+        case GetById: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case GetByIdFlush:
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+            
         case GetByVal: {
             if (node->child1()->shouldSpeculateFloat32Array()
                 || node->child1()->shouldSpeculateFloat64Array())
                 changed |= mergePrediction(SpecDouble);
             else
                 changed |= mergePrediction(node->getHeapPrediction());
+
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
+            break;
+        }
+            
+        case GetMyArgumentByValSafe: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
             break;
         }
             
@@ -369,9 +567,26 @@ private:
         case AllocatePropertyStorage:
         case ReallocatePropertyStorage: {
             changed |= setPrediction(SpecOther);
+            changed |= mergeDefaultFlags(node);
             break;
         }
 
+        case GetByOffset: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case Call:
+        case Construct: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            for (unsigned childIdx = node->firstChild();
+                childIdx < node->firstChild() + node->numChildren();
+                ++childIdx)
+                changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
+            break;
+        }
+            
         case ConvertThis: {
             SpeculatedType prediction = node->child1()->prediction();
             if (prediction) {
@@ -381,6 +596,28 @@ private:
                 }
                 changed |= mergePrediction(prediction);
             }
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case GetGlobalVar: {
+            changed |= mergePrediction(node->getHeapPrediction());
+            break;
+        }
+            
+        case PutGlobalVar:
+        case PutGlobalVarCheck: {
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            break;
+        }
+            
+        case GetScopedVar:
+        case Resolve:
+        case ResolveBase:
+        case ResolveBaseStrictPut:
+        case ResolveGlobal: {
+            SpeculatedType prediction = node->getHeapPrediction();
+            changed |= mergePrediction(prediction);
             break;
         }
             
@@ -399,25 +636,48 @@ private:
         case CreateThis:
         case NewObject: {
             changed |= setPrediction(SpecFinalObject);
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case NewArray: {
+            changed |= setPrediction(SpecArray);
+            for (unsigned childIdx = node->firstChild();
+                childIdx < node->firstChild() + node->numChildren();
+                ++childIdx)
+                changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
+            break;
+        }
+            
+        case NewArrayWithSize: {
+            changed |= setPrediction(SpecArray);
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt | NodeUsedAsIntLocally);
             break;
         }
             
-        case NewArray:
-        case NewArrayWithSize:
         case NewArrayBuffer: {
             changed |= setPrediction(SpecArray);
             break;
         }
             
-        case NewRegexp:
-        case CreateActivation: {
+        case NewRegexp: {
             changed |= setPrediction(SpecObjectOther);
             break;
         }
         
-        case StringCharAt:
+        case StringCharAt: {
+            changed |= setPrediction(SpecString);
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
+            break;
+        }
+            
         case StrCat: {
             changed |= setPrediction(SpecString);
+            for (unsigned childIdx = node->firstChild();
+                childIdx < node->firstChild() + node->numChildren();
+                ++childIdx)
+                changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);
             break;
         }
             
@@ -439,6 +699,12 @@ private:
                 } else
                     changed |= mergePrediction(child);
             }
+            changed |= node->child1()->mergeFlags(flags);
+            break;
+        }
+            
+        case CreateActivation: {
+            changed |= setPrediction(SpecObjectOther);
             break;
         }
             
@@ -477,27 +743,51 @@ private:
             break;
         }
         
+        case PutByVal:
+            changed |= m_graph.varArgChild(node, 0)->mergeFlags(NodeUsedAsValue);
+            changed |= m_graph.varArgChild(node, 1)->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
+            changed |= m_graph.varArgChild(node, 2)->mergeFlags(NodeUsedAsValue);
+            break;
+
+        case PutScopedVar:
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child3()->mergeFlags(NodeUsedAsValue);
+            break;
+            
+        case Return:
+        case Throw:
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            break;
+
+        case PutById:
+        case PutByIdDirect:
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child2()->mergeFlags(NodeUsedAsValue);
+            break;
+
+        case PutByOffset:
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            changed |= node->child3()->mergeFlags(NodeUsedAsValue);
+            break;
+            
         case Phi:
             // Phis should not be visible here since we're iterating the all-but-Phi's
             // part of basic blocks.
             CRASH();
             break;
 
+        case SetCallee:
+        case SetMyScope:
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            break;
+            
         case GetScope:
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
             changed |= setPrediction(SpecCellOther);
             break;
 
 #ifndef NDEBUG
         // These get ignored because they don't return anything.
-        case PutByVal:
-        case PutScopedVar:
-        case Return:
-        case Throw:
-        case PutById:
-        case PutByIdDirect:
-        case PutByOffset:
-        case SetCallee:
-        case SetMyScope:
         case DFG::Jump:
         case Branch:
         case Breakpoint:
@@ -519,8 +809,7 @@ private:
         case GarbageValue:
         case AllocationProfileWatchpoint:
         case Phantom:
-        case PutGlobalVar:
-        case PutGlobalVarCheck:
+            changed |= mergeDefaultFlags(node);
             break;
             
         // These gets ignored because it doesn't do anything.
@@ -528,7 +817,6 @@ private:
         case Nop:
         case CountExecution:
         case PhantomLocal:
-        case Flush:
             break;
             
         case LastNodeType:
@@ -536,6 +824,7 @@ private:
             break;
 #else
         default:
+            changed |= mergeDefaultFlags(node);
             break;
 #endif
         }
@@ -547,6 +836,30 @@ private:
         m_changed |= changed;
     }
         
+    bool mergeDefaultFlags(Node* node)
+    {
+        bool changed = false;
+        if (node->flags() & NodeHasVarArgs) {
+            for (unsigned childIdx = node->firstChild();
+                childIdx < node->firstChild() + node->numChildren();
+                childIdx++) {
+                if (!!m_graph.m_varArgChildren[childIdx])
+                    changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
+            }
+        } else {
+            if (!node->child1())
+                return changed;
+            changed |= node->child1()->mergeFlags(NodeUsedAsValue);
+            if (!node->child2())
+                return changed;
+            changed |= node->child2()->mergeFlags(NodeUsedAsValue);
+            if (!node->child3())
+                return changed;
+            changed |= node->child3()->mergeFlags(NodeUsedAsValue);
+        }
+        return changed;
+    }
+    
     void propagateForward()
     {
 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
index 9109f09..f906a23 100644 (file)
@@ -73,7 +73,6 @@ public:
             data->find()->mergeIsCaptured(data->isCaptured());
             data->find()->mergeStructureCheckHoistingFailed(data->structureCheckHoistingFailed());
             data->find()->mergeShouldNeverUnbox(data->shouldNeverUnbox());
-            data->find()->mergeIsLoadedFrom(data->isLoadedFrom());
         }
         
         m_graph.m_unificationState = GloballyUnified;
index feb0247..c836c1e 100644 (file)
@@ -51,7 +51,6 @@ public:
         , m_isArgumentsAlias(false)
         , m_structureCheckHoistingFailed(false)
         , m_isProfitableToUnbox(false)
-        , m_isLoadedFrom(false)
         , m_doubleFormatState(EmptyDoubleFormatState)
     {
         clearVotes();
@@ -150,21 +149,6 @@ public:
         return m_isArgumentsAlias;
     }
     
-    bool mergeIsLoadedFrom(bool isLoadedFrom)
-    {
-        return checkAndSet(m_isLoadedFrom, m_isLoadedFrom | isLoadedFrom);
-    }
-    
-    void setIsLoadedFrom(bool isLoadedFrom)
-    {
-        m_isLoadedFrom = isLoadedFrom;
-    }
-    
-    bool isLoadedFrom()
-    {
-        return m_isLoadedFrom;
-    }
-    
     bool predict(SpeculatedType prediction)
     {
         VariableAccessData* self = find();
@@ -322,7 +306,6 @@ private:
     bool m_isArgumentsAlias;
     bool m_structureCheckHoistingFailed;
     bool m_isProfitableToUnbox;
-    bool m_isLoadedFrom;
 
     float m_votes[2]; // Used primarily for double voting but may be reused for other purposes.
     DoubleFormatState m_doubleFormatState;