From: fpizlo@apple.com Date: Wed, 27 Jun 2012 01:34:01 +0000 (+0000) Subject: DFG PutByValAlias is too aggressive X-Git-Tag: 070512121124~580 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=580d9d77178206b1e73fe951f843a4a0cc0501bb;p=profile%2Fivi%2Fwebkit-efl.git DFG PutByValAlias is too aggressive https://bugs.webkit.org/show_bug.cgi?id=90026 Source/JavaScriptCore: Reviewed by Gavin Barraclough. For CSE on normal arrays, we now treat PutByVal as impure. This does not appear to affect performance by much. For CSE on typed arrays, we fix PutByValAlias by making GetByVal speculate that the access is within bounds. This also has the effect of making our out-of-bounds handling consistent with WebCore. * dfg/DFGCSEPhase.cpp: (JSC::DFG::CSEPhase::performNodeCSE): * dfg/DFGGraph.h: (JSC::DFG::Graph::byValIsPure): (JSC::DFG::Graph::clobbersWorld): * dfg/DFGNodeType.h: (DFG): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): LayoutTests: Reviewed by Gavin Barraclough. * fast/js/dfg-put-by-val-setter-then-get-by-val-expected.txt: Added. * fast/js/dfg-put-by-val-setter-then-get-by-val.html: Added. * fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias-expected.txt: Added. * fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.html: Added. * fast/js/script-tests/dfg-put-by-val-setter-then-get-by-val.js: Added. (foo): (for): * fast/js/script-tests/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.js: Added. (foo): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121307 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index 6e39859..7ac509d 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,21 @@ +2012-06-26 Filip Pizlo + + DFG PutByValAlias is too aggressive + https://bugs.webkit.org/show_bug.cgi?id=90026 + + + Reviewed by Gavin Barraclough. + + * fast/js/dfg-put-by-val-setter-then-get-by-val-expected.txt: Added. + * fast/js/dfg-put-by-val-setter-then-get-by-val.html: Added. + * fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias-expected.txt: Added. + * fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.html: Added. + * fast/js/script-tests/dfg-put-by-val-setter-then-get-by-val.js: Added. + (foo): + (for): + * fast/js/script-tests/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.js: Added. + (foo): + 2012-06-26 Kevin Ellis Touch adjustment does not target shadow DOM elements diff --git a/LayoutTests/fast/js/dfg-put-by-val-setter-then-get-by-val-expected.txt b/LayoutTests/fast/js/dfg-put-by-val-setter-then-get-by-val-expected.txt new file mode 100644 index 0000000..52ab432 --- /dev/null +++ b/LayoutTests/fast/js/dfg-put-by-val-setter-then-get-by-val-expected.txt @@ -0,0 +1,409 @@ +Tests that a GetByVal that accesses a value that was PutByVal'd, but where the PutByVal invoked a setter, works correctly. + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS foo(array, -1, i) is 42 +PASS thingy is 0 +PASS foo(array, -1, i) is 42 +PASS thingy is 1 +PASS foo(array, -1, i) is 42 +PASS thingy is 2 +PASS foo(array, -1, i) is 42 +PASS thingy is 3 +PASS foo(array, -1, i) is 42 +PASS thingy is 4 +PASS foo(array, -1, i) is 42 +PASS thingy is 5 +PASS foo(array, -1, i) is 42 +PASS thingy is 6 +PASS foo(array, -1, i) is 42 +PASS thingy is 7 +PASS foo(array, -1, i) is 42 +PASS thingy is 8 +PASS foo(array, -1, i) is 42 +PASS thingy is 9 +PASS foo(array, -1, i) is 42 +PASS thingy is 10 +PASS foo(array, -1, i) is 42 +PASS thingy is 11 +PASS foo(array, -1, i) is 42 +PASS thingy is 12 +PASS foo(array, -1, i) is 42 +PASS thingy is 13 +PASS foo(array, -1, i) is 42 +PASS thingy is 14 +PASS foo(array, -1, i) is 42 +PASS thingy is 15 +PASS foo(array, -1, i) is 42 +PASS thingy is 16 +PASS foo(array, -1, i) is 42 +PASS thingy is 17 +PASS foo(array, -1, i) is 42 +PASS thingy is 18 +PASS foo(array, -1, i) is 42 +PASS thingy is 19 +PASS foo(array, -1, i) is 42 +PASS thingy is 20 +PASS foo(array, -1, i) is 42 +PASS thingy is 21 +PASS foo(array, -1, i) is 42 +PASS thingy is 22 +PASS foo(array, -1, i) is 42 +PASS thingy is 23 +PASS foo(array, -1, i) is 42 +PASS thingy is 24 +PASS foo(array, -1, i) is 42 +PASS thingy is 25 +PASS foo(array, -1, i) is 42 +PASS thingy is 26 +PASS foo(array, -1, i) is 42 +PASS thingy is 27 +PASS foo(array, -1, i) is 42 +PASS thingy is 28 +PASS foo(array, -1, i) is 42 +PASS thingy is 29 +PASS foo(array, -1, i) is 42 +PASS thingy is 30 +PASS foo(array, -1, i) is 42 +PASS thingy is 31 +PASS foo(array, -1, i) is 42 +PASS thingy is 32 +PASS foo(array, -1, i) is 42 +PASS thingy is 33 +PASS foo(array, -1, i) is 42 +PASS thingy is 34 +PASS foo(array, -1, i) is 42 +PASS thingy is 35 +PASS foo(array, -1, i) is 42 +PASS thingy is 36 +PASS foo(array, -1, i) is 42 +PASS thingy is 37 +PASS foo(array, -1, i) is 42 +PASS thingy is 38 +PASS foo(array, -1, i) is 42 +PASS thingy is 39 +PASS foo(array, -1, i) is 42 +PASS thingy is 40 +PASS foo(array, -1, i) is 42 +PASS thingy is 41 +PASS foo(array, -1, i) is 42 +PASS thingy is 42 +PASS foo(array, -1, i) is 42 +PASS thingy is 43 +PASS foo(array, -1, i) is 42 +PASS thingy is 44 +PASS foo(array, -1, i) is 42 +PASS thingy is 45 +PASS foo(array, -1, i) is 42 +PASS thingy is 46 +PASS foo(array, -1, i) is 42 +PASS thingy is 47 +PASS foo(array, -1, i) is 42 +PASS thingy is 48 +PASS foo(array, -1, i) is 42 +PASS thingy is 49 +PASS foo(array, -1, i) is 42 +PASS thingy is 50 +PASS foo(array, -1, i) is 42 +PASS thingy is 51 +PASS foo(array, -1, i) is 42 +PASS thingy is 52 +PASS foo(array, -1, i) is 42 +PASS thingy is 53 +PASS foo(array, -1, i) is 42 +PASS thingy is 54 +PASS foo(array, -1, i) is 42 +PASS thingy is 55 +PASS foo(array, -1, i) is 42 +PASS thingy is 56 +PASS foo(array, -1, i) is 42 +PASS thingy is 57 +PASS foo(array, -1, i) is 42 +PASS thingy is 58 +PASS foo(array, -1, i) is 42 +PASS thingy is 59 +PASS foo(array, -1, i) is 42 +PASS thingy is 60 +PASS foo(array, -1, i) is 42 +PASS thingy is 61 +PASS foo(array, -1, i) is 42 +PASS thingy is 62 +PASS foo(array, -1, i) is 42 +PASS thingy is 63 +PASS foo(array, -1, i) is 42 +PASS thingy is 64 +PASS foo(array, -1, i) is 42 +PASS thingy is 65 +PASS foo(array, -1, i) is 42 +PASS thingy is 66 +PASS foo(array, -1, i) is 42 +PASS thingy is 67 +PASS foo(array, -1, i) is 42 +PASS thingy is 68 +PASS foo(array, -1, i) is 42 +PASS thingy is 69 +PASS foo(array, -1, i) is 42 +PASS thingy is 70 +PASS foo(array, -1, i) is 42 +PASS thingy is 71 +PASS foo(array, -1, i) is 42 +PASS thingy is 72 +PASS foo(array, -1, i) is 42 +PASS thingy is 73 +PASS foo(array, -1, i) is 42 +PASS thingy is 74 +PASS foo(array, -1, i) is 42 +PASS thingy is 75 +PASS foo(array, -1, i) is 42 +PASS thingy is 76 +PASS foo(array, -1, i) is 42 +PASS thingy is 77 +PASS foo(array, -1, i) is 42 +PASS thingy is 78 +PASS foo(array, -1, i) is 42 +PASS thingy is 79 +PASS foo(array, -1, i) is 42 +PASS thingy is 80 +PASS foo(array, -1, i) is 42 +PASS thingy is 81 +PASS foo(array, -1, i) is 42 +PASS thingy is 82 +PASS foo(array, -1, i) is 42 +PASS thingy is 83 +PASS foo(array, -1, i) is 42 +PASS thingy is 84 +PASS foo(array, -1, i) is 42 +PASS thingy is 85 +PASS foo(array, -1, i) is 42 +PASS thingy is 86 +PASS foo(array, -1, i) is 42 +PASS thingy is 87 +PASS foo(array, -1, i) is 42 +PASS thingy is 88 +PASS foo(array, -1, i) is 42 +PASS thingy is 89 +PASS foo(array, -1, i) is 42 +PASS thingy is 90 +PASS foo(array, -1, i) is 42 +PASS thingy is 91 +PASS foo(array, -1, i) is 42 +PASS thingy is 92 +PASS foo(array, -1, i) is 42 +PASS thingy is 93 +PASS foo(array, -1, i) is 42 +PASS thingy is 94 +PASS foo(array, -1, i) is 42 +PASS thingy is 95 +PASS foo(array, -1, i) is 42 +PASS thingy is 96 +PASS foo(array, -1, i) is 42 +PASS thingy is 97 +PASS foo(array, -1, i) is 42 +PASS thingy is 98 +PASS foo(array, -1, i) is 42 +PASS thingy is 99 +PASS foo(array, -1, i) is 42 +PASS thingy is 100 +PASS foo(array, -1, i) is 42 +PASS thingy is 101 +PASS foo(array, -1, i) is 42 +PASS thingy is 102 +PASS foo(array, -1, i) is 42 +PASS thingy is 103 +PASS foo(array, -1, i) is 42 +PASS thingy is 104 +PASS foo(array, -1, i) is 42 +PASS thingy is 105 +PASS foo(array, -1, i) is 42 +PASS thingy is 106 +PASS foo(array, -1, i) is 42 +PASS thingy is 107 +PASS foo(array, -1, i) is 42 +PASS thingy is 108 +PASS foo(array, -1, i) is 42 +PASS thingy is 109 +PASS foo(array, -1, i) is 42 +PASS thingy is 110 +PASS foo(array, -1, i) is 42 +PASS thingy is 111 +PASS foo(array, -1, i) is 42 +PASS thingy is 112 +PASS foo(array, -1, i) is 42 +PASS thingy is 113 +PASS foo(array, -1, i) is 42 +PASS thingy is 114 +PASS foo(array, -1, i) is 42 +PASS thingy is 115 +PASS foo(array, -1, i) is 42 +PASS thingy is 116 +PASS foo(array, -1, i) is 42 +PASS thingy is 117 +PASS foo(array, -1, i) is 42 +PASS thingy is 118 +PASS foo(array, -1, i) is 42 +PASS thingy is 119 +PASS foo(array, -1, i) is 42 +PASS thingy is 120 +PASS foo(array, -1, i) is 42 +PASS thingy is 121 +PASS foo(array, -1, i) is 42 +PASS thingy is 122 +PASS foo(array, -1, i) is 42 +PASS thingy is 123 +PASS foo(array, -1, i) is 42 +PASS thingy is 124 +PASS foo(array, -1, i) is 42 +PASS thingy is 125 +PASS foo(array, -1, i) is 42 +PASS thingy is 126 +PASS foo(array, -1, i) is 42 +PASS thingy is 127 +PASS foo(array, -1, i) is 42 +PASS thingy is 128 +PASS foo(array, -1, i) is 42 +PASS thingy is 129 +PASS foo(array, -1, i) is 42 +PASS thingy is 130 +PASS foo(array, -1, i) is 42 +PASS thingy is 131 +PASS foo(array, -1, i) is 42 +PASS thingy is 132 +PASS foo(array, -1, i) is 42 +PASS thingy is 133 +PASS foo(array, -1, i) is 42 +PASS thingy is 134 +PASS foo(array, -1, i) is 42 +PASS thingy is 135 +PASS foo(array, -1, i) is 42 +PASS thingy is 136 +PASS foo(array, -1, i) is 42 +PASS thingy is 137 +PASS foo(array, -1, i) is 42 +PASS thingy is 138 +PASS foo(array, -1, i) is 42 +PASS thingy is 139 +PASS foo(array, -1, i) is 42 +PASS thingy is 140 +PASS foo(array, -1, i) is 42 +PASS thingy is 141 +PASS foo(array, -1, i) is 42 +PASS thingy is 142 +PASS foo(array, -1, i) is 42 +PASS thingy is 143 +PASS foo(array, -1, i) is 42 +PASS thingy is 144 +PASS foo(array, -1, i) is 42 +PASS thingy is 145 +PASS foo(array, -1, i) is 42 +PASS thingy is 146 +PASS foo(array, -1, i) is 42 +PASS thingy is 147 +PASS foo(array, -1, i) is 42 +PASS thingy is 148 +PASS foo(array, -1, i) is 42 +PASS thingy is 149 +PASS foo(array, -1, i) is 42 +PASS thingy is 150 +PASS foo(array, -1, i) is 42 +PASS thingy is 151 +PASS foo(array, -1, i) is 42 +PASS thingy is 152 +PASS foo(array, -1, i) is 42 +PASS thingy is 153 +PASS foo(array, -1, i) is 42 +PASS thingy is 154 +PASS foo(array, -1, i) is 42 +PASS thingy is 155 +PASS foo(array, -1, i) is 42 +PASS thingy is 156 +PASS foo(array, -1, i) is 42 +PASS thingy is 157 +PASS foo(array, -1, i) is 42 +PASS thingy is 158 +PASS foo(array, -1, i) is 42 +PASS thingy is 159 +PASS foo(array, -1, i) is 42 +PASS thingy is 160 +PASS foo(array, -1, i) is 42 +PASS thingy is 161 +PASS foo(array, -1, i) is 42 +PASS thingy is 162 +PASS foo(array, -1, i) is 42 +PASS thingy is 163 +PASS foo(array, -1, i) is 42 +PASS thingy is 164 +PASS foo(array, -1, i) is 42 +PASS thingy is 165 +PASS foo(array, -1, i) is 42 +PASS thingy is 166 +PASS foo(array, -1, i) is 42 +PASS thingy is 167 +PASS foo(array, -1, i) is 42 +PASS thingy is 168 +PASS foo(array, -1, i) is 42 +PASS thingy is 169 +PASS foo(array, -1, i) is 42 +PASS thingy is 170 +PASS foo(array, -1, i) is 42 +PASS thingy is 171 +PASS foo(array, -1, i) is 42 +PASS thingy is 172 +PASS foo(array, -1, i) is 42 +PASS thingy is 173 +PASS foo(array, -1, i) is 42 +PASS thingy is 174 +PASS foo(array, -1, i) is 42 +PASS thingy is 175 +PASS foo(array, -1, i) is 42 +PASS thingy is 176 +PASS foo(array, -1, i) is 42 +PASS thingy is 177 +PASS foo(array, -1, i) is 42 +PASS thingy is 178 +PASS foo(array, -1, i) is 42 +PASS thingy is 179 +PASS foo(array, -1, i) is 42 +PASS thingy is 180 +PASS foo(array, -1, i) is 42 +PASS thingy is 181 +PASS foo(array, -1, i) is 42 +PASS thingy is 182 +PASS foo(array, -1, i) is 42 +PASS thingy is 183 +PASS foo(array, -1, i) is 42 +PASS thingy is 184 +PASS foo(array, -1, i) is 42 +PASS thingy is 185 +PASS foo(array, -1, i) is 42 +PASS thingy is 186 +PASS foo(array, -1, i) is 42 +PASS thingy is 187 +PASS foo(array, -1, i) is 42 +PASS thingy is 188 +PASS foo(array, -1, i) is 42 +PASS thingy is 189 +PASS foo(array, -1, i) is 42 +PASS thingy is 190 +PASS foo(array, -1, i) is 42 +PASS thingy is 191 +PASS foo(array, -1, i) is 42 +PASS thingy is 192 +PASS foo(array, -1, i) is 42 +PASS thingy is 193 +PASS foo(array, -1, i) is 42 +PASS thingy is 194 +PASS foo(array, -1, i) is 42 +PASS thingy is 195 +PASS foo(array, -1, i) is 42 +PASS thingy is 196 +PASS foo(array, -1, i) is 42 +PASS thingy is 197 +PASS foo(array, -1, i) is 42 +PASS thingy is 198 +PASS foo(array, -1, i) is 42 +PASS thingy is 199 +PASS successfullyParsed is true + +TEST COMPLETE + diff --git a/LayoutTests/fast/js/dfg-put-by-val-setter-then-get-by-val.html b/LayoutTests/fast/js/dfg-put-by-val-setter-then-get-by-val.html new file mode 100644 index 0000000..03f0a09 --- /dev/null +++ b/LayoutTests/fast/js/dfg-put-by-val-setter-then-get-by-val.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/LayoutTests/fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias-expected.txt b/LayoutTests/fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias-expected.txt new file mode 100644 index 0000000..08a397f --- /dev/null +++ b/LayoutTests/fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias-expected.txt @@ -0,0 +1,209 @@ +Tests that out-of-bounds stores to a Uint8ClampedArray that are aliased to out-of-bounds loads don't crash. + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS foo(array, 100000000, 42) is undefined +PASS successfullyParsed is true + +TEST COMPLETE + diff --git a/LayoutTests/fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.html b/LayoutTests/fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.html new file mode 100644 index 0000000..434455e --- /dev/null +++ b/LayoutTests/fast/js/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/LayoutTests/fast/js/script-tests/dfg-put-by-val-setter-then-get-by-val.js b/LayoutTests/fast/js/script-tests/dfg-put-by-val-setter-then-get-by-val.js new file mode 100644 index 0000000..a57b18b --- /dev/null +++ b/LayoutTests/fast/js/script-tests/dfg-put-by-val-setter-then-get-by-val.js @@ -0,0 +1,23 @@ +description( +"Tests that a GetByVal that accesses a value that was PutByVal'd, but where the PutByVal invoked a setter, works correctly." +); + +function foo(a, i, v) { + a[i] = v; + return a[i]; +} + +var array = []; +var thingy; +array.__defineSetter__( + "-1", function(x) { thingy = x; } +); +array.__defineGetter__( + "-1", function() { return 42; } +); + +for (var i = 0; i < 200; ++i) { + shouldBe("foo(array, -1, i)", "42"); + shouldBe("thingy", "" + i); +} + diff --git a/LayoutTests/fast/js/script-tests/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.js b/LayoutTests/fast/js/script-tests/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.js new file mode 100644 index 0000000..5feb011 --- /dev/null +++ b/LayoutTests/fast/js/script-tests/dfg-uint8clampedarray-out-of-bounds-put-by-val-alias.js @@ -0,0 +1,15 @@ +description( +"Tests that out-of-bounds stores to a Uint8ClampedArray that are aliased to out-of-bounds loads don't crash." +); + +function foo(a, i, v) +{ + var result = a[i]; + a[i] = v; + return result; +} + +for (var i = 0; i < 200; ++i) { + var array = new Uint8ClampedArray(1); + shouldBe("foo(array, 100000000, 42)", "" + (void 0)); +} diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 38fb5a1..5c5cd6b 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,29 @@ +2012-06-26 Filip Pizlo + + DFG PutByValAlias is too aggressive + https://bugs.webkit.org/show_bug.cgi?id=90026 + + + Reviewed by Gavin Barraclough. + + For CSE on normal arrays, we now treat PutByVal as impure. This does not appear to affect + performance by much. + + For CSE on typed arrays, we fix PutByValAlias by making GetByVal speculate that the access + is within bounds. This also has the effect of making our out-of-bounds handling consistent + with WebCore. + + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::byValIsPure): + (JSC::DFG::Graph::clobbersWorld): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): + (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): + 2012-06-26 Yong Li [BlackBerry] Add JSC statistics into about:memory diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp index a362e6e..be0012f 100644 --- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp @@ -1080,10 +1080,15 @@ private: break; case PutByVal: - if (m_graph.byValIsPure(node) - && !m_graph[node.child1()].shouldSpeculateArguments() - && getByValLoadElimination(node.child1().index(), node.child2().index()) != NoNode) + if (isActionableMutableArraySpeculation(m_graph[node.child1()].prediction()) + && m_graph[node.child2()].shouldSpeculateInteger() + && !m_graph[node.child1()].shouldSpeculateArguments()) { + NodeIndex nodeIndex = getByValLoadElimination( + node.child1().index(), node.child2().index()); + if (nodeIndex == NoNode) + break; node.setOp(PutByValAlias); + } break; case CheckStructure: diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index 9e4a28f..a9080d1 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -463,10 +463,31 @@ public: bool byValIsPure(Node& node) { - return at(node.child2()).shouldSpeculateInteger() - && ((node.op() == PutByVal || node.op() == PutByValAlias) - ? isActionableMutableArraySpeculation(at(node.child1()).prediction()) - : isActionableArraySpeculation(at(node.child1()).prediction())); + if (!at(node.child2()).shouldSpeculateInteger()) + return false; + SpeculatedType prediction = at(node.child1()).prediction(); + switch (node.op()) { + case PutByVal: + if (!isActionableMutableArraySpeculation(prediction)) + return false; + if (isArraySpeculation(prediction)) + return false; + return true; + + case PutByValAlias: + if (!isActionableMutableArraySpeculation(prediction)) + return false; + return true; + + case GetByVal: + if (!isActionableArraySpeculation(prediction)) + return false; + return true; + + default: + ASSERT_NOT_REACHED(); + return false; + } } bool clobbersWorld(Node& node) @@ -484,6 +505,8 @@ public: case CompareEq: return !isPredictedNumerical(node); case GetByVal: + case PutByVal: + case PutByValAlias: return !byValIsPure(node); default: ASSERT_NOT_REACHED(); diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h index db798d0..8c2f962 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeType.h +++ b/Source/JavaScriptCore/dfg/DFGNodeType.h @@ -111,8 +111,8 @@ namespace JSC { namespace DFG { /* Since a put to 'length' may invalidate optimizations here, */\ /* this must be the directly subsequent property put. */\ macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ - macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \ - macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \ + macro(PutByVal, NodeMustGenerate | NodeMightClobber) \ + macro(PutByValAlias, NodeMustGenerate | NodeMightClobber) \ macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ macro(PutById, NodeMustGenerate | NodeClobbersWorld) \ diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index b0fed46..0c0f326 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -2000,10 +2000,10 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& return; } - MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)); - m_jit.xorPtr(resultReg, resultReg); - MacroAssembler::Jump outOfBounds = m_jit.jump(); - inBounds.link(&m_jit); + speculationCheck( + Uncountable, JSValueRegs(), NoNode, + m_jit.branch32( + MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset))); switch (elementSize) { case 1: if (signedness == SignedTypedArray) @@ -2023,7 +2023,6 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& default: ASSERT_NOT_REACHED(); } - outOfBounds.link(&m_jit); if (elementSize < 4 || signedness == SignedTypedArray) { integerResult(resultReg, m_compileIndex); return; @@ -2162,11 +2161,10 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor FPRTemporary result(this); FPRReg resultReg = result.fpr(); ASSERT(speculationRequirements != NoTypedArraySpecCheck); - MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)); - static const double zero = 0; - m_jit.loadDouble(&zero, resultReg); - MacroAssembler::Jump outOfBounds = m_jit.jump(); - inBounds.link(&m_jit); + speculationCheck( + Uncountable, JSValueRegs(), NoNode, + m_jit.branch32( + MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset))); switch (elementSize) { case 4: m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg); @@ -2183,7 +2181,6 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor default: ASSERT_NOT_REACHED(); } - outOfBounds.link(&m_jit); doubleResult(resultReg, m_compileIndex); }