blob: fb6c6c7b34357fc37e82ba443c412d2fcbaad191 [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;
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.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());
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000123 node->setOpAndDefaultFlags(Identity);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000124 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000125 }
126
127 if (node->child1()->shouldSpeculateNumber()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000128 setUseKindAndUnboxIfProfitable<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000129 break;
130 }
131
132 if (node->child1()->shouldSpeculateBoolean()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000133 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000134 break;
135 }
136
fpizlo@apple.com35701872013-02-23 01:03:10 +0000137 setUseKindAndUnboxIfProfitable<NotCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000138 break;
139 }
140
141 case Int32ToDouble: {
142 RELEASE_ASSERT_NOT_REACHED();
143 break;
144 }
145
146 case ValueAdd: {
147 if (attemptToMakeIntegerAdd(node))
148 break;
149 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000150 fixDoubleEdge<NumberUse>(node->child1());
151 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000152 break;
153 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000154
155 // FIXME: Optimize for the case where one of the operands is the
156 // empty string. Also consider optimizing for the case where we don't
157 // believe either side is the emtpy string. Both of these things should
158 // be easy.
159
160 if (node->child1()->shouldSpeculateString()
161 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
162 break;
163 if (node->child2()->shouldSpeculateString()
164 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
165 break;
166 if (node->child1()->shouldSpeculateStringObject()
167 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
168 break;
169 if (node->child2()->shouldSpeculateStringObject()
170 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
171 break;
172 if (node->child1()->shouldSpeculateStringOrStringObject()
173 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
174 break;
175 if (node->child2()->shouldSpeculateStringOrStringObject()
176 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
177 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000178 break;
179 }
180
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000181 case MakeRope: {
182 fixupMakeRope(node);
183 break;
184 }
185
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000186 case ArithAdd:
187 case ArithSub: {
188 if (attemptToMakeIntegerAdd(node))
189 break;
fpizlo@apple.com35701872013-02-23 01:03:10 +0000190 fixDoubleEdge<NumberUse>(node->child1());
191 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000192 break;
193 }
194
195 case ArithNegate: {
196 if (m_graph.negateShouldSpeculateInteger(node)) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000197 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000198 break;
199 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000200 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000201 break;
202 }
203
204 case ArithMul: {
205 if (m_graph.mulShouldSpeculateInteger(node)) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000206 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
207 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000208 break;
209 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000210 fixDoubleEdge<NumberUse>(node->child1());
211 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000212 break;
213 }
214
oliver@apple.comf4443a72013-07-25 04:01:11 +0000215 case ArithDiv:
216 case ArithMod: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000217 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
218 && node->canSpeculateInteger()) {
rniwa@webkit.org3b9e15c2013-04-30 20:18:46 +0000219 if (isX86() || isARMv7s()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000220 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
221 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000222 break;
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000223 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000224 injectInt32ToDoubleNode(node->child1());
225 injectInt32ToDoubleNode(node->child2());
226
227 // We don't need to do ref'ing on the children because we're stealing them from
228 // the original division.
229 Node* newDivision = m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000230 m_indexInBlock, SpecDouble, *node);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000231
232 node->setOp(DoubleAsInt32);
233 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000234 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000235 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000236 fixDoubleEdge<NumberUse>(node->child1());
237 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000238 break;
239 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000240
241 case ArithMin:
oliver@apple.comf4443a72013-07-25 04:01:11 +0000242 case ArithMax: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000243 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
244 && node->canSpeculateInteger()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000245 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
246 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000247 break;
248 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000249 fixDoubleEdge<NumberUse>(node->child1());
250 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000251 break;
252 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000253
254 case ArithAbs: {
255 if (node->child1()->shouldSpeculateIntegerForArithmetic()
256 && node->canSpeculateInteger()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000257 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000258 break;
259 }
fpizlo@apple.com35701872013-02-23 01:03:10 +0000260 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000261 break;
262 }
263
264 case ArithSqrt: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000265 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000266 break;
267 }
268
269 case LogicalNot: {
270 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000271 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000272 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000273 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000274 else if (node->child1()->shouldSpeculateInteger())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000275 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000276 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000277 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000278 break;
279 }
280
281 case TypeOf: {
282 if (node->child1()->shouldSpeculateString())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000283 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000284 else if (node->child1()->shouldSpeculateCell())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000285 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000286 break;
287 }
288
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000289 case CompareEqConstant: {
290 break;
291 }
292
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000293 case CompareEq:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000294 case CompareLess:
295 case CompareLessEq:
296 case CompareGreater:
297 case CompareGreaterEq: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000298 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000299 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
300 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000301 break;
302 }
303 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000304 fixDoubleEdge<NumberUse>(node->child1());
305 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000306 break;
307 }
308 if (node->op() != CompareEq)
309 break;
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000310 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
311 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
312 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child2());
313 break;
314 }
oliver@apple.combd15be82013-07-25 04:03:42 +0000315 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
316 setUseKindAndUnboxIfProfitable<StringIdentUse>(node->child1());
317 setUseKindAndUnboxIfProfitable<StringIdentUse>(node->child2());
318 break;
319 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000320 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
321 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
322 setUseKindAndUnboxIfProfitable<StringUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000323 break;
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000324 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000325 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000326 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
327 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000328 break;
329 }
330 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000331 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
332 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000333 break;
334 }
335 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000336 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
337 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000338 break;
339 }
340 break;
341 }
342
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000343 case CompareStrictEqConstant: {
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000344 break;
345 }
346
347 case CompareStrictEq: {
ggaren@apple.com0f001eb2013-04-24 15:48:55 +0000348 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
349 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
350 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child2());
351 break;
352 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000353 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000354 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
355 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000356 break;
357 }
358 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000359 fixDoubleEdge<NumberUse>(node->child1());
360 fixDoubleEdge<NumberUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000361 break;
362 }
oliver@apple.combd15be82013-07-25 04:03:42 +0000363 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
364 setUseKindAndUnboxIfProfitable<StringIdentUse>(node->child1());
365 setUseKindAndUnboxIfProfitable<StringIdentUse>(node->child2());
366 break;
367 }
fpizlo@apple.comee10e452013-04-09 00:10:16 +0000368 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
369 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
370 setUseKindAndUnboxIfProfitable<StringUse>(node->child2());
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.com35701872013-02-23 01:03:10 +0000374 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
375 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000376 break;
377 }
378 break;
379 }
380
commit-queue@webkit.orgaa31a5e2013-04-09 06:45:16 +0000381 case StringFromCharCode:
382 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
383 break;
384
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000385 case StringCharAt:
386 case StringCharCodeAt: {
387 // Currently we have no good way of refining these.
388 ASSERT(node->arrayMode() == ArrayMode(Array::String));
389 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com35701872013-02-23 01:03:10 +0000390 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
391 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000392 break;
393 }
394
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000395 case GetByVal: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000396 node->setArrayMode(
397 node->arrayMode().refine(
398 node->child1()->prediction(),
399 node->child2()->prediction(),
400 SpecNone, node->flags()));
fpizlo@apple.com7aed8d82012-08-23 03:38:52 +0000401
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000402 blessArrayOperation(node->child1(), node->child2(), node->child3());
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000403
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000404 ArrayMode arrayMode = node->arrayMode();
oliver@apple.com211b3be2013-07-25 04:03:39 +0000405 switch (arrayMode.type()) {
406 case Array::Double:
407 if (arrayMode.arrayClass() == Array::OriginalArray
408 && arrayMode.speculation() == Array::InBounds
oliver@apple.com211b3be2013-07-25 04:03:39 +0000409 && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
410 && !(node->flags() & NodeUsedAsOther))
411 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
412 break;
413
414 case Array::String:
415 if ((node->prediction() & ~SpecString)
416 || m_graph.hasExitSite(node->codeOrigin, OutOfBounds))
417 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
418 break;
419
420 default:
421 break;
422 }
fpizlo@apple.com94e84e92012-11-11 02:56:12 +0000423
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000424 switch (node->arrayMode().type()) {
425 case Array::SelectUsingPredictions:
426 case Array::Unprofiled:
427 case Array::Undecided:
428 RELEASE_ASSERT_NOT_REACHED();
429 break;
430 case Array::Generic:
431#if USE(JSVALUE32_64)
fpizlo@apple.com35701872013-02-23 01:03:10 +0000432 setUseKindAndUnboxIfProfitable<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000433#endif
434 break;
435 case Array::ForceExit:
436 break;
437 default:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000438 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
439 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000440 break;
441 }
442
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000443 break;
444 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000445
446 case PutByVal:
447 case PutByValAlias: {
448 Edge& child1 = m_graph.varArgChild(node, 0);
449 Edge& child2 = m_graph.varArgChild(node, 1);
450 Edge& child3 = m_graph.varArgChild(node, 2);
451
452 node->setArrayMode(
453 node->arrayMode().refine(
454 child1->prediction(),
455 child2->prediction(),
456 child3->prediction()));
457
458 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
459
460 switch (node->arrayMode().modeForPut().type()) {
461 case Array::SelectUsingPredictions:
462 case Array::Unprofiled:
463 case Array::Undecided:
464 RELEASE_ASSERT_NOT_REACHED();
465 break;
466 case Array::ForceExit:
467 case Array::Generic:
468#if USE(JSVALUE32_64)
469 // Due to register pressure on 32-bit, we speculate cell and
470 // ignore the base-is-not-cell case entirely by letting the
471 // baseline JIT handle it.
fpizlo@apple.com35701872013-02-23 01:03:10 +0000472 setUseKindAndUnboxIfProfitable<CellUse>(child1);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000473#endif
474 break;
475 case Array::Int32:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000476 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
477 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
478 setUseKindAndUnboxIfProfitable<Int32Use>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000479 break;
480 case Array::Double:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000481 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
482 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
483 fixDoubleEdge<RealNumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000484 break;
485 case Array::Int8Array:
486 case Array::Int16Array:
487 case Array::Int32Array:
488 case Array::Uint8Array:
489 case Array::Uint8ClampedArray:
490 case Array::Uint16Array:
491 case Array::Uint32Array:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000492 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
493 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000494 if (child3->shouldSpeculateInteger())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000495 setUseKindAndUnboxIfProfitable<Int32Use>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000496 else
fpizlo@apple.com35701872013-02-23 01:03:10 +0000497 fixDoubleEdge<NumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000498 break;
499 case Array::Float32Array:
500 case Array::Float64Array:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000501 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
502 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
503 fixDoubleEdge<NumberUse>(child3);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000504 break;
505 default:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000506 setUseKindAndUnboxIfProfitable<KnownCellUse>(child1);
507 setUseKindAndUnboxIfProfitable<Int32Use>(child2);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000508 break;
509 }
fpizlo@apple.coma387b6a2012-11-01 07:41:43 +0000510 break;
511 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000512
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000513 case ArrayPush: {
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000514 // May need to refine the array mode in case the value prediction contravenes
515 // the array prediction. For example, we may have evidence showing that the
516 // array is in Int32 mode, but the value we're storing is likely to be a double.
517 // Then we should turn this into a conversion to Double array followed by the
518 // push. On the other hand, we absolutely don't want to refine based on the
519 // base prediction. If it has non-cell garbage in it, then we want that to be
520 // ignored. That's because ArrayPush can't handle any array modes that aren't
521 // array-related - so if refine() turned this into a "Generic" ArrayPush then
522 // that would break things.
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000523 node->setArrayMode(
524 node->arrayMode().refine(
525 node->child1()->prediction() & SpecCell,
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000526 SpecInt32,
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000527 node->child2()->prediction()));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000528 blessArrayOperation(node->child1(), Edge(), node->child3());
fpizlo@apple.com35701872013-02-23 01:03:10 +0000529 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000530
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000531 switch (node->arrayMode().type()) {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000532 case Array::Int32:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000533 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000534 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000535 case Array::Double:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000536 fixDoubleEdge<RealNumberUse>(node->child2());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000537 break;
538 default:
539 break;
540 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000541 break;
542 }
543
544 case ArrayPop: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000545 blessArrayOperation(node->child1(), Edge(), node->child2());
fpizlo@apple.com35701872013-02-23 01:03:10 +0000546 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com8fd79212012-10-16 21:59:35 +0000547 break;
fpizlo@apple.com04c19742012-08-26 22:35:26 +0000548 }
549
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000550 case RegExpExec:
551 case RegExpTest: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000552 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
553 setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000554 break;
555 }
556
557 case Branch: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000558 if (node->child1()->shouldSpeculateBoolean())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000559 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000560 else if (node->child1()->shouldSpeculateObjectOrOther())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000561 setUseKindAndUnboxIfProfitable<ObjectOrOtherUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000562 else if (node->child1()->shouldSpeculateInteger())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000563 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000564 else if (node->child1()->shouldSpeculateNumber())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000565 fixDoubleEdge<NumberUse>(node->child1());
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000566
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000567 Node* logicalNot = node->child1().node();
fpizlo@apple.com098a1452013-03-01 20:57:37 +0000568 if (logicalNot->op() == LogicalNot) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000569
570 // Make sure that OSR exit can't observe the LogicalNot. If it can,
571 // then we must compute it and cannot peephole around it.
572 bool found = false;
573 bool ok = true;
574 for (unsigned i = m_indexInBlock; i--;) {
575 Node* candidate = m_block->at(i);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000576 if (candidate == logicalNot) {
577 found = true;
578 break;
579 }
580 if (candidate->canExit()) {
581 ok = false;
582 found = true;
583 break;
584 }
585 }
586 ASSERT_UNUSED(found, found);
587
588 if (ok) {
589 Edge newChildEdge = logicalNot->child1();
590 if (newChildEdge->hasBooleanResult()) {
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000591 node->children.setChild1(newChildEdge);
592
oliver@apple.com426f5b02013-07-25 04:04:27 +0000593 BasicBlock* toBeTaken = node->notTakenBlock();
594 BasicBlock* toBeNotTaken = node->takenBlock();
595 node->setTakenBlock(toBeTaken);
596 node->setNotTakenBlock(toBeNotTaken);
fpizlo@apple.com573b9002013-02-13 21:00:01 +0000597 }
fpizlo@apple.coma6c889b2012-04-12 04:19:07 +0000598 }
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000599 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000600 break;
601 }
602
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000603 case Switch: {
604 SwitchData* data = node->switchData();
605 switch (data->kind) {
606 case SwitchImm:
607 if (node->child1()->shouldSpeculateInteger())
608 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
609 break;
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000610 case SwitchChar:
611 if (node->child1()->shouldSpeculateString())
612 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
613 break;
oliver@apple.com5c826c02013-07-25 04:03:51 +0000614 case SwitchString:
615 if (node->child1()->shouldSpeculateStringIdent())
616 setUseKindAndUnboxIfProfitable<StringIdentUse>(node->child1());
617 else if (node->child1()->shouldSpeculateString())
618 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
619 break;
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000620 }
621 break;
622 }
623
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000624 case ToPrimitive: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000625 fixupToPrimitive(node);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000626 break;
627 }
628
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000629 case ToString: {
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +0000630 fixupToString(node);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +0000631 break;
632 }
633
634 case NewStringObject: {
635 setUseKindAndUnboxIfProfitable<KnownStringUse>(node->child1());
636 break;
637 }
638
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000639 case NewArray: {
640 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000641 node->setIndexingType(
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000642 leastUpperBoundOfIndexingTypeAndType(
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000643 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000644 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000645 switch (node->indexingType()) {
646 case ALL_BLANK_INDEXING_TYPES:
647 CRASH();
648 break;
649 case ALL_UNDECIDED_INDEXING_TYPES:
650 if (node->numChildren()) {
651 // This will only happen if the children have no type predictions. We
652 // would have already exited by now, but insert a forced exit just to
653 // be safe.
654 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000655 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000656 }
657 break;
658 case ALL_INT32_INDEXING_TYPES:
659 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.com35701872013-02-23 01:03:10 +0000660 setUseKindAndUnboxIfProfitable<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000661 break;
662 case ALL_DOUBLE_INDEXING_TYPES:
663 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
fpizlo@apple.comed630542013-08-07 04:04:50 +0000664 fixDoubleEdge<RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000665 break;
666 case ALL_CONTIGUOUS_INDEXING_TYPES:
667 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
668 break;
669 default:
670 CRASH();
671 break;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000672 }
673 break;
674 }
675
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000676 case NewArrayWithSize: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000677 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000678 break;
679 }
680
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000681 case ToThis: {
682 ECMAMode ecmaMode = m_graph.executableFor(node->codeOrigin)->isStrictMode() ? StrictMode : NotStrictMode;
683
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000684 if (isOtherSpeculation(node->child1()->prediction())) {
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000685 if (ecmaMode == StrictMode) {
686 setUseKindAndUnboxIfProfitable<OtherUse>(node->child1());
687 node->convertToIdentity();
688 break;
689 }
690
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000691 m_insertionSet.insertNode(
692 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
693 Edge(node->child1().node(), OtherUse));
694 observeUseKindOnNode<OtherUse>(node->child1().node());
695 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->codeOrigin));
696 break;
697 }
698
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000699 if (isFinalObjectSpeculation(node->child1()->prediction())) {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000700 setUseKindAndUnboxIfProfitable<ObjectUse>(node->child1());
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +0000701 node->convertToIdentity();
702 break;
703 }
704
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000705 break;
706 }
707
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000708 case GetMyArgumentByVal:
709 case GetMyArgumentByValSafe: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000710 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000711 break;
712 }
713
oliver@apple.com58c86752013-07-25 04:02:40 +0000714 case GetClosureRegisters:
715 case PutClosureVar:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000716 case SkipTopScope:
717 case SkipScope:
718 case SetCallee:
719 case SetMyScope:
720 case PutStructure:
721 case AllocatePropertyStorage:
722 case ReallocatePropertyStorage:
oliver@apple.come17632e2013-07-25 04:05:31 +0000723 case GetScope: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000724 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000725 break;
726 }
727
fpizlo@apple.com151e9af2013-08-16 02:30:37 +0000728 case GetById:
729 case GetByIdFlush: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000730 if (!node->child1()->shouldSpeculateCell())
731 break;
fpizlo@apple.com35701872013-02-23 01:03:10 +0000732 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000733 if (!isInt32Speculation(node->prediction()))
734 break;
oliver@apple.com90fce822013-07-25 04:00:13 +0000735 if (m_graph.identifiers()[node->identifierNumber()] != vm().propertyNames->length.impl())
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000736 break;
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000737 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->codeOrigin);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000738 ArrayProfile* arrayProfile =
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000739 profiledBlock->getArrayProfile(node->codeOrigin.bytecodeIndex);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000740 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
741 if (arrayProfile) {
oliver@apple.comd2056662013-07-25 04:00:37 +0000742 ConcurrentJITLocker locker(profiledBlock->m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000743 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
744 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
fpizlo@apple.com151e9af2013-08-16 02:30:37 +0000745 if (arrayMode.type() == Array::Unprofiled) {
746 // For normal array operations, it makes sense to treat Unprofiled
747 // accesses as ForceExit and get more data rather than using
748 // predictions and then possibly ending up with a Generic. But here,
749 // we treat anything that is Unprofiled as Generic and keep the
750 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
751 // profit - from treating the Unprofiled case as
752 // SelectUsingPredictions.
753 arrayMode = ArrayMode(Array::SelectUsingPredictions);
754 }
755 }
756
757 arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction());
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000758
759 if (arrayMode.type() == Array::Generic) {
760 // Check if the input is something that we can't get array length for, but for which we
761 // could insert some conversions in order to transform it into something that we can do it
762 // for.
763 if (node->child1()->shouldSpeculateStringObject())
764 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
765 else if (node->child1()->shouldSpeculateStringOrStringObject())
766 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
767 }
768
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000769 if (!arrayMode.supportsLength())
770 break;
771 node->setOp(GetArrayLength);
772 ASSERT(node->flags() & NodeMustGenerate);
773 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
fpizlo@apple.com35701872013-02-23 01:03:10 +0000774 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000775 node->setArrayMode(arrayMode);
776
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000777 Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage);
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000778 if (!storage)
779 break;
780
781 node->child2() = Edge(storage);
782 break;
783 }
784
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000785 case CheckExecutable:
786 case CheckStructure:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000787 case StructureTransitionWatchpoint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000788 case CheckFunction:
789 case PutById:
790 case PutByIdDirect:
oliver@apple.come17632e2013-07-25 04:05:31 +0000791 case CheckHasInstance:
792 case CreateThis:
793 case GetButterfly: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000794 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000795 break;
796 }
797
oliver@apple.com500b53a2013-07-25 04:05:25 +0000798 case CheckArray: {
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000799 switch (node->arrayMode().type()) {
800 case Array::String:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000801 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000802 break;
803 default:
fpizlo@apple.com35701872013-02-23 01:03:10 +0000804 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000805 break;
806 }
807 break;
808 }
809
810 case Arrayify:
811 case ArrayifyToStructure: {
fpizlo@apple.com35701872013-02-23 01:03:10 +0000812 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000813 if (node->child2())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000814 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000815 break;
816 }
817
818 case GetByOffset: {
819 if (!node->child1()->hasStorageResult())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000820 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
oliver@apple.com0402d952013-07-25 04:05:07 +0000821 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000822 break;
823 }
824
825 case PutByOffset: {
826 if (!node->child1()->hasStorageResult())
fpizlo@apple.com35701872013-02-23 01:03:10 +0000827 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
828 setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000829 break;
830 }
831
832 case InstanceOf: {
833 // FIXME: This appears broken: CheckHasInstance already does an unconditional cell
834 // check. https://bugs.webkit.org/show_bug.cgi?id=107479
835 if (!(node->child1()->prediction() & ~SpecCell))
fpizlo@apple.com35701872013-02-23 01:03:10 +0000836 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
837 setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000838 break;
839 }
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000840
841 case In: {
842 // FIXME: We should at some point have array profiling on op_in, in which
843 // case we would be able to turn this into a kind of GetByVal.
844
845 setUseKindAndUnboxIfProfitable<CellUse>(node->child2());
846 break;
847 }
fpizlo@apple.com46955912013-04-26 01:18:18 +0000848
849 case Phantom:
850 case Identity: {
851 switch (node->child1().useKind()) {
852 case NumberUse:
853 if (node->child1()->shouldSpeculateIntegerForArithmetic())
854 node->child1().setUseKind(Int32Use);
855 break;
856 default:
857 break;
858 }
859 observeUseKindOnEdge(node->child1());
860 break;
861 }
862
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000863 case GetArrayLength:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000864 case Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000865 case Upsilon:
866 case GetArgument:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000867 case PhantomPutStructure:
868 case GetIndexedPropertyStorage:
869 case LastNodeType:
fpizlo@apple.com06f82b52013-03-06 02:27:16 +0000870 case MovHint:
871 case MovHintAndCheck:
872 case ZombieHint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000873 RELEASE_ASSERT_NOT_REACHED();
874 break;
875
876#if !ASSERT_DISABLED
877 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
878 case SetArgument:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000879 case JSConstant:
880 case WeakJSConstant:
881 case GetLocal:
882 case GetCallee:
883 case Flush:
884 case PhantomLocal:
885 case GetLocalUnlinked:
886 case InlineStart:
887 case GetMyScope:
oliver@apple.com58c86752013-07-25 04:02:40 +0000888 case GetClosureVar:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000889 case GetGlobalVar:
890 case PutGlobalVar:
891 case GlobalVarWatchpoint:
oliver@apple.com58c86752013-07-25 04:02:40 +0000892 case VarInjectionWatchpoint:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000893 case AllocationProfileWatchpoint:
894 case Call:
895 case Construct:
896 case NewObject:
897 case NewArrayBuffer:
898 case NewRegexp:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000899 case Breakpoint:
900 case IsUndefined:
901 case IsBoolean:
902 case IsNumber:
903 case IsString:
904 case IsObject:
905 case IsFunction:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000906 case CreateActivation:
907 case TearOffActivation:
908 case CreateArguments:
909 case PhantomArguments:
910 case TearOffArguments:
911 case GetMyArgumentsLength:
912 case GetMyArgumentsLengthSafe:
913 case CheckArgumentsNotCreated:
914 case NewFunction:
915 case NewFunctionNoCheck:
916 case NewFunctionExpression:
917 case Jump:
918 case Return:
919 case Throw:
920 case ThrowReferenceError:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000921 case CountExecution:
922 case ForceOSRExit:
mark.lam@apple.com10d23a12013-04-25 02:59:51 +0000923 case CheckWatchdogTimer:
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000924 break;
925#else
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000926 default:
927 break;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +0000928#endif
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000929 }
930
931#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000932 if (!(node->flags() & NodeHasVarArgs)) {
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000933 dataLogF("new children: ");
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +0000934 node->dumpChildren(WTF::dataFile());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000935 }
fpizlo@apple.com01902c82012-11-22 04:23:36 +0000936 dataLogF("\n");
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000937#endif
938 }
939
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000940 template<UseKind useKind>
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000941 void createToString(Node* node, Edge& edge)
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000942 {
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000943 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000944 m_indexInBlock, SpecString, ToString, node->codeOrigin,
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000945 Edge(edge.node(), useKind)));
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000946 }
947
948 template<UseKind useKind>
949 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
950 {
951 ASSERT(arrayMode == ArrayMode(Array::Generic));
952
953 if (!canOptimizeStringObjectAccess(node->codeOrigin))
954 return;
955
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000956 createToString<useKind>(node, node->child1());
fpizlo@apple.comcbc41132013-03-19 20:23:01 +0000957 arrayMode = ArrayMode(Array::String);
958 }
959
960 template<UseKind useKind>
fpizlo@apple.com8d225912013-03-19 00:44:57 +0000961 bool isStringObjectUse()
962 {
963 switch (useKind) {
964 case StringObjectUse:
965 case StringOrStringObjectUse:
966 return true;
967 default:
968 return false;
969 }
970 }
971
972 template<UseKind useKind>
973 void convertStringAddUse(Node* node, Edge& edge)
974 {
975 if (useKind == StringUse) {
976 // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
977 // two edges will always have identical use kinds, which makes the
978 // decision process much easier.
979 observeUseKindOnNode<StringUse>(edge.node());
980 m_insertionSet.insertNode(
981 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
982 Edge(edge.node(), StringUse));
983 edge.setUseKind(KnownStringUse);
984 return;
985 }
986
987 // FIXME: We ought to be able to have a ToPrimitiveToString node.
988
989 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com4463e442013-03-20 20:29:37 +0000990 createToString<useKind>(node, edge);
991 }
992
993 void convertToMakeRope(Node* node)
994 {
995 node->setOpAndDefaultFlags(MakeRope);
996 fixupMakeRope(node);
997 }
998
999 void fixupMakeRope(Node* node)
1000 {
1001 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1002 Edge& edge = node->children.child(i);
1003 if (!edge)
1004 break;
1005 edge.setUseKind(KnownStringUse);
1006 if (!m_graph.isConstant(edge.node()))
1007 continue;
1008 JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
1009 if (string->length())
1010 continue;
fpizlo@apple.com4bb938e2013-07-16 21:41:06 +00001011
1012 // Don't allow the MakeRope to have zero children.
1013 if (!i && !node->child2())
1014 break;
1015
fpizlo@apple.com4463e442013-03-20 20:29:37 +00001016 node->children.removeEdge(i--);
1017 }
1018
1019 if (!node->child2()) {
1020 ASSERT(!node->child3());
1021 node->convertToIdentity();
1022 }
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001023 }
1024
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001025 void fixupToPrimitive(Node* node)
1026 {
1027 if (node->child1()->shouldSpeculateInteger()) {
1028 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1029 node->convertToIdentity();
1030 return;
1031 }
1032
1033 if (node->child1()->shouldSpeculateString()) {
1034 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
1035 node->convertToIdentity();
1036 return;
1037 }
1038
1039 if (node->child1()->shouldSpeculateStringObject()
1040 && canOptimizeStringObjectAccess(node->codeOrigin)) {
1041 setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
1042 node->convertToToString();
1043 return;
1044 }
1045
1046 if (node->child1()->shouldSpeculateStringOrStringObject()
1047 && canOptimizeStringObjectAccess(node->codeOrigin)) {
1048 setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
1049 node->convertToToString();
1050 return;
1051 }
1052 }
1053
1054 void fixupToString(Node* node)
1055 {
1056 if (node->child1()->shouldSpeculateString()) {
1057 setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
1058 node->convertToIdentity();
1059 return;
1060 }
1061
1062 if (node->child1()->shouldSpeculateStringObject()
1063 && canOptimizeStringObjectAccess(node->codeOrigin)) {
1064 setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
1065 return;
1066 }
1067
1068 if (node->child1()->shouldSpeculateStringOrStringObject()
1069 && canOptimizeStringObjectAccess(node->codeOrigin)) {
1070 setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
1071 return;
1072 }
1073
1074 if (node->child1()->shouldSpeculateCell()) {
1075 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1076 return;
1077 }
1078 }
1079
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001080 template<UseKind leftUseKind>
1081 bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1082 {
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001083 Node* originalLeft = left.node();
1084 Node* originalRight = right.node();
1085
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001086 ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1087
1088 if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->codeOrigin))
1089 return false;
1090
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001091 convertStringAddUse<leftUseKind>(node, left);
1092
1093 if (right->shouldSpeculateString())
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001094 convertStringAddUse<StringUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001095 else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001096 convertStringAddUse<StringObjectUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001097 else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->codeOrigin))
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001098 convertStringAddUse<StringOrStringObjectUse>(node, right);
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001099 else {
1100 // At this point we know that the other operand is something weird. The semantically correct
1101 // way of dealing with this is:
1102 //
1103 // MakeRope(@left, ToString(ToPrimitive(@right)))
1104 //
1105 // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1106 // anything to @right, since ToPrimitive may be effectful.
1107
1108 Node* toPrimitive = m_insertionSet.insertNode(
1109 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive, node->codeOrigin,
1110 Edge(right.node()));
1111 Node* toString = m_insertionSet.insertNode(
1112 m_indexInBlock, SpecString, ToString, node->codeOrigin, Edge(toPrimitive));
1113
1114 fixupToPrimitive(toPrimitive);
1115 fixupToString(toString);
1116
1117 right.setNode(toString);
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001118 }
1119
fpizlo@apple.comdbeeff32013-07-24 04:51:57 +00001120 // We're doing checks up there, so we need to make sure that the
1121 // *original* inputs to the addition are live up to here.
1122 m_insertionSet.insertNode(
1123 m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
1124 Edge(originalLeft), Edge(originalRight));
1125
fpizlo@apple.com7e5ed6e2013-03-20 22:37:09 +00001126 convertToMakeRope(node);
1127 return true;
fpizlo@apple.com8d225912013-03-19 00:44:57 +00001128 }
1129
oliver@apple.com02039462013-07-25 03:59:29 +00001130 bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001131 {
1132 unsigned attributesUnused;
1133 JSCell* specificValue;
oliver@apple.com22fdb102013-07-25 03:58:56 +00001134 PropertyOffset offset = stringPrototypeStructure->getConcurrently(
oliver@apple.com02039462013-07-25 03:59:29 +00001135 vm(), uid, attributesUnused, specificValue);
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001136 if (!isValidOffset(offset))
1137 return false;
1138
1139 if (!specificValue)
1140 return false;
1141
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001142 if (!specificValue->inherits(JSFunction::info()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001143 return false;
1144
1145 JSFunction* function = jsCast<JSFunction*>(specificValue);
1146 if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1147 return false;
1148
1149 return true;
1150 }
1151
1152 bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1153 {
1154 if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1155 return false;
1156
1157 Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1158 ASSERT(stringObjectStructure->storedPrototype().isObject());
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +00001159 ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001160
1161 JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1162 Structure* stringPrototypeStructure = stringPrototypeObject->structure();
oliver@apple.com90fce822013-07-25 04:00:13 +00001163 if (!m_graph.watchpoints().isStillValid(stringPrototypeStructure->transitionWatchpointSet()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001164 return false;
1165
1166 if (stringPrototypeStructure->isDictionary())
1167 return false;
1168
1169 // We're being conservative here. We want DFG's ToString on StringObject to be
1170 // used in both numeric contexts (that would call valueOf()) and string contexts
1171 // (that would call toString()). We don't want the DFG to have to distinguish
1172 // between the two, just because that seems like it would get confusing. So we
1173 // just require both methods to be sane.
oliver@apple.com02039462013-07-25 03:59:29 +00001174 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001175 return false;
oliver@apple.com02039462013-07-25 03:59:29 +00001176 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001177 return false;
1178
1179 return true;
1180 }
1181
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001182 void fixupSetLocalsInBlock(BasicBlock* block)
1183 {
1184 if (!block)
1185 return;
1186 ASSERT(block->isReachable);
1187 m_block = block;
1188 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1189 Node* node = m_currentNode = block->at(m_indexInBlock);
1190 if (node->op() != SetLocal)
1191 continue;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001192
1193 VariableAccessData* variable = node->variableAccessData();
1194
1195 if (!variable->shouldUnboxIfPossible())
1196 continue;
1197
1198 if (variable->shouldUseDoubleFormat()) {
1199 fixDoubleEdge<NumberUse>(node->child1(), ForwardSpeculation);
1200 continue;
1201 }
1202
1203 SpeculatedType predictedType = variable->argumentAwarePrediction();
1204 if (isInt32Speculation(predictedType))
1205 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1206 else if (isCellSpeculation(predictedType))
1207 setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
1208 else if (isBooleanSpeculation(predictedType))
1209 setUseKindAndUnboxIfProfitable<BooleanUse>(node->child1());
1210 }
1211 m_insertionSet.execute(block);
1212 }
1213
fpizlo@apple.com7bda0582013-03-12 20:38:26 +00001214 Node* checkArray(ArrayMode arrayMode, const CodeOrigin& codeOrigin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001215 {
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001216 ASSERT(arrayMode.isSpecific());
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001217
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001218 Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
1219
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001220 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1221
fpizlo@apple.com34d1f082012-10-28 06:13:23 +00001222 if (arrayMode.doesConversion()) {
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001223 if (structure) {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001224 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001225 m_indexInBlock, SpecNone, ArrayifyToStructure, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001226 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001227 } else {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001228 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001229 m_indexInBlock, SpecNone, Arrayify, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001230 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
fpizlo@apple.com99f37622012-10-29 04:02:08 +00001231 }
1232 } else {
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001233 if (structure) {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001234 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001235 m_indexInBlock, SpecNone, CheckStructure, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001236 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001237 } else {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001238 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001239 m_indexInBlock, SpecNone, CheckArray, codeOrigin,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001240 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
fpizlo@apple.com3f1a01b2012-11-10 05:54:11 +00001241 }
fpizlo@apple.com497c7512012-09-19 01:20:52 +00001242 }
1243
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001244 if (!storageCheck(arrayMode))
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001245 return 0;
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001246
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001247 if (arrayMode.usesButterfly()) {
1248 return m_insertionSet.insertNode(
oliver@apple.come17632e2013-07-25 04:05:31 +00001249 m_indexInBlock, SpecNone, GetButterfly, codeOrigin, Edge(array, CellUse));
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001250 }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001251
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001252 return m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001253 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, codeOrigin,
1254 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001255 }
1256
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001257 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001258 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001259 Node* node = m_currentNode;
1260
1261 switch (node->arrayMode().type()) {
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001262 case Array::ForceExit: {
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001263 m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001264 m_indexInBlock, SpecNone, ForceOSRExit, node->codeOrigin);
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001265 return;
1266 }
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001267
fpizlo@apple.coma0ec0592012-10-22 23:52:15 +00001268 case Array::SelectUsingPredictions:
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001269 case Array::Unprofiled:
oliver@apple.com5598c182013-01-23 22:25:07 +00001270 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001271 return;
1272
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001273 case Array::Generic:
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001274 return;
1275
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001276 default: {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001277 Node* storage = checkArray(node->arrayMode(), node->codeOrigin, base.node(), index.node());
1278 if (!storage)
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001279 return;
1280
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001281 storageChild = Edge(storage);
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +00001282 return;
1283 } }
fpizlo@apple.com04c19742012-08-26 22:35:26 +00001284 }
1285
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001286 bool alwaysUnboxSimplePrimitives()
1287 {
1288#if USE(JSVALUE64)
1289 return false;
1290#else
1291 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1292 // reduces traffic.
1293 return true;
1294#endif
1295 }
fpizlo@apple.com46955912013-04-26 01:18:18 +00001296
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001297 template<UseKind useKind>
1298 void observeUseKindOnNode(Node* node)
1299 {
fpizlo@apple.com46955912013-04-26 01:18:18 +00001300 observeUseKindOnNode(node, useKind);
1301 }
1302
1303 void observeUseKindOnEdge(Edge edge)
1304 {
1305 observeUseKindOnNode(edge.node(), edge.useKind());
1306 }
1307
1308 void observeUseKindOnNode(Node* node, UseKind useKind)
1309 {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001310 if (node->op() != GetLocal)
1311 return;
1312
1313 VariableAccessData* variable = node->variableAccessData();
1314 switch (useKind) {
1315 case Int32Use:
1316 if (alwaysUnboxSimplePrimitives()
1317 || isInt32Speculation(variable->prediction()))
1318 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1319 break;
1320 case NumberUse:
1321 case RealNumberUse:
1322 if (variable->doubleFormatState() == UsingDoubleFormat)
1323 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1324 break;
1325 case BooleanUse:
1326 if (alwaysUnboxSimplePrimitives()
1327 || isBooleanSpeculation(variable->prediction()))
1328 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1329 break;
1330 case CellUse:
oliver@apple.com176a3472013-07-25 04:00:19 +00001331 case KnownCellUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001332 case ObjectUse:
1333 case StringUse:
fpizlo@apple.com0e6e1542013-03-18 18:09:22 +00001334 case KnownStringUse:
1335 case StringObjectUse:
1336 case StringOrStringObjectUse:
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001337 if (alwaysUnboxSimplePrimitives()
1338 || isCellSpeculation(variable->prediction()))
1339 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1340 break;
1341 default:
1342 break;
1343 }
1344 }
1345
fpizlo@apple.com35701872013-02-23 01:03:10 +00001346 // Set the use kind of the edge. In the future (https://bugs.webkit.org/show_bug.cgi?id=110433),
1347 // this can be used to notify the GetLocal that the variable is profitable to unbox.
1348 template<UseKind useKind>
1349 void setUseKindAndUnboxIfProfitable(Edge& edge)
1350 {
fpizlo@apple.com33b10ee2013-03-07 09:04:57 +00001351 observeUseKindOnNode<useKind>(edge.node());
fpizlo@apple.com35701872013-02-23 01:03:10 +00001352 edge.setUseKind(useKind);
1353 }
1354
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001355 void fixIntEdge(Edge& edge)
1356 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001357 Node* node = edge.node();
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001358 if (node->op() != ValueToInt32) {
fpizlo@apple.com35701872013-02-23 01:03:10 +00001359 setUseKindAndUnboxIfProfitable<KnownInt32Use>(edge);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001360 return;
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001361 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001362
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001363 Edge newEdge = node->child1();
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001364
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001365 if (newEdge.useKind() != Int32Use) {
1366 edge.setUseKind(KnownInt32Use);
1367 return;
1368 }
1369
1370 ASSERT(newEdge->shouldSpeculateInteger());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001371 edge = newEdge;
1372 }
1373
fpizlo@apple.com35701872013-02-23 01:03:10 +00001374 template<UseKind useKind>
1375 void fixDoubleEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation)
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001376 {
fpizlo@apple.com35701872013-02-23 01:03:10 +00001377 ASSERT(useKind == NumberUse || useKind == KnownNumberUse || useKind == RealNumberUse);
1378
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001379 if (edge->prediction() & SpecDouble) {
fpizlo@apple.com35701872013-02-23 01:03:10 +00001380 setUseKindAndUnboxIfProfitable<useKind>(edge);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001381 return;
1382 }
1383
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001384 injectInt32ToDoubleNode(edge, useKind, direction);
msaboff@apple.com268bb442013-01-18 21:45:06 +00001385 }
1386
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001387 void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
msaboff@apple.com268bb442013-01-18 21:45:06 +00001388 {
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001389 Node* result = m_insertionSet.insertNode(
oliver@apple.com500b53a2013-07-25 04:05:25 +00001390 m_indexInBlock, SpecDouble, Int32ToDouble,
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001391 m_currentNode->codeOrigin, Edge(edge.node(), NumberUse));
oliver@apple.com500b53a2013-07-25 04:05:25 +00001392 if (direction == ForwardSpeculation)
1393 result->mergeFlags(NodeExitsForward);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001394
1395#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001396 dataLogF(
1397 "(replacing @%u->@%u with @%u->@%u) ",
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001398 m_currentNode->index(), edge->index(), m_currentNode->index(), result->index());
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001399#endif
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001400
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001401 edge = Edge(result, useKind);
1402 }
1403
1404 void truncateConstantToInt32(Edge& edge)
1405 {
1406 Node* oldNode = edge.node();
1407
1408 ASSERT(oldNode->hasConstant());
1409 JSValue value = m_graph.valueOfJSConstant(oldNode);
1410 if (value.isInt32())
1411 return;
1412
1413 value = jsNumber(JSC::toInt32(value.asNumber()));
1414 ASSERT(value.isInt32());
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001415 unsigned constantRegister;
1416 if (!codeBlock()->findConstant(value, constantRegister)) {
1417 initializeLazyWriteBarrier(
1418 codeBlock()->addConstantLazily(),
1419 m_graph.m_plan.writeBarriers,
1420 codeBlock()->ownerExecutable(),
1421 value);
1422 }
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001423 edge.setNode(m_insertionSet.insertNode(
fpizlo@apple.com06f82b52013-03-06 02:27:16 +00001424 m_indexInBlock, SpecInt32, JSConstant, m_currentNode->codeOrigin,
mhahnenberg@apple.com941ab382013-08-16 03:28:39 +00001425 OpInfo(constantRegister)));
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001426 }
1427
1428 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1429 {
1430 if (mode != SpeculateIntegerAndTruncateConstants)
1431 return;
1432
1433 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1434 if (node->child1()->hasConstant())
1435 truncateConstantToInt32(node->child1());
1436 else
1437 truncateConstantToInt32(node->child2());
1438 }
1439
1440 bool attemptToMakeIntegerAdd(Node* node)
1441 {
1442 AddSpeculationMode mode = m_graph.addSpeculationMode(node);
1443 if (mode == DontSpeculateInteger)
1444 return false;
1445
1446 truncateConstantsIfNecessary(node, mode);
fpizlo@apple.com35701872013-02-23 01:03:10 +00001447 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
1448 setUseKindAndUnboxIfProfitable<Int32Use>(node->child2());
fpizlo@apple.com7a1964c2013-02-21 22:59:02 +00001449 return true;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001450 }
fpizlo@apple.comf10d0722012-12-03 09:21:22 +00001451
1452 BasicBlock* m_block;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +00001453 unsigned m_indexInBlock;
fpizlo@apple.com8ff092f2013-01-29 08:01:03 +00001454 Node* m_currentNode;
fpizlo@apple.comf45e88b2013-01-20 19:29:50 +00001455 InsertionSet m_insertionSet;
fpizlo@apple.combbaf6192013-02-27 01:45:28 +00001456 bool m_profitabilityChanged;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001457};
1458
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001459bool performFixup(Graph& graph)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001460{
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00001461 SamplingRegion samplingRegion("DFG Fixup Phase");
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +00001462 return runPhase<FixupPhase>(graph);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001463}
1464
1465} } // namespace JSC::DFG
1466
1467#endif // ENABLE(DFG_JIT)
1468