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