blob: 3af1b58f568458cb762f489f25f6498974c734c7 [file] [log] [blame]
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001/*
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00002 * Copyright (C) 2012, 2013 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"
27#include "DFGFixupPhase.h"
28
29#if ENABLE(DFG_JIT)
30
31#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.combbaf6192013-02-27 01:45:28 +000035#include "DFGVariableAccessDataDump.h"
fpizlo@apple.coma4b4cbe2013-01-12 04:47:03 +000036#include "Operations.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;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000054 for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
55 fixupBlock(m_graph.m_blocks[blockIndex].get());
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
63 for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
64 fixupSetLocalsInBlock(m_graph.m_blocks[blockIndex].get());
65 }
66
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000067 return true;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000068 }
69
70private:
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000071 void fixupBlock(BasicBlock* block)
72 {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000073 if (!block)
74 return;
75 ASSERT(block->isReachable);
fpizlo@apple.comf10d0722012-12-03 09:21:22 +000076 m_block = block;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000077 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000078 m_currentNode = block->at(m_indexInBlock);
79 fixupNode(m_currentNode);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000080 }
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +000081 m_insertionSet.execute(block);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000082 }
83
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000084 void fixupNode(Node* node)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000085 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000086 NodeType op = node->op();
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000087
88#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +000089 dataLogF(" %s @%u: ", Graph::opName(op), node->index());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000090#endif
91
92 switch (op) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000093 case SetLocal: {
fpizlo@apple.combbaf6192013-02-27 01:45:28 +000094 // This gets handled by fixupSetLocalsInBlock().
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +000095 break;
96 }
97
98 case BitAnd:
99 case BitOr:
100 case BitXor:
101 case BitRShift:
102 case BitLShift:
oliver@apple.com64367322013-04-26 00:41:38 +0000103 case BitURShift:
104 case ArithIMul: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000105 fixIntEdge(node->child1());
106 fixIntEdge(node->child2());
107 break;
108 }
109
110 case UInt32ToNumber: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000111 setUseKindAndUnboxIfProfitable<KnownInt32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000112 break;
113 }
114
115 case DoubleAsInt32: {
116 RELEASE_ASSERT_NOT_REACHED();
117 break;
118 }
119
120 case ValueToInt32: {
121 if (node->child1()->shouldSpeculateInteger()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000122 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000123 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000124 }
125
126 if (node->child1()->shouldSpeculateNumber()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000127 setUseKindAndUnboxIfProfitable<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000128 break;
129 }
130
131 if (node->child1()->shouldSpeculateBoolean()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000132 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000133 break;
134 }
135
fpizlo@apple.com35701872013-02-23 01:03:10 +0000136 setUseKindAndUnboxIfProfitable<NotCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000137 break;
138 }
139
140 case Int32ToDouble: {
141 RELEASE_ASSERT_NOT_REACHED();
142 break;
143 }
144
145 case ValueAdd: {
146 if (attemptToMakeIntegerAdd(node))
147 break;
148 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000149 fixDoubleEdge<NumberUse>(node->child1());
150 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000151 break;
152 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000153
154 // FIXME: Optimize for the case where one of the operands is the
155 // empty string. Also consider optimizing for the case where we don't
156 // believe either side is the emtpy string. Both of these things should
157 // be easy.
158
159 if (node->child1()->shouldSpeculateString()
160 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
161 break;
162 if (node->child2()->shouldSpeculateString()
163 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
164 break;
165 if (node->child1()->shouldSpeculateStringObject()
166 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
167 break;
168 if (node->child2()->shouldSpeculateStringObject()
169 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
170 break;
171 if (node->child1()->shouldSpeculateStringOrStringObject()
172 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
173 break;
174 if (node->child2()->shouldSpeculateStringOrStringObject()
175 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
176 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000177 break;
178 }
179
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000180 case MakeRope: {
181 fixupMakeRope(node);
182 break;
183 }
184
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000185 case ArithAdd:
186 case ArithSub: {
187 if (attemptToMakeIntegerAdd(node))
188 break;
fpizlo@apple.com35701872013-02-23 01:03:10 +0000189 fixDoubleEdge<NumberUse>(node->child1());
190 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000191 break;
192 }
193
194 case ArithNegate: {
195 if (m_graph.negateShouldSpeculateInteger(node)) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000196 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000197 break;
198 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000199 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000200 break;
201 }
202
203 case ArithMul: {
204 if (m_graph.mulShouldSpeculateInteger(node)) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000205 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
206 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000207 break;
208 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000209 fixDoubleEdge<NumberUse>(node->child1());
210 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000211 break;
212 }
213
214 case ArithDiv: {
215 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
216 && node->canSpeculateInteger()) {
217 if (isX86() || isARMv7s()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000218 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
219 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000220 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000221 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000222 injectInt32ToDoubleNode(node->child1());
223 injectInt32ToDoubleNode(node->child2());
224
225 // We don't need to do ref'ing on the children because we're stealing them from
226 // the original division.
227 Node* newDivision = m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000228 m_indexInBlock, SpecDouble, *node);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000229
230 node->setOp(DoubleAsInt32);
231 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000232 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000233 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000234 fixDoubleEdge<NumberUse>(node->child1());
235 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000236 break;
237 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000238
239 case ArithMin:
240 case ArithMax:
241 case ArithMod: {
242 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
243 && node->canSpeculateInteger()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000244 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
245 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000246 break;
247 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000248 fixDoubleEdge<NumberUse>(node->child1());
249 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000250 break;
251 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000252
253 case ArithAbs: {
254 if (node->child1()->shouldSpeculateIntegerForArithmetic()
255 && node->canSpeculateInteger()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000256 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000257 break;
258 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000259 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000260 break;
261 }
262
263 case ArithSqrt: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000264 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000265 break;
266 }
267
268 case LogicalNot: {
269 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000270 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000271 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000272 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000273 else if (node->child1()->shouldSpeculateInteger())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000274 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000275 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000276 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000277 break;
278 }
279
280 case TypeOf: {
281 if (node->child1()->shouldSpeculateString())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000282 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000283 else if (node->child1()->shouldSpeculateCell())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000284 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000285 break;
286 }
287
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000288 case CompareEqConstant: {
289 break;
290 }
291
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000292 case CompareEq:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000293 case CompareLess:
294 case CompareLessEq:
295 case CompareGreater:
296 case CompareGreaterEq: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000297 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000298 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
299 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000300 break;
301 }
302 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000303 fixDoubleEdge<NumberUse>(node->child1());
304 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000305 break;
306 }
307 if (node->op() != CompareEq)
308 break;
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000309 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
310 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
311 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child2());
312 break;
313 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000314 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
315 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
316 setUseKindAndUnboxIfProfitable<StringUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000317 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000318 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000319 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000320 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
321 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000322 break;
323 }
324 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000325 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
326 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000327 break;
328 }
329 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000330 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
331 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000332 break;
333 }
334 break;
335 }
336
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000337 case CompareStrictEqConstant: {
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000338 break;
339 }
340
341 case CompareStrictEq: {
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000342 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
343 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
344 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child2());
345 break;
346 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000347 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000348 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
349 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000350 break;
351 }
352 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000353 fixDoubleEdge<NumberUse>(node->child1());
354 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000355 break;
356 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000357 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
358 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
359 setUseKindAndUnboxIfProfitable<StringUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000360 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000361 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000362 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000363 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
364 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000365 break;
366 }
367 break;
368 }
369
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000370 case StringFromCharCode:
371 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
372 break;
373
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000374 case StringCharAt:
375 case StringCharCodeAt: {
376 // Currently we have no good way of refining these.
377 ASSERT(node->arrayMode() == ArrayMode(Array::String));
378 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com35701872013-02-23 01:03:10 +0000379 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
380 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000381 break;
382 }
383
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000384 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000385 node->setArrayMode(
386 node->arrayMode().refine(
387 node->child1()->prediction(),
388 node->child2()->prediction(),
389 SpecNone, node->flags()));
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000390
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000391 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000392
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000393 ArrayMode arrayMode = node->arrayMode();
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000394 if (arrayMode.type() == Array::Double
395 && arrayMode.arrayClass() == Array::OriginalArray
396 && arrayMode.speculation() == Array::InBounds
397 && arrayMode.conversion() == Array::AsIs
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000398 && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
399 && !(node->flags() & NodeUsedAsOther))
400 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000401
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000402 switch (node->arrayMode().type()) {
403 case Array::SelectUsingPredictions:
404 case Array::Unprofiled:
405 case Array::Undecided:
406 RELEASE_ASSERT_NOT_REACHED();
407 break;
408 case Array::Generic:
409#if USE(JSVALUE32_64)
fpizlo@apple.com35701872013-02-23 01:03:10 +0000410 setUseKindAndUnboxIfProfitable<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000411#endif
412 break;
413 case Array::ForceExit:
414 break;
415 default:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000416 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
417 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000418 break;
419 }
420
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000421 break;
422 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000423
424 case PutByVal:
425 case PutByValAlias: {
426 Edge& child1 = m_graph.varArgChild(node, 0);
427 Edge& child2 = m_graph.varArgChild(node, 1);
428 Edge& child3 = m_graph.varArgChild(node, 2);
429
430 node->setArrayMode(
431 node->arrayMode().refine(
432 child1->prediction(),
433 child2->prediction(),
434 child3->prediction()));
435
436 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
437
438 switch (node->arrayMode().modeForPut().type()) {
439 case Array::SelectUsingPredictions:
440 case Array::Unprofiled:
441 case Array::Undecided:
442 RELEASE_ASSERT_NOT_REACHED();
443 break;
444 case Array::ForceExit:
445 case Array::Generic:
446#if USE(JSVALUE32_64)
447 // Due to register pressure on 32-bit, we speculate cell and
448 // ignore the base-is-not-cell case entirely by letting the
449 // baseline JIT handle it.
fpizlo@apple.com35701872013-02-23 01:03:10 +0000450 setUseKindAndUnboxIfProfitable<CellUse>(child1);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000451#endif
452 break;
453 case Array::Int32:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000454 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
455 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
456 setUseKindAndUnboxIfProfitable<Int32Use>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000457 break;
458 case Array::Double:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000459 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
460 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
461 fixDoubleEdge<RealNumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000462 break;
463 case Array::Int8Array:
464 case Array::Int16Array:
465 case Array::Int32Array:
466 case Array::Uint8Array:
467 case Array::Uint8ClampedArray:
468 case Array::Uint16Array:
469 case Array::Uint32Array:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000470 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
471 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000472 if (child3->shouldSpeculateInteger())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000473 setUseKindAndUnboxIfProfitable<Int32Use>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000474 else
fpizlo@apple.com35701872013-02-23 01:03:10 +0000475 fixDoubleEdge<NumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000476 break;
477 case Array::Float32Array:
478 case Array::Float64Array:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000479 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
480 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
481 fixDoubleEdge<NumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000482 break;
483 default:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000484 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
485 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000486 break;
487 }
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000488 break;
489 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000490
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000491 case ArrayPush: {
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000492 // May need to refine the array mode in case the value prediction contravenes
493 // the array prediction. For example, we may have evidence showing that the
494 // array is in Int32 mode, but the value we're storing is likely to be a double.
495 // Then we should turn this into a conversion to Double array followed by the
496 // push. On the other hand, we absolutely don't want to refine based on the
497 // base prediction. If it has non-cell garbage in it, then we want that to be
498 // ignored. That's because ArrayPush can't handle any array modes that aren't
499 // array-related - so if refine() turned this into a "Generic" ArrayPush then
500 // that would break things.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000501 node->setArrayMode(
502 node->arrayMode().refine(
503 node->child1()->prediction() & SpecCell,
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000504 SpecInt32,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000505 node->child2()->prediction()));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000506 blessArrayOperation(node->child1(), Edge(), node->child3());
fpizlo@apple.com35701872013-02-23 01:03:10 +0000507 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000508
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000509 switch (node->arrayMode().type()) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000510 case Array::Int32:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000511 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000512 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000513 case Array::Double:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000514 fixDoubleEdge<RealNumberUse>(node->child2());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000515 break;
516 default:
517 break;
518 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000519 break;
520 }
521
522 case ArrayPop: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000523 blessArrayOperation(node->child1(), Edge(), node->child2());
fpizlo@apple.com35701872013-02-23 01:03:10 +0000524 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com8fd79212012-10-16 21:59:35 +0000525 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000526 }
527
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000528 case RegExpExec:
529 case RegExpTest: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000530 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
531 setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000532 break;
533 }
534
535 case Branch: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000536 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000537 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000538 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000539 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000540 else if (node->child1()->shouldSpeculateInteger())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000541 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000542 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000543 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000544
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000545 Node* logicalNot = node->child1().node();
fpizlo@apple.com098a1452013-03-01 20:57:37 +0000546 if (logicalNot->op() == LogicalNot) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000547
548 // Make sure that OSR exit can't observe the LogicalNot. If it can,
549 // then we must compute it and cannot peephole around it.
550 bool found = false;
551 bool ok = true;
552 for (unsigned i = m_indexInBlock; i--;) {
553 Node* candidate = m_block->at(i);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000554 if (candidate == logicalNot) {
555 found = true;
556 break;
557 }
558 if (candidate->canExit()) {
559 ok = false;
560 found = true;
561 break;
562 }
563 }
564 ASSERT_UNUSED(found, found);
565
566 if (ok) {
567 Edge newChildEdge = logicalNot->child1();
568 if (newChildEdge->hasBooleanResult()) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000569 node->children.setChild1(newChildEdge);
570
571 BlockIndex toBeTaken = node->notTakenBlockIndex();
572 BlockIndex toBeNotTaken = node->takenBlockIndex();
573 node->setTakenBlockIndex(toBeTaken);
574 node->setNotTakenBlockIndex(toBeNotTaken);
575 }
fpizlo@apple.coma6c889b2012-04-12 04:19:07 +0000576 }
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000577 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000578 break;
579 }
580
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000581 case ToPrimitive: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000582 fixupToPrimitive(node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000583 break;
584 }
585
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000586 case ToString: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000587 fixupToString(node);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000588 break;
589 }
590
591 case NewStringObject: {
592 setUseKindAndUnboxIfProfitable<KnownStringUse>(node->child1());
593 break;
594 }
595
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000596 case NewArray: {
597 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000598 node->setIndexingType(
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000599 leastUpperBoundOfIndexingTypeAndType(
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000600 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000601 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000602 switch (node->indexingType()) {
603 case ALL_BLANK_INDEXING_TYPES:
604 CRASH();
605 break;
606 case ALL_UNDECIDED_INDEXING_TYPES:
607 if (node->numChildren()) {
608 // This will only happen if the children have no type predictions. We
609 // would have already exited by now, but insert a forced exit just to
610 // be safe.
611 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000612 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000613 }
614 break;
615 case ALL_INT32_INDEXING_TYPES:
616 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com35701872013-02-23 01:03:10 +0000617 setUseKindAndUnboxIfProfitable<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000618 break;
619 case ALL_DOUBLE_INDEXING_TYPES:
620 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com35701872013-02-23 01:03:10 +0000621 setUseKindAndUnboxIfProfitable<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000622 break;
623 case ALL_CONTIGUOUS_INDEXING_TYPES:
624 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
625 break;
626 default:
627 CRASH();
628 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000629 }
630 break;
631 }
632
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000633 case NewArrayWithSize: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000634 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000635 break;
636 }
637
638 case ConvertThis: {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000639 if (isOtherSpeculation(node->child1()->prediction())) {
640 m_insertionSet.insertNode(
641 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
642 Edge(node->child1().node(), OtherUse));
643 observeUseKindOnNode<OtherUse>(node->child1().node());
644 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->codeOrigin));
645 break;
646 }
647
648 if (isObjectSpeculation(node->child1()->prediction())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000649 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000650 node->convertToIdentity();
651 break;
652 }
653
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000654 break;
655 }
656
657 case CreateThis: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000658 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000659 break;
660 }
661
662 case GetMyArgumentByVal:
663 case GetMyArgumentByValSafe: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000664 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000665 break;
666 }
667
668 case GetScopeRegisters:
669 case PutScopedVar:
670 case SkipTopScope:
671 case SkipScope:
672 case SetCallee:
673 case SetMyScope:
674 case PutStructure:
675 case AllocatePropertyStorage:
676 case ReallocatePropertyStorage:
677 case GetScope:
678 case GetButterfly: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000679 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000680 break;
681 }
682
683 case GetById: {
684 if (!node->child1()->shouldSpeculateCell())
685 break;
fpizlo@apple.com35701872013-02-23 01:03:10 +0000686 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000687 if (!isInt32Speculation(node->prediction()))
688 break;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000689 if (codeBlock()->identifier(node->identifierNumber()) != vm().propertyNames->length)
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000690 break;
691 ArrayProfile* arrayProfile =
692 m_graph.baselineCodeBlockFor(node->codeOrigin)->getArrayProfile(
693 node->codeOrigin.bytecodeIndex);
694 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
695 if (arrayProfile) {
696 arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node->codeOrigin));
697 arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false);
698 arrayMode = arrayMode.refine(
699 node->child1()->prediction(), node->prediction());
700 if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) {
701 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000702 m_indexInBlock, SpecNone, CheckStructure, node->codeOrigin,
703 OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())),
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000704 node->child1());
705 }
706 } else
707 arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000708
709 if (arrayMode.type() == Array::Generic) {
710 // Check if the input is something that we can't get array length for, but for which we
711 // could insert some conversions in order to transform it into something that we can do it
712 // for.
713 if (node->child1()->shouldSpeculateStringObject())
714 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
715 else if (node->child1()->shouldSpeculateStringOrStringObject())
716 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
717 }
718
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000719 if (!arrayMode.supportsLength())
720 break;
721 node->setOp(GetArrayLength);
722 ASSERT(node->flags() & NodeMustGenerate);
723 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com35701872013-02-23 01:03:10 +0000724 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000725 node->setArrayMode(arrayMode);
726
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000727 Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000728 if (!storage)
729 break;
730
731 node->child2() = Edge(storage);
732 break;
733 }
734
735 case GetByIdFlush: {
736 if (node->child1()->shouldSpeculateCell())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000737 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000738 break;
739 }
740
741 case CheckExecutable:
742 case CheckStructure:
743 case ForwardCheckStructure:
744 case StructureTransitionWatchpoint:
745 case ForwardStructureTransitionWatchpoint:
746 case CheckFunction:
747 case PutById:
748 case PutByIdDirect:
749 case CheckHasInstance: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000750 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000751 break;
752 }
753
754 case CheckArray: {
755 switch (node->arrayMode().type()) {
756 case Array::String:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000757 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000758 break;
759 default:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000760 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000761 break;
762 }
763 break;
764 }
765
766 case Arrayify:
767 case ArrayifyToStructure: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000768 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000769 if (node->child2())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000770 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000771 break;
772 }
773
774 case GetByOffset: {
775 if (!node->child1()->hasStorageResult())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000776 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000777 break;
778 }
779
780 case PutByOffset: {
781 if (!node->child1()->hasStorageResult())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000782 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
783 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000784 break;
785 }
786
787 case InstanceOf: {
788 // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
789 // check. https://bugs.webkit.org/show_bug.cgi?id=107479
790 if (!(node->child1()->prediction() & ~SpecCell))
fpizlo@apple.com35701872013-02-23 01:03:10 +0000791 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
792 setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000793 break;
794 }
795
796 case GetArrayLength:
797 case Identity:
798 case Nop:
799 case Phi:
800 case ForwardInt32ToDouble:
801 case PhantomPutStructure:
802 case GetIndexedPropertyStorage:
803 case LastNodeType:
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000804 case MovHint:
805 case MovHintAndCheck:
806 case ZombieHint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000807 RELEASE_ASSERT_NOT_REACHED();
808 break;
809
810#if !ASSERT_DISABLED
811 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
812 case SetArgument:
813 case Phantom:
814 case JSConstant:
815 case WeakJSConstant:
816 case GetLocal:
817 case GetCallee:
818 case Flush:
819 case PhantomLocal:
820 case GetLocalUnlinked:
821 case InlineStart:
822 case GetMyScope:
823 case GetScopedVar:
824 case GetGlobalVar:
825 case PutGlobalVar:
826 case GlobalVarWatchpoint:
827 case PutGlobalVarCheck:
828 case AllocationProfileWatchpoint:
829 case Call:
830 case Construct:
831 case NewObject:
832 case NewArrayBuffer:
833 case NewRegexp:
834 case Resolve:
835 case ResolveBase:
836 case ResolveBaseStrictPut:
837 case ResolveGlobal:
838 case Breakpoint:
839 case IsUndefined:
840 case IsBoolean:
841 case IsNumber:
842 case IsString:
843 case IsObject:
844 case IsFunction:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000845 case CreateActivation:
846 case TearOffActivation:
847 case CreateArguments:
848 case PhantomArguments:
849 case TearOffArguments:
850 case GetMyArgumentsLength:
851 case GetMyArgumentsLengthSafe:
852 case CheckArgumentsNotCreated:
853 case NewFunction:
854 case NewFunctionNoCheck:
855 case NewFunctionExpression:
856 case Jump:
857 case Return:
858 case Throw:
859 case ThrowReferenceError:
860 case GarbageValue:
861 case CountExecution:
862 case ForceOSRExit:
mark.lam@apple.com10d23a12013-04-25 02:59:51 +0000863 case CheckWatchdogTimer:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000864 break;
865#else
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000866 default:
867 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000868#endif
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000869 }
870
871#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000872 if (!(node->flags() & NodeHasVarArgs)) {
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000873 dataLogF("new children: ");
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000874 node->dumpChildren(WTF::dataFile());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000875 }
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000876 dataLogF("\n");
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000877#endif
878 }
879
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000880 template<UseKind useKind>
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000881 void createToString(Node* node, Edge& edge)
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000882 {
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000883 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000884 m_indexInBlock, SpecString, ToString, node->codeOrigin,
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000885 Edge(edge.node(), useKind)));
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000886 }
887
888 template<UseKind useKind>
889 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
890 {
891 ASSERT(arrayMode == ArrayMode(Array::Generic));
892
893 if (!canOptimizeStringObjectAccess(node->codeOrigin))
894 return;
895
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000896 createToString<useKind>(node, node->child1());
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000897 arrayMode = ArrayMode(Array::String);
898 }
899
900 template<UseKind useKind>
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000901 bool isStringObjectUse()
902 {
903 switch (useKind) {
904 case StringObjectUse:
905 case StringOrStringObjectUse:
906 return true;
907 default:
908 return false;
909 }
910 }
911
912 template<UseKind useKind>
913 void convertStringAddUse(Node* node, Edge& edge)
914 {
915 if (useKind == StringUse) {
916 // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
917 // two edges will always have identical use kinds, which makes the
918 // decision process much easier.
919 observeUseKindOnNode<StringUse>(edge.node());
920 m_insertionSet.insertNode(
921 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
922 Edge(edge.node(), StringUse));
923 edge.setUseKind(KnownStringUse);
924 return;
925 }
926
927 // FIXME: We ought to be able to have a ToPrimitiveToString node.
928
929 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000930 createToString<useKind>(node, edge);
931 }
932
933 void convertToMakeRope(Node* node)
934 {
935 node->setOpAndDefaultFlags(MakeRope);
936 fixupMakeRope(node);
937 }
938
939 void fixupMakeRope(Node* node)
940 {
941 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
942 Edge& edge = node->children.child(i);
943 if (!edge)
944 break;
945 edge.setUseKind(KnownStringUse);
946 if (!m_graph.isConstant(edge.node()))
947 continue;
948 JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
949 if (string->length())
950 continue;
951 node->children.removeEdge(i--);
952 }
953
954 if (!node->child2()) {
955 ASSERT(!node->child3());
956 node->convertToIdentity();
957 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000958 }
959
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000960 void fixupToPrimitive(Node* node)
961 {
962 if (node->child1()->shouldSpeculateInteger()) {
963 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
964 node->convertToIdentity();
965 return;
966 }
967
968 if (node->child1()->shouldSpeculateString()) {
969 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
970 node->convertToIdentity();
971 return;
972 }
973
974 if (node->child1()->shouldSpeculateStringObject()
975 && canOptimizeStringObjectAccess(node->codeOrigin)) {
976 setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
977 node->convertToToString();
978 return;
979 }
980
981 if (node->child1()->shouldSpeculateStringOrStringObject()
982 && canOptimizeStringObjectAccess(node->codeOrigin)) {
983 setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
984 node->convertToToString();
985 return;
986 }
987 }
988
989 void fixupToString(Node* node)
990 {
991 if (node->child1()->shouldSpeculateString()) {
992 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
993 node->convertToIdentity();
994 return;
995 }
996
997 if (node->child1()->shouldSpeculateStringObject()
998 && canOptimizeStringObjectAccess(node->codeOrigin)) {
999 setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
1000 return;
1001 }
1002
1003 if (node->child1()->shouldSpeculateStringOrStringObject()
1004 && canOptimizeStringObjectAccess(node->codeOrigin)) {
1005 setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
1006 return;
1007 }
1008
1009 if (node->child1()->shouldSpeculateCell()) {
1010 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1011 return;
1012 }
1013 }
1014
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001015 template<UseKind leftUseKind>
1016 bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1017 {
1018 ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1019
1020 if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
1021 return false;
1022
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001023 convertStringAddUse<leftUseKind>(node, left);
1024
1025 if (right->shouldSpeculateString())
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001026 convertStringAddUse<StringUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001027 else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001028 convertStringAddUse<StringObjectUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001029 else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001030 convertStringAddUse<StringOrStringObjectUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001031 else {
1032 // At this point we know that the other operand is something weird. The semantically correct
1033 // way of dealing with this is:
1034 //
1035 // MakeRope(@left, ToString(ToPrimitive(@right)))
1036 //
1037 // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1038 // anything to @right, since ToPrimitive may be effectful.
1039
1040 Node* toPrimitive = m_insertionSet.insertNode(
1041 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive, node->codeOrigin,
1042 Edge(right.node()));
1043 Node* toString = m_insertionSet.insertNode(
1044 m_indexInBlock, SpecString, ToString, node->codeOrigin, Edge(toPrimitive));
1045
1046 fixupToPrimitive(toPrimitive);
1047 fixupToString(toString);
1048
1049 right.setNode(toString);
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001050 }
1051
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001052 convertToMakeRope(node);
1053 return true;
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001054 }
1055
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001056 bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, const Identifier& ident)
1057 {
1058 unsigned attributesUnused;
1059 JSCell* specificValue;
1060 PropertyOffset offset = stringPrototypeStructure->get(
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001061 vm(), ident, attributesUnused, specificValue);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001062 if (!isValidOffset(offset))
1063 return false;
1064
1065 if (!specificValue)
1066 return false;
1067
1068 if (!specificValue->inherits(&JSFunction::s_info))
1069 return false;
1070
1071 JSFunction* function = jsCast<JSFunction*>(specificValue);
1072 if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1073 return false;
1074
1075 return true;
1076 }
1077
1078 bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1079 {
1080 if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1081 return false;
1082
1083 Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1084 ASSERT(stringObjectStructure->storedPrototype().isObject());
1085 ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == &StringPrototype::s_info);
1086
1087 JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1088 Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1089 if (stringPrototypeStructure->transitionWatchpointSetHasBeenInvalidated())
1090 return false;
1091
1092 if (stringPrototypeStructure->isDictionary())
1093 return false;
1094
1095 // We're being conservative here. We want DFG's ToString on StringObject to be
1096 // used in both numeric contexts (that would call valueOf()) and string contexts
1097 // (that would call toString()). We don't want the DFG to have to distinguish
1098 // between the two, just because that seems like it would get confusing. So we
1099 // just require both methods to be sane.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001100 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001101 return false;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001102 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001103 return false;
1104
1105 return true;
1106 }
1107
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001108 void fixupSetLocalsInBlock(BasicBlock* block)
1109 {
1110 if (!block)
1111 return;
1112 ASSERT(block->isReachable);
1113 m_block = block;
1114 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1115 Node* node = m_currentNode = block->at(m_indexInBlock);
1116 if (node->op() != SetLocal)
1117 continue;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001118
1119 VariableAccessData* variable = node->variableAccessData();
1120
1121 if (!variable->shouldUnboxIfPossible())
1122 continue;
1123
1124 if (variable->shouldUseDoubleFormat()) {
1125 fixDoubleEdge<NumberUse>(node->child1(), ForwardSpeculation);
1126 continue;
1127 }
1128
1129 SpeculatedType predictedType = variable->argumentAwarePrediction();
1130 if (isInt32Speculation(predictedType))
1131 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1132 else if (isCellSpeculation(predictedType))
1133 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1134 else if (isBooleanSpeculation(predictedType))
1135 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
1136 }
1137 m_insertionSet.execute(block);
1138 }
1139
fpizlo@apple.com7bda0582013-03-12 20:38:26 +00001140 void findAndRemoveUnnecessaryStructureCheck(Node* array, const CodeOrigin& codeOrigin)
1141 {
1142 for (unsigned index = m_indexInBlock; index--;) {
1143 Node* previousNode = m_block->at(index);
1144 if (previousNode->codeOrigin != codeOrigin)
1145 return;
1146
1147 if (previousNode->op() != CheckStructure)
1148 continue;
1149
1150 if (previousNode->child1() != array)
1151 continue;
1152
1153 previousNode->child1() = Edge();
1154 previousNode->convertToPhantom();
1155 return; // Assume we were smart enough to only insert one CheckStructure on the array.
1156 }
1157 }
1158
1159 Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001160 {
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001161 ASSERT(arrayMode.isSpecific());
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001162
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001163 Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1164
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001165 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1166
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001167 if (arrayMode.doesConversion()) {
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001168 if (structure) {
fpizlo@apple.comf10d0722012-12-03 09:21:22 +00001169 if (m_indexInBlock > 0) {
1170 // If the previous node was a CheckStructure inserted because of stuff
fpizlo@apple.com7bda0582013-03-12 20:38:26 +00001171 // that the array profile told us, then remove it, since we're going to be
1172 // doing arrayification instead.
1173 findAndRemoveUnnecessaryStructureCheck(array, codeOrigin);
fpizlo@apple.comf10d0722012-12-03 09:21:22 +00001174 }
1175
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001176 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001177 m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001178 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001179 } else {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001180 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001181 m_indexInBlock, SpecNone, Arrayify, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001182 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001183 }
1184 } else {
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001185 if (structure) {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001186 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001187 m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001188 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001189 } else {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001190 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001191 m_indexInBlock, SpecNone, CheckArray, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001192 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001193 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001194 }
1195
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001196 if (!storageCheck(arrayMode))
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001197 return 0;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001198
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001199 if (arrayMode.usesButterfly()) {
1200 return m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001201 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, KnownCellUse));
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001202 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001203
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001204 return m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001205 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1206 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001207 }
1208
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001209 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001210 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001211 Node* node = m_currentNode;
1212
1213 switch (node->arrayMode().type()) {
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001214 case Array::ForceExit: {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001215 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001216 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001217 return;
1218 }
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001219
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001220 case Array::SelectUsingPredictions:
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001221 case Array::Unprofiled:
oliver@apple.com5598c182013-01-23 22:25:07 +00001222 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001223 return;
1224
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001225 case Array::Generic:
fpizlo@apple.com7bda0582013-03-12 20:38:26 +00001226 findAndRemoveUnnecessaryStructureCheck(base.node(), node->codeOrigin);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001227 return;
1228
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001229 default: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001230 Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1231 if (!storage)
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001232 return;
1233
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001234 storageChild = Edge(storage);
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001235 return;
1236 } }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001237 }
1238
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001239 bool alwaysUnboxSimplePrimitives()
1240 {
1241#if USE(JSVALUE64)
1242 return false;
1243#else
1244 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1245 // reduces traffic.
1246 return true;
1247#endif
1248 }
1249
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001250 template<UseKind useKind>
1251 void observeUseKindOnNode(Node* node)
1252 {
1253 if (node->op() != GetLocal)
1254 return;
1255
1256 VariableAccessData* variable = node->variableAccessData();
1257 switch (useKind) {
1258 case Int32Use:
1259 if (alwaysUnboxSimplePrimitives()
1260 || isInt32Speculation(variable->prediction()))
1261 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1262 break;
1263 case NumberUse:
1264 case RealNumberUse:
1265 if (variable->doubleFormatState() == UsingDoubleFormat)
1266 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1267 break;
1268 case BooleanUse:
1269 if (alwaysUnboxSimplePrimitives()
1270 || isBooleanSpeculation(variable->prediction()))
1271 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1272 break;
1273 case CellUse:
1274 case ObjectUse:
1275 case StringUse:
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001276 case KnownStringUse:
1277 case StringObjectUse:
1278 case StringOrStringObjectUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001279 if (alwaysUnboxSimplePrimitives()
1280 || isCellSpeculation(variable->prediction()))
1281 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1282 break;
1283 default:
1284 break;
1285 }
1286 }
1287
fpizlo@apple.com35701872013-02-23 01:03:10 +00001288 // Set the use kind of the edge. In the future (https://bugs.webkit.org/show_bug.cgi?id=110433),
1289 // this can be used to notify the GetLocal that the variable is profitable to unbox.
1290 template<UseKind useKind>
1291 void setUseKindAndUnboxIfProfitable(Edge& edge)
1292 {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001293 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com35701872013-02-23 01:03:10 +00001294 edge.setUseKind(useKind);
1295 }
1296
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001297 void fixIntEdge(Edge& edge)
1298 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001299 Node* node = edge.node();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001300 if (node->op() != ValueToInt32) {
fpizlo@apple.com35701872013-02-23 01:03:10 +00001301 setUseKindAndUnboxIfProfitable<KnownInt32Use>(edge);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001302 return;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001303 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001304
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001305 Edge newEdge = node->child1();
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001306
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001307 if (newEdge.useKind() != Int32Use) {
1308 edge.setUseKind(KnownInt32Use);
1309 return;
1310 }
1311
1312 ASSERT(newEdge->shouldSpeculateInteger());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001313 edge = newEdge;
1314 }
1315
fpizlo@apple.com35701872013-02-23 01:03:10 +00001316 template<UseKind useKind>
1317 void fixDoubleEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001318 {
fpizlo@apple.com35701872013-02-23 01:03:10 +00001319 ASSERT(useKind == NumberUse || useKind == KnownNumberUse || useKind == RealNumberUse);
1320
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001321 if (edge->prediction() & SpecDouble) {
fpizlo@apple.com35701872013-02-23 01:03:10 +00001322 setUseKindAndUnboxIfProfitable<useKind>(edge);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001323 return;
1324 }
1325
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001326 injectInt32ToDoubleNode(edge, useKind, direction);
msaboff@apple.com268bb442013-01-18 21:45:06 +00001327 }
1328
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001329 void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
msaboff@apple.com268bb442013-01-18 21:45:06 +00001330 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001331 Node* result = m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001332 m_indexInBlock, SpecDouble,
fpizlo@apple.com393289d2013-02-12 00:29:20 +00001333 direction == BackwardSpeculation ? Int32ToDouble : ForwardInt32ToDouble,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001334 m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001335
1336#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001337 dataLogF(
1338 "(replacing @%u->@%u with @%u->@%u) ",
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001339 m_currentNode->index(), edge->index(), m_currentNode->index(), result->index());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001340#endif
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001341
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001342 edge = Edge(result, useKind);
1343 }
1344
1345 void truncateConstantToInt32(Edge& edge)
1346 {
1347 Node* oldNode = edge.node();
1348
1349 ASSERT(oldNode->hasConstant());
1350 JSValue value = m_graph.valueOfJSConstant(oldNode);
1351 if (value.isInt32())
1352 return;
1353
1354 value = jsNumber(JSC::toInt32(value.asNumber()));
1355 ASSERT(value.isInt32());
1356 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001357 m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
1358 OpInfo(codeBlock()->addOrFindConstant(value))));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001359 }
1360
1361 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1362 {
1363 if (mode != SpeculateIntegerAndTruncateConstants)
1364 return;
1365
1366 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1367 if (node->child1()->hasConstant())
1368 truncateConstantToInt32(node->child1());
1369 else
1370 truncateConstantToInt32(node->child2());
1371 }
1372
1373 bool attemptToMakeIntegerAdd(Node* node)
1374 {
1375 AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1376 if (mode == DontSpeculateInteger)
1377 return false;
1378
1379 truncateConstantsIfNecessary(node, mode);
fpizlo@apple.com35701872013-02-23 01:03:10 +00001380 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1381 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001382 return true;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001383 }
fpizlo@apple.comf10d0722012-12-03 09:21:22 +00001384
1385 BasicBlock* m_block;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001386 unsigned m_indexInBlock;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001387 Node* m_currentNode;
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001388 InsertionSet m_insertionSet;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001389 bool m_profitabilityChanged;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001390};
1391
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001392bool performFixup(Graph& graph)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001393{
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00001394 SamplingRegion samplingRegion("DFG Fixup Phase");
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001395 return runPhase<FixupPhase>(graph);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001396}
1397
1398} } // namespace JSC::DFG
1399
1400#endif // ENABLE(DFG_JIT)
1401