2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGNonSpeculativeJIT.h"
29 #include "DFGSpeculativeJIT.h"
33 namespace JSC
{ namespace DFG
{
35 const double twoToThe32
= (double)0x100000000ull
;
37 EntryLocation::EntryLocation(MacroAssembler::Label entry
, NonSpeculativeJIT
* jit
)
39 , m_nodeIndex(jit
->m_compileIndex
)
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();
47 m_gprInfo
[iter
.index()].nodeIndex
= NoNode
;
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();
55 m_fprInfo
[iter
.index()] = NoNode
;
59 void NonSpeculativeJIT::valueToNumber(JSValueOperand
& operand
, FPRReg fpr
)
61 GPRReg jsValueGpr
= operand
.gpr();
62 GPRReg tempGpr
= allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
64 JITCompiler::Jump isInteger
= m_jit
.branchPtr(MacroAssembler::AboveOrEqual
, jsValueGpr
, GPRInfo::tagTypeNumberRegister
);
65 JITCompiler::Jump nonNumeric
= m_jit
.branchTestPtr(MacroAssembler::Zero
, jsValueGpr
, GPRInfo::tagTypeNumberRegister
);
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();
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();
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
);
89 m_gprs
.unlock(tempGpr
);
92 void NonSpeculativeJIT::valueToInt32(JSValueOperand
& operand
, GPRReg result
)
94 GPRReg jsValueGpr
= operand
.gpr();
96 JITCompiler::Jump isInteger
= m_jit
.branchPtr(MacroAssembler::AboveOrEqual
, jsValueGpr
, GPRInfo::tagTypeNumberRegister
);
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();
107 // Then handle integers.
108 isInteger
.link(&m_jit
);
109 m_jit
.zeroExtend32ToPtr(jsValueGpr
, result
);
110 hasCalledToInt32
.link(&m_jit
);
113 void NonSpeculativeJIT::numberToInt32(FPRReg fpr
, GPRReg gpr
)
115 JITCompiler::Jump truncatedToInteger
= m_jit
.branchTruncateDoubleToInt32(fpr
, gpr
, JITCompiler::BranchIfTruncateSuccessful
);
117 silentSpillAllRegisters(gpr
);
119 m_jit
.moveDouble(fpr
, FPRInfo::argumentFPR0
);
120 appendCallWithExceptionCheck(toInt32
);
121 m_jit
.zeroExtend32ToPtr(GPRInfo::returnValueGPR
, gpr
);
123 silentFillAllRegisters(gpr
);
125 truncatedToInteger
.link(&m_jit
);
128 bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex
)
130 GenerationInfo
& info
= m_generationInfo
[m_jit
.graph()[nodeIndex
].virtualRegister()];
132 DataFormat registerFormat
= info
.registerFormat();
133 if (registerFormat
!= DataFormatNone
)
134 return (registerFormat
| DataFormatJS
) == DataFormatJSInteger
;
136 DataFormat spillFormat
= info
.spillFormat();
137 if (spillFormat
!= DataFormatNone
)
138 return (spillFormat
| DataFormatJS
) == DataFormatJSInteger
;
140 ASSERT(isConstant(nodeIndex
));
141 return isInt32Constant(nodeIndex
);
144 bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex
)
146 GenerationInfo
& info
= m_generationInfo
[m_jit
.graph()[nodeIndex
].virtualRegister()];
148 DataFormat registerFormat
= info
.registerFormat();
149 if (registerFormat
!= DataFormatNone
)
150 return (registerFormat
| DataFormatJS
) == DataFormatJSInteger
151 || (registerFormat
| DataFormatJS
) == DataFormatJSDouble
;
153 DataFormat spillFormat
= info
.spillFormat();
154 if (spillFormat
!= DataFormatNone
)
155 return (spillFormat
| DataFormatJS
) == DataFormatJSInteger
156 || (spillFormat
| DataFormatJS
) == DataFormatJSDouble
;
158 ASSERT(isConstant(nodeIndex
));
159 return isInt32Constant(nodeIndex
) || isDoubleConstant(nodeIndex
);
162 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator
& checkIterator
, Node
& node
)
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());
173 NodeType op
= node
.op
;
177 JSValueOperand
thisValue(this, node
.child1
);
178 GPRReg thisGPR
= thisValue
.gpr();
181 GPRResult
result(this);
182 callOperation(operationConvertThis
, result
.gpr(), thisGPR
);
183 cellResult(result
.gpr(), m_compileIndex
);
190 initConstantInfo(m_compileIndex
);
194 GPRTemporary
result(this);
195 m_jit
.loadPtr(JITCompiler::addressFor(node
.local()), result
.gpr());
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
);
206 JSValueOperand
value(this, node
.child1
);
207 m_jit
.storePtr(value
.gpr(), JITCompiler::addressFor(node
.local()));
208 noResult(m_compileIndex
);
215 if (isInt32Constant(node
.child1
)) {
216 IntegerOperand
op2(this, node
.child2
);
217 GPRTemporary
result(this, op2
);
219 bitOp(op
, valueOfInt32Constant(node
.child1
), op2
.gpr(), result
.gpr());
221 integerResult(result
.gpr(), m_compileIndex
);
222 } else if (isInt32Constant(node
.child2
)) {
223 IntegerOperand
op1(this, node
.child1
);
224 GPRTemporary
result(this, op1
);
226 bitOp(op
, valueOfInt32Constant(node
.child2
), op1
.gpr(), result
.gpr());
228 integerResult(result
.gpr(), m_compileIndex
);
230 IntegerOperand
op1(this, node
.child1
);
231 IntegerOperand
op2(this, node
.child2
);
232 GPRTemporary
result(this, op1
, op2
);
234 GPRReg reg1
= op1
.gpr();
235 GPRReg reg2
= op2
.gpr();
236 bitOp(op
, reg1
, reg2
, result
.gpr());
238 integerResult(result
.gpr(), m_compileIndex
);
245 if (isInt32Constant(node
.child2
)) {
246 IntegerOperand
op1(this, node
.child1
);
247 GPRTemporary
result(this, op1
);
249 int shiftAmount
= valueOfInt32Constant(node
.child2
) & 0x1f;
250 // Shifts by zero should have been optimized out of the graph!
252 shiftOp(op
, op1
.gpr(), shiftAmount
, result
.gpr());
254 integerResult(result
.gpr(), m_compileIndex
);
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
);
261 GPRReg reg1
= op1
.gpr();
262 GPRReg reg2
= op2
.gpr();
263 shiftOp(op
, reg1
, reg2
, result
.gpr());
265 integerResult(result
.gpr(), m_compileIndex
);
269 case UInt32ToNumber
: {
270 IntegerOperand
op1(this, node
.child1
);
271 FPRTemporary
result(this);
272 m_jit
.convertInt32ToDouble(op1
.gpr(), result
.fpr());
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
);
278 doubleResult(result
.fpr(), m_compileIndex
);
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
);
292 ASSERT(!isInt32Constant(node
.child1
));
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
);
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
);
310 // We should have handled this via isKnownInteger, or isKnownNumeric!
311 ASSERT(op
!= NumberToInt32
);
313 JSValueOperand
op1(this, node
.child1
);
314 GPRTemporary
result(this, op1
);
315 valueToInt32(op1
, result
.gpr());
316 integerResult(result
.gpr(), m_compileIndex
);
320 case ValueToNumber
: {
321 ASSERT(!isInt32Constant(node
.child1
));
322 ASSERT(!isDoubleConstant(node
.child1
));
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
);
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
);
340 JSValueOperand
op1(this, node
.child1
);
341 FPRTemporary
result(this);
342 valueToNumber(op1
, result
.fpr());
343 doubleResult(result
.fpr(), m_compileIndex
);
348 JSValueOperand
arg1(this, node
.child1
);
349 JSValueOperand
arg2(this, node
.child2
);
350 GPRReg arg1GPR
= arg1
.gpr();
351 GPRReg arg2GPR
= arg2
.gpr();
354 GPRResult
result(this);
355 callOperation(operationValueAdd
, result
.gpr(), arg1GPR
, arg2GPR
);
357 jsValueResult(result
.gpr(), m_compileIndex
);
362 DoubleOperand
op1(this, node
.child1
);
363 DoubleOperand
op2(this, node
.child2
);
364 FPRTemporary
result(this, op1
, op2
);
366 FPRReg reg1
= op1
.fpr();
367 FPRReg reg2
= op2
.fpr();
368 m_jit
.addDouble(reg1
, reg2
, result
.fpr());
370 doubleResult(result
.fpr(), m_compileIndex
);
375 DoubleOperand
op1(this, node
.child1
);
376 DoubleOperand
op2(this, node
.child2
);
377 FPRTemporary
result(this, op1
);
379 FPRReg reg1
= op1
.fpr();
380 FPRReg reg2
= op2
.fpr();
381 m_jit
.subDouble(reg1
, reg2
, result
.fpr());
383 doubleResult(result
.fpr(), m_compileIndex
);
388 DoubleOperand
op1(this, node
.child1
);
389 DoubleOperand
op2(this, node
.child2
);
390 FPRTemporary
result(this, op1
, op2
);
392 FPRReg reg1
= op1
.fpr();
393 FPRReg reg2
= op2
.fpr();
394 m_jit
.mulDouble(reg1
, reg2
, result
.fpr());
396 doubleResult(result
.fpr(), m_compileIndex
);
401 DoubleOperand
op1(this, node
.child1
);
402 DoubleOperand
op2(this, node
.child2
);
403 FPRTemporary
result(this, op1
);
405 FPRReg reg1
= op1
.fpr();
406 FPRReg reg2
= op2
.fpr();
407 m_jit
.divDouble(reg1
, reg2
, result
.fpr());
409 doubleResult(result
.fpr(), m_compileIndex
);
414 DoubleOperand
arg1(this, node
.child1
);
415 DoubleOperand
arg2(this, node
.child2
);
416 FPRReg arg1FPR
= arg1
.fpr();
417 FPRReg arg2FPR
= arg2
.fpr();
420 FPRResult
result(this);
421 callOperation(fmod
, result
.fpr(), arg1FPR
, arg2FPR
);
423 doubleResult(result
.fpr(), m_compileIndex
);
428 JSValueOperand
arg1(this, node
.child1
);
429 GPRReg arg1GPR
= arg1
.gpr();
432 GPRResult
result(this);
433 callOperation(dfgConvertJSValueToBoolean
, result
.gpr(), arg1GPR
);
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
);
442 JSValueOperand
arg1(this, node
.child1
);
443 JSValueOperand
arg2(this, node
.child2
);
444 GPRReg arg1GPR
= arg1
.gpr();
445 GPRReg arg2GPR
= arg2
.gpr();
448 GPRResult
result(this);
449 callOperation(operationCompareLess
, result
.gpr(), arg1GPR
, arg2GPR
);
450 m_jit
.or32(TrustedImm32(ValueFalse
), result
.gpr());
452 jsValueResult(result
.gpr(), m_compileIndex
);
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();
463 GPRResult
result(this);
464 callOperation(operationCompareLessEq
, result
.gpr(), arg1GPR
, arg2GPR
);
465 m_jit
.or32(TrustedImm32(ValueFalse
), result
.gpr());
467 jsValueResult(result
.gpr(), m_compileIndex
);
472 JSValueOperand
arg1(this, node
.child1
);
473 JSValueOperand
arg2(this, node
.child2
);
474 GPRReg arg1GPR
= arg1
.gpr();
475 GPRReg arg2GPR
= arg2
.gpr();
478 GPRResult
result(this);
479 callOperation(operationCompareEq
, result
.gpr(), arg1GPR
, arg2GPR
);
480 m_jit
.or32(TrustedImm32(ValueFalse
), result
.gpr());
482 jsValueResult(result
.gpr(), m_compileIndex
);
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();
493 GPRResult
result(this);
494 callOperation(operationCompareStrictEq
, result
.gpr(), arg1GPR
, arg2GPR
);
495 m_jit
.or32(TrustedImm32(ValueFalse
), result
.gpr());
497 jsValueResult(result
.gpr(), m_compileIndex
);
502 JSValueOperand
arg1(this, node
.child1
);
503 JSValueOperand
arg2(this, node
.child2
);
504 GPRReg arg1GPR
= arg1
.gpr();
505 GPRReg arg2GPR
= arg2
.gpr();
508 GPRResult
result(this);
509 callOperation(operationGetByVal
, result
.gpr(), arg1GPR
, arg2GPR
);
511 jsValueResult(result
.gpr(), m_compileIndex
);
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();
525 GPRResult
result(this);
526 callOperation(m_jit
.codeBlock()->isStrictMode() ? operationPutByValStrict
: operationPutByValNonStrict
, arg1GPR
, arg2GPR
, arg3GPR
);
528 noResult(m_compileIndex
);
533 JSValueOperand
base(this, node
.child1
);
534 GPRReg baseGPR
= base
.gpr();
537 GPRResult
result(this);
538 callOperation(operationGetById
, result
.gpr(), baseGPR
, identifier(node
.identifierNumber()));
539 jsValueResult(result
.gpr(), m_compileIndex
);
544 JSValueOperand
base(this, node
.child1
);
545 JSValueOperand
value(this, node
.child2
);
546 GPRReg valueGPR
= value
.gpr();
547 GPRReg baseGPR
= base
.gpr();
550 callOperation(m_jit
.codeBlock()->isStrictMode() ? operationPutByIdStrict
: operationPutByIdNonStrict
, valueGPR
, baseGPR
, identifier(node
.identifierNumber()));
551 noResult(m_compileIndex
);
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();
562 callOperation(m_jit
.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict
: operationPutByIdDirectNonStrict
, valueGPR
, baseGPR
, identifier(node
.identifierNumber()));
563 noResult(m_compileIndex
);
568 GPRTemporary
result(this);
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());
574 jsValueResult(result
.gpr(), m_compileIndex
);
579 JSValueOperand
value(this, node
.child1
);
580 GPRTemporary
temp(this);
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()));
586 noResult(m_compileIndex
);
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
);
599 JSValueOperand
value(this, node
.child1
);
600 GPRReg valueGPR
= value
.gpr();
603 GPRResult
result(this);
604 callOperation(dfgConvertJSValueToBoolean
, result
.gpr(), valueGPR
);
606 BlockIndex taken
= m_jit
.graph().blockIndexForBytecodeOffset(node
.takenBytecodeOffset());
607 BlockIndex notTaken
= m_jit
.graph().blockIndexForBytecodeOffset(node
.notTakenBytecodeOffset());
609 addBranch(m_jit
.branchTest8(MacroAssembler::NonZero
, result
.gpr()), taken
);
610 if (notTaken
!= (m_block
+ 1))
611 addBranch(m_jit
.jump(), notTaken
);
613 noResult(m_compileIndex
);
618 ASSERT(GPRInfo::callFrameRegister
!= GPRInfo::regT1
);
619 ASSERT(GPRInfo::regT1
!= GPRInfo::returnValueGPR
);
620 ASSERT(GPRInfo::returnValueGPR
!= GPRInfo::callFrameRegister
);
622 #if DFG_SUCCESS_STATS
623 static SamplingCounter
counter("NonSpeculativeJIT");
624 m_jit
.emitCount(counter
);
627 // Return the result in returnValueGPR.
628 JSValueOperand
op1(this, node
.child1
);
629 m_jit
.move(op1
.gpr(), GPRInfo::returnValueGPR
);
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
);
636 m_jit
.restoreReturnAddressBeforeReturn(GPRInfo::regT1
);
639 noResult(m_compileIndex
);
644 ASSERT_NOT_REACHED();
647 if (node
.hasResult() && node
.mustGenerate())
651 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator
& checkIterator
, BasicBlock
& block
)
653 ASSERT(m_compileIndex
== block
.begin
);
654 m_blockHeads
[m_block
] = m_jit
.label();
656 #if DFG_JIT_BREAK_ON_EVERY_BLOCK
660 for (; m_compileIndex
< block
.end
; ++m_compileIndex
) {
661 Node
& node
= m_jit
.graph()[m_compileIndex
];
662 if (!node
.shouldGenerate())
665 #if DFG_DEBUG_VERBOSE
666 fprintf(stderr
, "NonSpeculativeJIT generating Node @%d at code offset 0x%x\n", (int)m_compileIndex
, m_jit
.debugOffset());
668 #if DFG_JIT_BREAK_ON_EVERY_NODE
673 compile(checkIterator
, node
);
678 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator
& checkIterator
)
680 // Check for speculation checks added at function entry (checking argument types).
681 if (checkIterator
.hasCheckAtIndex(m_compileIndex
))
682 trackEntry(m_jit
.label());
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
]);
690 } } // namespace JSC::DFG