blob: 15d982263a7d3edd7a08cfeb276b11d9d43f55b8 [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)
64 fixupSetLocalsInBlock(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)
68 fixupUntypedSetLocalsInBlock(m_graph.block(blockIndex));
69
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);
82 fixupNode(m_currentNode);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000083 }
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +000084 m_insertionSet.execute(block);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000085 }
86
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000087 void fixupNode(Node* node)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000088 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000089 NodeType op = node->op();
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000090
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000091 switch (op) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000092 case SetLocal: {
fpizlo@apple.combbaf6192013-02-27 01:45:28 +000093 // This gets handled by fixupSetLocalsInBlock().
fpizlo@apple.com6921b292013-09-18 17:14:02 +000094 return;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000095 }
96
97 case BitAnd:
fpizlo@apple.com027ed672014-01-08 00:27:06 +000098 case BitOr:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000099 case BitXor:
100 case BitRShift:
101 case BitLShift:
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000102 case BitURShift: {
msaboff@apple.com95894332014-01-29 19:18:54 +0000103 fixIntEdge(node->child1());
104 fixIntEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000105 break;
106 }
fpizlo@apple.com027ed672014-01-08 00:27:06 +0000107
oliver@apple.com64367322013-04-26 00:41:38 +0000108 case ArithIMul: {
msaboff@apple.com95894332014-01-29 19:18:54 +0000109 fixIntEdge(node->child1());
110 fixIntEdge(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000111 node->setOp(ArithMul);
112 node->setArithMode(Arith::Unchecked);
113 node->child1().setUseKind(Int32Use);
114 node->child2().setUseKind(Int32Use);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000115 break;
116 }
117
118 case UInt32ToNumber: {
fpizlo@apple.com027ed672014-01-08 00:27:06 +0000119 fixIntEdge(node->child1());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +0000120 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
121 node->convertToIdentity();
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000122 else if (nodeCanSpeculateInt32(node->arithNodeFlags()))
123 node->setArithMode(Arith::CheckOverflow);
124 else
125 node->setArithMode(Arith::DoOverflow);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000126 break;
127 }
128
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000129 case ValueAdd: {
fpizlo@apple.com97756552014-01-02 20:15:25 +0000130 if (attemptToMakeIntegerAdd(node)) {
131 node->setOp(ArithAdd);
132 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000133 break;
fpizlo@apple.com97756552014-01-02 20:15:25 +0000134 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000135 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000136 fixEdge<NumberUse>(node->child1());
137 fixEdge<NumberUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000138 node->setOp(ArithAdd);
139 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000140 break;
141 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000142
143 // FIXME: Optimize for the case where one of the operands is the
144 // empty string. Also consider optimizing for the case where we don't
145 // believe either side is the emtpy string. Both of these things should
146 // be easy.
147
148 if (node->child1()->shouldSpeculateString()
149 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
150 break;
151 if (node->child2()->shouldSpeculateString()
152 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
153 break;
154 if (node->child1()->shouldSpeculateStringObject()
155 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
156 break;
157 if (node->child2()->shouldSpeculateStringObject()
158 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
159 break;
160 if (node->child1()->shouldSpeculateStringOrStringObject()
161 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
162 break;
163 if (node->child2()->shouldSpeculateStringOrStringObject()
164 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
165 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000166 break;
167 }
168
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000169 case MakeRope: {
170 fixupMakeRope(node);
171 break;
172 }
173
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000174 case ArithAdd:
175 case ArithSub: {
176 if (attemptToMakeIntegerAdd(node))
177 break;
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000178 fixEdge<NumberUse>(node->child1());
179 fixEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000180 break;
181 }
182
183 case ArithNegate: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000184 if (m_graph.negateShouldSpeculateInt32(node)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000185 fixEdge<Int32Use>(node->child1());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000186 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
187 node->setArithMode(Arith::Unchecked);
188 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
189 node->setArithMode(Arith::CheckOverflow);
190 else
191 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000192 break;
193 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000194 if (m_graph.negateShouldSpeculateMachineInt(node)) {
195 fixEdge<MachineIntUse>(node->child1());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000196 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
197 node->setArithMode(Arith::CheckOverflow);
198 else
199 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000200 break;
201 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000202 fixEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000203 break;
204 }
205
206 case ArithMul: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000207 if (m_graph.mulShouldSpeculateInt32(node)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000208 fixEdge<Int32Use>(node->child1());
209 fixEdge<Int32Use>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000210 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
211 node->setArithMode(Arith::Unchecked);
212 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
213 node->setArithMode(Arith::CheckOverflow);
214 else
215 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000216 break;
217 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000218 if (m_graph.mulShouldSpeculateMachineInt(node)) {
219 fixEdge<MachineIntUse>(node->child1());
220 fixEdge<MachineIntUse>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000221 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
222 node->setArithMode(Arith::CheckOverflow);
223 else
224 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000225 break;
226 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000227 fixEdge<NumberUse>(node->child1());
228 fixEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000229 break;
230 }
231
oliver@apple.comf4443a72013-07-25 04:01:11 +0000232 case ArithDiv:
233 case ArithMod: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000234 if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
235 && node->canSpeculateInt32()) {
fpizlo@apple.com51204922013-12-11 06:50:19 +0000236 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000237 fixEdge<Int32Use>(node->child1());
238 fixEdge<Int32Use>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000239 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
240 node->setArithMode(Arith::Unchecked);
241 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
242 node->setArithMode(Arith::CheckOverflow);
243 else
244 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000245 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000246 }
fpizlo@apple.com51204922013-12-11 06:50:19 +0000247 Edge child1 = node->child1();
248 Edge child2 = node->child2();
249
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000250 injectInt32ToDoubleNode(node->child1());
251 injectInt32ToDoubleNode(node->child2());
252
253 // We don't need to do ref'ing on the children because we're stealing them from
254 // the original division.
255 Node* newDivision = m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000256 m_indexInBlock, SpecDouble, *node);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000257
258 node->setOp(DoubleAsInt32);
259 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +0000260 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
261 node->setArithMode(Arith::CheckOverflow);
262 else
263 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
fpizlo@apple.com51204922013-12-11 06:50:19 +0000264
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000265 m_insertionSet.insertNode(m_indexInBlock + 1, SpecNone, Phantom, node->origin, child1, child2);
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000266 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000267 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000268 fixEdge<NumberUse>(node->child1());
269 fixEdge<NumberUse>(node->child2());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000270 break;
271 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000272
273 case ArithMin:
oliver@apple.comf4443a72013-07-25 04:01:11 +0000274 case ArithMax: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000275 if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
276 && node->canSpeculateInt32()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000277 fixEdge<Int32Use>(node->child1());
278 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000279 break;
280 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000281 fixEdge<NumberUse>(node->child1());
282 fixEdge<NumberUse>(node->child2());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000283 break;
284 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000285
286 case ArithAbs: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000287 if (node->child1()->shouldSpeculateInt32ForArithmetic()
288 && node->canSpeculateInt32()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000289 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000290 break;
291 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000292 fixEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000293 break;
294 }
295
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000296 case ArithSqrt:
297 case ArithSin:
298 case ArithCos: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000299 fixEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000300 break;
301 }
302
303 case LogicalNot: {
304 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000305 fixEdge<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000306 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000307 fixEdge<ObjectOrOtherUse>(node->child1());
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000308 else if (node->child1()->shouldSpeculateInt32())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000309 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000310 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000311 fixEdge<NumberUse>(node->child1());
commit-queue@webkit.org008e8dc2013-10-12 02:21:45 +0000312 else if (node->child1()->shouldSpeculateString())
313 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000314 break;
315 }
316
317 case TypeOf: {
318 if (node->child1()->shouldSpeculateString())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000319 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000320 else if (node->child1()->shouldSpeculateCell())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000321 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000322 break;
323 }
324
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000325 case CompareEqConstant: {
326 break;
327 }
328
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000329 case CompareEq:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000330 case CompareLess:
331 case CompareLessEq:
332 case CompareGreater:
333 case CompareGreaterEq: {
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000334 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000335 fixEdge<Int32Use>(node->child1());
336 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000337 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000338 break;
339 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000340 if (enableInt52()
341 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
342 fixEdge<MachineIntUse>(node->child1());
343 fixEdge<MachineIntUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000344 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000345 break;
346 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000347 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000348 fixEdge<NumberUse>(node->child1());
349 fixEdge<NumberUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000350 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000351 break;
352 }
353 if (node->op() != CompareEq)
354 break;
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000355 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000356 fixEdge<BooleanUse>(node->child1());
357 fixEdge<BooleanUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000358 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000359 break;
360 }
oliver@apple.combd15be82013-07-25 04:03:42 +0000361 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000362 fixEdge<StringIdentUse>(node->child1());
363 fixEdge<StringIdentUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000364 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
oliver@apple.combd15be82013-07-25 04:03:42 +0000365 break;
366 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000367 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000368 fixEdge<StringUse>(node->child1());
369 fixEdge<StringUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000370 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000371 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000372 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000373 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000374 fixEdge<ObjectUse>(node->child1());
375 fixEdge<ObjectUse>(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->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000380 fixEdge<ObjectUse>(node->child1());
381 fixEdge<ObjectOrOtherUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000382 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000383 break;
384 }
385 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000386 fixEdge<ObjectOrOtherUse>(node->child1());
387 fixEdge<ObjectUse>(node->child2());
fpizlo@apple.com97756552014-01-02 20:15:25 +0000388 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000389 break;
390 }
391 break;
392 }
393
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000394 case CompareStrictEqConstant: {
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000395 break;
396 }
397
398 case CompareStrictEq: {
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000399 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000400 fixEdge<BooleanUse>(node->child1());
401 fixEdge<BooleanUse>(node->child2());
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000402 break;
403 }
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000404 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000405 fixEdge<Int32Use>(node->child1());
406 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000407 break;
408 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000409 if (enableInt52()
410 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
411 fixEdge<MachineIntUse>(node->child1());
412 fixEdge<MachineIntUse>(node->child2());
413 break;
414 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000415 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000416 fixEdge<NumberUse>(node->child1());
417 fixEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000418 break;
419 }
oliver@apple.combd15be82013-07-25 04:03:42 +0000420 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000421 fixEdge<StringIdentUse>(node->child1());
422 fixEdge<StringIdentUse>(node->child2());
oliver@apple.combd15be82013-07-25 04:03:42 +0000423 break;
424 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000425 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000426 fixEdge<StringUse>(node->child1());
427 fixEdge<StringUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000428 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000429 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000430 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000431 fixEdge<ObjectUse>(node->child1());
432 fixEdge<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000433 break;
434 }
435 break;
436 }
437
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000438 case StringFromCharCode:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000439 fixEdge<Int32Use>(node->child1());
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000440 break;
441
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000442 case StringCharAt:
443 case StringCharCodeAt: {
444 // Currently we have no good way of refining these.
445 ASSERT(node->arrayMode() == ArrayMode(Array::String));
446 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000447 fixEdge<KnownCellUse>(node->child1());
448 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000449 break;
450 }
451
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000452 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000453 node->setArrayMode(
454 node->arrayMode().refine(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000455 m_graph, node->origin.semantic,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000456 node->child1()->prediction(),
457 node->child2()->prediction(),
458 SpecNone, node->flags()));
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000459
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000460 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000461
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000462 ArrayMode arrayMode = node->arrayMode();
oliver@apple.com211b3be2013-07-25 04:03:39 +0000463 switch (arrayMode.type()) {
464 case Array::Double:
465 if (arrayMode.arrayClass() == Array::OriginalArray
466 && arrayMode.speculation() == Array::InBounds
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000467 && m_graph.globalObjectFor(node->origin.semantic)->arrayPrototypeChainIsSane()
fpizlo@apple.comdc36e832013-09-11 03:24:09 +0000468 && !(node->flags() & NodeBytecodeUsesAsOther))
oliver@apple.com211b3be2013-07-25 04:03:39 +0000469 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
470 break;
471
472 case Array::String:
473 if ((node->prediction() & ~SpecString)
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000474 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
oliver@apple.com211b3be2013-07-25 04:03:39 +0000475 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
476 break;
477
478 default:
479 break;
480 }
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000481
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000482 switch (node->arrayMode().type()) {
483 case Array::SelectUsingPredictions:
484 case Array::Unprofiled:
485 case Array::Undecided:
486 RELEASE_ASSERT_NOT_REACHED();
487 break;
488 case Array::Generic:
489#if USE(JSVALUE32_64)
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000490 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000491#endif
492 break;
493 case Array::ForceExit:
494 break;
495 default:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000496 fixEdge<KnownCellUse>(node->child1());
497 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000498 break;
499 }
500
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000501 break;
502 }
oliver@apple.come050d642013-10-19 00:09:28 +0000503
504 case PutByValDirect:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000505 case PutByVal:
506 case PutByValAlias: {
507 Edge& child1 = m_graph.varArgChild(node, 0);
508 Edge& child2 = m_graph.varArgChild(node, 1);
509 Edge& child3 = m_graph.varArgChild(node, 2);
510
511 node->setArrayMode(
512 node->arrayMode().refine(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000513 m_graph, node->origin.semantic,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000514 child1->prediction(),
515 child2->prediction(),
516 child3->prediction()));
517
518 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
519
520 switch (node->arrayMode().modeForPut().type()) {
521 case Array::SelectUsingPredictions:
522 case Array::Unprofiled:
523 case Array::Undecided:
524 RELEASE_ASSERT_NOT_REACHED();
525 break;
526 case Array::ForceExit:
527 case Array::Generic:
528#if USE(JSVALUE32_64)
529 // Due to register pressure on 32-bit, we speculate cell and
530 // ignore the base-is-not-cell case entirely by letting the
531 // baseline JIT handle it.
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000532 fixEdge<CellUse>(child1);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000533#endif
534 break;
535 case Array::Int32:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000536 fixEdge<KnownCellUse>(child1);
537 fixEdge<Int32Use>(child2);
538 fixEdge<Int32Use>(child3);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000539 if (child3->prediction() & SpecInt52)
540 fixEdge<MachineIntUse>(child3);
541 else
542 fixEdge<Int32Use>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000543 break;
544 case Array::Double:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000545 fixEdge<KnownCellUse>(child1);
546 fixEdge<Int32Use>(child2);
547 fixEdge<RealNumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000548 break;
549 case Array::Int8Array:
550 case Array::Int16Array:
551 case Array::Int32Array:
552 case Array::Uint8Array:
553 case Array::Uint8ClampedArray:
554 case Array::Uint16Array:
555 case Array::Uint32Array:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000556 fixEdge<KnownCellUse>(child1);
557 fixEdge<Int32Use>(child2);
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000558 if (child3->shouldSpeculateInt32())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000559 fixEdge<Int32Use>(child3);
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000560 else if (child3->shouldSpeculateMachineInt())
561 fixEdge<MachineIntUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000562 else
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000563 fixEdge<NumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000564 break;
565 case Array::Float32Array:
566 case Array::Float64Array:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000567 fixEdge<KnownCellUse>(child1);
568 fixEdge<Int32Use>(child2);
569 fixEdge<NumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000570 break;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000571 case Array::Contiguous:
572 case Array::ArrayStorage:
573 case Array::SlowPutArrayStorage:
574 case Array::Arguments:
575 fixEdge<KnownCellUse>(child1);
576 fixEdge<Int32Use>(child2);
577 insertStoreBarrier(m_indexInBlock, child1, child3);
578 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000579 default:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000580 fixEdge<KnownCellUse>(child1);
581 fixEdge<Int32Use>(child2);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000582 break;
583 }
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000584 break;
585 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000586
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000587 case ArrayPush: {
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000588 // May need to refine the array mode in case the value prediction contravenes
589 // the array prediction. For example, we may have evidence showing that the
590 // array is in Int32 mode, but the value we're storing is likely to be a double.
591 // Then we should turn this into a conversion to Double array followed by the
592 // push. On the other hand, we absolutely don't want to refine based on the
593 // base prediction. If it has non-cell garbage in it, then we want that to be
594 // ignored. That's because ArrayPush can't handle any array modes that aren't
595 // array-related - so if refine() turned this into a "Generic" ArrayPush then
596 // that would break things.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000597 node->setArrayMode(
598 node->arrayMode().refine(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000599 m_graph, node->origin.semantic,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000600 node->child1()->prediction() & SpecCell,
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000601 SpecInt32,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000602 node->child2()->prediction()));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000603 blessArrayOperation(node->child1(), Edge(), node->child3());
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000604 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000605
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000606 switch (node->arrayMode().type()) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000607 case Array::Int32:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000608 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000609 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000610 case Array::Double:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000611 fixEdge<RealNumberUse>(node->child2());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000612 break;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000613 case Array::Contiguous:
614 case Array::ArrayStorage:
615 insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
616 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000617 default:
618 break;
619 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000620 break;
621 }
622
623 case ArrayPop: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000624 blessArrayOperation(node->child1(), Edge(), node->child2());
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000625 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com8fd79212012-10-16 21:59:35 +0000626 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000627 }
628
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000629 case RegExpExec:
630 case RegExpTest: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000631 fixEdge<CellUse>(node->child1());
632 fixEdge<CellUse>(node->child2());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000633 break;
634 }
635
636 case Branch: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000637 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000638 fixEdge<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000639 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000640 fixEdge<ObjectOrOtherUse>(node->child1());
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000641 else if (node->child1()->shouldSpeculateInt32())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000642 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000643 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000644 fixEdge<NumberUse>(node->child1());
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000645
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000646 Node* logicalNot = node->child1().node();
fpizlo@apple.com098a1452013-03-01 20:57:37 +0000647 if (logicalNot->op() == LogicalNot) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000648
649 // Make sure that OSR exit can't observe the LogicalNot. If it can,
650 // then we must compute it and cannot peephole around it.
651 bool found = false;
652 bool ok = true;
653 for (unsigned i = m_indexInBlock; i--;) {
654 Node* candidate = m_block->at(i);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000655 if (candidate == logicalNot) {
656 found = true;
657 break;
658 }
659 if (candidate->canExit()) {
660 ok = false;
661 found = true;
662 break;
663 }
664 }
665 ASSERT_UNUSED(found, found);
666
667 if (ok) {
668 Edge newChildEdge = logicalNot->child1();
669 if (newChildEdge->hasBooleanResult()) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000670 node->children.setChild1(newChildEdge);
671
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +0000672 BranchData* data = node->branchData();
673 std::swap(data->taken, data->notTaken);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000674 }
fpizlo@apple.coma6c889b2012-04-12 04:19:07 +0000675 }
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000676 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000677 break;
678 }
679
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000680 case Switch: {
681 SwitchData* data = node->switchData();
682 switch (data->kind) {
683 case SwitchImm:
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000684 if (node->child1()->shouldSpeculateInt32())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000685 fixEdge<Int32Use>(node->child1());
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000686 break;
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000687 case SwitchChar:
688 if (node->child1()->shouldSpeculateString())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000689 fixEdge<StringUse>(node->child1());
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000690 break;
oliver@apple.com5c826c02013-07-25 04:03:51 +0000691 case SwitchString:
692 if (node->child1()->shouldSpeculateStringIdent())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000693 fixEdge<StringIdentUse>(node->child1());
oliver@apple.com5c826c02013-07-25 04:03:51 +0000694 else if (node->child1()->shouldSpeculateString())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000695 fixEdge<StringUse>(node->child1());
oliver@apple.com5c826c02013-07-25 04:03:51 +0000696 break;
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000697 }
698 break;
699 }
700
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000701 case ToPrimitive: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000702 fixupToPrimitive(node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000703 break;
704 }
705
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000706 case ToString: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000707 fixupToString(node);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000708 break;
709 }
710
711 case NewStringObject: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000712 fixEdge<KnownStringUse>(node->child1());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000713 break;
714 }
715
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000716 case NewArray: {
717 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000718 node->setIndexingType(
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000719 leastUpperBoundOfIndexingTypeAndType(
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000720 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000721 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000722 switch (node->indexingType()) {
723 case ALL_BLANK_INDEXING_TYPES:
724 CRASH();
725 break;
726 case ALL_UNDECIDED_INDEXING_TYPES:
727 if (node->numChildren()) {
728 // This will only happen if the children have no type predictions. We
729 // would have already exited by now, but insert a forced exit just to
730 // be safe.
731 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000732 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000733 }
734 break;
735 case ALL_INT32_INDEXING_TYPES:
736 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000737 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000738 break;
739 case ALL_DOUBLE_INDEXING_TYPES:
740 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000741 fixEdge<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000742 break;
743 case ALL_CONTIGUOUS_INDEXING_TYPES:
744 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
745 break;
746 default:
747 CRASH();
748 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000749 }
750 break;
751 }
752
fpizlo@apple.com372fa822013-08-21 19:43:47 +0000753 case NewTypedArray: {
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());
fpizlo@apple.com372fa822013-08-21 19:43:47 +0000756 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
757 break;
758 }
759 break;
760 }
761
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000762 case NewArrayWithSize: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000763 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000764 break;
765 }
766
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000767 case ToThis: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000768 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000769
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000770 if (isOtherSpeculation(node->child1()->prediction())) {
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000771 if (ecmaMode == StrictMode) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000772 fixEdge<OtherUse>(node->child1());
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000773 node->convertToIdentity();
774 break;
775 }
776
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000777 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000778 m_indexInBlock, SpecNone, Phantom, node->origin,
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000779 Edge(node->child1().node(), OtherUse));
780 observeUseKindOnNode<OtherUse>(node->child1().node());
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000781 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->origin.semantic));
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000782 break;
783 }
784
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000785 if (isFinalObjectSpeculation(node->child1()->prediction())) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000786 fixEdge<FinalObjectUse>(node->child1());
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000787 node->convertToIdentity();
788 break;
789 }
790
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000791 break;
792 }
793
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000794 case GetMyArgumentByVal:
795 case GetMyArgumentByValSafe: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000796 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000797 break;
798 }
799
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000800 case PutStructure: {
801 fixEdge<KnownCellUse>(node->child1());
802 insertStoreBarrier(m_indexInBlock, node->child1());
803 break;
804 }
805
806 case PutClosureVar: {
807 fixEdge<KnownCellUse>(node->child1());
808 insertStoreBarrier(m_indexInBlock, node->child1(), node->child3());
809 break;
810 }
811
oliver@apple.com58c86752013-07-25 04:02:40 +0000812 case GetClosureRegisters:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000813 case SkipTopScope:
814 case SkipScope:
oliver@apple.come17632e2013-07-25 04:05:31 +0000815 case GetScope: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000816 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000817 break;
818 }
819
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000820 case AllocatePropertyStorage:
821 case ReallocatePropertyStorage: {
822 fixEdge<KnownCellUse>(node->child1());
823 insertStoreBarrier(m_indexInBlock + 1, node->child1());
824 break;
825 }
826
fpizlo@apple.com151e9af2013-08-16 02:30:37 +0000827 case GetById:
828 case GetByIdFlush: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000829 if (!node->child1()->shouldSpeculateCell())
830 break;
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000831 StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
832 if (impl == vm().propertyNames->length.impl()) {
fpizlo@apple.comc09dc632013-08-17 05:50:48 +0000833 attemptToMakeGetArrayLength(node);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000834 break;
fpizlo@apple.com151e9af2013-08-16 02:30:37 +0000835 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000836 if (impl == vm().propertyNames->byteLength.impl()) {
837 attemptToMakeGetTypedArrayByteLength(node);
838 break;
839 }
840 if (impl == vm().propertyNames->byteOffset.impl()) {
841 attemptToMakeGetTypedArrayByteOffset(node);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +0000842 break;
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000843 }
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000844 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000845 break;
846 }
847
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000848 case PutById:
849 case PutByIdDirect: {
850 fixEdge<CellUse>(node->child1());
851 insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
852 break;
853 }
854
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000855 case CheckExecutable:
856 case CheckStructure:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000857 case StructureTransitionWatchpoint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000858 case CheckFunction:
oliver@apple.come17632e2013-07-25 04:05:31 +0000859 case CheckHasInstance:
860 case CreateThis:
861 case GetButterfly: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000862 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000863 break;
864 }
865
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000866 case Arrayify:
867 case ArrayifyToStructure: {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000868 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000869 if (node->child2())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000870 fixEdge<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000871 break;
872 }
873
874 case GetByOffset: {
875 if (!node->child1()->hasStorageResult())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000876 fixEdge<KnownCellUse>(node->child1());
877 fixEdge<KnownCellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000878 break;
879 }
880
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000881 case MultiGetByOffset: {
882 fixEdge<CellUse>(node->child1());
883 break;
884 }
885
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000886 case PutByOffset: {
887 if (!node->child1()->hasStorageResult())
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000888 fixEdge<KnownCellUse>(node->child1());
889 fixEdge<KnownCellUse>(node->child2());
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000890 insertStoreBarrier(m_indexInBlock, node->child2(), node->child3());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000891 break;
892 }
893
894 case InstanceOf: {
895 // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
896 // check. https://bugs.webkit.org/show_bug.cgi?id=107479
897 if (!(node->child1()->prediction() & ~SpecCell))
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000898 fixEdge<CellUse>(node->child1());
899 fixEdge<CellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000900 break;
901 }
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000902
903 case In: {
904 // FIXME: We should at some point have array profiling on op_in, in which
905 // case we would be able to turn this into a kind of GetByVal.
906
fpizlo@apple.com1c560f52013-09-12 04:48:13 +0000907 fixEdge<CellUse>(node->child2());
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000908 break;
909 }
fpizlo@apple.com46955912013-04-26 01:18:18 +0000910
911 case Phantom:
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000912 case Identity:
913 case Check: {
fpizlo@apple.com46955912013-04-26 01:18:18 +0000914 switch (node->child1().useKind()) {
915 case NumberUse:
fpizlo@apple.comefacb612013-09-10 22:16:00 +0000916 if (node->child1()->shouldSpeculateInt32ForArithmetic())
fpizlo@apple.com46955912013-04-26 01:18:18 +0000917 node->child1().setUseKind(Int32Use);
918 break;
919 default:
920 break;
921 }
922 observeUseKindOnEdge(node->child1());
923 break;
924 }
925
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000926 case GetArrayLength:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000927 case Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000928 case Upsilon:
929 case GetArgument:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000930 case PhantomPutStructure:
931 case GetIndexedPropertyStorage:
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000932 case GetTypedArrayByteOffset:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000933 case LastNodeType:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000934 case CheckTierUpInLoop:
935 case CheckTierUpAtReturn:
936 case CheckTierUpAndOSREnter:
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000937 case Int52ToDouble:
938 case Int52ToValue:
fpizlo@apple.comd84425d2013-10-30 19:58:08 +0000939 case InvalidationPoint:
fpizlo@apple.com97ef5782013-11-05 05:39:03 +0000940 case CheckArray:
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +0000941 case CheckInBounds:
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +0000942 case ConstantStoragePointer:
fpizlo@apple.com027ed672014-01-08 00:27:06 +0000943 case DoubleAsInt32:
944 case Int32ToDouble:
945 case ValueToInt32:
fpizlo@apple.com4c96a842014-02-13 22:46:51 +0000946 case HardPhantom: // HardPhantom would be trivial to handle but anyway we assert that we won't see it here yet.
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +0000947 // These are just nodes that we don't currently expect to see during fixup.
948 // If we ever wanted to insert them prior to fixup, then we just have to create
949 // fixup rules for them.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000950 RELEASE_ASSERT_NOT_REACHED();
951 break;
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000952
953 case PutGlobalVar: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000954 Node* globalObjectNode = m_insertionSet.insertNode(
955 m_indexInBlock, SpecNone, WeakJSConstant, node->origin,
956 OpInfo(m_graph.globalObjectFor(node->origin.semantic)));
957 Node* barrierNode = m_graph.addNode(
958 SpecNone, ConditionalStoreBarrier, m_currentNode->origin,
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000959 Edge(globalObjectNode, KnownCellUse), Edge(node->child1().node(), UntypedUse));
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000960 m_insertionSet.insert(m_indexInBlock, barrierNode);
961 break;
962 }
963
964 case TearOffActivation: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000965 Node* barrierNode = m_graph.addNode(
966 SpecNone, StoreBarrierWithNullCheck, m_currentNode->origin,
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000967 Edge(node->child1().node(), UntypedUse));
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000968 m_insertionSet.insert(m_indexInBlock, barrierNode);
969 break;
970 }
commit-queue@webkit.org2faae0e2013-10-07 22:08:53 +0000971
972 case IsString:
973 if (node->child1()->shouldSpeculateString()) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +0000974 m_insertionSet.insertNode(
975 m_indexInBlock, SpecNone, Phantom, node->origin,
commit-queue@webkit.org2faae0e2013-10-07 22:08:53 +0000976 Edge(node->child1().node(), StringUse));
977 m_graph.convertToConstant(node, jsBoolean(true));
978 observeUseKindOnNode<StringUse>(node);
979 }
980 break;
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000981
commit-queue@webkit.org2faae0e2013-10-07 22:08:53 +0000982#if !ASSERT_DISABLED
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000983 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
984 case SetArgument:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000985 case JSConstant:
986 case WeakJSConstant:
987 case GetLocal:
988 case GetCallee:
989 case Flush:
990 case PhantomLocal:
991 case GetLocalUnlinked:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000992 case GetMyScope:
oliver@apple.com58c86752013-07-25 04:02:40 +0000993 case GetClosureVar:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000994 case GetGlobalVar:
fpizlo@apple.com86468342013-11-27 02:47:43 +0000995 case NotifyWrite:
996 case VariableWatchpoint:
oliver@apple.com58c86752013-07-25 04:02:40 +0000997 case VarInjectionWatchpoint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000998 case AllocationProfileWatchpoint:
999 case Call:
1000 case Construct:
1001 case NewObject:
1002 case NewArrayBuffer:
1003 case NewRegexp:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001004 case Breakpoint:
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00001005 case ProfileWillCall:
1006 case ProfileDidCall:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001007 case IsUndefined:
1008 case IsBoolean:
1009 case IsNumber:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001010 case IsObject:
1011 case IsFunction:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001012 case CreateActivation:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001013 case CreateArguments:
1014 case PhantomArguments:
1015 case TearOffArguments:
1016 case GetMyArgumentsLength:
1017 case GetMyArgumentsLengthSafe:
1018 case CheckArgumentsNotCreated:
1019 case NewFunction:
1020 case NewFunctionNoCheck:
1021 case NewFunctionExpression:
1022 case Jump:
1023 case Return:
1024 case Throw:
1025 case ThrowReferenceError:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001026 case CountExecution:
1027 case ForceOSRExit:
mark.lam@apple.com10d23a12013-04-25 02:59:51 +00001028 case CheckWatchdogTimer:
oliver@apple.com1fc04182013-08-19 19:40:13 +00001029 case Unreachable:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001030 case ExtractOSREntryLocal:
1031 case LoopHint:
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001032 case StoreBarrier:
1033 case ConditionalStoreBarrier:
1034 case StoreBarrierWithNullCheck:
fpizlo@apple.coma4ea0662013-12-02 19:09:15 +00001035 case FunctionReentryWatchpoint:
fpizlo@apple.comce995b22013-12-08 19:01:17 +00001036 case TypedArrayWatchpoint:
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001037 case MovHint:
1038 case ZombieHint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001039 break;
1040#else
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001041 default:
1042 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001043#endif
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001044 }
fpizlo@apple.comaa1cc982013-09-12 05:46:49 +00001045
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001046 if (!node->containsMovHint())
1047 DFG_NODE_DO_TO_CHILDREN(m_graph, node, observeUntypedEdge);
msaboff@apple.com95894332014-01-29 19:18:54 +00001048
1049 if (node->isTerminal()) {
1050 // Terminal nodes don't need post-phantoms, and inserting them would violate
1051 // the current requirement that a terminal is the last thing in a block. We
1052 // should eventually change that requirement but even if we did, this would
1053 // still be a valid optimization. All terminals accept just one input, and
1054 // if that input is a conversion node then no further speculations will be
1055 // performed.
1056 // FIXME: Get rid of this by allowing Phantoms after terminals.
1057 // https://bugs.webkit.org/show_bug.cgi?id=126778
1058 m_requiredPhantoms.resize(0);
1059 // Since StoreBarriers are recursively fixed up so that their children look
1060 // identical to that of the node they're barrier-ing, we need to avoid adding
1061 // any Phantoms when processing them because this would invalidate the
1062 // InsertionSet's invariant of inserting things in a monotonically increasing
1063 // order. This should be okay anyways because StoreBarriers can't exit.
1064 } else
1065 addPhantomsIfNecessary();
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001066 }
1067
fpizlo@apple.comaa1cc982013-09-12 05:46:49 +00001068 void observeUntypedEdge(Node*, Edge& edge)
1069 {
1070 if (edge.useKind() != UntypedUse)
1071 return;
1072 fixEdge<UntypedUse>(edge);
1073 }
1074
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001075 template<UseKind useKind>
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001076 void createToString(Node* node, Edge& edge)
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001077 {
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001078 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001079 m_indexInBlock, SpecString, ToString, node->origin,
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001080 Edge(edge.node(), useKind)));
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001081 }
1082
1083 template<UseKind useKind>
1084 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1085 {
1086 ASSERT(arrayMode == ArrayMode(Array::Generic));
1087
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001088 if (!canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001089 return;
1090
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001091 createToString<useKind>(node, node->child1());
fpizlo@apple.comcbc41132013-03-19 20:23:01 +00001092 arrayMode = ArrayMode(Array::String);
1093 }
1094
1095 template<UseKind useKind>
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001096 bool isStringObjectUse()
1097 {
1098 switch (useKind) {
1099 case StringObjectUse:
1100 case StringOrStringObjectUse:
1101 return true;
1102 default:
1103 return false;
1104 }
1105 }
1106
1107 template<UseKind useKind>
1108 void convertStringAddUse(Node* node, Edge& edge)
1109 {
1110 if (useKind == StringUse) {
1111 // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
1112 // two edges will always have identical use kinds, which makes the
1113 // decision process much easier.
1114 observeUseKindOnNode<StringUse>(edge.node());
1115 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001116 m_indexInBlock, SpecNone, Phantom, node->origin,
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001117 Edge(edge.node(), StringUse));
1118 edge.setUseKind(KnownStringUse);
1119 return;
1120 }
1121
1122 // FIXME: We ought to be able to have a ToPrimitiveToString node.
1123
1124 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001125 createToString<useKind>(node, edge);
1126 }
1127
1128 void convertToMakeRope(Node* node)
1129 {
1130 node->setOpAndDefaultFlags(MakeRope);
1131 fixupMakeRope(node);
1132 }
1133
1134 void fixupMakeRope(Node* node)
1135 {
1136 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1137 Edge& edge = node->children.child(i);
1138 if (!edge)
1139 break;
1140 edge.setUseKind(KnownStringUse);
1141 if (!m_graph.isConstant(edge.node()))
1142 continue;
1143 JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
1144 if (string->length())
1145 continue;
fpizlo@apple.com4bb938e2013-07-16 21:41:06 +00001146
1147 // Don't allow the MakeRope to have zero children.
1148 if (!i && !node->child2())
1149 break;
1150
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001151 node->children.removeEdge(i--);
1152 }
1153
1154 if (!node->child2()) {
1155 ASSERT(!node->child3());
1156 node->convertToIdentity();
1157 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001158 }
1159
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001160 void fixupToPrimitive(Node* node)
1161 {
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001162 if (node->child1()->shouldSpeculateInt32()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001163 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001164 node->convertToIdentity();
1165 return;
1166 }
1167
1168 if (node->child1()->shouldSpeculateString()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001169 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001170 node->convertToIdentity();
1171 return;
1172 }
1173
1174 if (node->child1()->shouldSpeculateStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001175 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001176 fixEdge<StringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001177 node->convertToToString();
1178 return;
1179 }
1180
1181 if (node->child1()->shouldSpeculateStringOrStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001182 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001183 fixEdge<StringOrStringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001184 node->convertToToString();
1185 return;
1186 }
1187 }
1188
1189 void fixupToString(Node* node)
1190 {
1191 if (node->child1()->shouldSpeculateString()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001192 fixEdge<StringUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001193 node->convertToIdentity();
1194 return;
1195 }
1196
1197 if (node->child1()->shouldSpeculateStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001198 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001199 fixEdge<StringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001200 return;
1201 }
1202
1203 if (node->child1()->shouldSpeculateStringOrStringObject()
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001204 && canOptimizeStringObjectAccess(node->origin.semantic)) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001205 fixEdge<StringOrStringObjectUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001206 return;
1207 }
1208
1209 if (node->child1()->shouldSpeculateCell()) {
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001210 fixEdge<CellUse>(node->child1());
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001211 return;
1212 }
1213 }
1214
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001215 template<UseKind leftUseKind>
1216 bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1217 {
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001218 Node* originalLeft = left.node();
1219 Node* originalRight = right.node();
1220
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001221 ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1222
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001223 if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001224 return false;
1225
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001226 convertStringAddUse<leftUseKind>(node, left);
1227
1228 if (right->shouldSpeculateString())
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001229 convertStringAddUse<StringUse>(node, right);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001230 else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001231 convertStringAddUse<StringObjectUse>(node, right);
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001232 else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->origin.semantic))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001233 convertStringAddUse<StringOrStringObjectUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001234 else {
1235 // At this point we know that the other operand is something weird. The semantically correct
1236 // way of dealing with this is:
1237 //
1238 // MakeRope(@left, ToString(ToPrimitive(@right)))
1239 //
1240 // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1241 // anything to @right, since ToPrimitive may be effectful.
1242
1243 Node* toPrimitive = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001244 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive,
1245 node->origin, Edge(right.node()));
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001246 Node* toString = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001247 m_indexInBlock, SpecString, ToString, node->origin, Edge(toPrimitive));
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001248
1249 fixupToPrimitive(toPrimitive);
1250 fixupToString(toString);
1251
1252 right.setNode(toString);
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001253 }
1254
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001255 // We're doing checks up there, so we need to make sure that the
1256 // *original* inputs to the addition are live up to here.
1257 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001258 m_indexInBlock, SpecNone, Phantom, node->origin,
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001259 Edge(originalLeft), Edge(originalRight));
1260
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001261 convertToMakeRope(node);
1262 return true;
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001263 }
1264
oliver@apple.com02039462013-07-25 03:59:29 +00001265 bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001266 {
1267 unsigned attributesUnused;
1268 JSCell* specificValue;
oliver@apple.com22fdb102013-07-25 03:58:56 +00001269 PropertyOffset offset = stringPrototypeStructure->getConcurrently(
oliver@apple.com02039462013-07-25 03:59:29 +00001270 vm(), uid, attributesUnused, specificValue);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001271 if (!isValidOffset(offset))
1272 return false;
1273
1274 if (!specificValue)
1275 return false;
1276
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001277 if (!specificValue->inherits(JSFunction::info()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001278 return false;
1279
1280 JSFunction* function = jsCast<JSFunction*>(specificValue);
1281 if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1282 return false;
1283
1284 return true;
1285 }
1286
1287 bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1288 {
1289 if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1290 return false;
1291
1292 Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1293 ASSERT(stringObjectStructure->storedPrototype().isObject());
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001294 ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001295
1296 JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1297 Structure* stringPrototypeStructure = stringPrototypeObject->structure();
oliver@apple.com90fce822013-07-25 04:00:13 +00001298 if (!m_graph.watchpoints().isStillValid(stringPrototypeStructure->transitionWatchpointSet()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001299 return false;
1300
1301 if (stringPrototypeStructure->isDictionary())
1302 return false;
1303
1304 // We're being conservative here. We want DFG's ToString on StringObject to be
1305 // used in both numeric contexts (that would call valueOf()) and string contexts
1306 // (that would call toString()). We don't want the DFG to have to distinguish
1307 // between the two, just because that seems like it would get confusing. So we
1308 // just require both methods to be sane.
oliver@apple.com02039462013-07-25 03:59:29 +00001309 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001310 return false;
oliver@apple.com02039462013-07-25 03:59:29 +00001311 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001312 return false;
1313
1314 return true;
1315 }
1316
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001317 void fixupSetLocalsInBlock(BasicBlock* block)
1318 {
1319 if (!block)
1320 return;
1321 ASSERT(block->isReachable);
1322 m_block = block;
1323 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1324 Node* node = m_currentNode = block->at(m_indexInBlock);
1325 if (node->op() != SetLocal)
1326 continue;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001327
1328 VariableAccessData* variable = node->variableAccessData();
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001329 switch (variable->flushFormat()) {
1330 case FlushedJSValue:
1331 break;
1332 case FlushedDouble:
fpizlo@apple.comc6bb4a92013-09-30 20:38:46 +00001333 fixEdge<NumberUse>(node->child1());
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001334 break;
1335 case FlushedInt32:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001336 fixEdge<Int32Use>(node->child1());
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001337 break;
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001338 case FlushedInt52:
1339 fixEdge<MachineIntUse>(node->child1());
1340 break;
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001341 case FlushedCell:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001342 fixEdge<CellUse>(node->child1());
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001343 break;
1344 case FlushedBoolean:
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001345 fixEdge<BooleanUse>(node->child1());
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001346 break;
1347 default:
1348 RELEASE_ASSERT_NOT_REACHED();
1349 break;
1350 }
msaboff@apple.com95894332014-01-29 19:18:54 +00001351 addPhantomsIfNecessary();
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001352 }
1353 m_insertionSet.execute(block);
1354 }
1355
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001356 void fixupUntypedSetLocalsInBlock(BasicBlock* block)
1357 {
1358 if (!block)
1359 return;
1360 ASSERT(block->isReachable);
1361 m_block = block;
1362 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1363 Node* node = m_currentNode = block->at(m_indexInBlock);
1364 if (node->op() != SetLocal)
1365 continue;
1366
msaboff@apple.com95894332014-01-29 19:18:54 +00001367 if (node->child1().useKind() == UntypedUse) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001368 fixEdge<UntypedUse>(node->child1());
msaboff@apple.com95894332014-01-29 19:18:54 +00001369 addPhantomsIfNecessary();
1370 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001371 }
1372 m_insertionSet.execute(block);
1373 }
1374
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001375 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001376 {
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001377 ASSERT(arrayMode.isSpecific());
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001378
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001379 if (arrayMode.type() == Array::String) {
1380 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001381 m_indexInBlock, SpecNone, Phantom, origin, Edge(array, StringUse));
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001382 } else {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001383 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001384
1385 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1386
1387 if (arrayMode.doesConversion()) {
1388 if (structure) {
1389 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001390 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001391 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1392 } else {
1393 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001394 m_indexInBlock, SpecNone, Arrayify, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001395 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1396 }
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001397 } else {
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001398 if (structure) {
1399 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001400 m_indexInBlock, SpecNone, CheckStructure, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001401 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1402 } else {
1403 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001404 m_indexInBlock, SpecNone, CheckArray, origin,
fpizlo@apple.com97ef5782013-11-05 05:39:03 +00001405 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1406 }
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001407 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001408 }
1409
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001410 if (!storageCheck(arrayMode))
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001411 return 0;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001412
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001413 if (arrayMode.usesButterfly()) {
1414 return m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001415 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001416 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001417
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001418 return m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001419 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001420 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001421 }
1422
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001423 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001424 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001425 Node* node = m_currentNode;
1426
1427 switch (node->arrayMode().type()) {
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001428 case Array::ForceExit: {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001429 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001430 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001431 return;
1432 }
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001433
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001434 case Array::SelectUsingPredictions:
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001435 case Array::Unprofiled:
oliver@apple.com5598c182013-01-23 22:25:07 +00001436 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001437 return;
1438
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001439 case Array::Generic:
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001440 return;
1441
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001442 default: {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001443 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001444 if (!storage)
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001445 return;
1446
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001447 storageChild = Edge(storage);
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001448 return;
1449 } }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001450 }
1451
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001452 bool alwaysUnboxSimplePrimitives()
1453 {
1454#if USE(JSVALUE64)
1455 return false;
1456#else
1457 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1458 // reduces traffic.
1459 return true;
1460#endif
1461 }
fpizlo@apple.com46955912013-04-26 01:18:18 +00001462
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001463 template<UseKind useKind>
1464 void observeUseKindOnNode(Node* node)
1465 {
fpizlo@apple.comaa1cc982013-09-12 05:46:49 +00001466 if (useKind == UntypedUse)
1467 return;
fpizlo@apple.com46955912013-04-26 01:18:18 +00001468 observeUseKindOnNode(node, useKind);
1469 }
1470
1471 void observeUseKindOnEdge(Edge edge)
1472 {
1473 observeUseKindOnNode(edge.node(), edge.useKind());
1474 }
1475
1476 void observeUseKindOnNode(Node* node, UseKind useKind)
1477 {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001478 if (node->op() != GetLocal)
1479 return;
1480
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001481 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
1482 // https://bugs.webkit.org/show_bug.cgi?id=121518
1483
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001484 VariableAccessData* variable = node->variableAccessData();
1485 switch (useKind) {
1486 case Int32Use:
1487 if (alwaysUnboxSimplePrimitives()
1488 || isInt32Speculation(variable->prediction()))
1489 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1490 break;
1491 case NumberUse:
1492 case RealNumberUse:
1493 if (variable->doubleFormatState() == UsingDoubleFormat)
1494 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1495 break;
1496 case BooleanUse:
1497 if (alwaysUnboxSimplePrimitives()
1498 || isBooleanSpeculation(variable->prediction()))
1499 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1500 break;
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001501 case MachineIntUse:
1502 if (isMachineIntSpeculation(variable->prediction()))
1503 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1504 break;
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001505 case CellUse:
oliver@apple.com176a3472013-07-25 04:00:19 +00001506 case KnownCellUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001507 case ObjectUse:
1508 case StringUse:
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001509 case KnownStringUse:
1510 case StringObjectUse:
1511 case StringOrStringObjectUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001512 if (alwaysUnboxSimplePrimitives()
1513 || isCellSpeculation(variable->prediction()))
1514 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1515 break;
1516 default:
1517 break;
1518 }
1519 }
1520
fpizlo@apple.comaa1cc982013-09-12 05:46:49 +00001521 // Set the use kind of the edge and perform any actions that need to be done for
1522 // that use kind, like inserting intermediate conversion nodes. Never call this
1523 // with useKind = UntypedUse explicitly; edges have UntypedUse implicitly and any
1524 // edge that survives fixup and still has UntypedUse will have this method called
1525 // from observeUntypedEdge(). Also, make sure that if you do change the type of an
1526 // edge, you either call fixEdge() or perform the equivalent functionality
1527 // yourself. Obviously, you should have a really good reason if you do the latter.
fpizlo@apple.com35701872013-02-23 01:03:10 +00001528 template<UseKind useKind>
fpizlo@apple.comc6bb4a92013-09-30 20:38:46 +00001529 void fixEdge(Edge& edge)
fpizlo@apple.com35701872013-02-23 01:03:10 +00001530 {
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001531 if (isDouble(useKind)) {
1532 if (edge->shouldSpeculateInt32ForArithmetic()) {
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001533 injectInt32ToDoubleNode(edge, useKind);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001534 return;
1535 }
1536
1537 if (enableInt52() && edge->shouldSpeculateMachineInt()) {
1538 // Make all double uses of int52 values have an intermediate Int52ToDouble.
1539 // This is for the same reason as Int52ToValue (see below) except that
1540 // Int8ToDouble will convert int52's that fit in an int32 into a double
1541 // rather than trying to create a boxed int32 like Int52ToValue does.
1542
msaboff@apple.com95894332014-01-29 19:18:54 +00001543 m_requiredPhantoms.append(edge.node());
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001544 Node* result = m_insertionSet.insertNode(
1545 m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001546 m_currentNode->origin, Edge(edge.node(), NumberUse));
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001547 edge = Edge(result, useKind);
1548 return;
1549 }
1550 }
1551
1552 if (enableInt52() && useKind != MachineIntUse
1553 && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) {
1554 // We make all non-int52 uses of int52 values have an intermediate Int52ToValue
1555 // node to ensure that we handle this properly:
1556 //
1557 // a: SomeInt52
1558 // b: ArithAdd(@a, ...)
1559 // c: Call(..., @a)
1560 // d: ArithAdd(@a, ...)
1561 //
1562 // Without an intermediate node and just labeling the uses, we will get:
1563 //
1564 // a: SomeInt52
1565 // b: ArithAdd(Int52:@a, ...)
1566 // c: Call(..., Untyped:@a)
1567 // d: ArithAdd(Int52:@a, ...)
1568 //
1569 // And now the c->Untyped:@a edge will box the value of @a into a double. This
1570 // is bad, because now the d->Int52:@a edge will either have to do double-to-int
1571 // conversions, or will have to OSR exit unconditionally. Alternatively we could
1572 // have the c->Untyped:@a edge box the value by copying rather than in-place.
1573 // But these boxings are also costly so this wouldn't be great.
1574 //
1575 // The solution we use is to always have non-Int52 uses of predicted Int52's use
1576 // an intervening Int52ToValue node:
1577 //
1578 // a: SomeInt52
1579 // b: ArithAdd(Int52:@a, ...)
1580 // x: Int52ToValue(Int52:@a)
1581 // c: Call(..., Untyped:@x)
1582 // d: ArithAdd(Int52:@a, ...)
1583 //
1584 // Note that even if we had multiple non-int52 uses of @a, the multiple
1585 // Int52ToValue's would get CSE'd together. So the boxing would only happen once.
1586 // At the same time, @a would continue to be represented as a native int52.
1587 //
1588 // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of
1589 // int52's. This would have handled the above example but would fall over for:
1590 //
1591 // a: SomeInt52
1592 // b: Call(..., @a)
1593 // c: ArithAdd(@a, ...)
1594 //
1595 // But the solution we use handles the above gracefully.
1596
msaboff@apple.com95894332014-01-29 19:18:54 +00001597 m_requiredPhantoms.append(edge.node());
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001598 Node* result = m_insertionSet.insertNode(
1599 m_indexInBlock, SpecInt52, Int52ToValue,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001600 m_currentNode->origin, Edge(edge.node(), UntypedUse));
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001601 edge = Edge(result, useKind);
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001602 return;
1603 }
1604
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001605 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001606
fpizlo@apple.com35701872013-02-23 01:03:10 +00001607 edge.setUseKind(useKind);
1608 }
1609
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001610 void insertStoreBarrier(unsigned indexInBlock, Edge child1, Edge child2 = Edge())
1611 {
1612 Node* barrierNode;
1613 if (!child2)
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001614 barrierNode = m_graph.addNode(SpecNone, StoreBarrier, m_currentNode->origin, Edge(child1.node(), child1.useKind()));
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001615 else {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001616 barrierNode = m_graph.addNode(SpecNone, ConditionalStoreBarrier, m_currentNode->origin,
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001617 Edge(child1.node(), child1.useKind()), Edge(child2.node(), child2.useKind()));
1618 }
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001619 m_insertionSet.insert(indexInBlock, barrierNode);
1620 }
1621
msaboff@apple.com95894332014-01-29 19:18:54 +00001622 void fixIntEdge(Edge& edge)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001623 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001624 Node* node = edge.node();
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001625 if (node->shouldSpeculateInt32()) {
1626 fixEdge<Int32Use>(edge);
msaboff@apple.com95894332014-01-29 19:18:54 +00001627 return;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001628 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001629
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001630 UseKind useKind;
1631 if (node->shouldSpeculateMachineInt())
1632 useKind = MachineIntUse;
1633 else if (node->shouldSpeculateNumber())
1634 useKind = NumberUse;
1635 else if (node->shouldSpeculateBoolean())
1636 useKind = BooleanUse;
1637 else
1638 useKind = NotCellUse;
1639 Node* newNode = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001640 m_indexInBlock, SpecInt32, ValueToInt32, m_currentNode->origin,
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001641 Edge(node, useKind));
1642 observeUseKindOnNode(node, useKind);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001643
fpizlo@apple.com027ed672014-01-08 00:27:06 +00001644 edge = Edge(newNode, KnownInt32Use);
msaboff@apple.com95894332014-01-29 19:18:54 +00001645 m_requiredPhantoms.append(node);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001646 }
1647
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +00001648 void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse)
msaboff@apple.com268bb442013-01-18 21:45:06 +00001649 {
msaboff@apple.com95894332014-01-29 19:18:54 +00001650 m_requiredPhantoms.append(edge.node());
1651
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001652 Node* result = m_insertionSet.insertNode(
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001653 m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001654 m_currentNode->origin, Edge(edge.node(), NumberUse));
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001655
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001656 edge = Edge(result, useKind);
1657 }
1658
1659 void truncateConstantToInt32(Edge& edge)
1660 {
1661 Node* oldNode = edge.node();
1662
1663 ASSERT(oldNode->hasConstant());
1664 JSValue value = m_graph.valueOfJSConstant(oldNode);
1665 if (value.isInt32())
1666 return;
1667
1668 value = jsNumber(JSC::toInt32(value.asNumber()));
1669 ASSERT(value.isInt32());
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001670 unsigned constantRegister;
1671 if (!codeBlock()->findConstant(value, constantRegister)) {
mhahnenberg@apple.com25e78932013-08-20 19:39:54 +00001672 constantRegister = codeBlock()->addConstantLazily();
mhahnenberg@apple.comfd433bf2013-08-18 03:08:52 +00001673 initializeLazyWriteBarrierForConstant(
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001674 m_graph.m_plan.writeBarriers,
mhahnenberg@apple.com25e78932013-08-20 19:39:54 +00001675 codeBlock()->constants()[constantRegister],
1676 codeBlock(),
1677 constantRegister,
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001678 codeBlock()->ownerExecutable(),
1679 value);
1680 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001681 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001682 m_indexInBlock, SpecInt32, JSConstant, m_currentNode->origin,
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001683 OpInfo(constantRegister)));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001684 }
1685
1686 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1687 {
fpizlo@apple.comefacb612013-09-10 22:16:00 +00001688 if (mode != SpeculateInt32AndTruncateConstants)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001689 return;
1690
1691 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1692 if (node->child1()->hasConstant())
1693 truncateConstantToInt32(node->child1());
1694 else
1695 truncateConstantToInt32(node->child2());
1696 }
1697
1698 bool attemptToMakeIntegerAdd(Node* node)
1699 {
1700 AddSpeculationMode mode = m_graph.addSpeculationMode(node);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001701 if (mode != DontSpeculateInt32) {
1702 truncateConstantsIfNecessary(node, mode);
1703 fixEdge<Int32Use>(node->child1());
1704 fixEdge<Int32Use>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001705 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
1706 node->setArithMode(Arith::Unchecked);
1707 else
1708 node->setArithMode(Arith::CheckOverflow);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001709 return true;
1710 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001711
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001712 if (m_graph.addShouldSpeculateMachineInt(node)) {
1713 fixEdge<MachineIntUse>(node->child1());
1714 fixEdge<MachineIntUse>(node->child2());
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001715 node->setArithMode(Arith::CheckOverflow);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001716 return true;
1717 }
1718
1719 return false;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001720 }
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001721
1722 bool attemptToMakeGetArrayLength(Node* node)
1723 {
1724 if (!isInt32Speculation(node->prediction()))
1725 return false;
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001726 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001727 ArrayProfile* arrayProfile =
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001728 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001729 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
1730 if (arrayProfile) {
1731 ConcurrentJITLocker locker(profiledBlock->m_lock);
1732 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
1733 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
1734 if (arrayMode.type() == Array::Unprofiled) {
1735 // For normal array operations, it makes sense to treat Unprofiled
1736 // accesses as ForceExit and get more data rather than using
1737 // predictions and then possibly ending up with a Generic. But here,
1738 // we treat anything that is Unprofiled as Generic and keep the
1739 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
1740 // profit - from treating the Unprofiled case as
1741 // SelectUsingPredictions.
1742 arrayMode = ArrayMode(Array::SelectUsingPredictions);
1743 }
1744 }
1745
msaboff@apple.com95894332014-01-29 19:18:54 +00001746 arrayMode = arrayMode.refine(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001747 m_graph, node->origin.semantic, node->child1()->prediction(), node->prediction());
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001748
1749 if (arrayMode.type() == Array::Generic) {
1750 // Check if the input is something that we can't get array length for, but for which we
1751 // could insert some conversions in order to transform it into something that we can do it
1752 // for.
1753 if (node->child1()->shouldSpeculateStringObject())
1754 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
1755 else if (node->child1()->shouldSpeculateStringOrStringObject())
1756 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
1757 }
1758
1759 if (!arrayMode.supportsLength())
1760 return false;
1761
1762 convertToGetArrayLength(node, arrayMode);
1763 return true;
1764 }
1765
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001766 bool attemptToMakeGetTypedArrayByteLength(Node* node)
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001767 {
1768 if (!isInt32Speculation(node->prediction()))
1769 return false;
1770
1771 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1772 if (!isTypedView(type))
1773 return false;
1774
1775 if (elementSize(type) == 1) {
1776 convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
1777 return true;
1778 }
1779
1780 Node* length = prependGetArrayLength(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001781 node->origin, node->child1().node(), ArrayMode(toArrayType(type)));
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001782
1783 Node* shiftAmount = m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001784 m_indexInBlock, SpecInt32, JSConstant, node->origin,
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001785 OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
1786
1787 // We can use a BitLShift here because typed arrays will never have a byteLength
1788 // that overflows int32.
1789 node->setOp(BitLShift);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001790 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1791 observeUseKindOnNode(length, Int32Use);
1792 observeUseKindOnNode(shiftAmount, Int32Use);
1793 node->child1() = Edge(length, Int32Use);
1794 node->child2() = Edge(shiftAmount, Int32Use);
1795 return true;
1796 }
1797
1798 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
1799 {
1800 node->setOp(GetArrayLength);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001801 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001802 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001803 node->setArrayMode(arrayMode);
1804
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001805 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001806 if (!storage)
1807 return;
1808
1809 node->child2() = Edge(storage);
1810 }
1811
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001812 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001813 {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001814 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001815 return m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001816 m_indexInBlock, SpecInt32, GetArrayLength, origin,
fpizlo@apple.comc09dc632013-08-17 05:50:48 +00001817 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
1818 }
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001819
1820 bool attemptToMakeGetTypedArrayByteOffset(Node* node)
1821 {
1822 if (!isInt32Speculation(node->prediction()))
1823 return false;
1824
1825 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1826 if (!isTypedView(type))
1827 return false;
1828
1829 checkArray(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001830 ArrayMode(toArrayType(type)), node->origin, node->child1().node(),
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001831 0, neverNeedsStorage);
1832
1833 node->setOp(GetTypedArrayByteOffset);
1834 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com1c560f52013-09-12 04:48:13 +00001835 fixEdge<KnownCellUse>(node->child1());
fpizlo@apple.com537a4772013-08-19 23:16:01 +00001836 return true;
1837 }
msaboff@apple.com95894332014-01-29 19:18:54 +00001838
1839 void addPhantomsIfNecessary()
1840 {
1841 if (m_requiredPhantoms.isEmpty())
1842 return;
1843
1844 for (unsigned i = m_requiredPhantoms.size(); i--;) {
1845 m_insertionSet.insertNode(
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001846 m_indexInBlock + 1, SpecNone, Phantom, m_currentNode->origin,
msaboff@apple.com95894332014-01-29 19:18:54 +00001847 Edge(m_requiredPhantoms[i], UntypedUse));
1848 }
1849
1850 m_requiredPhantoms.resize(0);
1851 }
fpizlo@apple.comf10d0722012-12-03 09:21:22 +00001852
1853 BasicBlock* m_block;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001854 unsigned m_indexInBlock;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001855 Node* m_currentNode;
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001856 InsertionSet m_insertionSet;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001857 bool m_profitabilityChanged;
msaboff@apple.com95894332014-01-29 19:18:54 +00001858 Vector<Node*, 3> m_requiredPhantoms;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001859};
1860
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001861bool performFixup(Graph& graph)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001862{
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00001863 SamplingRegion samplingRegion("DFG Fixup Phase");
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001864 return runPhase<FixupPhase>(graph);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001865}
1866
1867} } // namespace JSC::DFG
1868
1869#endif // ENABLE(DFG_JIT)
1870