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