]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGFixupPhase.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / dfg / DFGFixupPhase.cpp
1 /*
2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "DFGFixupPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "DFGInsertionSet.h"
33 #include "DFGPhase.h"
34 #include "DFGPredictionPropagationPhase.h"
35 #include "DFGVariableAccessDataDump.h"
36 #include "JSCInlines.h"
37
38 namespace JSC { namespace DFG {
39
40 class FixupPhase : public Phase {
41 public:
42 FixupPhase(Graph& graph)
43 : Phase(graph, "fixup")
44 , m_insertionSet(graph)
45 {
46 }
47
48 bool run()
49 {
50 ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
51 ASSERT(m_graph.m_form == ThreadedCPS);
52
53 m_profitabilityChanged = false;
54 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
55 fixupBlock(m_graph.block(blockIndex));
56
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.numBlocks(); ++blockIndex)
64 fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex));
65 }
66
67 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
68 injectTypeConversionsInBlock(m_graph.block(blockIndex));
69
70 return true;
71 }
72
73 private:
74 void fixupBlock(BasicBlock* block)
75 {
76 if (!block)
77 return;
78 ASSERT(block->isReachable);
79 m_block = block;
80 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
81 m_currentNode = block->at(m_indexInBlock);
82 addPhantomsIfNecessary();
83 fixupNode(m_currentNode);
84 }
85 clearPhantomsAtEnd();
86 m_insertionSet.execute(block);
87 }
88
89 void fixupNode(Node* node)
90 {
91 NodeType op = node->op();
92
93 switch (op) {
94 case SetLocal: {
95 // This gets handled by fixupSetLocalsInBlock().
96 return;
97 }
98
99 case BitAnd:
100 case BitOr:
101 case BitXor:
102 case BitRShift:
103 case BitLShift:
104 case BitURShift: {
105 fixIntConvertingEdge(node->child1());
106 fixIntConvertingEdge(node->child2());
107 break;
108 }
109
110 case ArithIMul: {
111 fixIntConvertingEdge(node->child1());
112 fixIntConvertingEdge(node->child2());
113 node->setOp(ArithMul);
114 node->setArithMode(Arith::Unchecked);
115 node->child1().setUseKind(Int32Use);
116 node->child2().setUseKind(Int32Use);
117 break;
118 }
119
120 case UInt32ToNumber: {
121 fixIntConvertingEdge(node->child1());
122 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
123 node->convertToIdentity();
124 else if (node->canSpeculateInt32(FixupPass))
125 node->setArithMode(Arith::CheckOverflow);
126 else {
127 node->setArithMode(Arith::DoOverflow);
128 node->setResult(NodeResultDouble);
129 }
130 break;
131 }
132
133 case ValueAdd: {
134 if (attemptToMakeIntegerAdd(node)) {
135 node->setOp(ArithAdd);
136 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
137 break;
138 }
139 if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
140 fixDoubleOrBooleanEdge(node->child1());
141 fixDoubleOrBooleanEdge(node->child2());
142 node->setOp(ArithAdd);
143 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
144 node->setResult(NodeResultDouble);
145 break;
146 }
147
148 // FIXME: Optimize for the case where one of the operands is the
149 // empty string. Also consider optimizing for the case where we don't
150 // believe either side is the emtpy string. Both of these things should
151 // be easy.
152
153 if (node->child1()->shouldSpeculateString()
154 && attemptToMakeFastStringAdd<StringUse>(node, node->child1(), node->child2()))
155 break;
156 if (node->child2()->shouldSpeculateString()
157 && attemptToMakeFastStringAdd<StringUse>(node, node->child2(), node->child1()))
158 break;
159 if (node->child1()->shouldSpeculateStringObject()
160 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child1(), node->child2()))
161 break;
162 if (node->child2()->shouldSpeculateStringObject()
163 && attemptToMakeFastStringAdd<StringObjectUse>(node, node->child2(), node->child1()))
164 break;
165 if (node->child1()->shouldSpeculateStringOrStringObject()
166 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child1(), node->child2()))
167 break;
168 if (node->child2()->shouldSpeculateStringOrStringObject()
169 && attemptToMakeFastStringAdd<StringOrStringObjectUse>(node, node->child2(), node->child1()))
170 break;
171 break;
172 }
173
174 case MakeRope: {
175 fixupMakeRope(node);
176 break;
177 }
178
179 case ArithAdd:
180 case ArithSub: {
181 if (attemptToMakeIntegerAdd(node))
182 break;
183 fixDoubleOrBooleanEdge(node->child1());
184 fixDoubleOrBooleanEdge(node->child2());
185 node->setResult(NodeResultDouble);
186 break;
187 }
188
189 case ArithNegate: {
190 if (m_graph.negateShouldSpeculateInt32(node, FixupPass)) {
191 fixIntOrBooleanEdge(node->child1());
192 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
193 node->setArithMode(Arith::Unchecked);
194 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
195 node->setArithMode(Arith::CheckOverflow);
196 else
197 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
198 break;
199 }
200 if (m_graph.negateShouldSpeculateMachineInt(node, FixupPass)) {
201 fixEdge<Int52RepUse>(node->child1());
202 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
203 node->setArithMode(Arith::CheckOverflow);
204 else
205 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
206 node->setResult(NodeResultInt52);
207 break;
208 }
209 fixDoubleOrBooleanEdge(node->child1());
210 node->setResult(NodeResultDouble);
211 break;
212 }
213
214 case ArithMul: {
215 if (m_graph.mulShouldSpeculateInt32(node, FixupPass)) {
216 fixIntOrBooleanEdge(node->child1());
217 fixIntOrBooleanEdge(node->child2());
218 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
219 node->setArithMode(Arith::Unchecked);
220 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
221 node->setArithMode(Arith::CheckOverflow);
222 else
223 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
224 break;
225 }
226 if (m_graph.mulShouldSpeculateMachineInt(node, FixupPass)) {
227 fixEdge<Int52RepUse>(node->child1());
228 fixEdge<Int52RepUse>(node->child2());
229 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
230 node->setArithMode(Arith::CheckOverflow);
231 else
232 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
233 node->setResult(NodeResultInt52);
234 break;
235 }
236 fixDoubleOrBooleanEdge(node->child1());
237 fixDoubleOrBooleanEdge(node->child2());
238 node->setResult(NodeResultDouble);
239 break;
240 }
241
242 case ArithDiv:
243 case ArithMod: {
244 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
245 && node->canSpeculateInt32(FixupPass)) {
246 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
247 fixIntOrBooleanEdge(node->child1());
248 fixIntOrBooleanEdge(node->child2());
249 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
250 node->setArithMode(Arith::Unchecked);
251 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
252 node->setArithMode(Arith::CheckOverflow);
253 else
254 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
255 break;
256 }
257
258 // This will cause conversion nodes to be inserted later.
259 fixDoubleOrBooleanEdge(node->child1());
260 fixDoubleOrBooleanEdge(node->child2());
261
262 // But we have to make sure that everything is phantom'd until after the
263 // DoubleAsInt32 node, which occurs after the Div/Mod node that the conversions
264 // will be insered on.
265 addRequiredPhantom(node->child1().node());
266 addRequiredPhantom(node->child2().node());
267
268 // We don't need to do ref'ing on the children because we're stealing them from
269 // the original division.
270 Node* newDivision = m_insertionSet.insertNode(
271 m_indexInBlock, SpecBytecodeDouble, *node);
272 newDivision->setResult(NodeResultDouble);
273
274 node->setOp(DoubleAsInt32);
275 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
276 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
277 node->setArithMode(Arith::CheckOverflow);
278 else
279 node->setArithMode(Arith::CheckOverflowAndNegativeZero);
280 break;
281 }
282 fixDoubleOrBooleanEdge(node->child1());
283 fixDoubleOrBooleanEdge(node->child2());
284 node->setResult(NodeResultDouble);
285 break;
286 }
287
288 case ArithMin:
289 case ArithMax: {
290 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
291 && node->canSpeculateInt32(FixupPass)) {
292 fixIntOrBooleanEdge(node->child1());
293 fixIntOrBooleanEdge(node->child2());
294 break;
295 }
296 fixDoubleOrBooleanEdge(node->child1());
297 fixDoubleOrBooleanEdge(node->child2());
298 node->setResult(NodeResultDouble);
299 break;
300 }
301
302 case ArithAbs: {
303 if (node->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
304 && node->canSpeculateInt32(FixupPass)) {
305 fixIntOrBooleanEdge(node->child1());
306 break;
307 }
308 fixDoubleOrBooleanEdge(node->child1());
309 node->setResult(NodeResultDouble);
310 break;
311 }
312
313 case ArithSqrt:
314 case ArithFRound:
315 case ArithSin:
316 case ArithCos: {
317 fixDoubleOrBooleanEdge(node->child1());
318 node->setResult(NodeResultDouble);
319 break;
320 }
321
322 case LogicalNot: {
323 if (node->child1()->shouldSpeculateBoolean())
324 fixEdge<BooleanUse>(node->child1());
325 else if (node->child1()->shouldSpeculateObjectOrOther())
326 fixEdge<ObjectOrOtherUse>(node->child1());
327 else if (node->child1()->shouldSpeculateInt32OrBoolean())
328 fixIntOrBooleanEdge(node->child1());
329 else if (node->child1()->shouldSpeculateNumber())
330 fixEdge<DoubleRepUse>(node->child1());
331 else if (node->child1()->shouldSpeculateString())
332 fixEdge<StringUse>(node->child1());
333 break;
334 }
335
336 case TypeOf: {
337 if (node->child1()->shouldSpeculateString())
338 fixEdge<StringUse>(node->child1());
339 else if (node->child1()->shouldSpeculateCell())
340 fixEdge<CellUse>(node->child1());
341 break;
342 }
343
344 case CompareEqConstant: {
345 break;
346 }
347
348 case CompareEq:
349 case CompareLess:
350 case CompareLessEq:
351 case CompareGreater:
352 case CompareGreaterEq: {
353 if (node->op() == CompareEq
354 && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
355 fixEdge<BooleanUse>(node->child1());
356 fixEdge<BooleanUse>(node->child2());
357 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
358 break;
359 }
360 if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
361 fixIntOrBooleanEdge(node->child1());
362 fixIntOrBooleanEdge(node->child2());
363 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
364 break;
365 }
366 if (enableInt52()
367 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
368 fixEdge<Int52RepUse>(node->child1());
369 fixEdge<Int52RepUse>(node->child2());
370 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
371 break;
372 }
373 if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
374 fixDoubleOrBooleanEdge(node->child1());
375 fixDoubleOrBooleanEdge(node->child2());
376 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
377 break;
378 }
379 if (node->op() != CompareEq)
380 break;
381 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
382 fixEdge<StringIdentUse>(node->child1());
383 fixEdge<StringIdentUse>(node->child2());
384 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
385 break;
386 }
387 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
388 fixEdge<StringUse>(node->child1());
389 fixEdge<StringUse>(node->child2());
390 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
391 break;
392 }
393 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
394 fixEdge<ObjectUse>(node->child1());
395 fixEdge<ObjectUse>(node->child2());
396 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
397 break;
398 }
399 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
400 fixEdge<ObjectUse>(node->child1());
401 fixEdge<ObjectOrOtherUse>(node->child2());
402 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
403 break;
404 }
405 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
406 fixEdge<ObjectOrOtherUse>(node->child1());
407 fixEdge<ObjectUse>(node->child2());
408 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
409 break;
410 }
411 break;
412 }
413
414 case CompareStrictEq: {
415 if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
416 fixEdge<BooleanUse>(node->child1());
417 fixEdge<BooleanUse>(node->child2());
418 break;
419 }
420 if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
421 fixEdge<Int32Use>(node->child1());
422 fixEdge<Int32Use>(node->child2());
423 break;
424 }
425 if (enableInt52()
426 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
427 fixEdge<Int52RepUse>(node->child1());
428 fixEdge<Int52RepUse>(node->child2());
429 break;
430 }
431 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
432 fixEdge<DoubleRepUse>(node->child1());
433 fixEdge<DoubleRepUse>(node->child2());
434 break;
435 }
436 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
437 fixEdge<StringIdentUse>(node->child1());
438 fixEdge<StringIdentUse>(node->child2());
439 break;
440 }
441 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && (GPRInfo::numberOfRegisters >= 7 || isFTL(m_graph.m_plan.mode))) {
442 fixEdge<StringUse>(node->child1());
443 fixEdge<StringUse>(node->child2());
444 break;
445 }
446 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
447 fixEdge<ObjectUse>(node->child1());
448 fixEdge<ObjectUse>(node->child2());
449 break;
450 }
451 if (node->child1()->shouldSpeculateMisc()) {
452 fixEdge<MiscUse>(node->child1());
453 break;
454 }
455 if (node->child2()->shouldSpeculateMisc()) {
456 fixEdge<MiscUse>(node->child2());
457 break;
458 }
459 if (node->child1()->shouldSpeculateStringIdent()
460 && node->child2()->shouldSpeculateNotStringVar()) {
461 fixEdge<StringIdentUse>(node->child1());
462 fixEdge<NotStringVarUse>(node->child2());
463 break;
464 }
465 if (node->child2()->shouldSpeculateStringIdent()
466 && node->child1()->shouldSpeculateNotStringVar()) {
467 fixEdge<StringIdentUse>(node->child2());
468 fixEdge<NotStringVarUse>(node->child1());
469 break;
470 }
471 if (node->child1()->shouldSpeculateString() && (GPRInfo::numberOfRegisters >= 8 || isFTL(m_graph.m_plan.mode))) {
472 fixEdge<StringUse>(node->child1());
473 break;
474 }
475 if (node->child2()->shouldSpeculateString() && (GPRInfo::numberOfRegisters >= 8 || isFTL(m_graph.m_plan.mode))) {
476 fixEdge<StringUse>(node->child2());
477 break;
478 }
479 break;
480 }
481
482 case StringFromCharCode:
483 fixEdge<Int32Use>(node->child1());
484 break;
485
486 case StringCharAt:
487 case StringCharCodeAt: {
488 // Currently we have no good way of refining these.
489 ASSERT(node->arrayMode() == ArrayMode(Array::String));
490 blessArrayOperation(node->child1(), node->child2(), node->child3());
491 fixEdge<KnownCellUse>(node->child1());
492 fixEdge<Int32Use>(node->child2());
493 break;
494 }
495
496 case GetByVal: {
497 node->setArrayMode(
498 node->arrayMode().refine(
499 m_graph, node,
500 node->child1()->prediction(),
501 node->child2()->prediction(),
502 SpecNone, node->flags()));
503
504 blessArrayOperation(node->child1(), node->child2(), node->child3());
505
506 ArrayMode arrayMode = node->arrayMode();
507 switch (arrayMode.type()) {
508 case Array::Double:
509 if (arrayMode.arrayClass() == Array::OriginalArray
510 && arrayMode.speculation() == Array::InBounds
511 && m_graph.globalObjectFor(node->origin.semantic)->arrayPrototypeChainIsSane()
512 && !(node->flags() & NodeBytecodeUsesAsOther))
513 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
514 break;
515
516 case Array::String:
517 if ((node->prediction() & ~SpecString)
518 || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
519 node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
520 break;
521
522 default:
523 break;
524 }
525
526 arrayMode = node->arrayMode();
527 switch (arrayMode.type()) {
528 case Array::SelectUsingPredictions:
529 case Array::Unprofiled:
530 case Array::Undecided:
531 RELEASE_ASSERT_NOT_REACHED();
532 break;
533 case Array::Generic:
534 #if USE(JSVALUE32_64)
535 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
536 #endif
537 break;
538 case Array::ForceExit:
539 break;
540 default:
541 fixEdge<KnownCellUse>(node->child1());
542 fixEdge<Int32Use>(node->child2());
543 break;
544 }
545
546 switch (arrayMode.type()) {
547 case Array::Double:
548 if (!arrayMode.isOutOfBounds())
549 node->setResult(NodeResultDouble);
550 break;
551
552 case Array::Float32Array:
553 case Array::Float64Array:
554 node->setResult(NodeResultDouble);
555 break;
556
557 case Array::Uint32Array:
558 if (node->shouldSpeculateInt32())
559 break;
560 if (node->shouldSpeculateMachineInt() && enableInt52())
561 node->setResult(NodeResultInt52);
562 else
563 node->setResult(NodeResultDouble);
564 break;
565
566 default:
567 break;
568 }
569
570 break;
571 }
572
573 case PutByValDirect:
574 case PutByVal:
575 case PutByValAlias: {
576 Edge& child1 = m_graph.varArgChild(node, 0);
577 Edge& child2 = m_graph.varArgChild(node, 1);
578 Edge& child3 = m_graph.varArgChild(node, 2);
579
580 node->setArrayMode(
581 node->arrayMode().refine(
582 m_graph, node,
583 child1->prediction(),
584 child2->prediction(),
585 child3->prediction()));
586
587 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
588
589 switch (node->arrayMode().modeForPut().type()) {
590 case Array::SelectUsingPredictions:
591 case Array::Unprofiled:
592 case Array::Undecided:
593 RELEASE_ASSERT_NOT_REACHED();
594 break;
595 case Array::ForceExit:
596 case Array::Generic:
597 #if USE(JSVALUE32_64)
598 // Due to register pressure on 32-bit, we speculate cell and
599 // ignore the base-is-not-cell case entirely by letting the
600 // baseline JIT handle it.
601 fixEdge<CellUse>(child1);
602 #endif
603 break;
604 case Array::Int32:
605 fixEdge<KnownCellUse>(child1);
606 fixEdge<Int32Use>(child2);
607 fixEdge<Int32Use>(child3);
608 break;
609 case Array::Double:
610 fixEdge<KnownCellUse>(child1);
611 fixEdge<Int32Use>(child2);
612 fixEdge<DoubleRepRealUse>(child3);
613 break;
614 case Array::Int8Array:
615 case Array::Int16Array:
616 case Array::Int32Array:
617 case Array::Uint8Array:
618 case Array::Uint8ClampedArray:
619 case Array::Uint16Array:
620 case Array::Uint32Array:
621 fixEdge<KnownCellUse>(child1);
622 fixEdge<Int32Use>(child2);
623 if (child3->shouldSpeculateInt32())
624 fixIntOrBooleanEdge(child3);
625 else if (child3->shouldSpeculateMachineInt())
626 fixEdge<Int52RepUse>(child3);
627 else
628 fixDoubleOrBooleanEdge(child3);
629 break;
630 case Array::Float32Array:
631 case Array::Float64Array:
632 fixEdge<KnownCellUse>(child1);
633 fixEdge<Int32Use>(child2);
634 fixDoubleOrBooleanEdge(child3);
635 break;
636 case Array::Contiguous:
637 case Array::ArrayStorage:
638 case Array::SlowPutArrayStorage:
639 case Array::Arguments:
640 fixEdge<KnownCellUse>(child1);
641 fixEdge<Int32Use>(child2);
642 insertStoreBarrier(m_indexInBlock, child1);
643 break;
644 default:
645 fixEdge<KnownCellUse>(child1);
646 fixEdge<Int32Use>(child2);
647 break;
648 }
649 break;
650 }
651
652 case ArrayPush: {
653 // May need to refine the array mode in case the value prediction contravenes
654 // the array prediction. For example, we may have evidence showing that the
655 // array is in Int32 mode, but the value we're storing is likely to be a double.
656 // Then we should turn this into a conversion to Double array followed by the
657 // push. On the other hand, we absolutely don't want to refine based on the
658 // base prediction. If it has non-cell garbage in it, then we want that to be
659 // ignored. That's because ArrayPush can't handle any array modes that aren't
660 // array-related - so if refine() turned this into a "Generic" ArrayPush then
661 // that would break things.
662 node->setArrayMode(
663 node->arrayMode().refine(
664 m_graph, node,
665 node->child1()->prediction() & SpecCell,
666 SpecInt32,
667 node->child2()->prediction()));
668 blessArrayOperation(node->child1(), Edge(), node->child3());
669 fixEdge<KnownCellUse>(node->child1());
670
671 switch (node->arrayMode().type()) {
672 case Array::Int32:
673 fixEdge<Int32Use>(node->child2());
674 break;
675 case Array::Double:
676 fixEdge<DoubleRepRealUse>(node->child2());
677 break;
678 case Array::Contiguous:
679 case Array::ArrayStorage:
680 insertStoreBarrier(m_indexInBlock, node->child1());
681 break;
682 default:
683 break;
684 }
685 break;
686 }
687
688 case ArrayPop: {
689 blessArrayOperation(node->child1(), Edge(), node->child2());
690 fixEdge<KnownCellUse>(node->child1());
691 break;
692 }
693
694 case RegExpExec:
695 case RegExpTest: {
696 fixEdge<CellUse>(node->child1());
697 fixEdge<CellUse>(node->child2());
698 break;
699 }
700
701 case Branch: {
702 if (node->child1()->shouldSpeculateBoolean())
703 fixEdge<BooleanUse>(node->child1());
704 else if (node->child1()->shouldSpeculateObjectOrOther())
705 fixEdge<ObjectOrOtherUse>(node->child1());
706 // FIXME: We should just be able to do shouldSpeculateInt32OrBoolean() and
707 // shouldSpeculateNumberOrBoolean() here, but we can't because then the Branch
708 // could speculate on the result of a non-speculative conversion node.
709 // https://bugs.webkit.org/show_bug.cgi?id=126778
710 else if (node->child1()->shouldSpeculateInt32())
711 fixEdge<Int32Use>(node->child1());
712 else if (node->child1()->shouldSpeculateNumber())
713 fixEdge<DoubleRepUse>(node->child1());
714
715 Node* logicalNot = node->child1().node();
716 if (logicalNot->op() == LogicalNot) {
717
718 // Make sure that OSR exit can't observe the LogicalNot. If it can,
719 // then we must compute it and cannot peephole around it.
720 bool found = false;
721 bool ok = true;
722 for (unsigned i = m_indexInBlock; i--;) {
723 Node* candidate = m_block->at(i);
724 if (candidate == logicalNot) {
725 found = true;
726 break;
727 }
728 if (candidate->canExit()) {
729 ok = false;
730 found = true;
731 break;
732 }
733 }
734 ASSERT_UNUSED(found, found);
735
736 if (ok) {
737 Edge newChildEdge = logicalNot->child1();
738 if (newChildEdge->hasBooleanResult()) {
739 node->children.setChild1(newChildEdge);
740
741 BranchData* data = node->branchData();
742 std::swap(data->taken, data->notTaken);
743 }
744 }
745 }
746 break;
747 }
748
749 case Switch: {
750 SwitchData* data = node->switchData();
751 switch (data->kind) {
752 case SwitchImm:
753 if (node->child1()->shouldSpeculateInt32())
754 fixEdge<Int32Use>(node->child1());
755 break;
756 case SwitchChar:
757 if (node->child1()->shouldSpeculateString())
758 fixEdge<StringUse>(node->child1());
759 break;
760 case SwitchString:
761 if (node->child1()->shouldSpeculateStringIdent())
762 fixEdge<StringIdentUse>(node->child1());
763 else if (node->child1()->shouldSpeculateString())
764 fixEdge<StringUse>(node->child1());
765 break;
766 }
767 break;
768 }
769
770 case ToPrimitive: {
771 fixupToPrimitive(node);
772 break;
773 }
774
775 case ToString: {
776 fixupToString(node);
777 break;
778 }
779
780 case NewStringObject: {
781 fixEdge<KnownStringUse>(node->child1());
782 break;
783 }
784
785 case NewArray: {
786 for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
787 node->setIndexingType(
788 leastUpperBoundOfIndexingTypeAndType(
789 node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
790 }
791 switch (node->indexingType()) {
792 case ALL_BLANK_INDEXING_TYPES:
793 CRASH();
794 break;
795 case ALL_UNDECIDED_INDEXING_TYPES:
796 if (node->numChildren()) {
797 // This will only happen if the children have no type predictions. We
798 // would have already exited by now, but insert a forced exit just to
799 // be safe.
800 m_insertionSet.insertNode(
801 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
802 }
803 break;
804 case ALL_INT32_INDEXING_TYPES:
805 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
806 fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
807 break;
808 case ALL_DOUBLE_INDEXING_TYPES:
809 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
810 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
811 break;
812 case ALL_CONTIGUOUS_INDEXING_TYPES:
813 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
814 break;
815 default:
816 CRASH();
817 break;
818 }
819 break;
820 }
821
822 case NewTypedArray: {
823 if (node->child1()->shouldSpeculateInt32()) {
824 fixEdge<Int32Use>(node->child1());
825 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
826 break;
827 }
828 break;
829 }
830
831 case NewArrayWithSize: {
832 fixEdge<Int32Use>(node->child1());
833 break;
834 }
835
836 case ToThis: {
837 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
838
839 if (node->child1()->shouldSpeculateOther()) {
840 if (ecmaMode == StrictMode) {
841 fixEdge<OtherUse>(node->child1());
842 node->convertToIdentity();
843 break;
844 }
845
846 m_insertionSet.insertNode(
847 m_indexInBlock, SpecNone, Phantom, node->origin,
848 Edge(node->child1().node(), OtherUse));
849 observeUseKindOnNode<OtherUse>(node->child1().node());
850 node->convertToWeakConstant(m_graph.globalThisObjectFor(node->origin.semantic));
851 break;
852 }
853
854 if (isFinalObjectSpeculation(node->child1()->prediction())) {
855 fixEdge<FinalObjectUse>(node->child1());
856 node->convertToIdentity();
857 break;
858 }
859
860 break;
861 }
862
863 case GetMyArgumentByVal:
864 case GetMyArgumentByValSafe: {
865 fixEdge<Int32Use>(node->child1());
866 break;
867 }
868
869 case PutStructure: {
870 fixEdge<KnownCellUse>(node->child1());
871 insertStoreBarrier(m_indexInBlock, node->child1());
872 break;
873 }
874
875 case PutClosureVar: {
876 fixEdge<KnownCellUse>(node->child1());
877 insertStoreBarrier(m_indexInBlock, node->child1());
878 break;
879 }
880
881 case GetClosureRegisters:
882 case SkipTopScope:
883 case SkipScope:
884 case GetScope: {
885 fixEdge<KnownCellUse>(node->child1());
886 break;
887 }
888
889 case AllocatePropertyStorage:
890 case ReallocatePropertyStorage: {
891 fixEdge<KnownCellUse>(node->child1());
892 insertStoreBarrier(m_indexInBlock + 1, node->child1());
893 break;
894 }
895
896 case GetById:
897 case GetByIdFlush: {
898 if (!node->child1()->shouldSpeculateCell())
899 break;
900 StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
901 if (impl == vm().propertyNames->length.impl()) {
902 attemptToMakeGetArrayLength(node);
903 break;
904 }
905 if (impl == vm().propertyNames->byteLength.impl()) {
906 attemptToMakeGetTypedArrayByteLength(node);
907 break;
908 }
909 if (impl == vm().propertyNames->byteOffset.impl()) {
910 attemptToMakeGetTypedArrayByteOffset(node);
911 break;
912 }
913 fixEdge<CellUse>(node->child1());
914 break;
915 }
916
917 case PutById:
918 case PutByIdFlush:
919 case PutByIdDirect: {
920 fixEdge<CellUse>(node->child1());
921 insertStoreBarrier(m_indexInBlock, node->child1());
922 break;
923 }
924
925 case CheckExecutable:
926 case CheckStructure:
927 case StructureTransitionWatchpoint:
928 case CheckFunction:
929 case CheckHasInstance:
930 case CreateThis:
931 case GetButterfly: {
932 fixEdge<CellUse>(node->child1());
933 break;
934 }
935
936 case Arrayify:
937 case ArrayifyToStructure: {
938 fixEdge<CellUse>(node->child1());
939 if (node->child2())
940 fixEdge<Int32Use>(node->child2());
941 break;
942 }
943
944 case GetByOffset: {
945 if (!node->child1()->hasStorageResult())
946 fixEdge<KnownCellUse>(node->child1());
947 fixEdge<KnownCellUse>(node->child2());
948 break;
949 }
950
951 case MultiGetByOffset: {
952 fixEdge<CellUse>(node->child1());
953 break;
954 }
955
956 case PutByOffset: {
957 if (!node->child1()->hasStorageResult())
958 fixEdge<KnownCellUse>(node->child1());
959 fixEdge<KnownCellUse>(node->child2());
960 insertStoreBarrier(m_indexInBlock, node->child2());
961 break;
962 }
963
964 case MultiPutByOffset: {
965 fixEdge<CellUse>(node->child1());
966 insertStoreBarrier(m_indexInBlock, node->child1());
967 break;
968 }
969
970 case InstanceOf: {
971 if (!(node->child1()->prediction() & ~SpecCell))
972 fixEdge<CellUse>(node->child1());
973 fixEdge<CellUse>(node->child2());
974 break;
975 }
976
977 case In: {
978 // FIXME: We should at some point have array profiling on op_in, in which
979 // case we would be able to turn this into a kind of GetByVal.
980
981 fixEdge<CellUse>(node->child2());
982 break;
983 }
984
985 case Phantom:
986 case Check: {
987 switch (node->child1().useKind()) {
988 case NumberUse:
989 if (node->child1()->shouldSpeculateInt32ForArithmetic())
990 node->child1().setUseKind(Int32Use);
991 break;
992 default:
993 break;
994 }
995 observeUseKindOnEdge(node->child1());
996 break;
997 }
998
999 case FiatInt52: {
1000 RELEASE_ASSERT(enableInt52());
1001 node->convertToIdentity();
1002 fixEdge<Int52RepUse>(node->child1());
1003 node->setResult(NodeResultInt52);
1004 break;
1005 }
1006
1007 case GetArrayLength:
1008 case Phi:
1009 case Upsilon:
1010 case GetArgument:
1011 case PhantomPutStructure:
1012 case GetIndexedPropertyStorage:
1013 case GetTypedArrayByteOffset:
1014 case LastNodeType:
1015 case CheckTierUpInLoop:
1016 case CheckTierUpAtReturn:
1017 case CheckTierUpAndOSREnter:
1018 case InvalidationPoint:
1019 case CheckArray:
1020 case CheckInBounds:
1021 case ConstantStoragePointer:
1022 case DoubleAsInt32:
1023 case ValueToInt32:
1024 case HardPhantom: // HardPhantom would be trivial to handle but anyway we assert that we won't see it here yet.
1025 case DoubleRep:
1026 case ValueRep:
1027 case Int52Rep:
1028 case DoubleConstant:
1029 case Int52Constant:
1030 case Identity: // This should have been cleaned up.
1031 case BooleanToNumber:
1032 // These are just nodes that we don't currently expect to see during fixup.
1033 // If we ever wanted to insert them prior to fixup, then we just have to create
1034 // fixup rules for them.
1035 RELEASE_ASSERT_NOT_REACHED();
1036 break;
1037
1038 case PutGlobalVar: {
1039 Node* globalObjectNode = m_insertionSet.insertNode(
1040 m_indexInBlock, SpecNone, WeakJSConstant, node->origin,
1041 OpInfo(m_graph.globalObjectFor(node->origin.semantic)));
1042 Node* barrierNode = m_graph.addNode(
1043 SpecNone, StoreBarrier, m_currentNode->origin,
1044 Edge(globalObjectNode, KnownCellUse));
1045 m_insertionSet.insert(m_indexInBlock, barrierNode);
1046 break;
1047 }
1048
1049 case TearOffActivation: {
1050 Node* barrierNode = m_graph.addNode(
1051 SpecNone, StoreBarrierWithNullCheck, m_currentNode->origin,
1052 Edge(node->child1().node(), UntypedUse));
1053 m_insertionSet.insert(m_indexInBlock, barrierNode);
1054 break;
1055 }
1056
1057 case IsString:
1058 if (node->child1()->shouldSpeculateString()) {
1059 m_insertionSet.insertNode(
1060 m_indexInBlock, SpecNone, Phantom, node->origin,
1061 Edge(node->child1().node(), StringUse));
1062 m_graph.convertToConstant(node, jsBoolean(true));
1063 observeUseKindOnNode<StringUse>(node);
1064 }
1065 break;
1066
1067 #if !ASSERT_DISABLED
1068 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
1069 case SetArgument:
1070 case JSConstant:
1071 case WeakJSConstant:
1072 case GetLocal:
1073 case GetCallee:
1074 case Flush:
1075 case PhantomLocal:
1076 case GetLocalUnlinked:
1077 case GetMyScope:
1078 case GetClosureVar:
1079 case GetGlobalVar:
1080 case NotifyWrite:
1081 case VariableWatchpoint:
1082 case VarInjectionWatchpoint:
1083 case AllocationProfileWatchpoint:
1084 case Call:
1085 case Construct:
1086 case NewObject:
1087 case NewArrayBuffer:
1088 case NewRegexp:
1089 case Breakpoint:
1090 case ProfileWillCall:
1091 case ProfileDidCall:
1092 case IsUndefined:
1093 case IsBoolean:
1094 case IsNumber:
1095 case IsObject:
1096 case IsFunction:
1097 case CreateActivation:
1098 case CreateArguments:
1099 case PhantomArguments:
1100 case TearOffArguments:
1101 case GetMyArgumentsLength:
1102 case GetMyArgumentsLengthSafe:
1103 case CheckArgumentsNotCreated:
1104 case NewFunction:
1105 case NewFunctionNoCheck:
1106 case NewFunctionExpression:
1107 case Jump:
1108 case Return:
1109 case Throw:
1110 case ThrowReferenceError:
1111 case CountExecution:
1112 case ForceOSRExit:
1113 case CheckWatchdogTimer:
1114 case Unreachable:
1115 case ExtractOSREntryLocal:
1116 case LoopHint:
1117 case StoreBarrier:
1118 case StoreBarrierWithNullCheck:
1119 case FunctionReentryWatchpoint:
1120 case TypedArrayWatchpoint:
1121 case MovHint:
1122 case ZombieHint:
1123 break;
1124 #else
1125 default:
1126 break;
1127 #endif
1128 }
1129 }
1130
1131 template<UseKind useKind>
1132 void createToString(Node* node, Edge& edge)
1133 {
1134 edge.setNode(m_insertionSet.insertNode(
1135 m_indexInBlock, SpecString, ToString, node->origin,
1136 Edge(edge.node(), useKind)));
1137 }
1138
1139 template<UseKind useKind>
1140 void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
1141 {
1142 ASSERT(arrayMode == ArrayMode(Array::Generic));
1143
1144 if (!canOptimizeStringObjectAccess(node->origin.semantic))
1145 return;
1146
1147 createToString<useKind>(node, node->child1());
1148 arrayMode = ArrayMode(Array::String);
1149 }
1150
1151 template<UseKind useKind>
1152 bool isStringObjectUse()
1153 {
1154 switch (useKind) {
1155 case StringObjectUse:
1156 case StringOrStringObjectUse:
1157 return true;
1158 default:
1159 return false;
1160 }
1161 }
1162
1163 template<UseKind useKind>
1164 void convertStringAddUse(Node* node, Edge& edge)
1165 {
1166 if (useKind == StringUse) {
1167 // This preserves the binaryUseKind() invariant ot ValueAdd: ValueAdd's
1168 // two edges will always have identical use kinds, which makes the
1169 // decision process much easier.
1170 observeUseKindOnNode<StringUse>(edge.node());
1171 m_insertionSet.insertNode(
1172 m_indexInBlock, SpecNone, Phantom, node->origin,
1173 Edge(edge.node(), StringUse));
1174 edge.setUseKind(KnownStringUse);
1175 return;
1176 }
1177
1178 // FIXME: We ought to be able to have a ToPrimitiveToString node.
1179
1180 observeUseKindOnNode<useKind>(edge.node());
1181 createToString<useKind>(node, edge);
1182 }
1183
1184 void convertToMakeRope(Node* node)
1185 {
1186 node->setOpAndDefaultFlags(MakeRope);
1187 fixupMakeRope(node);
1188 }
1189
1190 void fixupMakeRope(Node* node)
1191 {
1192 for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
1193 Edge& edge = node->children.child(i);
1194 if (!edge)
1195 break;
1196 edge.setUseKind(KnownStringUse);
1197 if (!m_graph.isConstant(edge.node()))
1198 continue;
1199 JSString* string = jsCast<JSString*>(m_graph.valueOfJSConstant(edge.node()).asCell());
1200 if (string->length())
1201 continue;
1202
1203 // Don't allow the MakeRope to have zero children.
1204 if (!i && !node->child2())
1205 break;
1206
1207 node->children.removeEdge(i--);
1208 }
1209
1210 if (!node->child2()) {
1211 ASSERT(!node->child3());
1212 node->convertToIdentity();
1213 }
1214 }
1215
1216 void fixupToPrimitive(Node* node)
1217 {
1218 if (node->child1()->shouldSpeculateInt32()) {
1219 fixEdge<Int32Use>(node->child1());
1220 node->convertToIdentity();
1221 return;
1222 }
1223
1224 if (node->child1()->shouldSpeculateString()) {
1225 fixEdge<StringUse>(node->child1());
1226 node->convertToIdentity();
1227 return;
1228 }
1229
1230 if (node->child1()->shouldSpeculateStringObject()
1231 && canOptimizeStringObjectAccess(node->origin.semantic)) {
1232 fixEdge<StringObjectUse>(node->child1());
1233 node->convertToToString();
1234 return;
1235 }
1236
1237 if (node->child1()->shouldSpeculateStringOrStringObject()
1238 && canOptimizeStringObjectAccess(node->origin.semantic)) {
1239 fixEdge<StringOrStringObjectUse>(node->child1());
1240 node->convertToToString();
1241 return;
1242 }
1243 }
1244
1245 void fixupToString(Node* node)
1246 {
1247 if (node->child1()->shouldSpeculateString()) {
1248 fixEdge<StringUse>(node->child1());
1249 node->convertToIdentity();
1250 return;
1251 }
1252
1253 if (node->child1()->shouldSpeculateStringObject()
1254 && canOptimizeStringObjectAccess(node->origin.semantic)) {
1255 fixEdge<StringObjectUse>(node->child1());
1256 return;
1257 }
1258
1259 if (node->child1()->shouldSpeculateStringOrStringObject()
1260 && canOptimizeStringObjectAccess(node->origin.semantic)) {
1261 fixEdge<StringOrStringObjectUse>(node->child1());
1262 return;
1263 }
1264
1265 if (node->child1()->shouldSpeculateCell()) {
1266 fixEdge<CellUse>(node->child1());
1267 return;
1268 }
1269 }
1270
1271 template<UseKind leftUseKind>
1272 bool attemptToMakeFastStringAdd(Node* node, Edge& left, Edge& right)
1273 {
1274 Node* originalLeft = left.node();
1275 Node* originalRight = right.node();
1276
1277 ASSERT(leftUseKind == StringUse || leftUseKind == StringObjectUse || leftUseKind == StringOrStringObjectUse);
1278
1279 if (isStringObjectUse<leftUseKind>() && !canOptimizeStringObjectAccess(node->origin.semantic))
1280 return false;
1281
1282 convertStringAddUse<leftUseKind>(node, left);
1283
1284 if (right->shouldSpeculateString())
1285 convertStringAddUse<StringUse>(node, right);
1286 else if (right->shouldSpeculateStringObject() && canOptimizeStringObjectAccess(node->origin.semantic))
1287 convertStringAddUse<StringObjectUse>(node, right);
1288 else if (right->shouldSpeculateStringOrStringObject() && canOptimizeStringObjectAccess(node->origin.semantic))
1289 convertStringAddUse<StringOrStringObjectUse>(node, right);
1290 else {
1291 // At this point we know that the other operand is something weird. The semantically correct
1292 // way of dealing with this is:
1293 //
1294 // MakeRope(@left, ToString(ToPrimitive(@right)))
1295 //
1296 // So that's what we emit. NB, we need to do all relevant type checks on @left before we do
1297 // anything to @right, since ToPrimitive may be effectful.
1298
1299 Node* toPrimitive = m_insertionSet.insertNode(
1300 m_indexInBlock, resultOfToPrimitive(right->prediction()), ToPrimitive,
1301 node->origin, Edge(right.node()));
1302 Node* toString = m_insertionSet.insertNode(
1303 m_indexInBlock, SpecString, ToString, node->origin, Edge(toPrimitive));
1304
1305 fixupToPrimitive(toPrimitive);
1306 fixupToString(toString);
1307
1308 right.setNode(toString);
1309 }
1310
1311 // We're doing checks up there, so we need to make sure that the
1312 // *original* inputs to the addition are live up to here.
1313 m_insertionSet.insertNode(
1314 m_indexInBlock, SpecNone, Phantom, node->origin,
1315 Edge(originalLeft), Edge(originalRight));
1316
1317 convertToMakeRope(node);
1318 return true;
1319 }
1320
1321 bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
1322 {
1323 unsigned attributesUnused;
1324 JSCell* specificValue;
1325 PropertyOffset offset = stringPrototypeStructure->getConcurrently(
1326 vm(), uid, attributesUnused, specificValue);
1327 if (!isValidOffset(offset))
1328 return false;
1329
1330 if (!specificValue)
1331 return false;
1332
1333 if (!specificValue->inherits(JSFunction::info()))
1334 return false;
1335
1336 JSFunction* function = jsCast<JSFunction*>(specificValue);
1337 if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
1338 return false;
1339
1340 return true;
1341 }
1342
1343 bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
1344 {
1345 if (m_graph.hasExitSite(codeOrigin, NotStringObject))
1346 return false;
1347
1348 Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
1349 ASSERT(stringObjectStructure->storedPrototype().isObject());
1350 ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == StringPrototype::info());
1351
1352 JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
1353 Structure* stringPrototypeStructure = stringPrototypeObject->structure();
1354 if (!m_graph.watchpoints().isStillValid(stringPrototypeStructure->transitionWatchpointSet()))
1355 return false;
1356
1357 if (stringPrototypeStructure->isDictionary())
1358 return false;
1359
1360 // We're being conservative here. We want DFG's ToString on StringObject to be
1361 // used in both numeric contexts (that would call valueOf()) and string contexts
1362 // (that would call toString()). We don't want the DFG to have to distinguish
1363 // between the two, just because that seems like it would get confusing. So we
1364 // just require both methods to be sane.
1365 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
1366 return false;
1367 if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
1368 return false;
1369
1370 return true;
1371 }
1372
1373 void fixupGetAndSetLocalsInBlock(BasicBlock* block)
1374 {
1375 if (!block)
1376 return;
1377 ASSERT(block->isReachable);
1378 m_block = block;
1379 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1380 Node* node = m_currentNode = block->at(m_indexInBlock);
1381 if (node->op() != SetLocal && node->op() != GetLocal)
1382 continue;
1383
1384 VariableAccessData* variable = node->variableAccessData();
1385 switch (node->op()) {
1386 case GetLocal:
1387 switch (variable->flushFormat()) {
1388 case FlushedDouble:
1389 node->setResult(NodeResultDouble);
1390 break;
1391 case FlushedInt52:
1392 node->setResult(NodeResultInt52);
1393 break;
1394 default:
1395 break;
1396 }
1397 break;
1398
1399 case SetLocal:
1400 switch (variable->flushFormat()) {
1401 case FlushedJSValue:
1402 break;
1403 case FlushedDouble:
1404 fixEdge<DoubleRepUse>(node->child1());
1405 break;
1406 case FlushedInt32:
1407 fixEdge<Int32Use>(node->child1());
1408 break;
1409 case FlushedInt52:
1410 fixEdge<Int52RepUse>(node->child1());
1411 break;
1412 case FlushedCell:
1413 fixEdge<CellUse>(node->child1());
1414 break;
1415 case FlushedBoolean:
1416 fixEdge<BooleanUse>(node->child1());
1417 break;
1418 default:
1419 RELEASE_ASSERT_NOT_REACHED();
1420 break;
1421 }
1422 break;
1423
1424 default:
1425 RELEASE_ASSERT_NOT_REACHED();
1426 break;
1427 }
1428 }
1429 m_insertionSet.execute(block);
1430 }
1431
1432 Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
1433 {
1434 ASSERT(arrayMode.isSpecific());
1435
1436 if (arrayMode.type() == Array::String) {
1437 m_insertionSet.insertNode(
1438 m_indexInBlock, SpecNone, Phantom, origin, Edge(array, StringUse));
1439 } else {
1440 Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
1441
1442 Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
1443
1444 if (arrayMode.doesConversion()) {
1445 if (structure) {
1446 m_insertionSet.insertNode(
1447 m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
1448 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1449 } else {
1450 m_insertionSet.insertNode(
1451 m_indexInBlock, SpecNone, Arrayify, origin,
1452 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
1453 }
1454 } else {
1455 if (structure) {
1456 m_insertionSet.insertNode(
1457 m_indexInBlock, SpecNone, CheckStructure, origin,
1458 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
1459 } else {
1460 m_insertionSet.insertNode(
1461 m_indexInBlock, SpecNone, CheckArray, origin,
1462 OpInfo(arrayMode.asWord()), Edge(array, CellUse));
1463 }
1464 }
1465 }
1466
1467 if (!storageCheck(arrayMode))
1468 return 0;
1469
1470 if (arrayMode.usesButterfly()) {
1471 return m_insertionSet.insertNode(
1472 m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
1473 }
1474
1475 return m_insertionSet.insertNode(
1476 m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
1477 OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
1478 }
1479
1480 void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
1481 {
1482 Node* node = m_currentNode;
1483
1484 switch (node->arrayMode().type()) {
1485 case Array::ForceExit: {
1486 m_insertionSet.insertNode(
1487 m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
1488 return;
1489 }
1490
1491 case Array::SelectUsingPredictions:
1492 case Array::Unprofiled:
1493 RELEASE_ASSERT_NOT_REACHED();
1494 return;
1495
1496 case Array::Generic:
1497 return;
1498
1499 default: {
1500 Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
1501 if (!storage)
1502 return;
1503
1504 storageChild = Edge(storage);
1505 return;
1506 } }
1507 }
1508
1509 bool alwaysUnboxSimplePrimitives()
1510 {
1511 #if USE(JSVALUE64)
1512 return false;
1513 #else
1514 // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
1515 // reduces traffic.
1516 return true;
1517 #endif
1518 }
1519
1520 template<UseKind useKind>
1521 void observeUseKindOnNode(Node* node)
1522 {
1523 if (useKind == UntypedUse)
1524 return;
1525 observeUseKindOnNode(node, useKind);
1526 }
1527
1528 void observeUseKindOnEdge(Edge edge)
1529 {
1530 observeUseKindOnNode(edge.node(), edge.useKind());
1531 }
1532
1533 void observeUseKindOnNode(Node* node, UseKind useKind)
1534 {
1535 if (node->op() != GetLocal)
1536 return;
1537
1538 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
1539 // https://bugs.webkit.org/show_bug.cgi?id=121518
1540
1541 VariableAccessData* variable = node->variableAccessData();
1542 switch (useKind) {
1543 case Int32Use:
1544 if (alwaysUnboxSimplePrimitives()
1545 || isInt32Speculation(variable->prediction()))
1546 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1547 break;
1548 case NumberUse:
1549 case DoubleRepUse:
1550 case DoubleRepRealUse:
1551 if (variable->doubleFormatState() == UsingDoubleFormat)
1552 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1553 break;
1554 case BooleanUse:
1555 if (alwaysUnboxSimplePrimitives()
1556 || isBooleanSpeculation(variable->prediction()))
1557 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1558 break;
1559 case Int52RepUse:
1560 if (isMachineIntSpeculation(variable->prediction()))
1561 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1562 break;
1563 case CellUse:
1564 case KnownCellUse:
1565 case ObjectUse:
1566 case StringUse:
1567 case KnownStringUse:
1568 case StringObjectUse:
1569 case StringOrStringObjectUse:
1570 if (alwaysUnboxSimplePrimitives()
1571 || isCellSpeculation(variable->prediction()))
1572 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
1573 break;
1574 default:
1575 break;
1576 }
1577 }
1578
1579 template<UseKind useKind>
1580 void fixEdge(Edge& edge)
1581 {
1582 observeUseKindOnNode<useKind>(edge.node());
1583 edge.setUseKind(useKind);
1584 }
1585
1586 void insertStoreBarrier(unsigned indexInBlock, Edge child1)
1587 {
1588 Node* barrierNode = m_graph.addNode(SpecNone, StoreBarrier, m_currentNode->origin, child1);
1589 m_insertionSet.insert(indexInBlock, barrierNode);
1590 }
1591
1592 void fixIntConvertingEdge(Edge& edge)
1593 {
1594 Node* node = edge.node();
1595 if (node->shouldSpeculateInt32OrBoolean()) {
1596 fixIntOrBooleanEdge(edge);
1597 return;
1598 }
1599
1600 UseKind useKind;
1601 if (node->shouldSpeculateMachineInt())
1602 useKind = Int52RepUse;
1603 else if (node->shouldSpeculateNumber())
1604 useKind = DoubleRepUse;
1605 else
1606 useKind = NotCellUse;
1607 Node* newNode = m_insertionSet.insertNode(
1608 m_indexInBlock, SpecInt32, ValueToInt32, m_currentNode->origin,
1609 Edge(node, useKind));
1610 observeUseKindOnNode(node, useKind);
1611
1612 edge = Edge(newNode, KnownInt32Use);
1613 addRequiredPhantom(node);
1614 }
1615
1616 void fixIntOrBooleanEdge(Edge& edge)
1617 {
1618 Node* node = edge.node();
1619 if (!node->sawBooleans()) {
1620 fixEdge<Int32Use>(edge);
1621 return;
1622 }
1623
1624 UseKind useKind;
1625 if (node->shouldSpeculateBoolean())
1626 useKind = BooleanUse;
1627 else
1628 useKind = UntypedUse;
1629 Node* newNode = m_insertionSet.insertNode(
1630 m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
1631 Edge(node, useKind));
1632 observeUseKindOnNode(node, useKind);
1633
1634 edge = Edge(newNode, Int32Use);
1635 addRequiredPhantom(node);
1636 }
1637
1638 void fixDoubleOrBooleanEdge(Edge& edge)
1639 {
1640 Node* node = edge.node();
1641 if (!node->sawBooleans()) {
1642 fixEdge<DoubleRepUse>(edge);
1643 return;
1644 }
1645
1646 UseKind useKind;
1647 if (node->shouldSpeculateBoolean())
1648 useKind = BooleanUse;
1649 else
1650 useKind = UntypedUse;
1651 Node* newNode = m_insertionSet.insertNode(
1652 m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
1653 Edge(node, useKind));
1654 observeUseKindOnNode(node, useKind);
1655
1656 edge = Edge(newNode, DoubleRepUse);
1657 addRequiredPhantom(node);
1658 }
1659
1660 void truncateConstantToInt32(Edge& edge)
1661 {
1662 Node* oldNode = edge.node();
1663
1664 ASSERT(oldNode->hasConstant());
1665 JSValue value = m_graph.valueOfJSConstant(oldNode);
1666 if (value.isInt32())
1667 return;
1668
1669 value = jsNumber(JSC::toInt32(value.asNumber()));
1670 ASSERT(value.isInt32());
1671 unsigned constantRegister;
1672 if (!codeBlock()->findConstant(value, constantRegister)) {
1673 constantRegister = codeBlock()->addConstantLazily();
1674 initializeLazyWriteBarrierForConstant(
1675 m_graph.m_plan.writeBarriers,
1676 codeBlock()->constants()[constantRegister],
1677 codeBlock(),
1678 constantRegister,
1679 codeBlock()->ownerExecutable(),
1680 value);
1681 }
1682 edge.setNode(m_insertionSet.insertNode(
1683 m_indexInBlock, SpecInt32, JSConstant, m_currentNode->origin,
1684 OpInfo(constantRegister)));
1685 }
1686
1687 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
1688 {
1689 if (mode != SpeculateInt32AndTruncateConstants)
1690 return;
1691
1692 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
1693 if (node->child1()->hasConstant())
1694 truncateConstantToInt32(node->child1());
1695 else
1696 truncateConstantToInt32(node->child2());
1697 }
1698
1699 bool attemptToMakeIntegerAdd(Node* node)
1700 {
1701 AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
1702 if (mode != DontSpeculateInt32) {
1703 truncateConstantsIfNecessary(node, mode);
1704 fixIntOrBooleanEdge(node->child1());
1705 fixIntOrBooleanEdge(node->child2());
1706 if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
1707 node->setArithMode(Arith::Unchecked);
1708 else
1709 node->setArithMode(Arith::CheckOverflow);
1710 return true;
1711 }
1712
1713 if (m_graph.addShouldSpeculateMachineInt(node)) {
1714 fixEdge<Int52RepUse>(node->child1());
1715 fixEdge<Int52RepUse>(node->child2());
1716 node->setArithMode(Arith::CheckOverflow);
1717 node->setResult(NodeResultInt52);
1718 return true;
1719 }
1720
1721 return false;
1722 }
1723
1724 bool attemptToMakeGetArrayLength(Node* node)
1725 {
1726 if (!isInt32Speculation(node->prediction()))
1727 return false;
1728 CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
1729 ArrayProfile* arrayProfile =
1730 profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex);
1731 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
1732 if (arrayProfile) {
1733 ConcurrentJITLocker locker(profiledBlock->m_lock);
1734 arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
1735 arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
1736 if (arrayMode.type() == Array::Unprofiled) {
1737 // For normal array operations, it makes sense to treat Unprofiled
1738 // accesses as ForceExit and get more data rather than using
1739 // predictions and then possibly ending up with a Generic. But here,
1740 // we treat anything that is Unprofiled as Generic and keep the
1741 // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
1742 // profit - from treating the Unprofiled case as
1743 // SelectUsingPredictions.
1744 arrayMode = ArrayMode(Array::SelectUsingPredictions);
1745 }
1746 }
1747
1748 arrayMode = arrayMode.refine(
1749 m_graph, node, node->child1()->prediction(), node->prediction());
1750
1751 if (arrayMode.type() == Array::Generic) {
1752 // Check if the input is something that we can't get array length for, but for which we
1753 // could insert some conversions in order to transform it into something that we can do it
1754 // for.
1755 if (node->child1()->shouldSpeculateStringObject())
1756 attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
1757 else if (node->child1()->shouldSpeculateStringOrStringObject())
1758 attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
1759 }
1760
1761 if (!arrayMode.supportsLength())
1762 return false;
1763
1764 convertToGetArrayLength(node, arrayMode);
1765 return true;
1766 }
1767
1768 bool attemptToMakeGetTypedArrayByteLength(Node* node)
1769 {
1770 if (!isInt32Speculation(node->prediction()))
1771 return false;
1772
1773 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1774 if (!isTypedView(type))
1775 return false;
1776
1777 if (elementSize(type) == 1) {
1778 convertToGetArrayLength(node, ArrayMode(toArrayType(type)));
1779 return true;
1780 }
1781
1782 Node* length = prependGetArrayLength(
1783 node->origin, node->child1().node(), ArrayMode(toArrayType(type)));
1784
1785 Node* shiftAmount = m_insertionSet.insertNode(
1786 m_indexInBlock, SpecInt32, JSConstant, node->origin,
1787 OpInfo(m_graph.constantRegisterForConstant(jsNumber(logElementSize(type)))));
1788
1789 // We can use a BitLShift here because typed arrays will never have a byteLength
1790 // that overflows int32.
1791 node->setOp(BitLShift);
1792 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1793 observeUseKindOnNode(length, Int32Use);
1794 observeUseKindOnNode(shiftAmount, Int32Use);
1795 node->child1() = Edge(length, Int32Use);
1796 node->child2() = Edge(shiftAmount, Int32Use);
1797 return true;
1798 }
1799
1800 void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
1801 {
1802 node->setOp(GetArrayLength);
1803 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1804 fixEdge<KnownCellUse>(node->child1());
1805 node->setArrayMode(arrayMode);
1806
1807 Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
1808 if (!storage)
1809 return;
1810
1811 node->child2() = Edge(storage);
1812 }
1813
1814 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
1815 {
1816 Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
1817 return m_insertionSet.insertNode(
1818 m_indexInBlock, SpecInt32, GetArrayLength, origin,
1819 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
1820 }
1821
1822 bool attemptToMakeGetTypedArrayByteOffset(Node* node)
1823 {
1824 if (!isInt32Speculation(node->prediction()))
1825 return false;
1826
1827 TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
1828 if (!isTypedView(type))
1829 return false;
1830
1831 checkArray(
1832 ArrayMode(toArrayType(type)), node->origin, node->child1().node(),
1833 0, neverNeedsStorage);
1834
1835 node->setOp(GetTypedArrayByteOffset);
1836 node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
1837 fixEdge<KnownCellUse>(node->child1());
1838 return true;
1839 }
1840
1841 void injectTypeConversionsInBlock(BasicBlock* block)
1842 {
1843 if (!block)
1844 return;
1845 ASSERT(block->isReachable);
1846 m_block = block;
1847 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
1848 m_currentNode = block->at(m_indexInBlock);
1849 addPhantomsIfNecessary();
1850 tryToRelaxRepresentation(m_currentNode);
1851 DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, injectTypeConversionsForEdge);
1852 }
1853 clearPhantomsAtEnd();
1854 m_insertionSet.execute(block);
1855 }
1856
1857 void tryToRelaxRepresentation(Node* node)
1858 {
1859 // Some operations may be able to operate more efficiently over looser representations.
1860 // Identify those here. This avoids inserting a redundant representation conversion.
1861 // Also, for some operations, like MovHint, this is a necessary optimization: inserting
1862 // an otherwise-dead conversion just for a MovHint would break OSR's understanding of
1863 // the IR.
1864
1865 switch (node->op()) {
1866 case MovHint:
1867 case Phantom:
1868 case Check:
1869 case HardPhantom:
1870 DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, fixEdgeRepresentation);
1871 break;
1872
1873 case ValueToInt32:
1874 if (node->child1().useKind() == DoubleRepUse
1875 && !node->child1()->hasDoubleResult()) {
1876 node->child1().setUseKind(NumberUse);
1877 break;
1878 }
1879 break;
1880
1881 default:
1882 break;
1883 }
1884 }
1885
1886 void fixEdgeRepresentation(Node*, Edge& edge)
1887 {
1888 switch (edge.useKind()) {
1889 case DoubleRepUse:
1890 case DoubleRepRealUse:
1891 if (edge->hasDoubleResult())
1892 break;
1893
1894 if (edge->hasInt52Result())
1895 edge.setUseKind(Int52RepUse);
1896 else if (edge.useKind() == DoubleRepUse)
1897 edge.setUseKind(NumberUse);
1898 break;
1899
1900 case Int52RepUse:
1901 // Nothing we can really do.
1902 break;
1903
1904 case UntypedUse:
1905 case NumberUse:
1906 if (edge->hasDoubleResult())
1907 edge.setUseKind(DoubleRepUse);
1908 else if (edge->hasInt52Result())
1909 edge.setUseKind(Int52RepUse);
1910 break;
1911
1912 default:
1913 break;
1914 }
1915 }
1916
1917 void injectTypeConversionsForEdge(Node* node, Edge& edge)
1918 {
1919 ASSERT(node == m_currentNode);
1920 Node* result = nullptr;
1921
1922 switch (edge.useKind()) {
1923 case DoubleRepUse:
1924 case DoubleRepRealUse:
1925 case DoubleRepMachineIntUse: {
1926 if (edge->hasDoubleResult())
1927 break;
1928
1929 addRequiredPhantom(edge.node());
1930
1931 if (edge->op() == JSConstant && m_graph.isNumberConstant(edge.node())) {
1932 result = m_insertionSet.insertNode(
1933 m_indexInBlock, SpecBytecodeDouble, DoubleConstant, node->origin,
1934 OpInfo(m_graph.constantRegisterForConstant(
1935 jsDoubleNumber(m_graph.valueOfNumberConstant(edge.node())))));
1936 } else if (edge->hasInt52Result()) {
1937 result = m_insertionSet.insertNode(
1938 m_indexInBlock, SpecInt52AsDouble, DoubleRep, node->origin,
1939 Edge(edge.node(), Int52RepUse));
1940 } else {
1941 result = m_insertionSet.insertNode(
1942 m_indexInBlock, SpecBytecodeDouble, DoubleRep, node->origin,
1943 Edge(edge.node(), NumberUse));
1944 }
1945
1946 edge.setNode(result);
1947 break;
1948 }
1949
1950 case Int52RepUse: {
1951 if (edge->hasInt52Result())
1952 break;
1953
1954 addRequiredPhantom(edge.node());
1955
1956 if (edge->op() == JSConstant && m_graph.isMachineIntConstant(edge.node())) {
1957 result = m_insertionSet.insertNode(
1958 m_indexInBlock, SpecMachineInt, Int52Constant, node->origin,
1959 OpInfo(edge->constantNumber()));
1960 } else if (edge->hasDoubleResult()) {
1961 result = m_insertionSet.insertNode(
1962 m_indexInBlock, SpecMachineInt, Int52Rep, node->origin,
1963 Edge(edge.node(), DoubleRepMachineIntUse));
1964 } else if (edge->shouldSpeculateInt32ForArithmetic()) {
1965 result = m_insertionSet.insertNode(
1966 m_indexInBlock, SpecInt32, Int52Rep, node->origin,
1967 Edge(edge.node(), Int32Use));
1968 } else {
1969 result = m_insertionSet.insertNode(
1970 m_indexInBlock, SpecMachineInt, Int52Rep, node->origin,
1971 Edge(edge.node(), MachineIntUse));
1972 }
1973
1974 edge.setNode(result);
1975 break;
1976 }
1977
1978 default: {
1979 if (!edge->hasDoubleResult() && !edge->hasInt52Result())
1980 break;
1981
1982 addRequiredPhantom(edge.node());
1983
1984 if (edge->hasDoubleResult()) {
1985 result = m_insertionSet.insertNode(
1986 m_indexInBlock, SpecBytecodeDouble, ValueRep, node->origin,
1987 Edge(edge.node(), DoubleRepUse));
1988 } else {
1989 result = m_insertionSet.insertNode(
1990 m_indexInBlock, SpecInt32 | SpecInt52AsDouble, ValueRep, node->origin,
1991 Edge(edge.node(), Int52RepUse));
1992 }
1993
1994 edge.setNode(result);
1995 break;
1996 } }
1997 }
1998
1999 void addRequiredPhantom(Node* node)
2000 {
2001 m_requiredPhantoms.append(node);
2002 }
2003
2004 void addPhantomsIfNecessary()
2005 {
2006 if (m_requiredPhantoms.isEmpty())
2007 return;
2008
2009 for (unsigned i = m_requiredPhantoms.size(); i--;) {
2010 Node* node = m_requiredPhantoms[i];
2011 m_insertionSet.insertNode(
2012 m_indexInBlock, SpecNone, Phantom, m_currentNode->origin,
2013 node->defaultEdge());
2014 }
2015
2016 m_requiredPhantoms.resize(0);
2017 }
2018
2019 void clearPhantomsAtEnd()
2020 {
2021 // Terminal nodes don't need post-phantoms, and inserting them would violate
2022 // the current requirement that a terminal is the last thing in a block. We
2023 // should eventually change that requirement. Currently we get around this by
2024 // ensuring that all terminals accept just one input, and if that input is a
2025 // conversion node then no further speculations will be performed. See
2026 // references to the bug, below, for places where we have to have hacks to
2027 // work around this.
2028 // FIXME: Get rid of this by allowing Phantoms after terminals.
2029 // https://bugs.webkit.org/show_bug.cgi?id=126778
2030
2031 m_requiredPhantoms.resize(0);
2032 }
2033
2034 BasicBlock* m_block;
2035 unsigned m_indexInBlock;
2036 Node* m_currentNode;
2037 InsertionSet m_insertionSet;
2038 bool m_profitabilityChanged;
2039 Vector<Node*, 3> m_requiredPhantoms;
2040 };
2041
2042 bool performFixup(Graph& graph)
2043 {
2044 SamplingRegion samplingRegion("DFG Fixup Phase");
2045 return runPhase<FixupPhase>(graph);
2046 }
2047
2048 } } // namespace JSC::DFG
2049
2050 #endif // ENABLE(DFG_JIT)
2051