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