fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 Apple Inc. All rights reserved. |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
| 7 | * 1. Redistributions of source code must retain the above copyright |
| 8 | * notice, this list of conditions and the following disclaimer. |
| 9 | * 2. Redistributions in binary form must reproduce the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer in the |
| 11 | * documentation and/or other materials provided with the distribution. |
| 12 | * |
| 13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| 14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 | */ |
| 25 | |
| 26 | #include "config.h" |
| 27 | #include "DFGFixupPhase.h" |
| 28 | |
| 29 | #if ENABLE(DFG_JIT) |
| 30 | |
| 31 | #include "DFGGraph.h" |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 32 | #include "DFGInsertionSet.h" |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 33 | #include "DFGPhase.h" |
fpizlo@apple.com | a4b4cbe | 2013-01-12 04:47:03 +0000 | [diff] [blame] | 34 | #include "Operations.h" |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 35 | |
| 36 | namespace JSC { namespace DFG { |
| 37 | |
| 38 | class FixupPhase : public Phase { |
| 39 | public: |
| 40 | FixupPhase(Graph& graph) |
| 41 | : Phase(graph, "fixup") |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 42 | , m_insertionSet(graph) |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 43 | { |
| 44 | } |
| 45 | |
fpizlo@apple.com | 79c51ee | 2012-05-18 22:30:24 +0000 | [diff] [blame] | 46 | bool run() |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 47 | { |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 48 | for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) |
| 49 | fixupBlock(m_graph.m_blocks[blockIndex].get()); |
fpizlo@apple.com | 79c51ee | 2012-05-18 22:30:24 +0000 | [diff] [blame] | 50 | return true; |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | private: |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 54 | void fixupBlock(BasicBlock* block) |
| 55 | { |
fpizlo@apple.com | 79c51ee | 2012-05-18 22:30:24 +0000 | [diff] [blame] | 56 | if (!block) |
| 57 | return; |
| 58 | ASSERT(block->isReachable); |
fpizlo@apple.com | f10d072 | 2012-12-03 09:21:22 +0000 | [diff] [blame] | 59 | m_block = block; |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 60 | for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) { |
| 61 | m_compileIndex = block->at(m_indexInBlock); |
| 62 | fixupNode(m_graph[m_compileIndex]); |
| 63 | } |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 64 | m_insertionSet.execute(block); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 65 | } |
| 66 | |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 67 | void fixupNode(Node& node) |
| 68 | { |
| 69 | if (!node.shouldGenerate()) |
| 70 | return; |
| 71 | |
| 72 | NodeType op = node.op(); |
| 73 | |
| 74 | #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) |
fpizlo@apple.com | 01902c8 | 2012-11-22 04:23:36 +0000 | [diff] [blame] | 75 | dataLogF(" %s @%u: ", Graph::opName(op), m_compileIndex); |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 76 | #endif |
| 77 | |
| 78 | switch (op) { |
| 79 | case GetById: { |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 80 | if (m_graph.m_fixpointState > BeforeFixpoint) |
| 81 | break; |
| 82 | |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 83 | Node* nodePtr = &node; |
| 84 | |
fpizlo@apple.com | 6233616 | 2012-06-07 01:35:59 +0000 | [diff] [blame] | 85 | if (!isInt32Speculation(m_graph[m_compileIndex].prediction())) |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 86 | break; |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 87 | if (codeBlock()->identifier(nodePtr->identifierNumber()) != globalData().propertyNames->length) |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 88 | break; |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 89 | ArrayProfile* arrayProfile = |
| 90 | m_graph.baselineCodeBlockFor(nodePtr->codeOrigin)->getArrayProfile( |
| 91 | nodePtr->codeOrigin.bytecodeIndex); |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 92 | ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions); |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 93 | if (arrayProfile) { |
fpizlo@apple.com | 99f3762 | 2012-10-29 04:02:08 +0000 | [diff] [blame] | 94 | arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node.codeOrigin)); |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 95 | arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false); |
| 96 | arrayMode = arrayMode.refine( |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 97 | m_graph[node.child1()].prediction(), |
fpizlo@apple.com | 4cafdbd | 2012-09-11 20:00:31 +0000 | [diff] [blame] | 98 | m_graph[m_compileIndex].prediction()); |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 99 | if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) { |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 100 | m_insertionSet.insertNode( |
| 101 | m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckStructure, |
| 102 | nodePtr->codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), |
| 103 | nodePtr->child1().index()); |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 104 | nodePtr = &m_graph[m_compileIndex]; |
| 105 | } |
| 106 | } else { |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 107 | arrayMode = arrayMode.refine( |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 108 | m_graph[node.child1()].prediction(), |
| 109 | m_graph[m_compileIndex].prediction()); |
fpizlo@apple.com | f24804c | 2012-08-15 02:48:35 +0000 | [diff] [blame] | 110 | } |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 111 | if (!arrayMode.supportsLength()) |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 112 | break; |
| 113 | nodePtr->setOp(GetArrayLength); |
| 114 | ASSERT(nodePtr->flags() & NodeMustGenerate); |
fpizlo@apple.com | d8dd053 | 2012-09-13 04:18:52 +0000 | [diff] [blame] | 115 | nodePtr->clearFlags(NodeMustGenerate | NodeClobbersWorld); |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 116 | m_graph.deref(m_compileIndex); |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 117 | nodePtr->setArrayMode(arrayMode); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 118 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 119 | NodeIndex storage = checkArray(arrayMode, nodePtr->codeOrigin, nodePtr->child1().index(), NoNode, lengthNeedsStorage, nodePtr->shouldGenerate()); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 120 | if (storage == NoNode) |
| 121 | break; |
| 122 | |
| 123 | nodePtr = &m_graph[m_compileIndex]; |
| 124 | nodePtr->children.child2() = Edge(storage); |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 125 | break; |
| 126 | } |
| 127 | case GetIndexedPropertyStorage: { |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 128 | ASSERT(node.arrayMode().canCSEStorage()); |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 129 | break; |
| 130 | } |
fpizlo@apple.com | a387b6a | 2012-11-01 07:41:43 +0000 | [diff] [blame] | 131 | case GetByVal: { |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 132 | node.setArrayMode( |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 133 | node.arrayMode().refine( |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 134 | m_graph[node.child1()].prediction(), |
fpizlo@apple.com | f10d072 | 2012-12-03 09:21:22 +0000 | [diff] [blame] | 135 | m_graph[node.child2()].prediction(), |
| 136 | SpecNone, node.flags())); |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 137 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 138 | blessArrayOperation(node.child1(), node.child2(), 2); |
fpizlo@apple.com | 94e84e9 | 2012-11-11 02:56:12 +0000 | [diff] [blame] | 139 | |
fpizlo@apple.com | f999d22 | 2012-11-14 23:34:19 +0000 | [diff] [blame] | 140 | Node* nodePtr = &m_graph[m_compileIndex]; |
| 141 | ArrayMode arrayMode = nodePtr->arrayMode(); |
fpizlo@apple.com | 94e84e9 | 2012-11-11 02:56:12 +0000 | [diff] [blame] | 142 | if (arrayMode.type() == Array::Double |
| 143 | && arrayMode.arrayClass() == Array::OriginalArray |
| 144 | && arrayMode.speculation() == Array::InBounds |
| 145 | && arrayMode.conversion() == Array::AsIs |
fpizlo@apple.com | f999d22 | 2012-11-14 23:34:19 +0000 | [diff] [blame] | 146 | && m_graph.globalObjectFor(nodePtr->codeOrigin)->arrayPrototypeChainIsSane() |
| 147 | && !(nodePtr->flags() & NodeUsedAsOther)) |
| 148 | nodePtr->setArrayMode(arrayMode.withSpeculation(Array::SaneChain)); |
fpizlo@apple.com | 94e84e9 | 2012-11-11 02:56:12 +0000 | [diff] [blame] | 149 | |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 150 | break; |
| 151 | } |
fpizlo@apple.com | a387b6a | 2012-11-01 07:41:43 +0000 | [diff] [blame] | 152 | case StringCharAt: |
| 153 | case StringCharCodeAt: { |
| 154 | // Currently we have no good way of refining these. |
| 155 | ASSERT(node.arrayMode() == ArrayMode(Array::String)); |
| 156 | blessArrayOperation(node.child1(), node.child2(), 2); |
| 157 | break; |
| 158 | } |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 159 | |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 160 | case ArrayPush: { |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 161 | // May need to refine the array mode in case the value prediction contravenes |
| 162 | // the array prediction. For example, we may have evidence showing that the |
| 163 | // array is in Int32 mode, but the value we're storing is likely to be a double. |
| 164 | // Then we should turn this into a conversion to Double array followed by the |
| 165 | // push. On the other hand, we absolutely don't want to refine based on the |
| 166 | // base prediction. If it has non-cell garbage in it, then we want that to be |
| 167 | // ignored. That's because ArrayPush can't handle any array modes that aren't |
| 168 | // array-related - so if refine() turned this into a "Generic" ArrayPush then |
| 169 | // that would break things. |
| 170 | node.setArrayMode( |
| 171 | node.arrayMode().refine( |
| 172 | m_graph[node.child1()].prediction() & SpecCell, |
| 173 | SpecInt32, |
| 174 | m_graph[node.child2()].prediction())); |
fpizlo@apple.com | c136365 | 2012-12-10 06:54:30 +0000 | [diff] [blame] | 175 | blessArrayOperation(node.child1(), Edge(), 2); |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 176 | |
| 177 | Node* nodePtr = &m_graph[m_compileIndex]; |
| 178 | switch (nodePtr->arrayMode().type()) { |
| 179 | case Array::Double: |
| 180 | fixDoubleEdge(1); |
| 181 | break; |
| 182 | default: |
| 183 | break; |
| 184 | } |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 185 | break; |
| 186 | } |
| 187 | |
| 188 | case ArrayPop: { |
fpizlo@apple.com | c136365 | 2012-12-10 06:54:30 +0000 | [diff] [blame] | 189 | blessArrayOperation(node.child1(), Edge(), 1); |
fpizlo@apple.com | 8fd7921 | 2012-10-16 21:59:35 +0000 | [diff] [blame] | 190 | break; |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 191 | } |
| 192 | |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 193 | case ValueToInt32: { |
fpizlo@apple.com | 888325a | 2012-06-12 23:16:51 +0000 | [diff] [blame] | 194 | if (m_graph[node.child1()].shouldSpeculateNumber() |
| 195 | && node.mustGenerate()) { |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 196 | node.clearFlags(NodeMustGenerate); |
| 197 | m_graph.deref(m_compileIndex); |
| 198 | } |
| 199 | break; |
| 200 | } |
| 201 | |
| 202 | case BitAnd: |
| 203 | case BitOr: |
| 204 | case BitXor: |
| 205 | case BitRShift: |
| 206 | case BitLShift: |
| 207 | case BitURShift: { |
| 208 | fixIntEdge(node.children.child1()); |
| 209 | fixIntEdge(node.children.child2()); |
| 210 | break; |
| 211 | } |
| 212 | |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 213 | case CompareEq: |
| 214 | case CompareLess: |
| 215 | case CompareLessEq: |
| 216 | case CompareGreater: |
| 217 | case CompareGreaterEq: |
| 218 | case CompareStrictEq: { |
| 219 | if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])) |
| 220 | break; |
| 221 | if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) |
| 222 | break; |
| 223 | fixDoubleEdge(0); |
| 224 | fixDoubleEdge(1); |
| 225 | break; |
| 226 | } |
| 227 | |
| 228 | case LogicalNot: { |
| 229 | if (m_graph[node.child1()].shouldSpeculateInteger()) |
| 230 | break; |
| 231 | if (!m_graph[node.child1()].shouldSpeculateNumber()) |
| 232 | break; |
| 233 | fixDoubleEdge(0); |
| 234 | break; |
| 235 | } |
| 236 | |
| 237 | case Branch: { |
fpizlo@apple.com | e2967fd | 2012-04-04 21:14:48 +0000 | [diff] [blame] | 238 | if (!m_graph[node.child1()].shouldSpeculateInteger() |
| 239 | && m_graph[node.child1()].shouldSpeculateNumber()) |
| 240 | fixDoubleEdge(0); |
| 241 | |
| 242 | Node& myNode = m_graph[m_compileIndex]; // reload because the graph may have changed |
| 243 | Edge logicalNotEdge = myNode.child1(); |
| 244 | Node& logicalNot = m_graph[logicalNotEdge]; |
| 245 | if (logicalNot.op() == LogicalNot |
| 246 | && logicalNot.adjustedRefCount() == 1) { |
| 247 | Edge newChildEdge = logicalNot.child1(); |
fpizlo@apple.com | a6c889b | 2012-04-12 04:19:07 +0000 | [diff] [blame] | 248 | if (m_graph[newChildEdge].hasBooleanResult()) { |
| 249 | m_graph.ref(newChildEdge); |
| 250 | m_graph.deref(logicalNotEdge); |
| 251 | myNode.children.setChild1(newChildEdge); |
| 252 | |
| 253 | BlockIndex toBeTaken = myNode.notTakenBlockIndex(); |
| 254 | BlockIndex toBeNotTaken = myNode.takenBlockIndex(); |
| 255 | myNode.setTakenBlockIndex(toBeTaken); |
| 256 | myNode.setNotTakenBlockIndex(toBeNotTaken); |
| 257 | } |
fpizlo@apple.com | e2967fd | 2012-04-04 21:14:48 +0000 | [diff] [blame] | 258 | } |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 259 | break; |
| 260 | } |
| 261 | |
| 262 | case SetLocal: { |
fpizlo@apple.com | 1688cc1 | 2012-05-23 07:29:02 +0000 | [diff] [blame] | 263 | if (node.variableAccessData()->isCaptured()) |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 264 | break; |
| 265 | if (!node.variableAccessData()->shouldUseDoubleFormat()) |
| 266 | break; |
| 267 | fixDoubleEdge(0); |
| 268 | break; |
| 269 | } |
| 270 | |
| 271 | case ArithAdd: |
| 272 | case ValueAdd: { |
| 273 | if (m_graph.addShouldSpeculateInteger(node)) |
| 274 | break; |
fpizlo@apple.com | 81f7537 | 2012-11-08 22:55:27 +0000 | [diff] [blame] | 275 | if (!Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 276 | break; |
| 277 | fixDoubleEdge(0); |
| 278 | fixDoubleEdge(1); |
| 279 | break; |
| 280 | } |
| 281 | |
| 282 | case ArithSub: { |
| 283 | if (m_graph.addShouldSpeculateInteger(node) |
| 284 | && node.canSpeculateInteger()) |
| 285 | break; |
| 286 | fixDoubleEdge(0); |
| 287 | fixDoubleEdge(1); |
| 288 | break; |
| 289 | } |
| 290 | |
| 291 | case ArithNegate: { |
| 292 | if (m_graph.negateShouldSpeculateInteger(node)) |
| 293 | break; |
| 294 | fixDoubleEdge(0); |
| 295 | break; |
| 296 | } |
| 297 | |
| 298 | case ArithMin: |
| 299 | case ArithMax: |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 300 | case ArithMod: { |
fpizlo@apple.com | 81f7537 | 2012-11-08 22:55:27 +0000 | [diff] [blame] | 301 | if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 302 | && node.canSpeculateInteger()) |
| 303 | break; |
| 304 | fixDoubleEdge(0); |
| 305 | fixDoubleEdge(1); |
| 306 | break; |
| 307 | } |
| 308 | |
fpizlo@apple.com | fa9f10c | 2012-05-22 17:18:21 +0000 | [diff] [blame] | 309 | case ArithMul: { |
| 310 | if (m_graph.mulShouldSpeculateInteger(node)) |
| 311 | break; |
| 312 | fixDoubleEdge(0); |
| 313 | fixDoubleEdge(1); |
| 314 | break; |
| 315 | } |
| 316 | |
fpizlo@apple.com | 0cf017f | 2012-04-18 22:31:54 +0000 | [diff] [blame] | 317 | case ArithDiv: { |
fpizlo@apple.com | 81f7537 | 2012-11-08 22:55:27 +0000 | [diff] [blame] | 318 | if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) |
fpizlo@apple.com | 3d22338 | 2012-04-24 19:19:35 +0000 | [diff] [blame] | 319 | && node.canSpeculateInteger()) { |
| 320 | if (isX86()) |
| 321 | break; |
msaboff@apple.com | 268bb44 | 2013-01-18 21:45:06 +0000 | [diff] [blame] | 322 | injectInt32ToDoubleNode(0); |
| 323 | injectInt32ToDoubleNode(1); |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 324 | |
| 325 | // We don't need to do ref'ing on the children because we're stealing them from |
| 326 | // the original division. |
| 327 | NodeIndex newDivisionIndex = m_insertionSet.insertNode( |
| 328 | m_indexInBlock, DontRefChildren, RefNode, SpecDouble, m_graph[m_compileIndex]); |
fpizlo@apple.com | 3d22338 | 2012-04-24 19:19:35 +0000 | [diff] [blame] | 329 | |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 330 | m_graph[m_compileIndex].setOp(DoubleAsInt32); |
| 331 | m_graph[m_compileIndex].children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge()); |
fpizlo@apple.com | 3d22338 | 2012-04-24 19:19:35 +0000 | [diff] [blame] | 332 | |
fpizlo@apple.com | 0cf017f | 2012-04-18 22:31:54 +0000 | [diff] [blame] | 333 | break; |
fpizlo@apple.com | 3d22338 | 2012-04-24 19:19:35 +0000 | [diff] [blame] | 334 | } |
fpizlo@apple.com | 0cf017f | 2012-04-18 22:31:54 +0000 | [diff] [blame] | 335 | fixDoubleEdge(0); |
| 336 | fixDoubleEdge(1); |
| 337 | break; |
| 338 | } |
| 339 | |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 340 | case ArithAbs: { |
fpizlo@apple.com | 81f7537 | 2012-11-08 22:55:27 +0000 | [diff] [blame] | 341 | if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic() |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 342 | && node.canSpeculateInteger()) |
| 343 | break; |
| 344 | fixDoubleEdge(0); |
| 345 | break; |
| 346 | } |
| 347 | |
| 348 | case ArithSqrt: { |
| 349 | fixDoubleEdge(0); |
| 350 | break; |
| 351 | } |
| 352 | |
fpizlo@apple.com | 270a7ad | 2012-08-02 01:28:10 +0000 | [diff] [blame] | 353 | case PutByVal: |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 354 | case PutByValAlias: { |
fpizlo@apple.com | a4eaa8a | 2012-07-15 05:23:58 +0000 | [diff] [blame] | 355 | Edge child1 = m_graph.varArgChild(node, 0); |
| 356 | Edge child2 = m_graph.varArgChild(node, 1); |
| 357 | Edge child3 = m_graph.varArgChild(node, 2); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 358 | |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 359 | node.setArrayMode( |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 360 | node.arrayMode().refine( |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 361 | m_graph[child1].prediction(), |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 362 | m_graph[child2].prediction(), |
| 363 | m_graph[child3].prediction())); |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 364 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 365 | blessArrayOperation(child1, child2, 3); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 366 | |
| 367 | Node* nodePtr = &m_graph[m_compileIndex]; |
| 368 | |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 369 | switch (nodePtr->arrayMode().modeForPut().type()) { |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 370 | case Array::Double: |
| 371 | fixDoubleEdge(2); |
| 372 | break; |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 373 | case Array::Int8Array: |
| 374 | case Array::Int16Array: |
| 375 | case Array::Int32Array: |
| 376 | case Array::Uint8Array: |
| 377 | case Array::Uint8ClampedArray: |
| 378 | case Array::Uint16Array: |
| 379 | case Array::Uint32Array: |
| 380 | if (!m_graph[child3].shouldSpeculateInteger()) |
| 381 | fixDoubleEdge(2); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 382 | break; |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 383 | case Array::Float32Array: |
| 384 | case Array::Float64Array: |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 385 | fixDoubleEdge(2); |
| 386 | break; |
fpizlo@apple.com | 7aed8d8 | 2012-08-23 03:38:52 +0000 | [diff] [blame] | 387 | default: |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 388 | break; |
| 389 | } |
| 390 | break; |
| 391 | } |
| 392 | |
fpizlo@apple.com | 75c91a7 | 2012-11-08 22:28:25 +0000 | [diff] [blame] | 393 | case NewArray: { |
| 394 | for (unsigned i = m_graph.varArgNumChildren(node); i--;) { |
| 395 | node.setIndexingType( |
| 396 | leastUpperBoundOfIndexingTypeAndType( |
| 397 | node.indexingType(), m_graph[m_graph.varArgChild(node, i)].prediction())); |
| 398 | } |
| 399 | if (node.indexingType() == ArrayWithDouble) { |
| 400 | for (unsigned i = m_graph.varArgNumChildren(node); i--;) |
| 401 | fixDoubleEdge(i); |
| 402 | } |
| 403 | break; |
| 404 | } |
| 405 | |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 406 | default: |
| 407 | break; |
| 408 | } |
| 409 | |
| 410 | #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) |
msaboff@apple.com | b744a17 | 2013-01-19 01:53:36 +0000 | [diff] [blame] | 411 | Node* nodePtr = &m_graph[m_compileIndex]; |
| 412 | if (!(nodePtr->flags() & NodeHasVarArgs)) { |
fpizlo@apple.com | 01902c8 | 2012-11-22 04:23:36 +0000 | [diff] [blame] | 413 | dataLogF("new children: "); |
msaboff@apple.com | b744a17 | 2013-01-19 01:53:36 +0000 | [diff] [blame] | 414 | nodePtr->dumpChildren(WTF::dataFile()); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 415 | } |
fpizlo@apple.com | 01902c8 | 2012-11-22 04:23:36 +0000 | [diff] [blame] | 416 | dataLogF("\n"); |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 417 | #endif |
| 418 | } |
| 419 | |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 420 | NodeIndex checkArray(ArrayMode arrayMode, CodeOrigin codeOrigin, NodeIndex array, NodeIndex index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage, bool shouldGenerate = true) |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 421 | { |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 422 | ASSERT(arrayMode.isSpecific()); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 423 | |
fpizlo@apple.com | 3f1a01b | 2012-11-10 05:54:11 +0000 | [diff] [blame] | 424 | Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin); |
| 425 | |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 426 | if (arrayMode.doesConversion()) { |
fpizlo@apple.com | 99f3762 | 2012-10-29 04:02:08 +0000 | [diff] [blame] | 427 | if (structure) { |
fpizlo@apple.com | f10d072 | 2012-12-03 09:21:22 +0000 | [diff] [blame] | 428 | if (m_indexInBlock > 0) { |
| 429 | // If the previous node was a CheckStructure inserted because of stuff |
| 430 | // that the array profile told us, then remove it. |
| 431 | Node& previousNode = m_graph[m_block->at(m_indexInBlock - 1)]; |
| 432 | if (previousNode.op() == CheckStructure |
| 433 | && previousNode.child1() == array |
| 434 | && previousNode.codeOrigin == codeOrigin) |
| 435 | previousNode.setOpAndDefaultFlags(Phantom); |
| 436 | } |
| 437 | |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 438 | m_insertionSet.insertNode( |
| 439 | m_indexInBlock, RefChildren, DontRefNode, SpecNone, ArrayifyToStructure, codeOrigin, |
| 440 | OpInfo(structure), OpInfo(arrayMode.asWord()), array, index); |
fpizlo@apple.com | 99f3762 | 2012-10-29 04:02:08 +0000 | [diff] [blame] | 441 | } else { |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 442 | m_insertionSet.insertNode( |
| 443 | m_indexInBlock, RefChildren, DontRefNode, SpecNone, Arrayify, codeOrigin, |
| 444 | OpInfo(arrayMode.asWord()), array, index); |
fpizlo@apple.com | 99f3762 | 2012-10-29 04:02:08 +0000 | [diff] [blame] | 445 | } |
| 446 | } else { |
fpizlo@apple.com | 3f1a01b | 2012-11-10 05:54:11 +0000 | [diff] [blame] | 447 | if (structure) { |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 448 | m_insertionSet.insertNode( |
| 449 | m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckStructure, codeOrigin, |
| 450 | OpInfo(m_graph.addStructureSet(structure)), array); |
fpizlo@apple.com | 3f1a01b | 2012-11-10 05:54:11 +0000 | [diff] [blame] | 451 | } else { |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 452 | m_insertionSet.insertNode( |
| 453 | m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckArray, codeOrigin, |
| 454 | OpInfo(arrayMode.asWord()), array); |
fpizlo@apple.com | 3f1a01b | 2012-11-10 05:54:11 +0000 | [diff] [blame] | 455 | } |
fpizlo@apple.com | 497c751 | 2012-09-19 01:20:52 +0000 | [diff] [blame] | 456 | } |
| 457 | |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 458 | if (!storageCheck(arrayMode)) |
| 459 | return NoNode; |
| 460 | |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 461 | if (arrayMode.usesButterfly()) { |
| 462 | return m_insertionSet.insertNode( |
| 463 | m_indexInBlock, |
| 464 | shouldGenerate ? RefChildren : DontRefChildren, |
| 465 | shouldGenerate ? RefNode : DontRefNode, |
| 466 | SpecNone, GetButterfly, codeOrigin, array); |
| 467 | } |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 468 | |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 469 | return m_insertionSet.insertNode( |
| 470 | m_indexInBlock, |
| 471 | shouldGenerate ? RefChildren : DontRefChildren, |
| 472 | shouldGenerate ? RefNode : DontRefNode, |
| 473 | SpecNone, GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode.asWord()), array); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 474 | } |
| 475 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 476 | void blessArrayOperation(Edge base, Edge index, unsigned storageChildIdx) |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 477 | { |
| 478 | if (m_graph.m_fixpointState > BeforeFixpoint) |
| 479 | return; |
| 480 | |
| 481 | Node* nodePtr = &m_graph[m_compileIndex]; |
| 482 | |
fpizlo@apple.com | 34d1f08 | 2012-10-28 06:13:23 +0000 | [diff] [blame] | 483 | switch (nodePtr->arrayMode().type()) { |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 484 | case Array::ForceExit: { |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 485 | m_insertionSet.insertNode( |
| 486 | m_indexInBlock, DontRefChildren, DontRefNode, SpecNone, ForceOSRExit, |
| 487 | nodePtr->codeOrigin); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 488 | return; |
| 489 | } |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 490 | |
fpizlo@apple.com | a0ec059 | 2012-10-22 23:52:15 +0000 | [diff] [blame] | 491 | case Array::SelectUsingPredictions: |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 492 | case Array::Unprofiled: |
| 493 | ASSERT_NOT_REACHED(); |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 494 | return; |
| 495 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 496 | case Array::Generic: |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 497 | return; |
| 498 | |
fpizlo@apple.com | 0e9910a | 2012-10-09 23:39:53 +0000 | [diff] [blame] | 499 | default: { |
| 500 | NodeIndex storage = checkArray(nodePtr->arrayMode(), nodePtr->codeOrigin, base.index(), index.indexUnchecked()); |
| 501 | if (storage == NoNode) |
| 502 | return; |
| 503 | |
| 504 | m_graph.child(m_graph[m_compileIndex], storageChildIdx) = Edge(storage); |
| 505 | return; |
| 506 | } } |
fpizlo@apple.com | 04c1974 | 2012-08-26 22:35:26 +0000 | [diff] [blame] | 507 | } |
| 508 | |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 509 | void fixIntEdge(Edge& edge) |
| 510 | { |
| 511 | Node& node = m_graph[edge]; |
| 512 | if (node.op() != ValueToInt32) |
| 513 | return; |
| 514 | |
| 515 | if (!m_graph[node.child1()].shouldSpeculateInteger()) |
| 516 | return; |
| 517 | |
| 518 | Edge oldEdge = edge; |
| 519 | Edge newEdge = node.child1(); |
| 520 | |
| 521 | m_graph.ref(newEdge); |
| 522 | m_graph.deref(oldEdge); |
| 523 | |
| 524 | edge = newEdge; |
| 525 | } |
| 526 | |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 527 | void fixDoubleEdge(unsigned childIndex) |
| 528 | { |
| 529 | Node& source = m_graph[m_compileIndex]; |
fpizlo@apple.com | a4eaa8a | 2012-07-15 05:23:58 +0000 | [diff] [blame] | 530 | Edge& edge = m_graph.child(source, childIndex); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 531 | |
msaboff@apple.com | de22d5f | 2013-01-18 21:28:30 +0000 | [diff] [blame] | 532 | if (m_graph[edge].prediction() & SpecDouble) { |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 533 | edge.setUseKind(DoubleUse); |
| 534 | return; |
| 535 | } |
| 536 | |
msaboff@apple.com | 268bb44 | 2013-01-18 21:45:06 +0000 | [diff] [blame] | 537 | injectInt32ToDoubleNode(childIndex); |
| 538 | } |
| 539 | |
| 540 | void injectInt32ToDoubleNode(unsigned childIndex) |
| 541 | { |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 542 | NodeIndex resultIndex = m_insertionSet.insertNode( |
| 543 | m_indexInBlock, DontRefChildren, RefNode, SpecDouble, Int32ToDouble, |
| 544 | m_graph[m_compileIndex].codeOrigin, |
| 545 | m_graph.child(m_graph[m_compileIndex], childIndex).index()); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 546 | |
| 547 | #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 548 | dataLogF( |
| 549 | "(replacing @%u->@%u with @%u->@%u) ", |
| 550 | m_compileIndex, m_graph.child(m_graph[m_compileIndex], childIndex).index(), m_compileIndex, resultIndex); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 551 | #endif |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 552 | |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 553 | m_graph.child(m_graph[m_compileIndex], childIndex) = Edge(resultIndex, DoubleUse); |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 554 | } |
fpizlo@apple.com | f10d072 | 2012-12-03 09:21:22 +0000 | [diff] [blame] | 555 | |
| 556 | BasicBlock* m_block; |
fpizlo@apple.com | 96cfc6b | 2012-03-25 23:50:24 +0000 | [diff] [blame] | 557 | unsigned m_indexInBlock; |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 558 | NodeIndex m_compileIndex; |
fpizlo@apple.com | f45e88b | 2013-01-20 19:29:50 +0000 | [diff] [blame] | 559 | InsertionSet m_insertionSet; |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 560 | }; |
| 561 | |
fpizlo@apple.com | 79c51ee | 2012-05-18 22:30:24 +0000 | [diff] [blame] | 562 | bool performFixup(Graph& graph) |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 563 | { |
fpizlo@apple.com | 8618e4b | 2012-07-03 01:27:16 +0000 | [diff] [blame] | 564 | SamplingRegion samplingRegion("DFG Fixup Phase"); |
fpizlo@apple.com | 79c51ee | 2012-05-18 22:30:24 +0000 | [diff] [blame] | 565 | return runPhase<FixupPhase>(graph); |
fpizlo@apple.com | a73f21d | 2012-03-24 03:23:02 +0000 | [diff] [blame] | 566 | } |
| 567 | |
| 568 | } } // namespace JSC::DFG |
| 569 | |
| 570 | #endif // ENABLE(DFG_JIT) |
| 571 | |