1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "DFGNonSpeculativeJIT.h" 28 29 #include "DFGSpeculativeJIT.h" 30 31 #if ENABLE(DFG_JIT) 32 33 namespace JSC { namespace DFG { 34 35 const double twoToThe32 = (double)0x100000000ull; 36 37 EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit) 38 : m_entry(entry) 39 , m_nodeIndex(jit->m_compileIndex) 40 { 41 for (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 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 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 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 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 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 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 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 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