7c50715ec43e9a82aa14451fad4af3c4ae7f3026
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNonSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011 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 "DFGNonSpeculativeJIT.h"
28
29 #include "DFGSpeculativeJIT.h"
30
31 #if ENABLE(DFG_JIT)
32
33 namespace JSC { namespace DFG {
34
35 const double twoToThe32 = (double)0x100000000ull;
36
37 EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit)
38     : m_entry(entry)
39     , m_nodeIndex(jit->m_compileIndex)
40 {
41     for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
42         if (iter.name() != InvalidVirtualRegister) {
43             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
44             m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
45             m_gprInfo[iter.index()].format = info.registerFormat();
46         } else
47             m_gprInfo[iter.index()].nodeIndex = NoNode;
48     }
49     for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
50         if (iter.name() != InvalidVirtualRegister) {
51             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
52             ASSERT(info.registerFormat() == DataFormatDouble);
53             m_fprInfo[iter.index()] = info.nodeIndex();
54         } else
55             m_fprInfo[iter.index()] = NoNode;
56     }
57 }
58
59 void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, FPRReg fpr)
60 {
61     GPRReg jsValueGpr = operand.gpr();
62     GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
63
64     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
65     JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
66
67     // First, if we get here we have a double encoded as a JSValue
68     m_jit.move(jsValueGpr, tempGpr);
69     m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
70     m_jit.movePtrToDouble(tempGpr, fpr);
71     JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
72
73     // Next handle cells (& other JS immediates)
74     nonNumeric.link(&m_jit);
75     silentSpillAllRegisters(fpr, jsValueGpr);
76     m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
77     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
78     appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
79     m_jit.moveDouble(FPRInfo::returnValueFPR, fpr);
80     silentFillAllRegisters(fpr);
81     JITCompiler::Jump hasCalledToNumber = m_jit.jump();
82     
83     // Finally, handle integers.
84     isInteger.link(&m_jit);
85     m_jit.convertInt32ToDouble(jsValueGpr, fpr);
86     hasUnboxedDouble.link(&m_jit);
87     hasCalledToNumber.link(&m_jit);
88
89     m_gprs.unlock(tempGpr);
90 }
91
92 void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)
93 {
94     GPRReg jsValueGpr = operand.gpr();
95
96     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
97
98     // First handle non-integers
99     silentSpillAllRegisters(result, jsValueGpr);
100     m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
101     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
102     appendCallWithExceptionCheck(dfgConvertJSValueToInt32);
103     m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
104     silentFillAllRegisters(result);
105     JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
106     
107     // Then handle integers.
108     isInteger.link(&m_jit);
109     m_jit.zeroExtend32ToPtr(jsValueGpr, result);
110     hasCalledToInt32.link(&m_jit);
111 }
112
113 void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
114 {
115     JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
116
117     silentSpillAllRegisters(gpr);
118
119     m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);
120     appendCallWithExceptionCheck(toInt32);
121     m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);
122
123     silentFillAllRegisters(gpr);
124
125     truncatedToInteger.link(&m_jit);
126 }
127
128 bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
129 {
130     GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
131
132     DataFormat registerFormat = info.registerFormat();
133     if (registerFormat != DataFormatNone)
134         return (registerFormat | DataFormatJS) == DataFormatJSInteger;
135
136     DataFormat spillFormat = info.spillFormat();
137     if (spillFormat != DataFormatNone)
138         return (spillFormat | DataFormatJS) == DataFormatJSInteger;
139
140     ASSERT(isConstant(nodeIndex));
141     return isInt32Constant(nodeIndex);
142 }
143
144 bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
145 {
146     GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
147
148     DataFormat registerFormat = info.registerFormat();
149     if (registerFormat != DataFormatNone)
150         return (registerFormat | DataFormatJS) == DataFormatJSInteger
151             || (registerFormat | DataFormatJS) == DataFormatJSDouble;
152
153     DataFormat spillFormat = info.spillFormat();
154     if (spillFormat != DataFormatNone)
155         return (spillFormat | DataFormatJS) == DataFormatJSInteger
156             || (spillFormat | DataFormatJS) == DataFormatJSDouble;
157
158     ASSERT(isConstant(nodeIndex));
159     return isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex);
160 }
161
162 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
163 {
164     // Check for speculation checks from the corresponding instruction in the
165     // speculative path. Do not check for NodeIndex 0, since this is checked
166     // in the outermost compile layer, at the head of the non-speculative path
167     // (for index 0 we may need to check regardless of whether or not the node
168     // will be generated, since argument type speculation checks will appear
169     // as speculation checks at this index).
170     if (m_compileIndex && checkIterator.hasCheckAtIndex(m_compileIndex))
171         trackEntry(m_jit.label());
172
173     NodeType op = node.op;
174
175     switch (op) {
176     case ConvertThis: {
177         JSValueOperand thisValue(this, node.child1);
178         GPRReg thisGPR = thisValue.gpr();
179         flushRegisters();
180
181         GPRResult result(this);
182         callOperation(operationConvertThis, result.gpr(), thisGPR);
183         cellResult(result.gpr(), m_compileIndex);
184         break;
185     }
186
187     case Int32Constant:
188     case DoubleConstant:
189     case JSConstant:
190         initConstantInfo(m_compileIndex);
191         break;
192
193     case GetLocal: {
194         GPRTemporary result(this);
195         m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
196
197         // Like jsValueResult, but don't useChildren - our children are phi nodes,
198         // and don't represent values within this dataflow with virtual registers.
199         VirtualRegister virtualRegister = node.virtualRegister();
200         m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
201         m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), DataFormatJS);
202         break;
203     }
204
205     case SetLocal: {
206         JSValueOperand value(this, node.child1);
207         m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
208         noResult(m_compileIndex);
209         break;
210     }
211
212     case BitAnd:
213     case BitOr:
214     case BitXor:
215         if (isInt32Constant(node.child1)) {
216             IntegerOperand op2(this, node.child2);
217             GPRTemporary result(this, op2);
218
219             bitOp(op, valueOfInt32Constant(node.child1), op2.gpr(), result.gpr());
220
221             integerResult(result.gpr(), m_compileIndex);
222         } else if (isInt32Constant(node.child2)) {
223             IntegerOperand op1(this, node.child1);
224             GPRTemporary result(this, op1);
225
226             bitOp(op, valueOfInt32Constant(node.child2), op1.gpr(), result.gpr());
227
228             integerResult(result.gpr(), m_compileIndex);
229         } else {
230             IntegerOperand op1(this, node.child1);
231             IntegerOperand op2(this, node.child2);
232             GPRTemporary result(this, op1, op2);
233
234             GPRReg reg1 = op1.gpr();
235             GPRReg reg2 = op2.gpr();
236             bitOp(op, reg1, reg2, result.gpr());
237
238             integerResult(result.gpr(), m_compileIndex);
239         }
240         break;
241
242     case BitRShift:
243     case BitLShift:
244     case BitURShift:
245         if (isInt32Constant(node.child2)) {
246             IntegerOperand op1(this, node.child1);
247             GPRTemporary result(this, op1);
248
249             int shiftAmount = valueOfInt32Constant(node.child2) & 0x1f;
250             // Shifts by zero should have been optimized out of the graph!
251             ASSERT(shiftAmount);
252             shiftOp(op, op1.gpr(), shiftAmount, result.gpr());
253
254             integerResult(result.gpr(), m_compileIndex);
255         } else {
256             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
257             IntegerOperand op1(this, node.child1);
258             IntegerOperand op2(this, node.child2);
259             GPRTemporary result(this, op1);
260
261             GPRReg reg1 = op1.gpr();
262             GPRReg reg2 = op2.gpr();
263             shiftOp(op, reg1, reg2, result.gpr());
264
265             integerResult(result.gpr(), m_compileIndex);
266         }
267         break;
268
269     case UInt32ToNumber: {
270         IntegerOperand op1(this, node.child1);
271         FPRTemporary result(this);
272         m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
273
274         MacroAssembler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
275         m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), result.fpr());
276         positive.link(&m_jit);
277
278         doubleResult(result.fpr(), m_compileIndex);
279         break;
280     }
281
282     case Int32ToNumber: {
283         IntegerOperand op1(this, node.child1);
284         FPRTemporary result(this);
285         m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
286         doubleResult(result.fpr(), m_compileIndex);
287         break;
288     }
289
290     case NumberToInt32:
291     case ValueToInt32: {
292         ASSERT(!isInt32Constant(node.child1));
293
294         if (isKnownInteger(node.child1)) {
295             IntegerOperand op1(this, node.child1);
296             GPRTemporary result(this, op1);
297             m_jit.move(op1.gpr(), result.gpr());
298             integerResult(result.gpr(), m_compileIndex);
299             break;
300         }
301
302         if (isKnownNumeric(node.child1)) {
303             DoubleOperand op1(this, node.child1);
304             GPRTemporary result(this);
305             numberToInt32(op1.fpr(), result.gpr());
306             integerResult(result.gpr(), m_compileIndex);
307             break;
308         }
309
310         // We should have handled this via isKnownInteger, or isKnownNumeric!
311         ASSERT(op != NumberToInt32);
312
313         JSValueOperand op1(this, node.child1);
314         GPRTemporary result(this, op1);
315         valueToInt32(op1, result.gpr());
316         integerResult(result.gpr(), m_compileIndex);
317         break;
318     }
319
320     case ValueToNumber: {
321         ASSERT(!isInt32Constant(node.child1));
322         ASSERT(!isDoubleConstant(node.child1));
323
324         if (isKnownInteger(node.child1)) {
325             IntegerOperand op1(this, node.child1);
326             FPRTemporary result(this);
327             m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
328             doubleResult(result.fpr(), m_compileIndex);
329             break;
330         }
331
332         if (isKnownNumeric(node.child1)) {
333             DoubleOperand op1(this, node.child1);
334             FPRTemporary result(this, op1);
335             m_jit.moveDouble(op1.fpr(), result.fpr());
336             doubleResult(result.fpr(), m_compileIndex);
337             break;
338         }
339
340         JSValueOperand op1(this, node.child1);
341         FPRTemporary result(this);
342         valueToNumber(op1, result.fpr());
343         doubleResult(result.fpr(), m_compileIndex);
344         break;
345     }
346
347     case ValueAdd: {
348         JSValueOperand arg1(this, node.child1);
349         JSValueOperand arg2(this, node.child2);
350         GPRReg arg1GPR = arg1.gpr();
351         GPRReg arg2GPR = arg2.gpr();
352         flushRegisters();
353
354         GPRResult result(this);
355         callOperation(operationValueAdd, result.gpr(), arg1GPR, arg2GPR);
356
357         jsValueResult(result.gpr(), m_compileIndex);
358         break;
359     }
360         
361     case ArithAdd: {
362         DoubleOperand op1(this, node.child1);
363         DoubleOperand op2(this, node.child2);
364         FPRTemporary result(this, op1, op2);
365
366         FPRReg reg1 = op1.fpr();
367         FPRReg reg2 = op2.fpr();
368         m_jit.addDouble(reg1, reg2, result.fpr());
369
370         doubleResult(result.fpr(), m_compileIndex);
371         break;
372     }
373
374     case ArithSub: {
375         DoubleOperand op1(this, node.child1);
376         DoubleOperand op2(this, node.child2);
377         FPRTemporary result(this, op1);
378
379         FPRReg reg1 = op1.fpr();
380         FPRReg reg2 = op2.fpr();
381         m_jit.subDouble(reg1, reg2, result.fpr());
382
383         doubleResult(result.fpr(), m_compileIndex);
384         break;
385     }
386
387     case ArithMul: {
388         DoubleOperand op1(this, node.child1);
389         DoubleOperand op2(this, node.child2);
390         FPRTemporary result(this, op1, op2);
391
392         FPRReg reg1 = op1.fpr();
393         FPRReg reg2 = op2.fpr();
394         m_jit.mulDouble(reg1, reg2, result.fpr());
395
396         doubleResult(result.fpr(), m_compileIndex);
397         break;
398     }
399
400     case ArithDiv: {
401         DoubleOperand op1(this, node.child1);
402         DoubleOperand op2(this, node.child2);
403         FPRTemporary result(this, op1);
404
405         FPRReg reg1 = op1.fpr();
406         FPRReg reg2 = op2.fpr();
407         m_jit.divDouble(reg1, reg2, result.fpr());
408
409         doubleResult(result.fpr(), m_compileIndex);
410         break;
411     }
412
413     case ArithMod: {
414         DoubleOperand arg1(this, node.child1);
415         DoubleOperand arg2(this, node.child2);
416         FPRReg arg1FPR = arg1.fpr();
417         FPRReg arg2FPR = arg2.fpr();
418         flushRegisters();
419
420         FPRResult result(this);
421         callOperation(fmod, result.fpr(), arg1FPR, arg2FPR);
422
423         doubleResult(result.fpr(), m_compileIndex);
424         break;
425     }
426
427     case LogicalNot: {
428         JSValueOperand arg1(this, node.child1);
429         GPRReg arg1GPR = arg1.gpr();
430         flushRegisters();
431
432         GPRResult result(this);
433         callOperation(dfgConvertJSValueToBoolean, result.gpr(), arg1GPR);
434
435         // If we add a DataFormatBool, we should use it here.
436         m_jit.xor32(TrustedImm32(ValueTrue), result.gpr());
437         jsValueResult(result.gpr(), m_compileIndex);
438         break;
439     }
440
441     case CompareLess: {
442         JSValueOperand arg1(this, node.child1);
443         JSValueOperand arg2(this, node.child2);
444         GPRReg arg1GPR = arg1.gpr();
445         GPRReg arg2GPR = arg2.gpr();
446         flushRegisters();
447
448         GPRResult result(this);
449         callOperation(operationCompareLess, result.gpr(), arg1GPR, arg2GPR);
450         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
451
452         jsValueResult(result.gpr(), m_compileIndex);
453         break;
454     }
455
456     case CompareLessEq: {
457         JSValueOperand arg1(this, node.child1);
458         JSValueOperand arg2(this, node.child2);
459         GPRReg arg1GPR = arg1.gpr();
460         GPRReg arg2GPR = arg2.gpr();
461         flushRegisters();
462
463         GPRResult result(this);
464         callOperation(operationCompareLessEq, result.gpr(), arg1GPR, arg2GPR);
465         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
466
467         jsValueResult(result.gpr(), m_compileIndex);
468         break;
469     }
470
471     case CompareEq: {
472         JSValueOperand arg1(this, node.child1);
473         JSValueOperand arg2(this, node.child2);
474         GPRReg arg1GPR = arg1.gpr();
475         GPRReg arg2GPR = arg2.gpr();
476         flushRegisters();
477
478         GPRResult result(this);
479         callOperation(operationCompareEq, result.gpr(), arg1GPR, arg2GPR);
480         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
481
482         jsValueResult(result.gpr(), m_compileIndex);
483         break;
484     }
485
486     case CompareStrictEq: {
487         JSValueOperand arg1(this, node.child1);
488         JSValueOperand arg2(this, node.child2);
489         GPRReg arg1GPR = arg1.gpr();
490         GPRReg arg2GPR = arg2.gpr();
491         flushRegisters();
492
493         GPRResult result(this);
494         callOperation(operationCompareStrictEq, result.gpr(), arg1GPR, arg2GPR);
495         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
496
497         jsValueResult(result.gpr(), m_compileIndex);
498         break;
499     }
500
501     case GetByVal: {
502         JSValueOperand arg1(this, node.child1);
503         JSValueOperand arg2(this, node.child2);
504         GPRReg arg1GPR = arg1.gpr();
505         GPRReg arg2GPR = arg2.gpr();
506         flushRegisters();
507
508         GPRResult result(this);
509         callOperation(operationGetByVal, result.gpr(), arg1GPR, arg2GPR);
510
511         jsValueResult(result.gpr(), m_compileIndex);
512         break;
513     }
514
515     case PutByVal:
516     case PutByValAlias: {
517         JSValueOperand arg1(this, node.child1);
518         JSValueOperand arg2(this, node.child2);
519         JSValueOperand arg3(this, node.child3);
520         GPRReg arg1GPR = arg1.gpr();
521         GPRReg arg2GPR = arg2.gpr();
522         GPRReg arg3GPR = arg3.gpr();
523         flushRegisters();
524
525         GPRResult result(this);
526         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
527
528         noResult(m_compileIndex);
529         break;
530     }
531
532     case GetById: {
533         JSValueOperand base(this, node.child1);
534         GPRReg baseGPR = base.gpr();
535         flushRegisters();
536
537         GPRResult result(this);
538         callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber()));
539         jsValueResult(result.gpr(), m_compileIndex);
540         break;
541     }
542
543     case PutById: {
544         JSValueOperand base(this, node.child1);
545         JSValueOperand value(this, node.child2);
546         GPRReg valueGPR = value.gpr();
547         GPRReg baseGPR = base.gpr();
548         flushRegisters();
549
550         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
551         noResult(m_compileIndex);
552         break;
553     }
554
555     case PutByIdDirect: {
556         JSValueOperand base(this, node.child1);
557         JSValueOperand value(this, node.child2);
558         GPRReg valueGPR = value.gpr();
559         GPRReg baseGPR = base.gpr();
560         flushRegisters();
561
562         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
563         noResult(m_compileIndex);
564         break;
565     }
566
567     case GetGlobalVar: {
568         GPRTemporary result(this);
569
570         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
571         m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
572         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
573
574         jsValueResult(result.gpr(), m_compileIndex);
575         break;
576     }
577
578     case PutGlobalVar: {
579         JSValueOperand value(this, node.child1);
580         GPRTemporary temp(this);
581
582         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
583         m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
584         m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
585
586         noResult(m_compileIndex);
587         break;
588     }
589
590     case DFG::Jump: {
591         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
592         if (taken != (m_block + 1))
593             addBranch(m_jit.jump(), taken);
594         noResult(m_compileIndex);
595         break;
596     }
597
598     case Branch: {
599         JSValueOperand value(this, node.child1);
600         GPRReg valueGPR = value.gpr();
601         flushRegisters();
602
603         GPRResult result(this);
604         callOperation(dfgConvertJSValueToBoolean, result.gpr(), valueGPR);
605
606         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
607         BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
608
609         addBranch(m_jit.branchTest8(MacroAssembler::NonZero, result.gpr()), taken);
610         if (notTaken != (m_block + 1))
611             addBranch(m_jit.jump(), notTaken);
612
613         noResult(m_compileIndex);
614         break;
615     }
616
617     case Return: {
618         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
619         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
620         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
621
622 #if DFG_SUCCESS_STATS
623         static SamplingCounter counter("NonSpeculativeJIT");
624         m_jit.emitCount(counter);
625 #endif
626
627         // Return the result in returnValueGPR.
628         JSValueOperand op1(this, node.child1);
629         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
630
631         // Grab the return address.
632         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
633         // Restore our caller's "r".
634         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
635         // Return.
636         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
637         m_jit.ret();
638
639         noResult(m_compileIndex);
640         break;
641     }
642
643     case Phi:
644         ASSERT_NOT_REACHED();
645     }
646
647     if (node.hasResult() && node.mustGenerate())
648         use(m_compileIndex);
649 }
650
651 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, BasicBlock& block)
652 {
653     ASSERT(m_compileIndex == block.begin);
654     m_blockHeads[m_block] = m_jit.label();
655
656 #if DFG_JIT_BREAK_ON_EVERY_BLOCK
657     m_jit.breakpoint();
658 #endif
659
660     for (; m_compileIndex < block.end; ++m_compileIndex) {
661         Node& node = m_jit.graph()[m_compileIndex];
662         if (!node.shouldGenerate())
663             continue;
664
665 #if DFG_DEBUG_VERBOSE
666         fprintf(stderr, "NonSpeculativeJIT generating Node @%d at code offset 0x%x\n", (int)m_compileIndex, m_jit.debugOffset());
667 #endif
668 #if DFG_JIT_BREAK_ON_EVERY_NODE
669         m_jit.breakpoint();
670 #endif
671
672         checkConsistency();
673         compile(checkIterator, node);
674         checkConsistency();
675     }
676 }
677
678 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator)
679 {
680     // Check for speculation checks added at function entry (checking argument types).
681     if (checkIterator.hasCheckAtIndex(m_compileIndex))
682         trackEntry(m_jit.label());
683
684     ASSERT(!m_compileIndex);
685     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
686         compile(checkIterator, *m_jit.graph().m_blocks[m_block]);
687     linkBranches();
688 }
689
690 } } // namespace JSC::DFG
691
692 #endif