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 "DFGJITCodeGenerator.h" 28 29 #if ENABLE(DFG_JIT) 30 31 #include "DFGNonSpeculativeJIT.h" 32 #include "DFGSpeculativeJIT.h" 33 #include "LinkBuffer.h" 34 35 namespace JSC { namespace DFG { 36 37 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat) 38 { 39 Node& node = m_jit.graph()[nodeIndex]; 40 VirtualRegister virtualRegister = node.virtualRegister; 41 GenerationInfo& info = m_generationInfo[virtualRegister]; 42 43 if (info.registerFormat() == DataFormatNone) { 44 GPRReg gpr = allocate(); 45 JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); 46 47 if (node.isConstant()) { 48 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 49 if (isInt32Constant(nodeIndex)) { 50 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg); 51 info.fillInteger(gpr); 52 returnFormat = DataFormatInteger; 53 return gpr; 54 } 55 if (isDoubleConstant(nodeIndex)) { 56 JSValue jsValue = jsNumber(valueOfDoubleConstant(nodeIndex)); 57 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); 58 } else { 59 ASSERT(isJSConstant(nodeIndex)); 60 JSValue jsValue = valueOfJSConstant(nodeIndex); 61 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); 62 } 63 } else { 64 ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger); 65 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 66 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); 67 } 68 69 // Since we statically know that we're filling an integer, and values 70 // in the RegisterFile are boxed, this must be DataFormatJSInteger. 71 // We will check this with a jitAssert below. 72 info.fillJSValue(gpr, DataFormatJSInteger); 73 unlock(gpr); 74 } 75 76 switch (info.registerFormat()) { 77 case DataFormatNone: 78 // Should have filled, above. 79 case DataFormatJSDouble: 80 case DataFormatDouble: 81 case DataFormatJS: 82 case DataFormatCell: 83 case DataFormatJSCell: 84 // Should only be calling this function if we know this operand to be integer. 85 ASSERT_NOT_REACHED(); 86 87 case DataFormatJSInteger: { 88 GPRReg gpr = info.gpr(); 89 m_gprs.lock(gpr); 90 m_jit.jitAssertIsJSInt32(gpr); 91 returnFormat = DataFormatJSInteger; 92 return gpr; 93 } 94 95 case DataFormatInteger: { 96 GPRReg gpr = info.gpr(); 97 m_gprs.lock(gpr); 98 m_jit.jitAssertIsInt32(gpr); 99 returnFormat = DataFormatInteger; 100 return gpr; 101 } 102 } 103 104 ASSERT_NOT_REACHED(); 105 return InvalidGPRReg; 106 } 107 108 FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex) 109 { 110 Node& node = m_jit.graph()[nodeIndex]; 111 VirtualRegister virtualRegister = node.virtualRegister; 112 GenerationInfo& info = m_generationInfo[virtualRegister]; 113 114 if (info.registerFormat() == DataFormatNone) { 115 GPRReg gpr = allocate(); 116 JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); 117 118 if (node.isConstant()) { 119 if (isInt32Constant(nodeIndex)) { 120 // FIXME: should not be reachable? 121 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg); 122 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 123 info.fillInteger(gpr); 124 unlock(gpr); 125 } else if (isDoubleConstant(nodeIndex)) { 126 FPRReg fpr = fprAllocate(); 127 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), reg); 128 m_jit.movePtrToDouble(reg, JITCompiler::fprToRegisterID(fpr)); 129 unlock(gpr); 130 131 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 132 info.fillDouble(fpr); 133 return fpr; 134 } else { 135 // FIXME: should not be reachable? 136 ASSERT(isJSConstant(nodeIndex)); 137 JSValue jsValue = valueOfJSConstant(nodeIndex); 138 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); 139 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 140 info.fillJSValue(gpr, DataFormatJS); 141 unlock(gpr); 142 } 143 } else { 144 DataFormat spillFormat = info.spillFormat(); 145 ASSERT(spillFormat & DataFormatJS); 146 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 147 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); 148 info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS); 149 unlock(gpr); 150 } 151 } 152 153 switch (info.registerFormat()) { 154 case DataFormatNone: 155 // Should have filled, above. 156 case DataFormatCell: 157 case DataFormatJSCell: 158 // Should only be calling this function if we know this operand to be numeric. 159 ASSERT_NOT_REACHED(); 160 161 case DataFormatJS: { 162 GPRReg jsValueGpr = info.gpr(); 163 m_gprs.lock(jsValueGpr); 164 FPRReg fpr = fprAllocate(); 165 GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register? 166 167 JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr); 168 JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); 169 JITCompiler::RegisterID tempReg = JITCompiler::gprToRegisterID(tempGpr); 170 171 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister); 172 173 m_jit.jitAssertIsJSDouble(jsValueGpr); 174 175 // First, if we get here we have a double encoded as a JSValue 176 m_jit.move(jsValueReg, tempReg); 177 m_jit.addPtr(JITCompiler::tagTypeNumberRegister, tempReg); 178 m_jit.movePtrToDouble(tempReg, fpReg); 179 JITCompiler::Jump hasUnboxedDouble = m_jit.jump(); 180 181 // Finally, handle integers. 182 isInteger.link(&m_jit); 183 m_jit.convertInt32ToDouble(jsValueReg, fpReg); 184 hasUnboxedDouble.link(&m_jit); 185 186 m_gprs.release(jsValueGpr); 187 m_gprs.unlock(jsValueGpr); 188 m_gprs.unlock(tempGpr); 189 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 190 info.fillDouble(fpr); 191 return fpr; 192 } 193 194 case DataFormatJSInteger: 195 case DataFormatInteger: { 196 FPRReg fpr = fprAllocate(); 197 GPRReg gpr = info.gpr(); 198 m_gprs.lock(gpr); 199 JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); 200 JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); 201 202 m_jit.convertInt32ToDouble(reg, fpReg); 203 204 m_gprs.release(gpr); 205 m_gprs.unlock(gpr); 206 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 207 info.fillDouble(fpr); 208 return fpr; 209 } 210 211 // Unbox the double 212 case DataFormatJSDouble: { 213 GPRReg gpr = info.gpr(); 214 FPRReg fpr = unboxDouble(gpr); 215 216 m_gprs.release(gpr); 217 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 218 219 info.fillDouble(fpr); 220 return fpr; 221 } 222 223 case DataFormatDouble: { 224 FPRReg fpr = info.fpr(); 225 m_fprs.lock(fpr); 226 return fpr; 227 } 228 } 229 230 ASSERT_NOT_REACHED(); 231 return InvalidFPRReg; 232 } 233 234 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex) 235 { 236 Node& node = m_jit.graph()[nodeIndex]; 237 VirtualRegister virtualRegister = node.virtualRegister; 238 GenerationInfo& info = m_generationInfo[virtualRegister]; 239 240 switch (info.registerFormat()) { 241 case DataFormatNone: { 242 GPRReg gpr = allocate(); 243 JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); 244 245 if (node.isConstant()) { 246 if (isInt32Constant(nodeIndex)) { 247 info.fillJSValue(gpr, DataFormatJSInteger); 248 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); 249 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); 250 } else if (isDoubleConstant(nodeIndex)) { 251 info.fillJSValue(gpr, DataFormatJSDouble); 252 JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex)); 253 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); 254 } else { 255 ASSERT(isJSConstant(nodeIndex)); 256 JSValue jsValue = valueOfJSConstant(nodeIndex); 257 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); 258 info.fillJSValue(gpr, DataFormatJS); 259 } 260 261 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 262 } else { 263 DataFormat spillFormat = info.spillFormat(); 264 ASSERT(spillFormat & DataFormatJS); 265 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 266 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); 267 info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS); 268 } 269 return gpr; 270 } 271 272 case DataFormatInteger: { 273 GPRReg gpr = info.gpr(); 274 // If the register has already been locked we need to take a copy. 275 // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger. 276 if (m_gprs.isLocked(gpr)) { 277 GPRReg result = allocate(); 278 m_jit.orPtr(JITCompiler::tagTypeNumberRegister, JITCompiler::gprToRegisterID(gpr), JITCompiler::gprToRegisterID(result)); 279 return result; 280 } 281 m_gprs.lock(gpr); 282 m_jit.orPtr(JITCompiler::tagTypeNumberRegister, JITCompiler::gprToRegisterID(gpr)); 283 info.fillJSValue(gpr, DataFormatJSInteger); 284 return gpr; 285 } 286 287 case DataFormatDouble: { 288 FPRReg fpr = info.fpr(); 289 GPRReg gpr = boxDouble(fpr); 290 291 // Update all info 292 info.fillJSValue(gpr, DataFormatJSDouble); 293 m_fprs.release(fpr); 294 m_gprs.retain(gpr, virtualRegister, SpillOrderJS); 295 296 return gpr; 297 } 298 299 case DataFormatCell: 300 // No retag required on JSVALUE64! 301 case DataFormatJS: 302 case DataFormatJSInteger: 303 case DataFormatJSDouble: 304 case DataFormatJSCell: { 305 GPRReg gpr = info.gpr(); 306 m_gprs.lock(gpr); 307 return gpr; 308 } 309 } 310 311 ASSERT_NOT_REACHED(); 312 return InvalidGPRReg; 313 } 314 315 void JITCodeGenerator::useChildren(Node& node) 316 { 317 NodeIndex child1 = node.child1; 318 if (child1 == NoNode) { 319 ASSERT(node.child2 == NoNode && node.child3 == NoNode); 320 return; 321 } 322 use(child1); 323 324 NodeIndex child2 = node.child2; 325 if (child2 == NoNode) { 326 ASSERT(node.child3 == NoNode); 327 return; 328 } 329 use(child2); 330 331 NodeIndex child3 = node.child3; 332 if (child3 == NoNode) 333 return; 334 use(child3); 335 } 336 337 #ifndef NDEBUG 338 static const char* dataFormatString(DataFormat format) 339 { 340 // These values correspond to the DataFormat enum. 341 const char* strings[] = { 342 "[ ]", 343 "[ i]", 344 "[ d]", 345 "[ c]", 346 "Err!", 347 "Err!", 348 "Err!", 349 "Err!", 350 "[J ]", 351 "[Ji]", 352 "[Jd]", 353 "[Jc]", 354 "Err!", 355 "Err!", 356 "Err!", 357 "Err!", 358 }; 359 return strings[format]; 360 } 361 362 void JITCodeGenerator::dump(const char* label) 363 { 364 if (label) 365 fprintf(stderr, "<%s>\n", label); 366 367 fprintf(stderr, " gprs:\n"); 368 m_gprs.dump(); 369 fprintf(stderr, " fprs:\n"); 370 m_fprs.dump(); 371 fprintf(stderr, " VirtualRegisters:\n"); 372 for (unsigned i = 0; i < m_generationInfo.size(); ++i) { 373 GenerationInfo& info = m_generationInfo[i]; 374 if (info.alive()) 375 fprintf(stderr, " % 3d:%s%s\n", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat())); 376 else 377 fprintf(stderr, " % 3d:[__][__]\n", i); 378 } 379 if (label) 380 fprintf(stderr, "</%s>\n", label); 381 } 382 #endif 383 384 385 #if DFG_CONSISTENCY_CHECK 386 void JITCodeGenerator::checkConsistency() 387 { 388 VirtualRegister grpContents[numberOfGPRs]; 389 VirtualRegister frpContents[numberOfFPRs]; 390 391 for (unsigned i = 0; i < numberOfGPRs; ++i) 392 grpContents[i] = InvalidVirtualRegister; 393 for (unsigned i = 0; i < numberOfFPRs; ++i) 394 frpContents[i] = InvalidVirtualRegister; 395 for (unsigned i = 0; i < m_generationInfo.size(); ++i) { 396 GenerationInfo& info = m_generationInfo[i]; 397 if (!info.alive()) 398 continue; 399 switch (info.registerFormat()) { 400 case DataFormatNone: 401 break; 402 case DataFormatInteger: 403 case DataFormatCell: 404 case DataFormatJS: 405 case DataFormatJSInteger: 406 case DataFormatJSDouble: 407 case DataFormatJSCell: { 408 GPRReg gpr = info.gpr(); 409 ASSERT(gpr != InvalidGPRReg); 410 grpContents[gpr] = (VirtualRegister)i; 411 break; 412 } 413 case DataFormatDouble: { 414 FPRReg fpr = info.fpr(); 415 ASSERT(fpr != InvalidFPRReg); 416 frpContents[fpr] = (VirtualRegister)i; 417 break; 418 } 419 } 420 } 421 422 for (GPRReg i = gpr0; i < numberOfGPRs; next(i)) { 423 if (m_gprs.isLocked(i) || m_gprs.name(i) != grpContents[i]) { 424 dump(); 425 CRASH(); 426 } 427 } 428 for (FPRReg i = fpr0; i < numberOfFPRs; next(i)) { 429 if (m_fprs.isLocked(i) || m_fprs.name(i) != frpContents[i]) { 430 dump(); 431 CRASH(); 432 } 433 } 434 } 435 #endif 436 437 GPRTemporary::GPRTemporary(JITCodeGenerator* jit) 438 : m_jit(jit) 439 , m_gpr(InvalidGPRReg) 440 { 441 m_gpr = m_jit->allocate(); 442 } 443 444 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1) 445 : m_jit(jit) 446 , m_gpr(InvalidGPRReg) 447 { 448 // locking into a register may free for reuse! 449 op1.gpr(); 450 if (m_jit->canReuse(op1.index())) 451 m_gpr = m_jit->reuse(op1.gpr()); 452 else 453 m_gpr = m_jit->allocate(); 454 } 455 456 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2) 457 : m_jit(jit) 458 , m_gpr(InvalidGPRReg) 459 { 460 // locking into a register may free for reuse! 461 op1.gpr(); 462 op2.gpr(); 463 if (m_jit->canReuse(op1.index())) 464 m_gpr = m_jit->reuse(op1.gpr()); 465 else if (m_jit->canReuse(op2.index())) 466 m_gpr = m_jit->reuse(op2.gpr()); 467 else 468 m_gpr = m_jit->allocate(); 469 } 470 471 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1) 472 : m_jit(jit) 473 , m_gpr(InvalidGPRReg) 474 { 475 // locking into a register may free for reuse! 476 op1.gpr(); 477 if (m_jit->canReuse(op1.index())) 478 m_gpr = m_jit->reuse(op1.gpr()); 479 else 480 m_gpr = m_jit->allocate(); 481 } 482 483 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2) 484 : m_jit(jit) 485 , m_gpr(InvalidGPRReg) 486 { 487 // locking into a register may free for reuse! 488 op1.gpr(); 489 op2.gpr(); 490 if (m_jit->canReuse(op1.index())) 491 m_gpr = m_jit->reuse(op1.gpr()); 492 else if (m_jit->canReuse(op2.index())) 493 m_gpr = m_jit->reuse(op2.gpr()); 494 else 495 m_gpr = m_jit->allocate(); 496 } 497 498 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1) 499 : m_jit(jit) 500 , m_gpr(InvalidGPRReg) 501 { 502 // locking into a register may free for reuse! 503 op1.gpr(); 504 if (m_jit->canReuse(op1.index())) 505 m_gpr = m_jit->reuse(op1.gpr()); 506 else 507 m_gpr = m_jit->allocate(); 508 } 509 510 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1) 511 : m_jit(jit) 512 , m_gpr(InvalidGPRReg) 513 { 514 // locking into a register may free for reuse! 515 op1.gpr(); 516 if (m_jit->canReuse(op1.index())) 517 m_gpr = m_jit->reuse(op1.gpr()); 518 else 519 m_gpr = m_jit->allocate(); 520 } 521 522 FPRTemporary::FPRTemporary(JITCodeGenerator* jit) 523 : m_jit(jit) 524 , m_fpr(InvalidFPRReg) 525 { 526 m_fpr = m_jit->fprAllocate(); 527 } 528 529 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1) 530 : m_jit(jit) 531 , m_fpr(InvalidFPRReg) 532 { 533 // locking into a register may free for reuse! 534 op1.fpr(); 535 if (m_jit->canReuse(op1.index())) 536 m_fpr = m_jit->reuse(op1.fpr()); 537 else 538 m_fpr = m_jit->fprAllocate(); 539 } 540 541 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2) 542 : m_jit(jit) 543 , m_fpr(InvalidFPRReg) 544 { 545 // locking into a register may free for reuse! 546 op1.fpr(); 547 op2.fpr(); 548 if (m_jit->canReuse(op1.index())) 549 m_fpr = m_jit->reuse(op1.fpr()); 550 else if (m_jit->canReuse(op2.index())) 551 m_fpr = m_jit->reuse(op2.fpr()); 552 else 553 m_fpr = m_jit->fprAllocate(); 554 } 555 556 } } // namespace JSC::DFG 557 558 #endif 559