Changeset 100095 in webkit
- Timestamp:
- Nov 13, 2011 2:44:16 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r100086 r100095 1 2011-11-13 Yuqiang Xian <yuqiang.xian@intel.com> 2 3 Fix silent spilling/filling GPRs in DFG 32_64 4 https://bugs.webkit.org/show_bug.cgi?id=72201 5 6 Reviewed by Gavin Barraclough. 7 8 Current silentSpillGPR/silentFillGPR may not work as expected for some 9 cases in 32_64. If there's a JSValue which was retained by two GPRs, 10 we may end up failing to spill/fill some GPRs or redundantly 11 spilling/filling some GPRs. For example, if we tend to exclude "eax" 12 from spilling while a JSValue is retained by both "eax" and "edx", 13 then "edx" won't be spilled as well (wrong). And if another JSValue is 14 retained by "ecx" and "ebx", both "ecx" and "ebx" will be spilled 15 twice. The similar problem applies to silentFillGPR. 16 The fix is to make silentSpillGPR/silentFillGPR more straightforward, 17 i.e., spilling/filling based on the GPR instead of the virtual 18 register. FPR spilling/filling is also modified accordingly to make it 19 consistent with GPR spilling/filling. 20 21 * dfg/DFGJITCodeGenerator.h: 22 (JSC::DFG::JITCodeGenerator::silentSpillGPR): 23 (JSC::DFG::JITCodeGenerator::silentSpillFPR): 24 (JSC::DFG::JITCodeGenerator::silentFillGPR): 25 (JSC::DFG::JITCodeGenerator::silentFillFPR): 26 (JSC::DFG::JITCodeGenerator::silentSpillAllRegisters): 27 (JSC::DFG::JITCodeGenerator::silentFillAllRegisters): 28 1 29 2011-11-12 Laszlo Gombos <laszlo.1.gombos@nokia.com> 2 30 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r99904 r100095 263 263 void clearGenerationInfo(); 264 264 265 #if USE(JSVALUE32_64)266 bool registersMatched(GenerationInfo& info, GPRReg exclude, GPRReg exclude2)267 {268 ASSERT(info.registerFormat() != DataFormatNone);269 ASSERT(info.registerFormat() != DataFormatDouble);270 ASSERT(info.registerFormat() != DataFormatJSDouble);271 272 if (exclude == InvalidGPRReg && exclude2 == InvalidGPRReg)273 return false;274 275 bool matched = false;276 if (exclude2 == InvalidGPRReg)277 matched = (!(info.registerFormat() & DataFormatJS)) ? (info.gpr() == exclude) : (info.tagGPR() == exclude || info.payloadGPR() == exclude);278 else if (exclude == InvalidGPRReg)279 matched = (!(info.registerFormat() & DataFormatJS)) ? (info.gpr() == exclude2) : (info.tagGPR() == exclude2 || info.payloadGPR() == exclude2);280 else281 matched = (!(info.registerFormat() & DataFormatJS)) ? (info.gpr() == exclude || info.gpr() == exclude2) : (info.tagGPR() == exclude || info.tagGPR() == exclude2 || info.payloadGPR() == exclude || info.payloadGPR() == exclude2);282 return matched;283 }284 #endif285 286 265 // These methods are used when generating 'unexpected' 287 266 // calls out from JIT code to C++ helper routines - … … 289 268 // slots in the RegisterFile without changing any state 290 269 // in the GenerationInfo. 291 void silentSpillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg, GPRReg exclude2 = InvalidGPRReg)270 void silentSpillGPR(VirtualRegister spillMe, GPRReg source) 292 271 { 293 272 GenerationInfo& info = m_generationInfo[spillMe]; … … 295 274 ASSERT(info.registerFormat() != DataFormatDouble); 296 275 276 if (!info.needsSpill()) 277 return; 278 279 DataFormat registerFormat = info.registerFormat(); 280 297 281 #if USE(JSVALUE64) 298 UNUSED_PARAM(exclude2); 299 if (!info.needsSpill() || (info.gpr() == exclude)) 300 #elif USE(JSVALUE32_64) 301 if (!info.needsSpill() || registersMatched(info, exclude, exclude2)) 302 #endif 303 return; 304 305 DataFormat registerFormat = info.registerFormat(); 306 307 #if USE(JSVALUE64) 282 ASSERT(info.gpr() == source); 308 283 if (registerFormat == DataFormatInteger) 309 m_jit.store32( info.gpr(), JITCompiler::addressFor(spillMe));284 m_jit.store32(source, JITCompiler::addressFor(spillMe)); 310 285 else { 311 286 ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell || registerFormat == DataFormatStorage); 312 m_jit.storePtr( info.gpr(), JITCompiler::addressFor(spillMe));287 m_jit.storePtr(source, JITCompiler::addressFor(spillMe)); 313 288 } 314 289 #elif USE(JSVALUE32_64) 315 if (registerFormat == DataFormatInteger || registerFormat == DataFormatBoolean) 316 m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe)); 317 else if (registerFormat == DataFormatCell) 318 m_jit.storePtr(info.gpr(), JITCompiler::payloadFor(spillMe)); 319 else if (registerFormat == DataFormatStorage) 320 m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe)); 321 else { 322 ASSERT(registerFormat & DataFormatJS); 323 m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe)); 324 m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe)); 325 } 326 #endif 327 } 328 void silentSpillFPR(VirtualRegister spillMe, FPRReg exclude = InvalidFPRReg) 290 if (registerFormat & DataFormatJS) { 291 ASSERT(info.tagGPR() == source || info.payloadGPR() == source); 292 m_jit.store32(source, source == info.tagGPR() ? JITCompiler::tagFor(spillMe) : JITCompiler::payloadFor(spillMe)); 293 } else { 294 ASSERT(info.gpr() == source); 295 m_jit.store32(source, JITCompiler::payloadFor(spillMe)); 296 } 297 #endif 298 } 299 void silentSpillFPR(VirtualRegister spillMe, FPRReg source) 329 300 { 330 301 GenerationInfo& info = m_generationInfo[spillMe]; 331 302 ASSERT(info.registerFormat() == DataFormatDouble); 332 303 333 if (info.fpr() == exclude)334 return;335 304 if (!info.needsSpill()) { 336 305 // it's either a constant or it's already been spilled … … 342 311 ASSERT(!at(info.nodeIndex()).hasConstant()); 343 312 ASSERT(info.spillFormat() == DataFormatNone); 344 345 m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe)); 346 } 347 348 void silentFillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg, GPRReg exclude2 = InvalidGPRReg) 313 ASSERT(info.fpr() == source); 314 315 m_jit.storeDouble(source, JITCompiler::addressFor(spillMe)); 316 } 317 318 void silentFillGPR(VirtualRegister spillMe, GPRReg target) 349 319 { 350 320 GenerationInfo& info = m_generationInfo[spillMe]; 351 #if USE(JSVALUE64)352 UNUSED_PARAM(exclude2);353 if (info.gpr() == exclude)354 #elif USE(JSVALUE32_64)355 if (registersMatched(info, exclude, exclude2))356 #endif357 return;358 321 359 322 NodeIndex nodeIndex = info.nodeIndex(); … … 364 327 365 328 if (registerFormat == DataFormatInteger) { 329 ASSERT(info.gpr() == target); 366 330 ASSERT(isJSInteger(info.registerFormat())); 367 331 if (node.hasConstant()) { 368 332 ASSERT(isInt32Constant(nodeIndex)); 369 m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());333 m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), target); 370 334 } else 371 m_jit.load32(JITCompiler::payloadFor(spillMe), info.gpr());335 m_jit.load32(JITCompiler::payloadFor(spillMe), target); 372 336 return; 373 337 } … … 377 341 ASSERT_NOT_REACHED(); 378 342 #elif USE(JSVALUE32_64) 343 ASSERT(info.gpr() == target); 379 344 if (node.hasConstant()) { 380 345 ASSERT(isBooleanConstant(nodeIndex)); 381 m_jit.move(Imm32(valueOfBooleanConstant(nodeIndex)), info.gpr());346 m_jit.move(Imm32(valueOfBooleanConstant(nodeIndex)), target); 382 347 } else 383 m_jit.load32(JITCompiler::payloadFor(spillMe), info.gpr());348 m_jit.load32(JITCompiler::payloadFor(spillMe), target); 384 349 #endif 385 350 return; … … 387 352 388 353 if (registerFormat == DataFormatCell) { 354 ASSERT(info.gpr() == target); 389 355 if (node.isConstant()) { 390 356 JSValue value = valueOfJSConstant(nodeIndex); 391 357 ASSERT(value.isCell()); 392 m_jit.move(ImmPtr(value.asCell()), info.gpr());358 m_jit.move(ImmPtr(value.asCell()), target); 393 359 } else 394 m_jit.loadPtr(JITCompiler::payloadFor(spillMe), info.gpr());360 m_jit.loadPtr(JITCompiler::payloadFor(spillMe), target); 395 361 return; 396 362 } 397 363 398 364 if (registerFormat == DataFormatStorage) { 399 m_jit.loadPtr(JITCompiler::addressFor(spillMe), info.gpr()); 365 ASSERT(info.gpr() == target); 366 m_jit.loadPtr(JITCompiler::addressFor(spillMe), target); 400 367 return; 401 368 } … … 403 370 ASSERT(registerFormat & DataFormatJS); 404 371 #if USE(JSVALUE64) 372 ASSERT(info.gpr() == target); 405 373 if (node.hasConstant()) 406 m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), info.gpr());374 m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), target); 407 375 else if (info.spillFormat() == DataFormatInteger) { 408 376 ASSERT(registerFormat == DataFormatJSInteger); 409 m_jit.load32(JITCompiler::payloadFor(spillMe), info.gpr());410 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, info.gpr());377 m_jit.load32(JITCompiler::payloadFor(spillMe), target); 378 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, target); 411 379 } else if (info.spillFormat() == DataFormatDouble) { 412 380 ASSERT(registerFormat == DataFormatJSDouble); 413 m_jit.loadPtr(JITCompiler::addressFor(spillMe), info.gpr());414 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, info.gpr());381 m_jit.loadPtr(JITCompiler::addressFor(spillMe), target); 382 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, target); 415 383 } else 416 m_jit.loadPtr(JITCompiler::addressFor(spillMe), info.gpr());384 m_jit.loadPtr(JITCompiler::addressFor(spillMe), target); 417 385 #else 418 if (node.hasConstant()) 419 m_jit.emitLoad(valueOfJSConstant(nodeIndex), info.tagGPR(), info.payloadGPR()); 420 else if (info.spillFormat() == DataFormatInteger) { 386 ASSERT(info.tagGPR() == target || info.payloadGPR() == target); 387 if (node.hasConstant()) { 388 JSValue v = valueOfJSConstant(nodeIndex); 389 m_jit.move(info.tagGPR() == target ? Imm32(v.tag()) : Imm32(v.payload()), target); 390 } else if (info.spillFormat() == DataFormatInteger) { 421 391 ASSERT(registerFormat == DataFormatJSInteger); 422 m_jit.load32(JITCompiler::payloadFor(spillMe), info.payloadGPR()); 423 m_jit.move(TrustedImm32(JSValue::Int32Tag), info.tagGPR()); 392 if (info.payloadGPR() == target) 393 m_jit.load32(JITCompiler::payloadFor(spillMe), target); 394 else 395 m_jit.move(TrustedImm32(JSValue::Int32Tag), target); 424 396 } else 425 m_jit. emitLoad(nodeIndex, info.tagGPR(), info.payloadGPR());426 #endif 427 } 428 429 void silentFillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg exclude = InvalidFPRReg)397 m_jit.load32(info.tagGPR() == target ? JITCompiler::tagFor(spillMe) : JITCompiler::payloadFor(spillMe), target); 398 #endif 399 } 400 401 void silentFillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg target) 430 402 { 431 403 GenerationInfo& info = m_generationInfo[spillMe]; 432 if (info.fpr() == exclude) 433 return; 404 ASSERT(info.fpr() == target); 434 405 435 406 NodeIndex nodeIndex = info.nodeIndex(); … … 441 412 ASSERT(isNumberConstant(nodeIndex)); 442 413 m_jit.move(ImmPtr(bitwise_cast<void*>(valueOfNumberConstant(nodeIndex))), canTrample); 443 m_jit.movePtrToDouble(canTrample, info.fpr());414 m_jit.movePtrToDouble(canTrample, target); 444 415 return; 445 416 } … … 449 420 ASSERT(info.spillFormat() & DataFormatJS); 450 421 m_jit.loadPtr(JITCompiler::addressFor(spillMe), canTrample); 451 unboxDouble(canTrample, info.fpr());452 return; 453 } 454 455 m_jit.loadDouble(JITCompiler::addressFor(spillMe), info.fpr());422 unboxDouble(canTrample, target); 423 return; 424 } 425 426 m_jit.loadDouble(JITCompiler::addressFor(spillMe), target); 456 427 #elif USE(JSVALUE32_64) 457 428 UNUSED_PARAM(canTrample); 458 429 ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble); 459 m_jit.emitLoadDouble(nodeIndex, info.fpr());430 m_jit.emitLoadDouble(nodeIndex, target); 460 431 #endif 461 432 } 462 433 463 434 void silentSpillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg) 435 { 436 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 437 GPRReg gpr = iter.regID(); 438 if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2) 439 silentSpillGPR(iter.name(), gpr); 440 } 441 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 442 if (iter.name() != InvalidVirtualRegister) 443 silentSpillFPR(iter.name(), iter.regID()); 444 } 445 } 446 void silentSpillAllRegisters(FPRReg exclude) 464 447 { 465 448 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 466 449 if (iter.name() != InvalidVirtualRegister) 467 silentSpillGPR(iter.name(), exclude, exclude2);450 silentSpillGPR(iter.name(), iter.regID()); 468 451 } 469 452 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 470 if (iter.name() != InvalidVirtualRegister) 471 silentSpillFPR(iter.name()); 472 } 473 } 474 void silentSpillAllRegisters(FPRReg exclude) 475 { 476 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 477 if (iter.name() != InvalidVirtualRegister) 478 silentSpillGPR(iter.name()); 479 } 480 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 481 if (iter.name() != InvalidVirtualRegister) 482 silentSpillFPR(iter.name(), exclude); 453 FPRReg fpr = iter.regID(); 454 if (iter.name() != InvalidVirtualRegister && fpr != exclude) 455 silentSpillFPR(iter.name(), fpr); 483 456 } 484 457 } … … 492 465 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 493 466 if (iter.name() != InvalidVirtualRegister) 494 silentFillFPR(iter.name(), canTrample );467 silentFillFPR(iter.name(), canTrample, iter.regID()); 495 468 } 496 469 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 497 if (iter.name() != InvalidVirtualRegister) 498 silentFillGPR(iter.name(), exclude, exclude2); 470 GPRReg gpr = iter.regID(); 471 if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2) 472 silentFillGPR(iter.name(), gpr); 499 473 } 500 474 } … … 504 478 505 479 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 506 if (iter.name() != InvalidVirtualRegister) { 507 ASSERT_UNUSED(exclude, iter.regID() != exclude); 508 silentFillFPR(iter.name(), canTrample, exclude); 509 } 480 FPRReg fpr = iter.regID(); 481 if (iter.name() != InvalidVirtualRegister && fpr != exclude) 482 silentFillFPR(iter.name(), canTrample, fpr); 510 483 } 511 484 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 512 485 if (iter.name() != InvalidVirtualRegister) 513 silentFillGPR(iter.name() );486 silentFillGPR(iter.name(), iter.regID()); 514 487 } 515 488 }
Note: See TracChangeset
for help on using the changeset viewer.