blob: 4c49417d7bb637df8c7f6595be063dc2364097d4 [file] [log] [blame]
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001/*
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00003 *
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"
ossy@webkit.orgbeb0de42014-02-17 19:00:03 +000027#include "DFGFixupPhase.h"
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000028
29#if ENABLE(DFG_JIT)
30
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000031#include "DFGGraph.h"
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000032#include "DFGInsertionSet.h"
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000033#include "DFGPhase.h"
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +000034#include "DFGPredictionPropagationPhase.h"
fpizlo@apple.com0bef2a12014-02-10 19:26:29 +000035#include "DFGVariableAccessDataDump.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000036#include "JSCInlines.h"
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000037
38namespace JSC { namespace DFG {
39
40class FixupPhase : public Phase {
41public:
42 FixupPhase(Graph& graph)
43 : Phase(graph, "fixup")
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +000044 , m_insertionSet(graph)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000045 {
46 }
47
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000048 bool run()
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000049 {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000050 ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
51 ASSERT(m_graph.m_form == ThreadedCPS);
52
fpizlo@apple.combbaf6192013-02-27 01:45:28 +000053 m_profitabilityChanged = false;
oliver@apple.com426f5b02013-07-25 04:04:27 +000054 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
55 fixupBlock(m_graph.block(blockIndex));
fpizlo@apple.combbaf6192013-02-27 01:45:28 +000056
57 while (m_profitabilityChanged) {
58 m_profitabilityChanged = false;
59
60 for (unsigned i = m_graph.m_argumentPositions.size(); i--;)
61 m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
62
oliver@apple.com426f5b02013-07-25 04:04:27 +000063 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000064 fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex));
fpizlo@apple.combbaf6192013-02-27 01:45:28 +000065 }
66
fpizlo@apple.com6921b292013-09-18 17:14:02 +000067 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +000068 injectTypeConversionsInBlock(m_graph.block(blockIndex));
fpizlo@apple.com6921b292013-09-18 17:14:02 +000069
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000070 return true;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000071 }
72
73private:
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000074 void fixupBlock(BasicBlock* block)
75 {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000076 if (!block)
77 return;
78 ASSERT(block->isReachable);
fpizlo@apple.comf10d0722012-12-03 09:21:22 +000079 m_block = block;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000080 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000081 m_currentNode = block->at(m_indexInBlock);
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +000082 addPhantomsIfNecessary();
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000083 fixupNode(m_currentNode);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000084 }
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +000085 clearPhantomsAtEnd();
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +000086 m_insertionSet.execute(block);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000087 }
88
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000089 void fixupNode(Node* node)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000090 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000091 NodeType op = node->op();
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000092
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000093 switch (op) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000094 case SetLocal: {
fpizlo@apple.combbaf6192013-02-27 01:45:28 +000095 // This gets handled by fixupSetLocalsInBlock().
fpizlo@apple.com6921b292013-09-18 17:14:02 +000096 return;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000097 }
98
99 case BitAnd:
fpizlo@apple.com027ed672014-01-08 00:27:06 +0000100 case BitOr:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000101 case BitXor:
102 case BitRShift:
103 case BitLShift:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000104 case BitURShift: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000105 fixIntConvertingEdge(node->child1());
106 fixIntConvertingEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000107 break;
108 }
fpizlo@apple.com027ed672014-01-08 00:27:06 +0000109
oliver@apple.com64367322013-04-26 00:41:38 +0000110 case ArithIMul: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000111 fixIntConvertingEdge(node->child1());
112 fixIntConvertingEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000113 node->setOp(ArithMul);
114 node->setArithMode(Arith::Unchecked);
115 node->child1().setUseKind(Int32Use);
116 node->child2().setUseKind(Int32Use);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000117 break;
118 }
119
120 case UInt32ToNumber: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000121 fixIntConvertingEdge(node->child1());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +0000122 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
123 node->convertToIdentity();
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000124 else if (node->canSpeculateInt32(FixupPass))
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000125 node->setArithMode(Arith::CheckOverflow);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000126 else {
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000127 node->setArithMode(Arith::DoOverflow);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000128 node->setResult(NodeResultDouble);
129 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000130 break;
131 }
132
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000133 case ValueAdd: {
fpizlo@apple.com97756552014-01-02 20:15:25 +0000134 if (attemptToMakeIntegerAdd(node)) {
135 node->setOp(ArithAdd);
136 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000137 break;
fpizlo@apple.com97756552014-01-02 20:15:25 +0000138 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000139 if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
140 fixDoubleOrBooleanEdge(node->child1());
141 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000142 node->setOp(ArithAdd);
143 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000144 node->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000145 break;
146 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000147
148 // FIXME: Optimize for the case where one of the operands is the
149 // empty string. Also consider optimizing for the case where we don't
150 // believe either side is the emtpy string. Both of these things should
151 // be easy.
152
153 if (node->child1()->shouldSpeculateString()
154 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
155 break;
156 if (node->child2()->shouldSpeculateString()
157 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
158 break;
159 if (node->child1()->shouldSpeculateStringObject()
160 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
161 break;
162 if (node->child2()->shouldSpeculateStringObject()
163 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
164 break;
165 if (node->child1()->shouldSpeculateStringOrStringObject()
166 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
167 break;
168 if (node->child2()->shouldSpeculateStringOrStringObject()
169 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
170 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000171 break;
172 }
173
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000174 case MakeRope: {
175 fixupMakeRope(node);
176 break;
177 }
178
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000179 case ArithAdd:
180 case ArithSub: {
181 if (attemptToMakeIntegerAdd(node))
182 break;
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000183 fixDoubleOrBooleanEdge(node->child1());
184 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000185 node->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000186 break;
187 }
188
189 case ArithNegate: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000190 if (m_graph.negateShouldSpeculateInt32(node, FixupPass)) {
191 fixIntOrBooleanEdge(node->child1());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000192 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
193 node->setArithMode(Arith::Unchecked);
194 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
195 node->setArithMode(Arith::CheckOverflow);
196 else
197 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000198 break;
199 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000200 if (m_graph.negateShouldSpeculateMachineInt(node, FixupPass)) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000201 fixEdge<Int52RepUse>(node->child1());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000202 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
203 node->setArithMode(Arith::CheckOverflow);
204 else
205 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000206 node->setResult(NodeResultInt52);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000207 break;
208 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000209 fixDoubleOrBooleanEdge(node->child1());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000210 node->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000211 break;
212 }
213
214 case ArithMul: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000215 if (m_graph.mulShouldSpeculateInt32(node, FixupPass)) {
216 fixIntOrBooleanEdge(node->child1());
217 fixIntOrBooleanEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000218 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
219 node->setArithMode(Arith::Unchecked);
220 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
221 node->setArithMode(Arith::CheckOverflow);
222 else
223 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000224 break;
225 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000226 if (m_graph.mulShouldSpeculateMachineInt(node, FixupPass)) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000227 fixEdge<Int52RepUse>(node->child1());
228 fixEdge<Int52RepUse>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000229 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
230 node->setArithMode(Arith::CheckOverflow);
231 else
232 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000233 node->setResult(NodeResultInt52);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000234 break;
235 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000236 fixDoubleOrBooleanEdge(node->child1());
237 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000238 node->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000239 break;
240 }
241
oliver@apple.comf4443a72013-07-25 04:01:11 +0000242 case ArithDiv:
243 case ArithMod: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000244 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
245 && node->canSpeculateInt32(FixupPass)) {
fpizlo@apple.com51204922013-12-11 06:50:19 +0000246 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000247 fixIntOrBooleanEdge(node->child1());
248 fixIntOrBooleanEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000249 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
250 node->setArithMode(Arith::Unchecked);
251 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
252 node->setArithMode(Arith::CheckOverflow);
253 else
254 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000255 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000256 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000257
258 // This will cause conversion nodes to be inserted later.
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000259 fixDoubleOrBooleanEdge(node->child1());
260 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000261
262 // But we have to make sure that everything is phantom'd until after the
263 // DoubleAsInt32 node, which occurs after the Div/Mod node that the conversions
264 // will be insered on.
265 addRequiredPhantom(node->child1().node());
266 addRequiredPhantom(node->child2().node());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000267
268 // We don't need to do ref'ing on the children because we're stealing them from
269 // the original division.
270 Node* newDivision = m_insertionSet.insertNode(
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +0000271 m_indexInBlock, SpecBytecodeDouble, *node);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000272 newDivision->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000273
274 node->setOp(DoubleAsInt32);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000275 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000276 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
277 node->setArithMode(Arith::CheckOverflow);
278 else
279 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000280 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000281 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000282 fixDoubleOrBooleanEdge(node->child1());
283 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000284 node->setResult(NodeResultDouble);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000285 break;
286 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000287
288 case ArithMin:
oliver@apple.comf4443a72013-07-25 04:01:11 +0000289 case ArithMax: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000290 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
291 && node->canSpeculateInt32(FixupPass)) {
292 fixIntOrBooleanEdge(node->child1());
293 fixIntOrBooleanEdge(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000294 break;
295 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000296 fixDoubleOrBooleanEdge(node->child1());
297 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000298 node->setResult(NodeResultDouble);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000299 break;
300 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000301
302 case ArithAbs: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000303 if (node->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
304 && node->canSpeculateInt32(FixupPass)) {
305 fixIntOrBooleanEdge(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000306 break;
307 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000308 fixDoubleOrBooleanEdge(node->child1());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000309 node->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000310 break;
311 }
312
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000313 case ArithSqrt:
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000314 case ArithFRound:
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000315 case ArithSin:
316 case ArithCos: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000317 fixDoubleOrBooleanEdge(node->child1());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000318 node->setResult(NodeResultDouble);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000319 break;
320 }
321
322 case LogicalNot: {
323 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000324 fixEdge<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000325 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000326 fixEdge<ObjectOrOtherUse>(node->child1());
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000327 else if (node->child1()->shouldSpeculateInt32OrBoolean())
328 fixIntOrBooleanEdge(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000329 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000330 fixEdge<DoubleRepUse>(node->child1());
commit-queue@webkit.org008e8dc2013-10-12 02:21:45 +0000331 else if (node->child1()->shouldSpeculateString())
332 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000333 break;
334 }
335
336 case TypeOf: {
337 if (node->child1()->shouldSpeculateString())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000338 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000339 else if (node->child1()->shouldSpeculateCell())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000340 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000341 break;
342 }
343
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000344 case CompareEqConstant: {
345 break;
346 }
347
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000348 case CompareEq:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000349 case CompareLess:
350 case CompareLessEq:
351 case CompareGreater:
352 case CompareGreaterEq: {
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000353 if (node->op() == CompareEq
354 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
355 fixEdge<BooleanUse>(node->child1());
356 fixEdge<BooleanUse>(node->child2());
357 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
358 break;
359 }
360 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
361 fixIntOrBooleanEdge(node->child1());
362 fixIntOrBooleanEdge(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000363 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000364 break;
365 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000366 if (enableInt52()
367 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000368 fixEdge<Int52RepUse>(node->child1());
369 fixEdge<Int52RepUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000370 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000371 break;
372 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000373 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
374 fixDoubleOrBooleanEdge(node->child1());
375 fixDoubleOrBooleanEdge(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000376 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000377 break;
378 }
379 if (node->op() != CompareEq)
380 break;
oliver@apple.combd15be82013-07-25 04:03:42 +0000381 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000382 fixEdge<StringIdentUse>(node->child1());
383 fixEdge<StringIdentUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000384 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
oliver@apple.combd15be82013-07-25 04:03:42 +0000385 break;
386 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000387 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000388 fixEdge<StringUse>(node->child1());
389 fixEdge<StringUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000390 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000391 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000392 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000393 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000394 fixEdge<ObjectUse>(node->child1());
395 fixEdge<ObjectUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000396 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000397 break;
398 }
399 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000400 fixEdge<ObjectUse>(node->child1());
401 fixEdge<ObjectOrOtherUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000402 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000403 break;
404 }
405 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000406 fixEdge<ObjectOrOtherUse>(node->child1());
407 fixEdge<ObjectUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000408 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000409 break;
410 }
411 break;
412 }
413
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000414 case CompareStrictEq: {
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000415 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000416 fixEdge<BooleanUse>(node->child1());
417 fixEdge<BooleanUse>(node->child2());
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000418 break;
419 }
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000420 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000421 fixEdge<Int32Use>(node->child1());
422 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000423 break;
424 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000425 if (enableInt52()
426 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000427 fixEdge<Int52RepUse>(node->child1());
428 fixEdge<Int52RepUse>(node->child2());
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000429 break;
430 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000431 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000432 fixEdge<DoubleRepUse>(node->child1());
433 fixEdge<DoubleRepUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000434 break;
435 }
oliver@apple.combd15be82013-07-25 04:03:42 +0000436 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000437 fixEdge<StringIdentUse>(node->child1());
438 fixEdge<StringIdentUse>(node->child2());
oliver@apple.combd15be82013-07-25 04:03:42 +0000439 break;
440 }
fpizlo@apple.com322ad4f2014-03-19 20:36:45 +0000441 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && (GPRInfo::numberOfRegisters >= 7 || isFTL(m_graph.m_plan.mode))) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000442 fixEdge<StringUse>(node->child1());
443 fixEdge<StringUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000444 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000445 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000446 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000447 fixEdge<ObjectUse>(node->child1());
448 fixEdge<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000449 break;
450 }
fpizlo@apple.com312efcd2014-03-10 22:11:35 +0000451 if (node->child1()->shouldSpeculateMisc()) {
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000452 fixEdge<MiscUse>(node->child1());
fpizlo@apple.com312efcd2014-03-10 22:11:35 +0000453 break;
454 }
455 if (node->child2()->shouldSpeculateMisc()) {
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000456 fixEdge<MiscUse>(node->child2());
457 break;
458 }
fpizlo@apple.com385a33a2014-03-18 20:53:07 +0000459 if (node->child1()->shouldSpeculateStringIdent()
460 && node->child2()->shouldSpeculateNotStringVar()) {
461 fixEdge<StringIdentUse>(node->child1());
462 fixEdge<NotStringVarUse>(node->child2());
463 break;
464 }
465 if (node->child2()->shouldSpeculateStringIdent()
466 && node->child1()->shouldSpeculateNotStringVar()) {
467 fixEdge<StringIdentUse>(node->child2());
468 fixEdge<NotStringVarUse>(node->child1());
469 break;
470 }
fpizlo@apple.com322ad4f2014-03-19 20:36:45 +0000471 if (node->child1()->shouldSpeculateString() && (GPRInfo::numberOfRegisters >= 8 || isFTL(m_graph.m_plan.mode))) {
fpizlo@apple.com385a33a2014-03-18 20:53:07 +0000472 fixEdge<StringUse>(node->child1());
473 break;
474 }
fpizlo@apple.com322ad4f2014-03-19 20:36:45 +0000475 if (node->child2()->shouldSpeculateString() && (GPRInfo::numberOfRegisters >= 8 || isFTL(m_graph.m_plan.mode))) {
fpizlo@apple.com385a33a2014-03-18 20:53:07 +0000476 fixEdge<StringUse>(node->child2());
477 break;
478 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000479 break;
480 }
481
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000482 case StringFromCharCode:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000483 fixEdge<Int32Use>(node->child1());
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000484 break;
485
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000486 case StringCharAt:
487 case StringCharCodeAt: {
488 // Currently we have no good way of refining these.
489 ASSERT(node->arrayMode() == ArrayMode(Array::String));
490 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000491 fixEdge<KnownCellUse>(node->child1());
492 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000493 break;
494 }
495
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000496 case GetByVal: {
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000497 if (!node->prediction()) {
498 m_insertionSet.insertNode(
499 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
500 }
501
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000502 node->setArrayMode(
503 node->arrayMode().refine(
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000504 m_graph, node,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000505 node->child1()->prediction(),
506 node->child2()->prediction(),
507 SpecNone, node->flags()));
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000508
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000509 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000510
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000511 ArrayMode arrayMode = node->arrayMode();
oliver@apple.com211b3be2013-07-25 04:03:39 +0000512 switch (arrayMode.type()) {
513 case Array::Double:
514 if (arrayMode.arrayClass() == Array::OriginalArray
515 && arrayMode.speculation() == Array::InBounds
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000516 && m_graph.globalObjectFor(node->origin.semantic)->arrayPrototypeChainIsSane()
fpizlo@apple.comdc36e832013-09-11 03:24:09 +0000517 && !(node->flags() & NodeBytecodeUsesAsOther))
oliver@apple.com211b3be2013-07-25 04:03:39 +0000518 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
519 break;
520
521 case Array::String:
522 if ((node->prediction() & ~SpecString)
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000523 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
oliver@apple.com211b3be2013-07-25 04:03:39 +0000524 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
525 break;
526
527 default:
528 break;
529 }
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000530
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000531 arrayMode = node->arrayMode();
532 switch (arrayMode.type()) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000533 case Array::SelectUsingPredictions:
534 case Array::Unprofiled:
535 case Array::Undecided:
536 RELEASE_ASSERT_NOT_REACHED();
537 break;
538 case Array::Generic:
539#if USE(JSVALUE32_64)
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000540 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000541#endif
542 break;
543 case Array::ForceExit:
544 break;
545 default:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000546 fixEdge<KnownCellUse>(node->child1());
547 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000548 break;
549 }
550
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000551 switch (arrayMode.type()) {
552 case Array::Double:
553 if (!arrayMode.isOutOfBounds())
554 node->setResult(NodeResultDouble);
555 break;
556
557 case Array::Float32Array:
558 case Array::Float64Array:
559 node->setResult(NodeResultDouble);
560 break;
561
562 case Array::Uint32Array:
563 if (node->shouldSpeculateInt32())
564 break;
565 if (node->shouldSpeculateMachineInt() && enableInt52())
566 node->setResult(NodeResultInt52);
567 else
568 node->setResult(NodeResultDouble);
569 break;
570
571 default:
572 break;
573 }
574
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000575 break;
576 }
oliver@apple.come050d642013-10-19 00:09:28 +0000577
578 case PutByValDirect:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000579 case PutByVal:
580 case PutByValAlias: {
581 Edge& child1 = m_graph.varArgChild(node, 0);
582 Edge& child2 = m_graph.varArgChild(node, 1);
583 Edge& child3 = m_graph.varArgChild(node, 2);
584
585 node->setArrayMode(
586 node->arrayMode().refine(
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000587 m_graph, node,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000588 child1->prediction(),
589 child2->prediction(),
590 child3->prediction()));
591
592 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
593
594 switch (node->arrayMode().modeForPut().type()) {
595 case Array::SelectUsingPredictions:
596 case Array::Unprofiled:
597 case Array::Undecided:
598 RELEASE_ASSERT_NOT_REACHED();
599 break;
600 case Array::ForceExit:
601 case Array::Generic:
602#if USE(JSVALUE32_64)
603 // Due to register pressure on 32-bit, we speculate cell and
604 // ignore the base-is-not-cell case entirely by letting the
605 // baseline JIT handle it.
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000606 fixEdge<CellUse>(child1);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000607#endif
608 break;
609 case Array::Int32:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000610 fixEdge<KnownCellUse>(child1);
611 fixEdge<Int32Use>(child2);
612 fixEdge<Int32Use>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000613 break;
614 case Array::Double:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000615 fixEdge<KnownCellUse>(child1);
616 fixEdge<Int32Use>(child2);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000617 fixEdge<DoubleRepRealUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000618 break;
619 case Array::Int8Array:
620 case Array::Int16Array:
621 case Array::Int32Array:
622 case Array::Uint8Array:
623 case Array::Uint8ClampedArray:
624 case Array::Uint16Array:
625 case Array::Uint32Array:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000626 fixEdge<KnownCellUse>(child1);
627 fixEdge<Int32Use>(child2);
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000628 if (child3->shouldSpeculateInt32())
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000629 fixIntOrBooleanEdge(child3);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000630 else if (child3->shouldSpeculateMachineInt())
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000631 fixEdge<Int52RepUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000632 else
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000633 fixDoubleOrBooleanEdge(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000634 break;
635 case Array::Float32Array:
636 case Array::Float64Array:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000637 fixEdge<KnownCellUse>(child1);
638 fixEdge<Int32Use>(child2);
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000639 fixDoubleOrBooleanEdge(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000640 break;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000641 case Array::Contiguous:
642 case Array::ArrayStorage:
643 case Array::SlowPutArrayStorage:
644 case Array::Arguments:
645 fixEdge<KnownCellUse>(child1);
646 fixEdge<Int32Use>(child2);
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +0000647 insertStoreBarrier(m_indexInBlock, child1);
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000648 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000649 default:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000650 fixEdge<KnownCellUse>(child1);
651 fixEdge<Int32Use>(child2);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000652 break;
653 }
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000654 break;
655 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000656
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000657 case ArrayPush: {
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000658 // May need to refine the array mode in case the value prediction contravenes
659 // the array prediction. For example, we may have evidence showing that the
660 // array is in Int32 mode, but the value we're storing is likely to be a double.
661 // Then we should turn this into a conversion to Double array followed by the
662 // push. On the other hand, we absolutely don't want to refine based on the
663 // base prediction. If it has non-cell garbage in it, then we want that to be
664 // ignored. That's because ArrayPush can't handle any array modes that aren't
665 // array-related - so if refine() turned this into a "Generic" ArrayPush then
666 // that would break things.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000667 node->setArrayMode(
668 node->arrayMode().refine(
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000669 m_graph, node,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000670 node->child1()->prediction() & SpecCell,
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000671 SpecInt32,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000672 node->child2()->prediction()));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000673 blessArrayOperation(node->child1(), Edge(), node->child3());
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000674 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000675
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000676 switch (node->arrayMode().type()) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000677 case Array::Int32:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000678 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000679 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000680 case Array::Double:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000681 fixEdge<DoubleRepRealUse>(node->child2());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000682 break;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000683 case Array::Contiguous:
684 case Array::ArrayStorage:
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +0000685 insertStoreBarrier(m_indexInBlock, node->child1());
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000686 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000687 default:
688 break;
689 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000690 break;
691 }
692
693 case ArrayPop: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000694 blessArrayOperation(node->child1(), Edge(), node->child2());
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000695 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com8fd79212012-10-16 21:59:35 +0000696 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000697 }
698
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000699 case RegExpExec:
700 case RegExpTest: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000701 fixEdge<CellUse>(node->child1());
702 fixEdge<CellUse>(node->child2());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000703 break;
704 }
705
706 case Branch: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000707 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000708 fixEdge<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000709 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000710 fixEdge<ObjectOrOtherUse>(node->child1());
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000711 else if (node->child1()->shouldSpeculateInt32OrBoolean())
712 fixIntOrBooleanEdge(node->child1());
713 else if (node->child1()->shouldSpeculateNumberOrBoolean())
714 fixDoubleOrBooleanEdge(node->child1());
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000715
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000716 Node* logicalNot = node->child1().node();
fpizlo@apple.com098a1452013-03-01 20:57:37 +0000717 if (logicalNot->op() == LogicalNot) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000718
719 // Make sure that OSR exit can't observe the LogicalNot. If it can,
720 // then we must compute it and cannot peephole around it.
721 bool found = false;
722 bool ok = true;
723 for (unsigned i = m_indexInBlock; i--;) {
724 Node* candidate = m_block->at(i);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000725 if (candidate == logicalNot) {
726 found = true;
727 break;
728 }
729 if (candidate->canExit()) {
730 ok = false;
731 found = true;
732 break;
733 }
734 }
735 ASSERT_UNUSED(found, found);
736
737 if (ok) {
738 Edge newChildEdge = logicalNot->child1();
739 if (newChildEdge->hasBooleanResult()) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000740 node->children.setChild1(newChildEdge);
741
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +0000742 BranchData* data = node->branchData();
743 std::swap(data->taken, data->notTaken);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000744 }
fpizlo@apple.coma6c889b2012-04-12 04:19:07 +0000745 }
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000746 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000747 break;
748 }
749
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000750 case Switch: {
751 SwitchData* data = node->switchData();
752 switch (data->kind) {
753 case SwitchImm:
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000754 if (node->child1()->shouldSpeculateInt32())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000755 fixEdge<Int32Use>(node->child1());
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000756 break;
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000757 case SwitchChar:
758 if (node->child1()->shouldSpeculateString())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000759 fixEdge<StringUse>(node->child1());
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000760 break;
oliver@apple.com5c826c02013-07-25 04:03:51 +0000761 case SwitchString:
762 if (node->child1()->shouldSpeculateStringIdent())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000763 fixEdge<StringIdentUse>(node->child1());
oliver@apple.com5c826c02013-07-25 04:03:51 +0000764 else if (node->child1()->shouldSpeculateString())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000765 fixEdge<StringUse>(node->child1());
oliver@apple.com5c826c02013-07-25 04:03:51 +0000766 break;
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000767 }
768 break;
769 }
770
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000771 case ToPrimitive: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000772 fixupToPrimitive(node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000773 break;
774 }
775
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000776 case ToString: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000777 fixupToString(node);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000778 break;
779 }
780
781 case NewStringObject: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000782 fixEdge<KnownStringUse>(node->child1());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000783 break;
784 }
785
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000786 case NewArray: {
787 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000788 node->setIndexingType(
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000789 leastUpperBoundOfIndexingTypeAndType(
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000790 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000791 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000792 switch (node->indexingType()) {
793 case ALL_BLANK_INDEXING_TYPES:
794 CRASH();
795 break;
796 case ALL_UNDECIDED_INDEXING_TYPES:
797 if (node->numChildren()) {
798 // This will only happen if the children have no type predictions. We
799 // would have already exited by now, but insert a forced exit just to
800 // be safe.
801 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000802 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000803 }
804 break;
805 case ALL_INT32_INDEXING_TYPES:
806 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000807 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000808 break;
809 case ALL_DOUBLE_INDEXING_TYPES:
810 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000811 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000812 break;
813 case ALL_CONTIGUOUS_INDEXING_TYPES:
814 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
815 break;
816 default:
817 CRASH();
818 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000819 }
820 break;
821 }
822
fpizlo@apple.com372fa822013-08-21 19:43:47 +0000823 case NewTypedArray: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000824 if (node->child1()->shouldSpeculateInt32()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000825 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com372fa822013-08-21 19:43:47 +0000826 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
827 break;
828 }
829 break;
830 }
831
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000832 case NewArrayWithSize: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000833 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000834 break;
835 }
836
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000837 case ToThis: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000838 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000839
fpizlo@apple.com312efcd2014-03-10 22:11:35 +0000840 if (node->child1()->shouldSpeculateOther()) {
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000841 if (ecmaMode == StrictMode) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000842 fixEdge<OtherUse>(node->child1());
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000843 node->convertToIdentity();
844 break;
845 }
846
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000847 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000848 m_indexInBlock, SpecNone, Phantom, node->origin,
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000849 Edge(node->child1().node(), OtherUse));
850 observeUseKindOnNode<OtherUse>(node->child1().node());
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000851 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->origin.semantic));
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000852 break;
853 }
854
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000855 if (isFinalObjectSpeculation(node->child1()->prediction())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000856 fixEdge<FinalObjectUse>(node->child1());
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000857 node->convertToIdentity();
858 break;
859 }
860
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000861 break;
862 }
863
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000864 case GetMyArgumentByVal:
865 case GetMyArgumentByValSafe: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000866 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000867 break;
868 }
869
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000870 case PutStructure: {
871 fixEdge<KnownCellUse>(node->child1());
872 insertStoreBarrier(m_indexInBlock, node->child1());
873 break;
874 }
875
876 case PutClosureVar: {
877 fixEdge<KnownCellUse>(node->child1());
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +0000878 insertStoreBarrier(m_indexInBlock, node->child1());
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000879 break;
880 }
881
oliver@apple.com58c86752013-07-25 04:02:40 +0000882 case GetClosureRegisters:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000883 case SkipTopScope:
884 case SkipScope:
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000885 case GetScope:
886 case GetGetter:
887 case GetSetter: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000888 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000889 break;
890 }
891
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000892 case AllocatePropertyStorage:
893 case ReallocatePropertyStorage: {
894 fixEdge<KnownCellUse>(node->child1());
895 insertStoreBarrier(m_indexInBlock + 1, node->child1());
896 break;
897 }
898
fpizlo@apple.com151e9af2013-08-16 02:30:37 +0000899 case GetById:
900 case GetByIdFlush: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000901 if (!node->child1()->shouldSpeculateCell())
902 break;
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000903 StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
904 if (impl == vm().propertyNames->length.impl()) {
fpizlo@apple.comc09dc632013-08-17 05:50:48 +0000905 attemptToMakeGetArrayLength(node);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000906 break;
fpizlo@apple.com151e9af2013-08-16 02:30:37 +0000907 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000908 if (impl == vm().propertyNames->byteLength.impl()) {
909 attemptToMakeGetTypedArrayByteLength(node);
910 break;
911 }
912 if (impl == vm().propertyNames->byteOffset.impl()) {
913 attemptToMakeGetTypedArrayByteOffset(node);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +0000914 break;
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000915 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000916 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000917 break;
918 }
919
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000920 case PutById:
oliver@apple.com11ce5ff2014-03-06 21:27:13 +0000921 case PutByIdFlush:
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000922 case PutByIdDirect: {
923 fixEdge<CellUse>(node->child1());
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +0000924 insertStoreBarrier(m_indexInBlock, node->child1());
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000925 break;
926 }
927
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000928 case CheckExecutable:
929 case CheckStructure:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000930 case CheckFunction:
oliver@apple.come17632e2013-07-25 04:05:31 +0000931 case CheckHasInstance:
932 case CreateThis:
933 case GetButterfly: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000934 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000935 break;
936 }
937
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000938 case Arrayify:
939 case ArrayifyToStructure: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000940 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000941 if (node->child2())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000942 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000943 break;
944 }
945
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000946 case GetByOffset:
947 case GetGetterSetterByOffset: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000948 if (!node->child1()->hasStorageResult())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000949 fixEdge<KnownCellUse>(node->child1());
950 fixEdge<KnownCellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000951 break;
952 }
953
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000954 case MultiGetByOffset: {
955 fixEdge<CellUse>(node->child1());
956 break;
957 }
958
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000959 case PutByOffset: {
960 if (!node->child1()->hasStorageResult())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000961 fixEdge<KnownCellUse>(node->child1());
962 fixEdge<KnownCellUse>(node->child2());
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +0000963 insertStoreBarrier(m_indexInBlock, node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000964 break;
965 }
966
fpizlo@apple.com43219522014-02-25 02:02:50 +0000967 case MultiPutByOffset: {
968 fixEdge<CellUse>(node->child1());
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +0000969 insertStoreBarrier(m_indexInBlock, node->child1());
fpizlo@apple.com43219522014-02-25 02:02:50 +0000970 break;
971 }
972
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000973 case InstanceOf: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000974 if (!(node->child1()->prediction() & ~SpecCell))
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000975 fixEdge<CellUse>(node->child1());
976 fixEdge<CellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000977 break;
978 }
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000979
980 case In: {
981 // FIXME: We should at some point have array profiling on op_in, in which
982 // case we would be able to turn this into a kind of GetByVal.
983
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000984 fixEdge<CellUse>(node->child2());
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000985 break;
986 }
fpizlo@apple.com46955912013-04-26 01:18:18 +0000987
988 case Phantom:
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000989 case Check: {
fpizlo@apple.com46955912013-04-26 01:18:18 +0000990 switch (node->child1().useKind()) {
991 case NumberUse:
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000992 if (node->child1()->shouldSpeculateInt32ForArithmetic())
fpizlo@apple.com46955912013-04-26 01:18:18 +0000993 node->child1().setUseKind(Int32Use);
994 break;
995 default:
996 break;
997 }
998 observeUseKindOnEdge(node->child1());
999 break;
1000 }
1001
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001002 case FiatInt52: {
1003 RELEASE_ASSERT(enableInt52());
1004 node->convertToIdentity();
1005 fixEdge<Int52RepUse>(node->child1());
1006 node->setResult(NodeResultInt52);
1007 break;
1008 }
1009
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001010 case GetArrayLength:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001011 case Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001012 case Upsilon:
1013 case GetArgument:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001014 case PhantomPutStructure:
1015 case GetIndexedPropertyStorage:
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001016 case GetTypedArrayByteOffset:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001017 case LastNodeType:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001018 case CheckTierUpInLoop:
1019 case CheckTierUpAtReturn:
1020 case CheckTierUpAndOSREnter:
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001021 case InvalidationPoint:
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001022 case CheckArray:
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00001023 case CheckInBounds:
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +00001024 case ConstantStoragePointer:
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001025 case DoubleAsInt32:
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001026 case ValueToInt32:
fpizlo@apple.com4c96a842014-02-13 22:46:51 +00001027 case HardPhantom: // HardPhantom would be trivial to handle but anyway we assert that we won't see it here yet.
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001028 case DoubleRep:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001029 case ValueRep:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001030 case Int52Rep:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001031 case DoubleConstant:
1032 case Int52Constant:
1033 case Identity: // This should have been cleaned up.
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001034 case BooleanToNumber:
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +00001035 // These are just nodes that we don't currently expect to see during fixup.
1036 // If we ever wanted to insert them prior to fixup, then we just have to create
1037 // fixup rules for them.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001038 RELEASE_ASSERT_NOT_REACHED();
1039 break;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001040
1041 case PutGlobalVar: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001042 Node* globalObjectNode = m_insertionSet.insertNode(
1043 m_indexInBlock, SpecNone, WeakJSConstant, node->origin,
1044 OpInfo(m_graph.globalObjectFor(node->origin.semantic)));
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00001045 // FIXME: This probably shouldn't have an unconditional barrier.
1046 // https://bugs.webkit.org/show_bug.cgi?id=133104
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001047 Node* barrierNode = m_graph.addNode(
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +00001048 SpecNone, StoreBarrier, m_currentNode->origin,
1049 Edge(globalObjectNode, KnownCellUse));
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001050 m_insertionSet.insert(m_indexInBlock, barrierNode);
1051 break;
1052 }
1053
1054 case TearOffActivation: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001055 Node* barrierNode = m_graph.addNode(
1056 SpecNone, StoreBarrierWithNullCheck, m_currentNode->origin,
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001057 Edge(node->child1().node(), UntypedUse));
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001058 m_insertionSet.insert(m_indexInBlock, barrierNode);
1059 break;
1060 }
commit-queue@webkit.org2faae0e2013-10-07 22:08:53 +00001061
1062 case IsString:
1063 if (node->child1()->shouldSpeculateString()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001064 m_insertionSet.insertNode(
1065 m_indexInBlock, SpecNone, Phantom, node->origin,
commit-queue@webkit.org2faae0e2013-10-07 22:08:53 +00001066 Edge(node->child1().node(), StringUse));
1067 m_graph.convertToConstant(node, jsBoolean(true));
1068 observeUseKindOnNode<StringUse>(node);
1069 }
1070 break;
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001071
commit-queue@webkit.org2faae0e2013-10-07 22:08:53 +00001072#if !ASSERT_DISABLED
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001073 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
1074 case SetArgument:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001075 case JSConstant:
1076 case WeakJSConstant:
1077 case GetLocal:
1078 case GetCallee:
1079 case Flush:
1080 case PhantomLocal:
1081 case GetLocalUnlinked:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001082 case GetMyScope:
oliver@apple.com58c86752013-07-25 04:02:40 +00001083 case GetClosureVar:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001084 case GetGlobalVar:
fpizlo@apple.com86468342013-11-27 02:47:43 +00001085 case NotifyWrite:
1086 case VariableWatchpoint:
oliver@apple.com58c86752013-07-25 04:02:40 +00001087 case VarInjectionWatchpoint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001088 case AllocationProfileWatchpoint:
1089 case Call:
1090 case Construct:
1091 case NewObject:
1092 case NewArrayBuffer:
1093 case NewRegexp:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001094 case Breakpoint:
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00001095 case ProfileWillCall:
1096 case ProfileDidCall:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001097 case IsUndefined:
1098 case IsBoolean:
1099 case IsNumber:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001100 case IsObject:
1101 case IsFunction:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001102 case CreateActivation:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001103 case CreateArguments:
1104 case PhantomArguments:
1105 case TearOffArguments:
1106 case GetMyArgumentsLength:
1107 case GetMyArgumentsLengthSafe:
1108 case CheckArgumentsNotCreated:
1109 case NewFunction:
1110 case NewFunctionNoCheck:
1111 case NewFunctionExpression:
1112 case Jump:
1113 case Return:
1114 case Throw:
1115 case ThrowReferenceError:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001116 case CountExecution:
1117 case ForceOSRExit:
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00001118 case CheckWatchdogTimer:
oliver@apple.com1fc04182013-08-19 19:40:13 +00001119 case Unreachable:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001120 case ExtractOSREntryLocal:
1121 case LoopHint:
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001122 case StoreBarrier:
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001123 case StoreBarrierWithNullCheck:
fpizlo@apple.coma4ea0662013-12-02 19:09:15 +00001124 case FunctionReentryWatchpoint:
fpizlo@apple.comce995b22013-12-08 19:01:17 +00001125 case TypedArrayWatchpoint:
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001126 case MovHint:
1127 case ZombieHint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001128 break;
1129#else
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001130 default:
1131 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001132#endif
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001133 }
fpizlo@apple.comaa1cc982013-09-12 05:46:49 +00001134 }
1135
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001136 template<UseKind useKind>
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001137 void createToString(Node* node, Edge& edge)
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001138 {
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001139 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001140 m_indexInBlock, SpecString, ToString, node->origin,
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001141 Edge(edge.node(), useKind)));
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001142 }
1143
1144 template<UseKind useKind>
1145 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1146 {
1147 ASSERT(arrayMode == ArrayMode(Array::Generic));
1148
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001149 if (!canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001150 return;
1151
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001152 createToString<useKind>(node, node->child1());
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001153 arrayMode = ArrayMode(Array::String);
1154 }
1155
1156 template<UseKind useKind>
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001157 bool isStringObjectUse()
1158 {
1159 switch (useKind) {
1160 case StringObjectUse:
1161 case StringOrStringObjectUse:
1162 return true;
1163 default:
1164 return false;
1165 }
1166 }
1167
1168 template<UseKind useKind>
1169 void convertStringAddUse(Node* node, Edge& edge)
1170 {
1171 if (useKind == StringUse) {
1172 // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
1173 // two edges will always have identical use kinds, which makes the
1174 // decision process much easier.
1175 observeUseKindOnNode<StringUse>(edge.node());
1176 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001177 m_indexInBlock, SpecNone, Phantom, node->origin,
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001178 Edge(edge.node(), StringUse));
1179 edge.setUseKind(KnownStringUse);
1180 return;
1181 }
1182
1183 // FIXME: We ought to be able to have a ToPrimitiveToString node.
1184
1185 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001186 createToString<useKind>(node, edge);
1187 }
1188
1189 void convertToMakeRope(Node* node)
1190 {
1191 node->setOpAndDefaultFlags(MakeRope);
1192 fixupMakeRope(node);
1193 }
1194
1195 void fixupMakeRope(Node* node)
1196 {
1197 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1198 Edge& edge = node->children.child(i);
1199 if (!edge)
1200 break;
1201 edge.setUseKind(KnownStringUse);
1202 if (!m_graph.isConstant(edge.node()))
1203 continue;
1204 JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
1205 if (string->length())
1206 continue;
fpizlo@apple.com4bb938e2013-07-16 21:41:06 +00001207
1208 // Don't allow the MakeRope to have zero children.
1209 if (!i && !node->child2())
1210 break;
1211
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001212 node->children.removeEdge(i--);
1213 }
1214
1215 if (!node->child2()) {
1216 ASSERT(!node->child3());
1217 node->convertToIdentity();
1218 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001219 }
1220
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001221 void fixupToPrimitive(Node* node)
1222 {
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001223 if (node->child1()->shouldSpeculateInt32()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001224 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001225 node->convertToIdentity();
1226 return;
1227 }
1228
1229 if (node->child1()->shouldSpeculateString()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001230 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001231 node->convertToIdentity();
1232 return;
1233 }
1234
1235 if (node->child1()->shouldSpeculateStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001236 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001237 fixEdge<StringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001238 node->convertToToString();
1239 return;
1240 }
1241
1242 if (node->child1()->shouldSpeculateStringOrStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001243 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001244 fixEdge<StringOrStringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001245 node->convertToToString();
1246 return;
1247 }
1248 }
1249
1250 void fixupToString(Node* node)
1251 {
1252 if (node->child1()->shouldSpeculateString()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001253 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001254 node->convertToIdentity();
1255 return;
1256 }
1257
1258 if (node->child1()->shouldSpeculateStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001259 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001260 fixEdge<StringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001261 return;
1262 }
1263
1264 if (node->child1()->shouldSpeculateStringOrStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001265 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001266 fixEdge<StringOrStringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001267 return;
1268 }
1269
1270 if (node->child1()->shouldSpeculateCell()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001271 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001272 return;
1273 }
1274 }
1275
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001276 template<UseKind leftUseKind>
1277 bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1278 {
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001279 Node* originalLeft = left.node();
1280 Node* originalRight = right.node();
1281
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001282 ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1283
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001284 if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001285 return false;
1286
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001287 convertStringAddUse<leftUseKind>(node, left);
1288
1289 if (right->shouldSpeculateString())
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001290 convertStringAddUse<StringUse>(node, right);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001291 else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001292 convertStringAddUse<StringObjectUse>(node, right);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001293 else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001294 convertStringAddUse<StringOrStringObjectUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001295 else {
1296 // At this point we know that the other operand is something weird. The semantically correct
1297 // way of dealing with this is:
1298 //
1299 // MakeRope(@left, ToString(ToPrimitive(@right)))
1300 //
1301 // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1302 // anything to @right, since ToPrimitive may be effectful.
1303
1304 Node* toPrimitive = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001305 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive,
1306 node->origin, Edge(right.node()));
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001307 Node* toString = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001308 m_indexInBlock, SpecString, ToString, node->origin, Edge(toPrimitive));
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001309
1310 fixupToPrimitive(toPrimitive);
1311 fixupToString(toString);
1312
1313 right.setNode(toString);
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001314 }
1315
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001316 // We're doing checks up there, so we need to make sure that the
1317 // *original* inputs to the addition are live up to here.
1318 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001319 m_indexInBlock, SpecNone, Phantom, node->origin,
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001320 Edge(originalLeft), Edge(originalRight));
1321
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001322 convertToMakeRope(node);
1323 return true;
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001324 }
1325
oliver@apple.com02039462013-07-25 03:59:29 +00001326 bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001327 {
1328 unsigned attributesUnused;
1329 JSCell* specificValue;
oliver@apple.com22fdb102013-07-25 03:58:56 +00001330 PropertyOffset offset = stringPrototypeStructure->getConcurrently(
oliver@apple.com02039462013-07-25 03:59:29 +00001331 vm(), uid, attributesUnused, specificValue);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001332 if (!isValidOffset(offset))
1333 return false;
1334
1335 if (!specificValue)
1336 return false;
1337
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001338 if (!specificValue->inherits(JSFunction::info()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001339 return false;
1340
1341 JSFunction* function = jsCast<JSFunction*>(specificValue);
1342 if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1343 return false;
1344
1345 return true;
1346 }
1347
1348 bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1349 {
1350 if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1351 return false;
1352
1353 Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1354 ASSERT(stringObjectStructure->storedPrototype().isObject());
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001355 ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001356
1357 JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1358 Structure* stringPrototypeStructure = stringPrototypeObject->structure();
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00001359 if (!m_graph.watchpoints().consider(stringPrototypeStructure))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001360 return false;
1361
1362 if (stringPrototypeStructure->isDictionary())
1363 return false;
1364
1365 // We're being conservative here. We want DFG's ToString on StringObject to be
1366 // used in both numeric contexts (that would call valueOf()) and string contexts
1367 // (that would call toString()). We don't want the DFG to have to distinguish
1368 // between the two, just because that seems like it would get confusing. So we
1369 // just require both methods to be sane.
oliver@apple.com02039462013-07-25 03:59:29 +00001370 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001371 return false;
oliver@apple.com02039462013-07-25 03:59:29 +00001372 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001373 return false;
1374
1375 return true;
1376 }
1377
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001378 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001379 {
1380 if (!block)
1381 return;
1382 ASSERT(block->isReachable);
1383 m_block = block;
1384 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1385 Node* node = m_currentNode = block->at(m_indexInBlock);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001386 if (node->op() != SetLocal && node->op() != GetLocal)
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001387 continue;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001388
1389 VariableAccessData* variable = node->variableAccessData();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001390 switch (node->op()) {
1391 case GetLocal:
1392 switch (variable->flushFormat()) {
1393 case FlushedDouble:
1394 node->setResult(NodeResultDouble);
1395 break;
1396 case FlushedInt52:
1397 node->setResult(NodeResultInt52);
1398 break;
1399 default:
1400 break;
1401 }
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001402 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001403
1404 case SetLocal:
1405 switch (variable->flushFormat()) {
1406 case FlushedJSValue:
1407 break;
1408 case FlushedDouble:
1409 fixEdge<DoubleRepUse>(node->child1());
1410 break;
1411 case FlushedInt32:
1412 fixEdge<Int32Use>(node->child1());
1413 break;
1414 case FlushedInt52:
1415 fixEdge<Int52RepUse>(node->child1());
1416 break;
1417 case FlushedCell:
1418 fixEdge<CellUse>(node->child1());
1419 break;
1420 case FlushedBoolean:
1421 fixEdge<BooleanUse>(node->child1());
1422 break;
1423 default:
1424 RELEASE_ASSERT_NOT_REACHED();
1425 break;
1426 }
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001427 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001428
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001429 default:
1430 RELEASE_ASSERT_NOT_REACHED();
1431 break;
1432 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001433 }
1434 m_insertionSet.execute(block);
1435 }
1436
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001437 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001438 {
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001439 ASSERT(arrayMode.isSpecific());
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001440
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001441 if (arrayMode.type() == Array::String) {
1442 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001443 m_indexInBlock, SpecNone, Phantom, origin, Edge(array, StringUse));
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001444 } else {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001445 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001446
1447 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1448
1449 if (arrayMode.doesConversion()) {
1450 if (structure) {
1451 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001452 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001453 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1454 } else {
1455 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001456 m_indexInBlock, SpecNone, Arrayify, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001457 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1458 }
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001459 } else {
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001460 if (structure) {
1461 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001462 m_indexInBlock, SpecNone, CheckStructure, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001463 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1464 } else {
1465 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001466 m_indexInBlock, SpecNone, CheckArray, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001467 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1468 }
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001469 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001470 }
1471
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001472 if (!storageCheck(arrayMode))
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001473 return 0;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001474
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001475 if (arrayMode.usesButterfly()) {
1476 return m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001477 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001478 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001479
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001480 return m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001481 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001482 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001483 }
1484
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001485 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001486 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001487 Node* node = m_currentNode;
1488
1489 switch (node->arrayMode().type()) {
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001490 case Array::ForceExit: {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001491 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001492 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001493 return;
1494 }
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001495
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001496 case Array::SelectUsingPredictions:
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001497 case Array::Unprofiled:
oliver@apple.com5598c182013-01-23 22:25:07 +00001498 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001499 return;
1500
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001501 case Array::Generic:
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001502 return;
1503
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001504 default: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001505 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001506 if (!storage)
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001507 return;
1508
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001509 storageChild = Edge(storage);
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001510 return;
1511 } }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001512 }
1513
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001514 bool alwaysUnboxSimplePrimitives()
1515 {
1516#if USE(JSVALUE64)
1517 return false;
1518#else
1519 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1520 // reduces traffic.
1521 return true;
1522#endif
1523 }
fpizlo@apple.com46955912013-04-26 01:18:18 +00001524
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001525 template<UseKind useKind>
1526 void observeUseKindOnNode(Node* node)
1527 {
fpizlo@apple.comaa1cc982013-09-12 05:46:49 +00001528 if (useKind == UntypedUse)
1529 return;
fpizlo@apple.com46955912013-04-26 01:18:18 +00001530 observeUseKindOnNode(node, useKind);
1531 }
1532
1533 void observeUseKindOnEdge(Edge edge)
1534 {
1535 observeUseKindOnNode(edge.node(), edge.useKind());
1536 }
1537
1538 void observeUseKindOnNode(Node* node, UseKind useKind)
1539 {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001540 if (node->op() != GetLocal)
1541 return;
1542
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001543 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
1544 // https://bugs.webkit.org/show_bug.cgi?id=121518
1545
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001546 VariableAccessData* variable = node->variableAccessData();
1547 switch (useKind) {
1548 case Int32Use:
1549 if (alwaysUnboxSimplePrimitives()
1550 || isInt32Speculation(variable->prediction()))
1551 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1552 break;
1553 case NumberUse:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001554 case DoubleRepUse:
1555 case DoubleRepRealUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001556 if (variable->doubleFormatState() == UsingDoubleFormat)
1557 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1558 break;
1559 case BooleanUse:
1560 if (alwaysUnboxSimplePrimitives()
1561 || isBooleanSpeculation(variable->prediction()))
1562 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1563 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001564 case Int52RepUse:
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001565 if (isMachineIntSpeculation(variable->prediction()))
1566 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1567 break;
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001568 case CellUse:
oliver@apple.com176a3472013-07-25 04:00:19 +00001569 case KnownCellUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001570 case ObjectUse:
1571 case StringUse:
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001572 case KnownStringUse:
1573 case StringObjectUse:
1574 case StringOrStringObjectUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001575 if (alwaysUnboxSimplePrimitives()
1576 || isCellSpeculation(variable->prediction()))
1577 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1578 break;
1579 default:
1580 break;
1581 }
1582 }
1583
fpizlo@apple.com35701872013-02-23 01:03:10 +00001584 template<UseKind useKind>
fpizlo@apple.comc6bb4a92013-09-30 20:38:46 +00001585 void fixEdge(Edge& edge)
fpizlo@apple.com35701872013-02-23 01:03:10 +00001586 {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001587 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com35701872013-02-23 01:03:10 +00001588 edge.setUseKind(useKind);
1589 }
1590
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +00001591 void insertStoreBarrier(unsigned indexInBlock, Edge child1)
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001592 {
mhahnenberg@apple.comf37746e2014-03-10 22:21:44 +00001593 Node* barrierNode = m_graph.addNode(SpecNone, StoreBarrier, m_currentNode->origin, child1);
fpizlo@apple.com239e2682014-02-25 17:47:29 +00001594 m_insertionSet.insert(indexInBlock, barrierNode);
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001595 }
1596
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001597 void fixIntConvertingEdge(Edge& edge)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001598 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001599 Node* node = edge.node();
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001600 if (node->shouldSpeculateInt32OrBoolean()) {
1601 fixIntOrBooleanEdge(edge);
msaboff@apple.com95894332014-01-29 19:18:54 +00001602 return;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001603 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001604
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001605 UseKind useKind;
1606 if (node->shouldSpeculateMachineInt())
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001607 useKind = Int52RepUse;
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001608 else if (node->shouldSpeculateNumber())
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001609 useKind = DoubleRepUse;
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001610 else
1611 useKind = NotCellUse;
1612 Node* newNode = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001613 m_indexInBlock, SpecInt32, ValueToInt32, m_currentNode->origin,
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001614 Edge(node, useKind));
1615 observeUseKindOnNode(node, useKind);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001616
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001617 edge = Edge(newNode, KnownInt32Use);
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001618 addRequiredPhantom(node);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001619 }
1620
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001621 void fixIntOrBooleanEdge(Edge& edge)
1622 {
1623 Node* node = edge.node();
1624 if (!node->sawBooleans()) {
1625 fixEdge<Int32Use>(edge);
1626 return;
1627 }
1628
1629 UseKind useKind;
1630 if (node->shouldSpeculateBoolean())
1631 useKind = BooleanUse;
1632 else
1633 useKind = UntypedUse;
1634 Node* newNode = m_insertionSet.insertNode(
1635 m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
1636 Edge(node, useKind));
1637 observeUseKindOnNode(node, useKind);
1638
1639 edge = Edge(newNode, Int32Use);
1640 addRequiredPhantom(node);
1641 }
1642
1643 void fixDoubleOrBooleanEdge(Edge& edge)
1644 {
1645 Node* node = edge.node();
1646 if (!node->sawBooleans()) {
1647 fixEdge<DoubleRepUse>(edge);
1648 return;
1649 }
1650
1651 UseKind useKind;
1652 if (node->shouldSpeculateBoolean())
1653 useKind = BooleanUse;
1654 else
1655 useKind = UntypedUse;
1656 Node* newNode = m_insertionSet.insertNode(
1657 m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
1658 Edge(node, useKind));
1659 observeUseKindOnNode(node, useKind);
1660
1661 edge = Edge(newNode, DoubleRepUse);
1662 addRequiredPhantom(node);
1663 }
1664
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001665 void truncateConstantToInt32(Edge& edge)
1666 {
1667 Node* oldNode = edge.node();
1668
1669 ASSERT(oldNode->hasConstant());
1670 JSValue value = m_graph.valueOfJSConstant(oldNode);
1671 if (value.isInt32())
1672 return;
1673
1674 value = jsNumber(JSC::toInt32(value.asNumber()));
1675 ASSERT(value.isInt32());
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001676 unsigned constantRegister;
1677 if (!codeBlock()->findConstant(value, constantRegister)) {
mhahnenberg@apple.com25e78932013-08-20 19:39:54 +00001678 constantRegister = codeBlock()->addConstantLazily();
mhahnenberg@apple.comfd433bf2013-08-18 03:08:52 +00001679 initializeLazyWriteBarrierForConstant(
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001680 m_graph.m_plan.writeBarriers,
mhahnenberg@apple.com25e78932013-08-20 19:39:54 +00001681 codeBlock()->constants()[constantRegister],
1682 codeBlock(),
1683 constantRegister,
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001684 codeBlock()->ownerExecutable(),
1685 value);
1686 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001687 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001688 m_indexInBlock, SpecInt32, JSConstant, m_currentNode->origin,
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001689 OpInfo(constantRegister)));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001690 }
1691
1692 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1693 {
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001694 if (mode != SpeculateInt32AndTruncateConstants)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001695 return;
1696
1697 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1698 if (node->child1()->hasConstant())
1699 truncateConstantToInt32(node->child1());
1700 else
1701 truncateConstantToInt32(node->child2());
1702 }
1703
1704 bool attemptToMakeIntegerAdd(Node* node)
1705 {
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001706 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001707 if (mode != DontSpeculateInt32) {
1708 truncateConstantsIfNecessary(node, mode);
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001709 fixIntOrBooleanEdge(node->child1());
1710 fixIntOrBooleanEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001711 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
1712 node->setArithMode(Arith::Unchecked);
1713 else
1714 node->setArithMode(Arith::CheckOverflow);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001715 return true;
1716 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001717
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001718 if (m_graph.addShouldSpeculateMachineInt(node)) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001719 fixEdge<Int52RepUse>(node->child1());
1720 fixEdge<Int52RepUse>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001721 node->setArithMode(Arith::CheckOverflow);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001722 node->setResult(NodeResultInt52);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001723 return true;
1724 }
1725
1726 return false;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001727 }
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001728
1729 bool attemptToMakeGetArrayLength(Node* node)
1730 {
1731 if (!isInt32Speculation(node->prediction()))
1732 return false;
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001733 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001734 ArrayProfile* arrayProfile =
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001735 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001736 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
1737 if (arrayProfile) {
1738 ConcurrentJITLocker locker(profiledBlock->m_lock);
1739 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
1740 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
1741 if (arrayMode.type() == Array::Unprofiled) {
1742 // For normal array operations, it makes sense to treat Unprofiled
1743 // accesses as ForceExit and get more data rather than using
1744 // predictions and then possibly ending up with a Generic. But here,
1745 // we treat anything that is Unprofiled as Generic and keep the
1746 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
1747 // profit - from treating the Unprofiled case as
1748 // SelectUsingPredictions.
1749 arrayMode = ArrayMode(Array::SelectUsingPredictions);
1750 }
1751 }
1752
msaboff@apple.com95894332014-01-29 19:18:54 +00001753 arrayMode = arrayMode.refine(
fpizlo@apple.come079bb52014-03-05 07:41:03 +00001754 m_graph, node, node->child1()->prediction(), node->prediction());
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001755
1756 if (arrayMode.type() == Array::Generic) {
1757 // Check if the input is something that we can't get array length for, but for which we
1758 // could insert some conversions in order to transform it into something that we can do it
1759 // for.
1760 if (node->child1()->shouldSpeculateStringObject())
1761 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
1762 else if (node->child1()->shouldSpeculateStringOrStringObject())
1763 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
1764 }
1765
1766 if (!arrayMode.supportsLength())
1767 return false;
1768
1769 convertToGetArrayLength(node, arrayMode);
1770 return true;
1771 }
1772
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001773 bool attemptToMakeGetTypedArrayByteLength(Node* node)
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001774 {
1775 if (!isInt32Speculation(node->prediction()))
1776 return false;
1777
1778 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1779 if (!isTypedView(type))
1780 return false;
1781
1782 if (elementSize(type) == 1) {
1783 convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
1784 return true;
1785 }
1786
1787 Node* length = prependGetArrayLength(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001788 node->origin, node->child1().node(), ArrayMode(toArrayType(type)));
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001789
1790 Node* shiftAmount = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001791 m_indexInBlock, SpecInt32, JSConstant, node->origin,
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001792 OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
1793
1794 // We can use a BitLShift here because typed arrays will never have a byteLength
1795 // that overflows int32.
1796 node->setOp(BitLShift);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001797 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1798 observeUseKindOnNode(length, Int32Use);
1799 observeUseKindOnNode(shiftAmount, Int32Use);
1800 node->child1() = Edge(length, Int32Use);
1801 node->child2() = Edge(shiftAmount, Int32Use);
1802 return true;
1803 }
1804
1805 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
1806 {
1807 node->setOp(GetArrayLength);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001808 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001809 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001810 node->setArrayMode(arrayMode);
1811
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001812 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001813 if (!storage)
1814 return;
1815
1816 node->child2() = Edge(storage);
1817 }
1818
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001819 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001820 {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001821 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001822 return m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001823 m_indexInBlock, SpecInt32, GetArrayLength, origin,
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001824 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
1825 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001826
1827 bool attemptToMakeGetTypedArrayByteOffset(Node* node)
1828 {
1829 if (!isInt32Speculation(node->prediction()))
1830 return false;
1831
1832 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1833 if (!isTypedView(type))
1834 return false;
1835
1836 checkArray(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001837 ArrayMode(toArrayType(type)), node->origin, node->child1().node(),
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001838 0, neverNeedsStorage);
1839
1840 node->setOp(GetTypedArrayByteOffset);
1841 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001842 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001843 return true;
1844 }
msaboff@apple.com95894332014-01-29 19:18:54 +00001845
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001846 void injectTypeConversionsInBlock(BasicBlock* block)
1847 {
1848 if (!block)
1849 return;
1850 ASSERT(block->isReachable);
1851 m_block = block;
1852 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1853 m_currentNode = block->at(m_indexInBlock);
1854 addPhantomsIfNecessary();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001855 tryToRelaxRepresentation(m_currentNode);
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001856 DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, injectTypeConversionsForEdge);
1857 }
1858 clearPhantomsAtEnd();
1859 m_insertionSet.execute(block);
1860 }
1861
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001862 void tryToRelaxRepresentation(Node* node)
1863 {
1864 // Some operations may be able to operate more efficiently over looser representations.
1865 // Identify those here. This avoids inserting a redundant representation conversion.
1866 // Also, for some operations, like MovHint, this is a necessary optimization: inserting
1867 // an otherwise-dead conversion just for a MovHint would break OSR's understanding of
1868 // the IR.
1869
1870 switch (node->op()) {
1871 case MovHint:
1872 case Phantom:
1873 case Check:
1874 case HardPhantom:
1875 DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, fixEdgeRepresentation);
1876 break;
1877
1878 case ValueToInt32:
1879 if (node->child1().useKind() == DoubleRepUse
1880 && !node->child1()->hasDoubleResult()) {
1881 node->child1().setUseKind(NumberUse);
1882 break;
1883 }
1884 break;
1885
1886 default:
1887 break;
1888 }
1889 }
1890
1891 void fixEdgeRepresentation(Node*, Edge& edge)
1892 {
1893 switch (edge.useKind()) {
1894 case DoubleRepUse:
1895 case DoubleRepRealUse:
1896 if (edge->hasDoubleResult())
1897 break;
1898
1899 if (edge->hasInt52Result())
1900 edge.setUseKind(Int52RepUse);
1901 else if (edge.useKind() == DoubleRepUse)
1902 edge.setUseKind(NumberUse);
1903 break;
1904
1905 case Int52RepUse:
1906 // Nothing we can really do.
1907 break;
1908
1909 case UntypedUse:
1910 case NumberUse:
1911 if (edge->hasDoubleResult())
1912 edge.setUseKind(DoubleRepUse);
1913 else if (edge->hasInt52Result())
1914 edge.setUseKind(Int52RepUse);
1915 break;
1916
1917 default:
1918 break;
1919 }
1920 }
1921
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001922 void injectTypeConversionsForEdge(Node* node, Edge& edge)
1923 {
1924 ASSERT(node == m_currentNode);
commit-queue@webkit.orga9964a22014-05-09 18:20:39 +00001925 Node* result = nullptr;
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001926
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001927 switch (edge.useKind()) {
1928 case DoubleRepUse:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001929 case DoubleRepRealUse:
1930 case DoubleRepMachineIntUse: {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001931 if (edge->hasDoubleResult())
1932 break;
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001933
1934 addRequiredPhantom(edge.node());
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001935
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001936 if (edge->op() == JSConstant && m_graph.isNumberConstant(edge.node())) {
1937 result = m_insertionSet.insertNode(
1938 m_indexInBlock, SpecBytecodeDouble, DoubleConstant, node->origin,
1939 OpInfo(m_graph.constantRegisterForConstant(
1940 jsDoubleNumber(m_graph.valueOfNumberConstant(edge.node())))));
1941 } else if (edge->hasInt52Result()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001942 result = m_insertionSet.insertNode(
1943 m_indexInBlock, SpecInt52AsDouble, DoubleRep, node->origin,
1944 Edge(edge.node(), Int52RepUse));
1945 } else {
1946 result = m_insertionSet.insertNode(
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001947 m_indexInBlock, SpecBytecodeDouble, DoubleRep, node->origin,
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001948 Edge(edge.node(), NumberUse));
1949 }
1950
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001951 edge.setNode(result);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001952 break;
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00001953 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001954
1955 case Int52RepUse: {
1956 if (edge->hasInt52Result())
1957 break;
1958
1959 addRequiredPhantom(edge.node());
1960
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001961 if (edge->op() == JSConstant && m_graph.isMachineIntConstant(edge.node())) {
1962 result = m_insertionSet.insertNode(
1963 m_indexInBlock, SpecMachineInt, Int52Constant, node->origin,
1964 OpInfo(edge->constantNumber()));
1965 } else if (edge->hasDoubleResult()) {
1966 result = m_insertionSet.insertNode(
1967 m_indexInBlock, SpecMachineInt, Int52Rep, node->origin,
1968 Edge(edge.node(), DoubleRepMachineIntUse));
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001969 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
1970 result = m_insertionSet.insertNode(
1971 m_indexInBlock, SpecInt32, Int52Rep, node->origin,
1972 Edge(edge.node(), Int32Use));
1973 } else {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001974 result = m_insertionSet.insertNode(
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001975 m_indexInBlock, SpecMachineInt, Int52Rep, node->origin,
1976 Edge(edge.node(), MachineIntUse));
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001977 }
1978
1979 edge.setNode(result);
1980 break;
1981 }
1982
1983 default: {
1984 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
1985 break;
1986
1987 addRequiredPhantom(edge.node());
1988
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001989 if (edge->hasDoubleResult()) {
1990 result = m_insertionSet.insertNode(
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001991 m_indexInBlock, SpecBytecodeDouble, ValueRep, node->origin,
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001992 Edge(edge.node(), DoubleRepUse));
1993 } else {
1994 result = m_insertionSet.insertNode(
1995 m_indexInBlock, SpecInt32 | SpecInt52AsDouble, ValueRep, node->origin,
1996 Edge(edge.node(), Int52RepUse));
1997 }
1998
1999 edge.setNode(result);
2000 break;
2001 } }
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00002002 }
2003
2004 void addRequiredPhantom(Node* node)
2005 {
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00002006 m_requiredPhantoms.append(node);
2007 }
2008
msaboff@apple.com95894332014-01-29 19:18:54 +00002009 void addPhantomsIfNecessary()
2010 {
2011 if (m_requiredPhantoms.isEmpty())
2012 return;
2013
2014 for (unsigned i = m_requiredPhantoms.size(); i--;) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002015 Node* node = m_requiredPhantoms[i];
msaboff@apple.com95894332014-01-29 19:18:54 +00002016 m_insertionSet.insertNode(
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002017 m_indexInBlock, SpecNone, Phantom, m_currentNode->origin,
2018 node->defaultEdge());
msaboff@apple.com95894332014-01-29 19:18:54 +00002019 }
2020
2021 m_requiredPhantoms.resize(0);
2022 }
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00002023
2024 void clearPhantomsAtEnd()
2025 {
2026 // Terminal nodes don't need post-phantoms, and inserting them would violate
2027 // the current requirement that a terminal is the last thing in a block. We
2028 // should eventually change that requirement but even if we did, this would
2029 // still be a valid optimization. All terminals accept just one input, and
2030 // if that input is a conversion node then no further speculations will be
2031 // performed.
2032
2033 // FIXME: Get rid of this by allowing Phantoms after terminals.
2034 // https://bugs.webkit.org/show_bug.cgi?id=126778
2035
2036 m_requiredPhantoms.resize(0);
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +00002037 }
2038
fpizlo@apple.comf10d0722012-12-03 09:21:22 +00002039 BasicBlock* m_block;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00002040 unsigned m_indexInBlock;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002041 Node* m_currentNode;
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00002042 InsertionSet m_insertionSet;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00002043 bool m_profitabilityChanged;
msaboff@apple.com95894332014-01-29 19:18:54 +00002044 Vector<Node*, 3> m_requiredPhantoms;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00002045};
2046
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00002047bool performFixup(Graph& graph)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00002048{
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00002049 SamplingRegion samplingRegion("DFG Fixup Phase");
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00002050 return runPhase<FixupPhase>(graph);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00002051}
2052
2053} } // namespace JSC::DFG
2054
2055#endif // ENABLE(DFG_JIT)
2056