]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGNonSpeculativeJIT.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / dfg / DFGNonSpeculativeJIT.cpp
CommitLineData
14957cd0
A
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
33namespace JSC { namespace DFG {
34
35const double twoToThe32 = (double)0x100000000ull;
36
37EntryLocation::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
59void 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
92void 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
113void 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
128bool 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
144bool 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
162void 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
651void 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
678void 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