Changeset 96377 in webkit
- Timestamp:
- Sep 29, 2011 4:29:09 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r96375 r96377 1 2011-09-29 Gavin Barraclough <barraclough@apple.com> 2 3 Refactor out trivially duplicated code in DFGJITCodeGenerator. 4 https://bugs.webkit.org/show_bug.cgi?id=69109 5 6 Reviewed by Oliver Hunt. 7 8 Some code is trivially redundant between DFGJITCodeGenerator.cpp & DFGJITCodeGenerator32_64.cpp 9 10 Basically move a JSVALUE64 specific code into a new DFGJITCodeGenerator64.cpp, leave common code 11 in DFGJITCodeGenerator.cpp, and remove copies from DFGJITCodeGenerator32_64.cpp. 12 13 For some function differences are trivial & make more sense to ifdef individually, and some 14 Operand methods make more sense left in DFGJITCodeGenerator.cpp alongside similar constructors. 15 16 * JavaScriptCore.xcodeproj/project.pbxproj: 17 * dfg/DFGJITCodeGenerator.cpp: 18 (JSC::DFG::JITCodeGenerator::isKnownNotNumber): 19 (JSC::DFG::JITCodeGenerator::isKnownBoolean): 20 (JSC::DFG::JITCodeGenerator::writeBarrier): 21 (JSC::DFG::JITCodeGenerator::dump): 22 (JSC::DFG::JITCodeGenerator::checkConsistency): 23 (JSC::DFG::GPRTemporary::GPRTemporary): 24 (JSC::DFG::FPRTemporary::FPRTemporary): 25 * dfg/DFGJITCodeGenerator32_64.cpp: 26 * dfg/DFGJITCodeGenerator64.cpp: Copied from Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp. 27 * dfg/DFGJITCompiler.h: 28 (JSC::DFG::JITCompiler::branchIfNotCell): 29 * dfg/DFGJITCompilerInlineMethods.h: 30 1 31 2011-09-28 Filip Pizlo <fpizlo@apple.com> 2 32 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r96375 r96377 304 304 86880F1E14328BB900B08D42 /* DFGJITCompilerInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 86880F1A14328BB900B08D42 /* DFGJITCompilerInlineMethods.h */; }; 305 305 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */; }; 306 86880F44143531A800B08D42 /* DFGJITCodeGenerator64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F43143531A700B08D42 /* DFGJITCodeGenerator64.cpp */; }; 306 307 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; }; 307 308 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA01117CEFD100B908B1 /* AtomicString.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1070 1071 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT32_64.cpp; path = dfg/DFGSpeculativeJIT32_64.cpp; sourceTree = "<group>"; }; 1071 1072 86880F311434FFAF00B08D42 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; }; 1073 86880F43143531A700B08D42 /* DFGJITCodeGenerator64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGJITCodeGenerator64.cpp; path = dfg/DFGJITCodeGenerator64.cpp; sourceTree = "<group>"; }; 1072 1074 868BFA00117CEFD100B908B1 /* AtomicString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AtomicString.cpp; path = text/AtomicString.cpp; sourceTree = "<group>"; }; 1073 1075 868BFA01117CEFD100B908B1 /* AtomicString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicString.h; path = text/AtomicString.h; sourceTree = "<group>"; }; … … 2281 2283 86EC9DBA1328DF82002B2AD7 /* DFGJITCodeGenerator.h */, 2282 2284 86880F1814328BB900B08D42 /* DFGJITCodeGenerator32_64.cpp */, 2285 86880F43143531A700B08D42 /* DFGJITCodeGenerator64.cpp */, 2283 2286 86EC9DBB1328DF82002B2AD7 /* DFGJITCompiler.cpp */, 2284 2287 86EC9DBC1328DF82002B2AD7 /* DFGJITCompiler.h */, … … 3381 3384 86880F1D14328BB900B08D42 /* DFGJITCompiler32_64.cpp in Sources */, 3382 3385 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */, 3386 86880F44143531A800B08D42 /* DFGJITCodeGenerator64.cpp in Sources */, 3383 3387 ); 3384 3388 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r96372 r96377 28 28 29 29 #if ENABLE(DFG_JIT) 30 #if USE(JSVALUE64) 31 30 31 #include "DFGJITCompilerInlineMethods.h" 32 32 #include "DFGSpeculativeJIT.h" 33 33 #include "LinkBuffer.h" … … 43 43 m_gprs = RegisterBank<GPRInfo>(); 44 44 m_fprs = RegisterBank<FPRInfo>(); 45 }46 47 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)48 {49 Node& node = m_jit.graph()[nodeIndex];50 VirtualRegister virtualRegister = node.virtualRegister();51 GenerationInfo& info = m_generationInfo[virtualRegister];52 53 if (info.registerFormat() == DataFormatNone) {54 GPRReg gpr = allocate();55 56 if (node.hasConstant()) {57 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);58 if (isInt32Constant(nodeIndex)) {59 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);60 info.fillInteger(gpr);61 returnFormat = DataFormatInteger;62 return gpr;63 }64 if (isNumberConstant(nodeIndex)) {65 JSValue jsValue = jsNumber(valueOfNumberConstant(nodeIndex));66 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);67 } else {68 ASSERT(isJSConstant(nodeIndex));69 JSValue jsValue = valueOfJSConstant(nodeIndex);70 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);71 }72 } else {73 ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);74 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);75 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);76 }77 78 // Since we statically know that we're filling an integer, and values79 // in the RegisterFile are boxed, this must be DataFormatJSInteger.80 // We will check this with a jitAssert below.81 info.fillJSValue(gpr, DataFormatJSInteger);82 unlock(gpr);83 }84 85 switch (info.registerFormat()) {86 case DataFormatNone:87 // Should have filled, above.88 case DataFormatJSDouble:89 case DataFormatDouble:90 case DataFormatJS:91 case DataFormatCell:92 case DataFormatJSCell:93 case DataFormatBoolean:94 case DataFormatJSBoolean:95 case DataFormatStorage:96 // Should only be calling this function if we know this operand to be integer.97 ASSERT_NOT_REACHED();98 99 case DataFormatJSInteger: {100 GPRReg gpr = info.gpr();101 m_gprs.lock(gpr);102 m_jit.jitAssertIsJSInt32(gpr);103 returnFormat = DataFormatJSInteger;104 return gpr;105 }106 107 case DataFormatInteger: {108 GPRReg gpr = info.gpr();109 m_gprs.lock(gpr);110 m_jit.jitAssertIsInt32(gpr);111 returnFormat = DataFormatInteger;112 return gpr;113 }114 }115 116 ASSERT_NOT_REACHED();117 return InvalidGPRReg;118 }119 120 FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)121 {122 Node& node = m_jit.graph()[nodeIndex];123 VirtualRegister virtualRegister = node.virtualRegister();124 GenerationInfo& info = m_generationInfo[virtualRegister];125 126 if (info.registerFormat() == DataFormatNone) {127 GPRReg gpr = allocate();128 129 if (node.hasConstant()) {130 if (isInt32Constant(nodeIndex)) {131 // FIXME: should not be reachable?132 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);133 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);134 info.fillInteger(gpr);135 unlock(gpr);136 } else if (isNumberConstant(nodeIndex)) {137 FPRReg fpr = fprAllocate();138 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);139 m_jit.movePtrToDouble(gpr, fpr);140 unlock(gpr);141 142 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);143 info.fillDouble(fpr);144 return fpr;145 } else {146 // FIXME: should not be reachable?147 ASSERT(isJSConstant(nodeIndex));148 JSValue jsValue = valueOfJSConstant(nodeIndex);149 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);150 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);151 info.fillJSValue(gpr, DataFormatJS);152 unlock(gpr);153 }154 } else {155 DataFormat spillFormat = info.spillFormat();156 ASSERT(spillFormat & DataFormatJS);157 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);158 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);159 info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);160 unlock(gpr);161 }162 }163 164 switch (info.registerFormat()) {165 case DataFormatNone:166 // Should have filled, above.167 case DataFormatCell:168 case DataFormatJSCell:169 case DataFormatBoolean:170 case DataFormatJSBoolean:171 case DataFormatStorage:172 // Should only be calling this function if we know this operand to be numeric.173 ASSERT_NOT_REACHED();174 175 case DataFormatJS: {176 GPRReg jsValueGpr = info.gpr();177 m_gprs.lock(jsValueGpr);178 FPRReg fpr = fprAllocate();179 GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?180 181 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);182 183 m_jit.jitAssertIsJSDouble(jsValueGpr);184 185 // First, if we get here we have a double encoded as a JSValue186 m_jit.move(jsValueGpr, tempGpr);187 unboxDouble(tempGpr, fpr);188 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();189 190 // Finally, handle integers.191 isInteger.link(&m_jit);192 m_jit.convertInt32ToDouble(jsValueGpr, fpr);193 hasUnboxedDouble.link(&m_jit);194 195 m_gprs.release(jsValueGpr);196 m_gprs.unlock(jsValueGpr);197 m_gprs.unlock(tempGpr);198 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);199 info.fillDouble(fpr);200 info.killSpilled();201 return fpr;202 }203 204 case DataFormatJSInteger:205 case DataFormatInteger: {206 FPRReg fpr = fprAllocate();207 GPRReg gpr = info.gpr();208 m_gprs.lock(gpr);209 m_jit.convertInt32ToDouble(gpr, fpr);210 m_gprs.unlock(gpr);211 return fpr;212 }213 214 // Unbox the double215 case DataFormatJSDouble: {216 GPRReg gpr = info.gpr();217 FPRReg fpr = fprAllocate();218 if (m_gprs.isLocked(gpr)) {219 // Make sure we don't trample gpr if it is in use.220 GPRReg temp = allocate();221 m_jit.move(gpr, temp);222 unboxDouble(temp, fpr);223 unlock(temp);224 } else225 unboxDouble(gpr, fpr);226 227 m_gprs.release(gpr);228 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);229 230 info.fillDouble(fpr);231 return fpr;232 }233 234 case DataFormatDouble: {235 FPRReg fpr = info.fpr();236 m_fprs.lock(fpr);237 return fpr;238 }239 }240 241 ASSERT_NOT_REACHED();242 return InvalidFPRReg;243 }244 245 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)246 {247 Node& node = m_jit.graph()[nodeIndex];248 VirtualRegister virtualRegister = node.virtualRegister();249 GenerationInfo& info = m_generationInfo[virtualRegister];250 251 switch (info.registerFormat()) {252 case DataFormatNone: {253 GPRReg gpr = allocate();254 255 if (node.hasConstant()) {256 if (isInt32Constant(nodeIndex)) {257 info.fillJSValue(gpr, DataFormatJSInteger);258 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));259 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);260 } else if (isNumberConstant(nodeIndex)) {261 info.fillJSValue(gpr, DataFormatJSDouble);262 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(nodeIndex));263 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);264 } else {265 ASSERT(isJSConstant(nodeIndex));266 JSValue jsValue = valueOfJSConstant(nodeIndex);267 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);268 info.fillJSValue(gpr, DataFormatJS);269 }270 271 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);272 } else {273 DataFormat spillFormat = info.spillFormat();274 ASSERT(spillFormat & DataFormatJS);275 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);276 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);277 info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);278 }279 return gpr;280 }281 282 case DataFormatInteger: {283 GPRReg gpr = info.gpr();284 // If the register has already been locked we need to take a copy.285 // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.286 if (m_gprs.isLocked(gpr)) {287 GPRReg result = allocate();288 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);289 return result;290 }291 m_gprs.lock(gpr);292 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);293 info.fillJSValue(gpr, DataFormatJSInteger);294 return gpr;295 }296 297 case DataFormatDouble: {298 FPRReg fpr = info.fpr();299 GPRReg gpr = boxDouble(fpr);300 301 // Update all info302 info.fillJSValue(gpr, DataFormatJSDouble);303 m_fprs.release(fpr);304 m_gprs.retain(gpr, virtualRegister, SpillOrderJS);305 306 return gpr;307 }308 309 case DataFormatCell:310 // No retag required on JSVALUE64!311 case DataFormatJS:312 case DataFormatJSInteger:313 case DataFormatJSDouble:314 case DataFormatJSCell:315 case DataFormatJSBoolean: {316 GPRReg gpr = info.gpr();317 m_gprs.lock(gpr);318 return gpr;319 }320 321 case DataFormatBoolean:322 case DataFormatStorage:323 // this type currently never occurs324 ASSERT_NOT_REACHED();325 }326 327 ASSERT_NOT_REACHED();328 return InvalidGPRReg;329 45 } 330 46 … … 476 192 } 477 193 478 void JITCodeGenerator::nonSpeculativeValueToNumber(Node& node)479 {480 if (isKnownNumeric(node.child1())) {481 JSValueOperand op1(this, node.child1());482 GPRTemporary result(this, op1);483 m_jit.move(op1.gpr(), result.gpr());484 jsValueResult(result.gpr(), m_compileIndex);485 return;486 }487 488 JSValueOperand op1(this, node.child1());489 GPRTemporary result(this);490 491 ASSERT(!isInt32Constant(node.child1()));492 ASSERT(!isNumberConstant(node.child1()));493 494 GPRReg jsValueGpr = op1.gpr();495 GPRReg gpr = result.gpr();496 op1.use();497 498 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);499 JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);500 501 // First, if we get here we have a double encoded as a JSValue502 m_jit.move(jsValueGpr, gpr);503 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();504 505 // Next handle cells (& other JS immediates)506 nonNumeric.link(&m_jit);507 silentSpillAllRegisters(gpr);508 m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);509 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);510 appendCallWithExceptionCheck(dfgConvertJSValueToNumber);511 boxDouble(FPRInfo::returnValueFPR, gpr);512 silentFillAllRegisters(gpr);513 JITCompiler::Jump hasCalledToNumber = m_jit.jump();514 515 // Finally, handle integers.516 isInteger.link(&m_jit);517 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);518 hasUnboxedDouble.link(&m_jit);519 hasCalledToNumber.link(&m_jit);520 521 jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);522 }523 524 void JITCodeGenerator::nonSpeculativeValueToInt32(Node& node)525 {526 ASSERT(!isInt32Constant(node.child1()));527 528 if (isKnownInteger(node.child1())) {529 IntegerOperand op1(this, node.child1());530 GPRTemporary result(this, op1);531 m_jit.move(op1.gpr(), result.gpr());532 integerResult(result.gpr(), m_compileIndex);533 return;534 }535 536 GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1()].virtualRegister()];537 if (isJSDouble(childInfo.registerFormat())) {538 DoubleOperand op1(this, node.child1());539 GPRTemporary result(this);540 FPRReg fpr = op1.fpr();541 GPRReg gpr = result.gpr();542 op1.use();543 JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);544 545 silentSpillAllRegisters(gpr);546 547 m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);548 appendCallWithExceptionCheck(toInt32);549 m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);550 551 silentFillAllRegisters(gpr);552 553 truncatedToInteger.link(&m_jit);554 integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);555 return;556 }557 558 JSValueOperand op1(this, node.child1());559 GPRTemporary result(this, op1);560 GPRReg jsValueGpr = op1.gpr();561 GPRReg resultGPR = result.gpr();562 op1.use();563 564 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);565 566 // First handle non-integers567 silentSpillAllRegisters(resultGPR);568 m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);569 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);570 appendCallWithExceptionCheck(dfgConvertJSValueToInt32);571 m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, resultGPR);572 silentFillAllRegisters(resultGPR);573 JITCompiler::Jump hasCalledToInt32 = m_jit.jump();574 575 // Then handle integers.576 isInteger.link(&m_jit);577 m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);578 hasCalledToInt32.link(&m_jit);579 integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);580 }581 582 void JITCodeGenerator::nonSpeculativeUInt32ToNumber(Node& node)583 {584 IntegerOperand op1(this, node.child1());585 FPRTemporary boxer(this);586 GPRTemporary result(this, op1);587 588 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));589 590 m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());591 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr());592 593 boxDouble(boxer.fpr(), result.gpr());594 595 JITCompiler::Jump done = m_jit.jump();596 597 positive.link(&m_jit);598 599 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());600 601 done.link(&m_jit);602 603 jsValueResult(result.gpr(), m_compileIndex);604 }605 606 void JITCodeGenerator::nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)607 {608 JSValueOperand regArg(this, regChild);609 GPRReg regArgGPR = regArg.gpr();610 GPRTemporary result(this);611 GPRReg resultGPR = result.gpr();612 FPRTemporary tmp1(this);613 FPRTemporary tmp2(this);614 FPRReg tmp1FPR = tmp1.fpr();615 FPRReg tmp2FPR = tmp2.fpr();616 617 regArg.use();618 use(immChild);619 620 JITCompiler::Jump notInt;621 622 int32_t imm = valueOfInt32Constant(immChild);623 624 if (!isKnownInteger(regChild))625 notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);626 627 JITCompiler::Jump overflow;628 629 switch (op) {630 case ValueAdd:631 case ArithAdd:632 overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);633 break;634 635 case ArithSub:636 overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);637 break;638 639 default:640 ASSERT_NOT_REACHED();641 }642 643 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);644 645 JITCompiler::Jump done = m_jit.jump();646 647 overflow.link(&m_jit);648 649 JITCompiler::Jump notNumber;650 651 // first deal with overflow case652 m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR);653 654 // now deal with not-int case, if applicable655 if (!isKnownInteger(regChild)) {656 JITCompiler::Jump haveValue = m_jit.jump();657 658 notInt.link(&m_jit);659 660 if (!isKnownNumeric(regChild)) {661 ASSERT(op == ValueAdd);662 notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister);663 }664 665 m_jit.move(regArgGPR, resultGPR);666 m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR);667 m_jit.movePtrToDouble(resultGPR, tmp2FPR);668 669 haveValue.link(&m_jit);670 }671 672 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR);673 m_jit.movePtrToDouble(resultGPR, tmp1FPR);674 switch (op) {675 case ValueAdd:676 case ArithAdd:677 m_jit.addDouble(tmp1FPR, tmp2FPR);678 break;679 680 case ArithSub:681 m_jit.subDouble(tmp1FPR, tmp2FPR);682 break;683 684 default:685 ASSERT_NOT_REACHED();686 }687 688 JITCompiler::Jump doneCaseConvertedToInt;689 690 if (op == ValueAdd) {691 JITCompiler::JumpList failureCases;692 m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR);693 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);694 695 doneCaseConvertedToInt = m_jit.jump();696 697 failureCases.link(&m_jit);698 }699 700 m_jit.moveDoubleToPtr(tmp2FPR, resultGPR);701 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR);702 703 if (!isKnownNumeric(regChild)) {704 ASSERT(notNumber.isSet());705 ASSERT(op == ValueAdd);706 707 JITCompiler::Jump doneCaseWasNumber = m_jit.jump();708 709 notNumber.link(&m_jit);710 711 silentSpillAllRegisters(resultGPR);712 if (commute) {713 m_jit.move(regArgGPR, GPRInfo::argumentGPR2);714 m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);715 } else {716 m_jit.move(regArgGPR, GPRInfo::argumentGPR1);717 m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR2);718 }719 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);720 appendCallWithExceptionCheck(operationValueAddNotNumber);721 m_jit.move(GPRInfo::returnValueGPR, resultGPR);722 silentFillAllRegisters(resultGPR);723 724 doneCaseWasNumber.link(&m_jit);725 }726 727 done.link(&m_jit);728 if (doneCaseConvertedToInt.isSet())729 doneCaseConvertedToInt.link(&m_jit);730 731 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);732 }733 734 void JITCodeGenerator::nonSpeculativeBasicArithOp(NodeType op, Node &node)735 {736 JSValueOperand arg1(this, node.child1());737 JSValueOperand arg2(this, node.child2());738 739 FPRTemporary tmp1(this);740 FPRTemporary tmp2(this);741 FPRReg tmp1FPR = tmp1.fpr();742 FPRReg tmp2FPR = tmp2.fpr();743 744 GPRTemporary result(this);745 746 GPRReg arg1GPR = arg1.gpr();747 GPRReg arg2GPR = arg2.gpr();748 749 GPRReg resultGPR = result.gpr();750 751 arg1.use();752 arg2.use();753 754 JITCompiler::Jump child1NotInt;755 JITCompiler::Jump child2NotInt;756 JITCompiler::JumpList overflow;757 758 if (!isKnownInteger(node.child1()))759 child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister);760 if (!isKnownInteger(node.child2()))761 child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);762 763 switch (op) {764 case ValueAdd:765 case ArithAdd: {766 overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));767 break;768 }769 770 case ArithSub: {771 overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));772 break;773 }774 775 case ArithMul: {776 overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));777 overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));778 break;779 }780 781 default:782 ASSERT_NOT_REACHED();783 }784 785 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);786 787 JITCompiler::Jump done = m_jit.jump();788 789 JITCompiler::JumpList haveFPRArguments;790 791 overflow.link(&m_jit);792 793 // both arguments are integers794 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);795 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);796 797 haveFPRArguments.append(m_jit.jump());798 799 JITCompiler::JumpList notNumbers;800 801 JITCompiler::Jump child2NotInt2;802 803 if (!isKnownInteger(node.child1())) {804 child1NotInt.link(&m_jit);805 806 if (!isKnownNumeric(node.child1())) {807 ASSERT(op == ValueAdd);808 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister));809 }810 811 m_jit.move(arg1GPR, resultGPR);812 unboxDouble(resultGPR, tmp1FPR);813 814 // child1 is converted to a double; child2 may either be an int or815 // a boxed double816 817 if (!isKnownInteger(node.child2())) {818 if (isKnownNumeric(node.child2()))819 child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);820 else {821 ASSERT(op == ValueAdd);822 JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);823 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));824 child2NotInt2 = m_jit.jump();825 child2IsInt.link(&m_jit);826 }827 }828 829 // child 2 is definitely an integer830 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);831 832 haveFPRArguments.append(m_jit.jump());833 }834 835 if (!isKnownInteger(node.child2())) {836 child2NotInt.link(&m_jit);837 838 if (!isKnownNumeric(node.child2())) {839 ASSERT(op == ValueAdd);840 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));841 }842 843 // child1 is definitely an integer, and child 2 is definitely not844 845 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);846 847 if (child2NotInt2.isSet())848 child2NotInt2.link(&m_jit);849 850 m_jit.move(arg2GPR, resultGPR);851 unboxDouble(resultGPR, tmp2FPR);852 }853 854 haveFPRArguments.link(&m_jit);855 856 switch (op) {857 case ValueAdd:858 case ArithAdd:859 m_jit.addDouble(tmp2FPR, tmp1FPR);860 break;861 862 case ArithSub:863 m_jit.subDouble(tmp2FPR, tmp1FPR);864 break;865 866 case ArithMul:867 m_jit.mulDouble(tmp2FPR, tmp1FPR);868 break;869 870 default:871 ASSERT_NOT_REACHED();872 }873 874 JITCompiler::Jump doneCaseConvertedToInt;875 876 if (op == ValueAdd) {877 JITCompiler::JumpList failureCases;878 m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR);879 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);880 881 doneCaseConvertedToInt = m_jit.jump();882 883 failureCases.link(&m_jit);884 }885 886 boxDouble(tmp1FPR, resultGPR);887 888 if (!notNumbers.empty()) {889 ASSERT(op == ValueAdd);890 891 JITCompiler::Jump doneCaseWasNumber = m_jit.jump();892 893 notNumbers.link(&m_jit);894 895 silentSpillAllRegisters(resultGPR);896 setupStubArguments(arg1GPR, arg2GPR);897 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);898 appendCallWithExceptionCheck(operationValueAddNotNumber);899 m_jit.move(GPRInfo::returnValueGPR, resultGPR);900 silentFillAllRegisters(resultGPR);901 902 doneCaseWasNumber.link(&m_jit);903 }904 905 done.link(&m_jit);906 if (doneCaseConvertedToInt.isSet())907 doneCaseConvertedToInt.link(&m_jit);908 909 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);910 }911 912 void JITCodeGenerator::nonSpeculativeArithMod(Node& node)913 {914 JSValueOperand op1(this, node.child1());915 JSValueOperand op2(this, node.child2());916 GPRTemporary eax(this, X86Registers::eax);917 GPRTemporary edx(this, X86Registers::edx);918 919 FPRTemporary op1Double(this);920 FPRTemporary op2Double(this);921 922 GPRReg op1GPR = op1.gpr();923 GPRReg op2GPR = op2.gpr();924 925 FPRReg op1FPR = op1Double.fpr();926 FPRReg op2FPR = op2Double.fpr();927 928 op1.use();929 op2.use();930 931 GPRReg temp2 = InvalidGPRReg;932 GPRReg unboxGPR;933 if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {934 temp2 = allocate();935 m_jit.move(op2GPR, temp2);936 op2GPR = temp2;937 unboxGPR = temp2;938 } else if (op1GPR == X86Registers::eax)939 unboxGPR = X86Registers::edx;940 else941 unboxGPR = X86Registers::eax;942 ASSERT(unboxGPR != op1.gpr());943 ASSERT(unboxGPR != op2.gpr());944 945 JITCompiler::Jump firstOpNotInt;946 JITCompiler::Jump secondOpNotInt;947 JITCompiler::JumpList done;948 JITCompiler::Jump modByZero;949 950 if (!isKnownInteger(node.child1()))951 firstOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op1GPR, GPRInfo::tagTypeNumberRegister);952 if (!isKnownInteger(node.child2()))953 secondOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister);954 955 modByZero = m_jit.branchTest32(MacroAssembler::Zero, op2GPR);956 957 m_jit.move(op1GPR, eax.gpr());958 m_jit.assembler().cdq();959 m_jit.assembler().idivl_r(op2GPR);960 961 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, X86Registers::edx);962 963 done.append(m_jit.jump());964 965 JITCompiler::Jump gotDoubleArgs;966 967 modByZero.link(&m_jit);968 969 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(std::numeric_limits<double>::quiet_NaN()))), X86Registers::edx);970 done.append(m_jit.jump());971 972 if (!isKnownInteger(node.child1())) {973 firstOpNotInt.link(&m_jit);974 975 JITCompiler::Jump secondOpNotInt2;976 977 if (!isKnownInteger(node.child2()))978 secondOpNotInt2 = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister);979 980 // first op is a double, second op is an int.981 m_jit.convertInt32ToDouble(op2GPR, op2FPR);982 983 if (!isKnownInteger(node.child2())) {984 JITCompiler::Jump gotSecondOp = m_jit.jump();985 986 secondOpNotInt2.link(&m_jit);987 988 // first op is a double, second op is a double.989 m_jit.move(op2GPR, unboxGPR);990 unboxDouble(unboxGPR, op2FPR);991 992 gotSecondOp.link(&m_jit);993 }994 995 m_jit.move(op1GPR, unboxGPR);996 unboxDouble(unboxGPR, op1FPR);997 998 gotDoubleArgs = m_jit.jump();999 }1000 1001 if (!isKnownInteger(node.child2())) {1002 secondOpNotInt.link(&m_jit);1003 1004 // we know that the first op is an int, and the second is a double1005 m_jit.convertInt32ToDouble(op1GPR, op1FPR);1006 m_jit.move(op2GPR, unboxGPR);1007 unboxDouble(unboxGPR, op2FPR);1008 }1009 1010 if (!isKnownInteger(node.child1()))1011 gotDoubleArgs.link(&m_jit);1012 1013 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {1014 silentSpillAllRegisters(X86Registers::edx);1015 setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(op1FPR, op2FPR);1016 m_jit.appendCall(fmod);1017 boxDouble(FPRInfo::returnValueFPR, X86Registers::edx);1018 silentFillAllRegisters(X86Registers::edx);1019 }1020 1021 done.link(&m_jit);1022 1023 if (temp2 != InvalidGPRReg)1024 unlock(temp2);1025 1026 jsValueResult(X86Registers::edx, m_compileIndex, UseChildrenCalledExplicitly);1027 }1028 1029 void JITCodeGenerator::nonSpeculativeCheckHasInstance(Node& node)1030 {1031 JSValueOperand base(this, node.child1());1032 GPRTemporary structure(this);1033 1034 GPRReg baseReg = base.gpr();1035 GPRReg structureReg = structure.gpr();1036 1037 // Check that base is a cell.1038 MacroAssembler::Jump baseNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseReg, GPRInfo::tagMaskRegister);1039 1040 // Check that base 'ImplementsHasInstance'.1041 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureReg);1042 MacroAssembler::Jump implementsHasInstance = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(structureReg, Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsHasInstance));1043 1044 // At this point we always throw, so no need to preserve registers.1045 baseNotCell.link(&m_jit);1046 m_jit.move(baseReg, GPRInfo::argumentGPR1);1047 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1048 // At some point we could optimize this to plant a direct jump, rather then checking1049 // for an exception (operationThrowHasInstanceError always throws). Probably not worth1050 // adding the extra interface to do this now, but we may also want this for op_throw.1051 appendCallWithExceptionCheck(operationThrowHasInstanceError);1052 1053 implementsHasInstance.link(&m_jit);1054 noResult(m_compileIndex);1055 }1056 1057 void JITCodeGenerator::nonSpeculativeInstanceOf(Node& node)1058 {1059 JSValueOperand value(this, node.child1());1060 JSValueOperand base(this, node.child2());1061 JSValueOperand prototype(this, node.child3());1062 GPRTemporary scratch(this, base);1063 1064 GPRReg valueReg = value.gpr();1065 GPRReg baseReg = base.gpr();1066 GPRReg prototypeReg = prototype.gpr();1067 GPRReg scratchReg = scratch.gpr();1068 1069 value.use();1070 base.use();1071 prototype.use();1072 1073 // Check that operands are cells (base is checked by CheckHasInstance, so we can just assert).1074 MacroAssembler::Jump valueNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueReg, GPRInfo::tagMaskRegister);1075 m_jit.jitAssertIsCell(baseReg);1076 MacroAssembler::Jump prototypeNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, prototypeReg, GPRInfo::tagMaskRegister);1077 1078 // Check that baseVal 'ImplementsDefaultHasInstance'.1079 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), scratchReg);1080 MacroAssembler::Jump notDefaultHasInstance = m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance));1081 1082 // Check that prototype is an object1083 m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);1084 MacroAssembler::Jump protoNotObject = m_jit.branchIfNotObject(scratchReg);1085 1086 // Initialize scratchReg with the value being checked.1087 m_jit.move(valueReg, scratchReg);1088 1089 // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.1090 MacroAssembler::Label loop(&m_jit);1091 m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);1092 m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);1093 MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);1094 m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);1095 1096 // No match - result is false.1097 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);1098 MacroAssembler::Jump wasNotInstance = m_jit.jump();1099 1100 // Link to here if any checks fail that require us to try calling out to an operation to help,1101 // e.g. for an API overridden HasInstance.1102 valueNotCell.link(&m_jit);1103 prototypeNotCell.link(&m_jit);1104 notDefaultHasInstance.link(&m_jit);1105 protoNotObject.link(&m_jit);1106 1107 silentSpillAllRegisters(scratchReg);1108 setupStubArguments(valueReg, baseReg, prototypeReg);1109 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1110 appendCallWithExceptionCheck(operationInstanceOf);1111 m_jit.move(GPRInfo::returnValueGPR, scratchReg);1112 silentFillAllRegisters(scratchReg);1113 1114 MacroAssembler::Jump wasNotDefaultHasInstance = m_jit.jump();1115 1116 isInstance.link(&m_jit);1117 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);1118 1119 wasNotInstance.link(&m_jit);1120 wasNotDefaultHasInstance.link(&m_jit);1121 jsValueResult(scratchReg, m_compileIndex, UseChildrenCalledExplicitly);1122 }1123 1124 JITCompiler::Call JITCodeGenerator::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, NodeType nodeType)1125 {1126 JITCompiler::DataLabelPtr structureToCompare;1127 JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));1128 1129 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);1130 JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);1131 1132 JITCompiler::Jump done = m_jit.jump();1133 1134 structureCheck.link(&m_jit);1135 1136 if (slowPathTarget.isSet())1137 slowPathTarget.link(&m_jit);1138 1139 JITCompiler::Label slowCase = m_jit.label();1140 1141 silentSpillAllRegisters(resultGPR);1142 m_jit.move(baseGPR, GPRInfo::argumentGPR1);1143 m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR2);1144 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1145 JITCompiler::Call functionCall;1146 switch (nodeType) {1147 case GetById:1148 functionCall = appendCallWithExceptionCheck(operationGetByIdOptimize);1149 break;1150 1151 case GetMethod:1152 functionCall = appendCallWithExceptionCheck(operationGetMethodOptimize);1153 break;1154 1155 default:1156 ASSERT_NOT_REACHED();1157 return JITCompiler::Call();1158 }1159 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1160 silentFillAllRegisters(resultGPR);1161 1162 done.link(&m_jit);1163 1164 JITCompiler::Label doneLabel = m_jit.label();1165 1166 int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));1167 int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));1168 int16_t callToLoad = safeCast<int16_t>(m_jit.differenceBetween(functionCall, loadWithPatch));1169 int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));1170 int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));1171 1172 m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToLoad, callToSlowCase, callToDone, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR));1173 1174 if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg)1175 unlock(scratchGPR);1176 1177 return functionCall;1178 }1179 1180 194 void JITCodeGenerator::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind) 1181 195 { … … 1232 246 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) { 1233 247 hadCellCheck = true; 1234 rhsNotCell = m_jit.branch TestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);248 rhsNotCell = m_jit.branchIfNotCell(valueGPR); 1235 249 } 1236 250 … … 1273 287 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) { 1274 288 hadCellCheck = true; 1275 rhsNotCell = m_jit.branch TestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);289 rhsNotCell = m_jit.branchIfNotCell(valueGPR); 1276 290 } 1277 291 … … 1292 306 } 1293 307 1294 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)1295 {1296 1297 JITCompiler::DataLabelPtr structureToCompare;1298 JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));1299 1300 writeBarrier(baseGPR, valueGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR);1301 1302 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);1303 JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));1304 1305 JITCompiler::Jump done = m_jit.jump();1306 1307 structureCheck.link(&m_jit);1308 1309 if (slowPathTarget.isSet())1310 slowPathTarget.link(&m_jit);1311 1312 JITCompiler::Label slowCase = m_jit.label();1313 1314 silentSpillAllRegisters(InvalidGPRReg);1315 setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(valueGPR, baseGPR);1316 m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR3);1317 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1318 V_DFGOperation_EJJI optimizedCall;1319 if (m_jit.codeBlock()->isStrictMode()) {1320 if (putKind == Direct)1321 optimizedCall = operationPutByIdDirectStrictOptimize;1322 else1323 optimizedCall = operationPutByIdStrictOptimize;1324 } else {1325 if (putKind == Direct)1326 optimizedCall = operationPutByIdDirectNonStrictOptimize;1327 else1328 optimizedCall = operationPutByIdNonStrictOptimize;1329 }1330 JITCompiler::Call functionCall = appendCallWithExceptionCheck(optimizedCall);1331 silentFillAllRegisters(InvalidGPRReg);1332 1333 done.link(&m_jit);1334 JITCompiler::Label doneLabel = m_jit.label();1335 1336 int16_t checkImmToCall = safeCast<int16_t>(m_jit.differenceBetween(structureToCompare, functionCall));1337 int16_t callToCheck = safeCast<int16_t>(m_jit.differenceBetween(functionCall, structureCheck));1338 int16_t callToStore = safeCast<int16_t>(m_jit.differenceBetween(functionCall, storeWithPatch));1339 int16_t callToSlowCase = safeCast<int16_t>(m_jit.differenceBetween(functionCall, slowCase));1340 int16_t callToDone = safeCast<int16_t>(m_jit.differenceBetween(functionCall, doneLabel));1341 1342 m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR));1343 }1344 1345 void JITCodeGenerator::cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)1346 {1347 JITCompiler::Call slowCall;1348 JITCompiler::DataLabelPtr structToCompare, protoObj, protoStructToCompare, putFunction;1349 1350 JITCompiler::Jump wrongStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));1351 protoObj = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);1352 JITCompiler::Jump wrongProtoStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(resultGPR, JSCell::structureOffset()), protoStructToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));1353 1354 putFunction = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR);1355 1356 JITCompiler::Jump done = m_jit.jump();1357 1358 wrongStructure.link(&m_jit);1359 wrongProtoStructure.link(&m_jit);1360 1361 slowCall = cachedGetById(baseGPR, resultGPR, scratchGPR, identifierNumber, slowPathTarget, GetMethod);1362 1363 done.link(&m_jit);1364 1365 m_jit.addMethodGet(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction);1366 }1367 1368 void JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)1369 {1370 JSValueOperand arg(this, operand);1371 GPRReg argGPR = arg.gpr();1372 1373 GPRTemporary result(this, arg);1374 GPRReg resultGPR = result.gpr();1375 1376 JITCompiler::Jump notCell;1377 1378 if (!isKnownCell(operand))1379 notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);1380 1381 m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);1382 m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);1383 1384 if (!isKnownCell(operand)) {1385 JITCompiler::Jump done = m_jit.jump();1386 1387 notCell.link(&m_jit);1388 1389 m_jit.move(argGPR, resultGPR);1390 m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);1391 m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);1392 1393 done.link(&m_jit);1394 }1395 1396 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);1397 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);1398 }1399 1400 void JITCodeGenerator::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert)1401 {1402 Node& branchNode = m_jit.graph()[branchNodeIndex];1403 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());1404 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());1405 1406 if (taken == (m_block + 1)) {1407 invert = !invert;1408 BlockIndex tmp = taken;1409 taken = notTaken;1410 notTaken = tmp;1411 }1412 1413 JSValueOperand arg(this, operand);1414 GPRReg argGPR = arg.gpr();1415 1416 GPRTemporary result(this, arg);1417 GPRReg resultGPR = result.gpr();1418 1419 JITCompiler::Jump notCell;1420 1421 if (!isKnownCell(operand))1422 notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);1423 1424 m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);1425 addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken);1426 1427 if (!isKnownCell(operand)) {1428 addBranch(m_jit.jump(), notTaken);1429 1430 notCell.link(&m_jit);1431 1432 m_jit.move(argGPR, resultGPR);1433 m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);1434 addBranch(m_jit.branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))), taken);1435 }1436 1437 if (notTaken != (m_block + 1))1438 addBranch(m_jit.jump(), notTaken);1439 }1440 1441 bool JITCodeGenerator::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert)1442 {1443 NodeIndex branchNodeIndex = detectPeepHoleBranch();1444 if (branchNodeIndex != NoNode) {1445 ASSERT(node.adjustedRefCount() == 1);1446 1447 nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);1448 1449 use(node.child1());1450 use(node.child2());1451 m_compileIndex = branchNodeIndex;1452 1453 return true;1454 }1455 1456 nonSpeculativeNonPeepholeCompareNull(operand, invert);1457 1458 return false;1459 }1460 1461 void JITCodeGenerator::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)1462 {1463 Node& branchNode = m_jit.graph()[branchNodeIndex];1464 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());1465 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());1466 1467 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;1468 1469 // The branch instruction will branch to the taken block.1470 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.1471 if (taken == (m_block + 1)) {1472 cond = JITCompiler::invert(cond);1473 callResultCondition = JITCompiler::Zero;1474 BlockIndex tmp = taken;1475 taken = notTaken;1476 notTaken = tmp;1477 }1478 1479 JSValueOperand arg1(this, node.child1());1480 JSValueOperand arg2(this, node.child2());1481 GPRReg arg1GPR = arg1.gpr();1482 GPRReg arg2GPR = arg2.gpr();1483 1484 JITCompiler::JumpList slowPath;1485 1486 if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {1487 GPRResult result(this);1488 GPRReg resultGPR = result.gpr();1489 1490 arg1.use();1491 arg2.use();1492 1493 flushRegisters();1494 1495 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);1496 addBranch(m_jit.branchTest8(callResultCondition, resultGPR), taken);1497 } else {1498 GPRTemporary result(this, arg2);1499 GPRReg resultGPR = result.gpr();1500 1501 arg1.use();1502 arg2.use();1503 1504 if (!isKnownInteger(node.child1()))1505 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));1506 if (!isKnownInteger(node.child2()))1507 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));1508 1509 addBranch(m_jit.branch32(cond, arg1GPR, arg2GPR), taken);1510 1511 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {1512 addBranch(m_jit.jump(), notTaken);1513 1514 slowPath.link(&m_jit);1515 1516 silentSpillAllRegisters(resultGPR);1517 setupStubArguments(arg1GPR, arg2GPR);1518 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1519 appendCallWithExceptionCheck(helperFunction);1520 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1521 silentFillAllRegisters(resultGPR);1522 1523 addBranch(m_jit.branchTest8(callResultCondition, resultGPR), taken);1524 }1525 }1526 1527 if (notTaken != (m_block + 1))1528 addBranch(m_jit.jump(), notTaken);1529 }1530 1531 void JITCodeGenerator::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)1532 {1533 JSValueOperand arg1(this, node.child1());1534 JSValueOperand arg2(this, node.child2());1535 GPRReg arg1GPR = arg1.gpr();1536 GPRReg arg2GPR = arg2.gpr();1537 1538 JITCompiler::JumpList slowPath;1539 1540 if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) {1541 GPRResult result(this);1542 GPRReg resultGPR = result.gpr();1543 1544 arg1.use();1545 arg2.use();1546 1547 flushRegisters();1548 1549 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);1550 1551 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);1552 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);1553 } else {1554 GPRTemporary result(this, arg2);1555 GPRReg resultGPR = result.gpr();1556 1557 arg1.use();1558 arg2.use();1559 1560 if (!isKnownInteger(node.child1()))1561 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));1562 if (!isKnownInteger(node.child2()))1563 slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));1564 1565 m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);1566 1567 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {1568 JITCompiler::Jump haveResult = m_jit.jump();1569 1570 slowPath.link(&m_jit);1571 1572 silentSpillAllRegisters(resultGPR);1573 setupStubArguments(arg1GPR, arg2GPR);1574 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1575 appendCallWithExceptionCheck(helperFunction);1576 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1577 silentFillAllRegisters(resultGPR);1578 1579 m_jit.andPtr(TrustedImm32(1), resultGPR);1580 1581 haveResult.link(&m_jit);1582 }1583 1584 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);1585 1586 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);1587 }1588 }1589 1590 308 bool JITCodeGenerator::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction) 1591 309 { … … 1606 324 } 1607 325 1608 void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)1609 {1610 Node& branchNode = m_jit.graph()[branchNodeIndex];1611 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());1612 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());1613 1614 // The branch instruction will branch to the taken block.1615 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.1616 if (taken == (m_block + 1)) {1617 invert = !invert;1618 BlockIndex tmp = taken;1619 taken = notTaken;1620 notTaken = tmp;1621 }1622 1623 JSValueOperand arg1(this, node.child1());1624 JSValueOperand arg2(this, node.child2());1625 GPRReg arg1GPR = arg1.gpr();1626 GPRReg arg2GPR = arg2.gpr();1627 1628 GPRTemporary result(this);1629 GPRReg resultGPR = result.gpr();1630 1631 arg1.use();1632 arg2.use();1633 1634 if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {1635 // see if we get lucky: if the arguments are cells and they reference the same1636 // cell, then they must be strictly equal.1637 addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);1638 1639 silentSpillAllRegisters(resultGPR);1640 setupStubArguments(arg1GPR, arg2GPR);1641 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1642 appendCallWithExceptionCheck(operationCompareStrictEqCell);1643 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1644 silentFillAllRegisters(resultGPR);1645 1646 addBranch(m_jit.branchTest8(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);1647 } else {1648 m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);1649 1650 JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);1651 1652 JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);1653 1654 addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);1655 addBranch(m_jit.jump(), notTaken);1656 1657 twoCellsCase.link(&m_jit);1658 addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);1659 1660 numberCase.link(&m_jit);1661 1662 silentSpillAllRegisters(resultGPR);1663 setupStubArguments(arg1GPR, arg2GPR);1664 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1665 appendCallWithExceptionCheck(operationCompareStrictEq);1666 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1667 silentFillAllRegisters(resultGPR);1668 1669 addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);1670 }1671 1672 if (notTaken != (m_block + 1))1673 addBranch(m_jit.jump(), notTaken);1674 }1675 1676 void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)1677 {1678 JSValueOperand arg1(this, node.child1());1679 JSValueOperand arg2(this, node.child2());1680 GPRReg arg1GPR = arg1.gpr();1681 GPRReg arg2GPR = arg2.gpr();1682 1683 GPRTemporary result(this);1684 GPRReg resultGPR = result.gpr();1685 1686 arg1.use();1687 arg2.use();1688 1689 if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {1690 // see if we get lucky: if the arguments are cells and they reference the same1691 // cell, then they must be strictly equal.1692 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);1693 1694 m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);1695 1696 JITCompiler::Jump done = m_jit.jump();1697 1698 notEqualCase.link(&m_jit);1699 1700 silentSpillAllRegisters(resultGPR);1701 setupStubArguments(arg1GPR, arg2GPR);1702 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1703 appendCallWithExceptionCheck(operationCompareStrictEqCell);1704 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1705 silentFillAllRegisters(resultGPR);1706 1707 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);1708 m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);1709 1710 done.link(&m_jit);1711 } else {1712 m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);1713 1714 JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);1715 1716 JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);1717 1718 m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);1719 1720 JITCompiler::Jump done1 = m_jit.jump();1721 1722 twoCellsCase.link(&m_jit);1723 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);1724 1725 m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);1726 1727 JITCompiler::Jump done2 = m_jit.jump();1728 1729 numberCase.link(&m_jit);1730 notEqualCase.link(&m_jit);1731 1732 silentSpillAllRegisters(resultGPR);1733 setupStubArguments(arg1GPR, arg2GPR);1734 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1735 appendCallWithExceptionCheck(operationCompareStrictEq);1736 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1737 silentFillAllRegisters(resultGPR);1738 1739 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);1740 1741 done1.link(&m_jit);1742 1743 m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);1744 1745 done2.link(&m_jit);1746 }1747 1748 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);1749 }1750 1751 326 bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert) 1752 327 { … … 1768 343 1769 344 return false; 1770 }1771 1772 void JITCodeGenerator::emitBranch(Node& node)1773 {1774 JSValueOperand value(this, node.child1());1775 GPRReg valueGPR = value.gpr();1776 1777 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());1778 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());1779 1780 if (isKnownBoolean(node.child1())) {1781 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;1782 1783 if (taken == (m_block + 1)) {1784 condition = MacroAssembler::Zero;1785 BlockIndex tmp = taken;1786 taken = notTaken;1787 notTaken = tmp;1788 }1789 1790 addBranch(m_jit.branchTest32(condition, valueGPR, TrustedImm32(true)), taken);1791 if (notTaken != (m_block + 1))1792 addBranch(m_jit.jump(), notTaken);1793 1794 noResult(m_compileIndex);1795 } else {1796 GPRTemporary result(this);1797 GPRReg resultGPR = result.gpr();1798 1799 bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));1800 1801 if (predictBoolean) {1802 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);1803 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);1804 }1805 1806 if (m_isSpeculative && predictBoolean) {1807 speculationCheck(m_jit.jump());1808 value.use();1809 } else {1810 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);1811 addBranch(m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister), taken);1812 1813 if (!predictBoolean) {1814 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);1815 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);1816 }1817 1818 value.use();1819 1820 silentSpillAllRegisters(resultGPR);1821 m_jit.move(valueGPR, GPRInfo::argumentGPR1);1822 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1823 appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);1824 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1825 silentFillAllRegisters(resultGPR);1826 1827 addBranch(m_jit.branchTest8(MacroAssembler::NonZero, resultGPR), taken);1828 if (notTaken != (m_block + 1))1829 addBranch(m_jit.jump(), notTaken);1830 }1831 1832 noResult(m_compileIndex, UseChildrenCalledExplicitly);1833 }1834 }1835 1836 void JITCodeGenerator::nonSpeculativeLogicalNot(Node& node)1837 {1838 JSValueOperand arg1(this, node.child1());1839 GPRTemporary result(this);1840 1841 GPRReg arg1GPR = arg1.gpr();1842 GPRReg resultGPR = result.gpr();1843 1844 arg1.use();1845 1846 m_jit.move(arg1GPR, resultGPR);1847 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);1848 JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));1849 1850 silentSpillAllRegisters(resultGPR);1851 m_jit.move(arg1GPR, GPRInfo::argumentGPR1);1852 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1853 appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);1854 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1855 silentFillAllRegisters(resultGPR);1856 1857 fastCase.link(&m_jit);1858 1859 m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);1860 jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);1861 }1862 1863 void JITCodeGenerator::emitCall(Node& node)1864 {1865 P_DFGOperation_E slowCallFunction;1866 bool isCall;1867 1868 if (node.op == Call) {1869 slowCallFunction = operationLinkCall;1870 isCall = true;1871 } else {1872 ASSERT(node.op == Construct);1873 slowCallFunction = operationLinkConstruct;1874 isCall = false;1875 }1876 1877 NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];1878 JSValueOperand callee(this, calleeNodeIndex);1879 GPRReg calleeGPR = callee.gpr();1880 use(calleeNodeIndex);1881 1882 // the call instruction's first child is either the function (normal call) or the1883 // receiver (method call). subsequent children are the arguments.1884 int numArgs = node.numChildren() - 1;1885 1886 // For constructors, the this argument is not passed but we have to make space1887 // for it.1888 int numPassedArgs = numArgs + (isCall ? 0 : 1);1889 1890 // amount of stuff (in units of sizeof(Register)) that we need to place at the1891 // top of the JS stack.1892 int callDataSize = 0;1893 1894 // first there are the arguments1895 callDataSize += numPassedArgs;1896 1897 // and then there is the call frame header1898 callDataSize += RegisterFile::CallFrameHeaderSize;1899 1900 m_jit.storePtr(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(numPassedArgs))), addressOfCallData(RegisterFile::ArgumentCount));1901 m_jit.storePtr(GPRInfo::callFrameRegister, addressOfCallData(RegisterFile::CallerFrame));1902 1903 for (int argIdx = 0; argIdx < numArgs; argIdx++) {1904 NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + argIdx];1905 JSValueOperand arg(this, argNodeIndex);1906 GPRReg argGPR = arg.gpr();1907 use(argNodeIndex);1908 1909 m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx + (isCall ? 0 : 1)));1910 }1911 1912 m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));1913 1914 flushRegisters();1915 1916 GPRResult result(this);1917 GPRReg resultGPR = result.gpr();1918 1919 JITCompiler::DataLabelPtr targetToCheck;1920 JITCompiler::Jump slowPath;1921 1922 slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));1923 m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);1924 m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));1925 1926 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);1927 1928 JITCompiler::Call fastCall = m_jit.nearCall();1929 m_jit.notifyCall(fastCall, m_jit.graph()[m_compileIndex].codeOrigin);1930 1931 JITCompiler::Jump done = m_jit.jump();1932 1933 slowPath.link(&m_jit);1934 1935 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);1936 JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, m_jit.graph()[m_compileIndex].codeOrigin);1937 m_jit.move(Imm32(numPassedArgs), GPRInfo::regT1);1938 m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);1939 m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), m_jit.graph()[m_compileIndex].codeOrigin);1940 1941 done.link(&m_jit);1942 1943 m_jit.move(GPRInfo::returnValueGPR, resultGPR);1944 1945 jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);1946 1947 m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, m_jit.graph()[m_compileIndex].codeOrigin);1948 345 } 1949 346 … … 1997 394 if (info.registerFormat() == DataFormatDouble) 1998 395 fprintf(stderr, ":fpr%d\n", info.fpr()); 1999 else if (info.registerFormat() != DataFormatNone) { 396 else if (info.registerFormat() != DataFormatNone 397 #if USE(JSVALUE32_64) 398 && !(info.registerFormat() & DataFormatJS) 399 #endif 400 ) { 2000 401 ASSERT(info.gpr() != InvalidGPRReg); 2001 402 fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr())); … … 2035 436 case DataFormatNone: 2036 437 break; 2037 case DataFormatInteger:2038 case DataFormatCell:2039 438 case DataFormatJS: 2040 439 case DataFormatJSInteger: 2041 440 case DataFormatJSDouble: 2042 case DataFormatJSCell: { 441 case DataFormatJSCell: 442 #if USE(JSVALUE32_64) 443 break; 444 #endif 445 case DataFormatInteger: 446 case DataFormatCell: { 2043 447 GPRReg gpr = info.gpr(); 2044 448 ASSERT(gpr != InvalidGPRReg); … … 2067 471 2068 472 GenerationInfo& info = m_generationInfo[virtualRegister]; 473 #if USE(JSVALUE64) 2069 474 if (iter.regID() != info.gpr()) { 2070 475 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 2071 476 failed = true; 2072 477 } 478 #else 479 if (!(info.registerFormat() & DataFormatJS)) { 480 if (iter.regID() != info.gpr()) { 481 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 482 failed = true; 483 } 484 } else { 485 if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) { 486 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 487 failed = true; 488 } 489 } 490 #endif 2073 491 } 2074 492 … … 2102 520 , m_gpr(InvalidGPRReg) 2103 521 { 522 #if CPU(X86) 523 // we currenty lazily allocate the reg, as the number of regs on X86 is limited. 524 #else 2104 525 m_gpr = m_jit->allocate(); 526 #endif 2105 527 } 2106 528 … … 2186 608 } 2187 609 610 #if USE(JSVALUE64) 2188 611 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1) 2189 612 : m_jit(jit) … … 2195 618 m_gpr = m_jit->allocate(); 2196 619 } 620 #else 621 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1, bool tag) 622 : m_jit(jit) 623 , m_gpr(InvalidGPRReg) 624 { 625 if (!op1.isDouble() && m_jit->canReuse(op1.index())) 626 m_gpr = m_jit->reuse(tag ? op1.tagGPR() : op1.payloadGPR()); 627 else 628 m_gpr = m_jit->allocate(); 629 } 630 #endif 2197 631 2198 632 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, StorageOperand& op1) … … 2269 703 } 2270 704 705 #if USE(JSVALUE32_64) 706 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1) 707 : m_jit(jit) 708 , m_fpr(InvalidFPRReg) 709 { 710 if (op1.isDouble() && m_jit->canReuse(op1.index())) 711 m_fpr = m_jit->reuse(op1.fpr()); 712 else 713 m_fpr = m_jit->fprAllocate(); 714 } 715 #endif 716 2271 717 } } // namespace JSC::DFG 2272 718 2273 719 #endif 2274 #endif -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator32_64.cpp
r96372 r96377 28 28 29 29 #if ENABLE(DFG_JIT) 30 #if USE(JSVALUE32_64)31 30 32 31 #include "DFGJITCompilerInlineMethods.h" … … 36 35 namespace JSC { namespace DFG { 37 36 38 const double JITCodeGenerator::twoToThe32 = (double)0x100000000ull; 39 40 void JITCodeGenerator::clearGenerationInfo() 41 { 42 for (unsigned i = 0; i < m_generationInfo.size(); ++i) 43 m_generationInfo[i] = GenerationInfo(); 44 m_gprs = RegisterBank<GPRInfo>(); 45 m_fprs = RegisterBank<FPRInfo>(); 46 } 37 #if USE(JSVALUE32_64) 47 38 48 39 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat) … … 315 306 } 316 307 317 GPRReg JITCodeGenerator::fillStorage(NodeIndex nodeIndex)318 {319 Node& node = m_jit.graph()[nodeIndex];320 VirtualRegister virtualRegister = node.virtualRegister();321 GenerationInfo& info = m_generationInfo[virtualRegister];322 323 switch (info.registerFormat()) {324 case DataFormatNone: {325 GPRReg gpr = allocate();326 ASSERT(info.spillFormat() == DataFormatStorage);327 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);328 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);329 info.fillStorage(gpr);330 return gpr;331 }332 333 case DataFormatStorage: {334 GPRReg gpr = info.gpr();335 m_gprs.lock(gpr);336 return gpr;337 }338 339 default:340 ASSERT_NOT_REACHED();341 }342 343 return InvalidGPRReg;344 }345 346 void JITCodeGenerator::useChildren(Node& node)347 {348 if (node.op & NodeHasVarArgs) {349 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)350 use(m_jit.graph().m_varArgChildren[childIdx]);351 } else {352 NodeIndex child1 = node.child1();353 if (child1 == NoNode) {354 ASSERT(node.child2() == NoNode && node.child3() == NoNode);355 return;356 }357 use(child1);358 359 NodeIndex child2 = node.child2();360 if (child2 == NoNode) {361 ASSERT(node.child3() == NoNode);362 return;363 }364 use(child2);365 366 NodeIndex child3 = node.child3();367 if (child3 == NoNode)368 return;369 use(child3);370 }371 }372 373 bool JITCodeGenerator::isStrictInt32(NodeIndex nodeIndex)374 {375 if (isInt32Constant(nodeIndex))376 return true;377 378 Node& node = m_jit.graph()[nodeIndex];379 GenerationInfo& info = m_generationInfo[node.virtualRegister()];380 381 return info.registerFormat() == DataFormatInteger;382 }383 384 bool JITCodeGenerator::isKnownInteger(NodeIndex nodeIndex)385 {386 if (isInt32Constant(nodeIndex))387 return true;388 389 Node& node = m_jit.graph()[nodeIndex];390 391 if (node.hasInt32Result())392 return true;393 394 GenerationInfo& info = m_generationInfo[node.virtualRegister()];395 396 return info.isJSInteger();397 }398 399 bool JITCodeGenerator::isKnownNumeric(NodeIndex nodeIndex)400 {401 if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))402 return true;403 404 Node& node = m_jit.graph()[nodeIndex];405 406 if (node.hasNumberResult())407 return true;408 409 GenerationInfo& info = m_generationInfo[node.virtualRegister()];410 411 return info.isJSInteger() || info.isJSDouble();412 }413 414 bool JITCodeGenerator::isKnownCell(NodeIndex nodeIndex)415 {416 return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();417 }418 419 bool JITCodeGenerator::isKnownNotCell(NodeIndex nodeIndex)420 {421 Node& node = m_jit.graph()[nodeIndex];422 VirtualRegister virtualRegister = node.virtualRegister();423 GenerationInfo& info = m_generationInfo[virtualRegister];424 if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell())425 return true;426 return !(info.isJSCell() || info.isUnknownJS());427 }428 429 bool JITCodeGenerator::isKnownNotInteger(NodeIndex nodeIndex)430 {431 Node& node = m_jit.graph()[nodeIndex];432 VirtualRegister virtualRegister = node.virtualRegister();433 GenerationInfo& info = m_generationInfo[virtualRegister];434 435 return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()436 || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());437 }438 439 bool JITCodeGenerator::isKnownNotNumber(NodeIndex nodeIndex)440 {441 Node& node = m_jit.graph()[nodeIndex];442 VirtualRegister virtualRegister = node.virtualRegister();443 GenerationInfo& info = m_generationInfo[virtualRegister];444 445 return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())446 || (node.hasConstant() && !isNumberConstant(nodeIndex));447 }448 449 bool JITCodeGenerator::isKnownBoolean(NodeIndex nodeIndex)450 {451 Node& node = m_jit.graph()[nodeIndex];452 if (node.hasBooleanResult())453 return true;454 455 if (isBooleanConstant(nodeIndex))456 return true;457 458 VirtualRegister virtualRegister = node.virtualRegister();459 GenerationInfo& info = m_generationInfo[virtualRegister];460 461 return info.isJSBoolean();462 }463 464 308 void JITCodeGenerator::nonSpeculativeValueToNumber(Node& node) 465 309 { … … 1226 1070 1227 1071 return functionCall; 1228 }1229 1230 void JITCodeGenerator::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)1231 {1232 UNUSED_PARAM(jit);1233 UNUSED_PARAM(owner);1234 UNUSED_PARAM(scratch1);1235 UNUSED_PARAM(scratch2);1236 UNUSED_PARAM(useKind);1237 ASSERT(owner != scratch1);1238 ASSERT(owner != scratch2);1239 ASSERT(scratch1 != scratch2);1240 1241 #if ENABLE(WRITE_BARRIER_PROFILING)1242 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));1243 #endif1244 markCellCard(jit, owner, scratch1, scratch2);1245 }1246 1247 void JITCodeGenerator::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2)1248 {1249 UNUSED_PARAM(jit);1250 UNUSED_PARAM(owner);1251 UNUSED_PARAM(scratch1);1252 UNUSED_PARAM(scratch2);1253 1254 #if ENABLE(GGC)1255 jit.move(owner, scratch1);1256 jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1);1257 jit.move(owner, scratch2);1258 jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2);1259 jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2);1260 jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards()));1261 #endif1262 }1263 1264 void JITCodeGenerator::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)1265 {1266 UNUSED_PARAM(ownerGPR);1267 UNUSED_PARAM(valueGPR);1268 UNUSED_PARAM(scratch1);1269 UNUSED_PARAM(scratch2);1270 UNUSED_PARAM(useKind);1271 1272 if (isKnownNotCell(valueIndex))1273 return;1274 1275 #if ENABLE(WRITE_BARRIER_PROFILING)1276 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));1277 #endif1278 1279 #if ENABLE(GGC)1280 JITCompiler::Jump rhsNotCell;1281 bool hadCellCheck = false;1282 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.graph().getPrediction(m_jit.graph()[valueIndex]))) {1283 hadCellCheck = true;1284 rhsNotCell = m_jit.branch32(MacroAssembler::NotEqual, valueGPR, TrustedImm32(JSValue::CellTag));1285 }1286 1287 GPRTemporary temp1;1288 GPRTemporary temp2;1289 if (scratch1 == InvalidGPRReg) {1290 GPRTemporary scratchGPR(this);1291 temp1.adopt(scratchGPR);1292 scratch1 = temp1.gpr();1293 }1294 if (scratch2 == InvalidGPRReg) {1295 GPRTemporary scratchGPR(this);1296 temp2.adopt(scratchGPR);1297 scratch2 = temp2.gpr();1298 }1299 1300 markCellCard(m_jit, ownerGPR, scratch1, scratch2);1301 if (hadCellCheck)1302 rhsNotCell.link(&m_jit);1303 #endif1304 }1305 1306 void JITCodeGenerator::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch)1307 {1308 UNUSED_PARAM(owner);1309 UNUSED_PARAM(valueGPR);1310 UNUSED_PARAM(scratch);1311 UNUSED_PARAM(useKind);1312 1313 if (isKnownNotCell(valueIndex))1314 return;1315 1316 #if ENABLE(WRITE_BARRIER_PROFILING)1317 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));1318 #endif1319 1320 #if ENABLE(GGC)1321 JITCompiler::Jump rhsNotCell;1322 bool hadCellCheck = false;1323 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.graph().getPrediction(m_jit.graph()[valueIndex]))) {1324 hadCellCheck = true;1325 rhsNotCell = m_jit.branch32(MacroAssembler::NotEqual, valueGPR, TrustedImm32(JSValue::CellTag));1326 }1327 1328 GPRTemporary temp;1329 if (scratch == InvalidGPRReg) {1330 GPRTemporary scratchGPR(this);1331 temp.adopt(scratchGPR);1332 scratch = temp.gpr();1333 }1334 1335 uint8_t* cardAddress = Heap::addressOfCardFor(owner);1336 m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch);1337 m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch));1338 1339 if (hadCellCheck)1340 rhsNotCell.link(&m_jit);1341 #endif1342 1072 } 1343 1073 … … 1662 1392 } 1663 1393 1664 bool JITCodeGenerator::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)1665 {1666 NodeIndex branchNodeIndex = detectPeepHoleBranch();1667 if (branchNodeIndex != NoNode) {1668 ASSERT(node.adjustedRefCount() == 1);1669 1670 nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);1671 1672 m_compileIndex = branchNodeIndex;1673 1674 return true;1675 }1676 1677 nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);1678 1679 return false;1680 }1681 1682 1394 void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert) 1683 1395 { … … 1804 1516 } 1805 1517 1806 bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert)1807 {1808 if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())))1809 return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);1810 1811 NodeIndex branchNodeIndex = detectPeepHoleBranch();1812 if (branchNodeIndex != NoNode) {1813 ASSERT(node.adjustedRefCount() == 1);1814 1815 nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);1816 1817 m_compileIndex = branchNodeIndex;1818 1819 return true;1820 }1821 1822 nonSpeculativeNonPeepholeStrictEq(node, invert);1823 1824 return false;1825 }1826 1827 1518 void JITCodeGenerator::emitBranch(Node& node) 1828 1519 { … … 1903 1594 } 1904 1595 1905 void JITCodeGenerator::speculationCheck(MacroAssembler::Jump jumpToFail)1906 {1907 ASSERT(m_isSpeculative);1908 static_cast<SpeculativeJIT*>(this)->speculationCheck(jumpToFail);1909 }1910 1911 #ifndef NDEBUG1912 static const char* dataFormatString(DataFormat format)1913 {1914 // These values correspond to the DataFormat enum.1915 const char* strings[] = {1916 "[ ]",1917 "[ i]",1918 "[ d]",1919 "[ c]",1920 "Err!",1921 "Err!",1922 "Err!",1923 "Err!",1924 "[J ]",1925 "[Ji]",1926 "[Jd]",1927 "[Jc]",1928 "Err!",1929 "Err!",1930 "Err!",1931 "Err!",1932 };1933 return strings[format];1934 }1935 1936 void JITCodeGenerator::dump(const char* label)1937 {1938 if (label)1939 fprintf(stderr, "<%s>\n", label);1940 1941 fprintf(stderr, " gprs:\n");1942 m_gprs.dump();1943 fprintf(stderr, " fprs:\n");1944 m_fprs.dump();1945 fprintf(stderr, " VirtualRegisters:\n");1946 for (unsigned i = 0; i < m_generationInfo.size(); ++i) {1947 GenerationInfo& info = m_generationInfo[i];1948 if (info.alive())1949 fprintf(stderr, " % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));1950 else1951 fprintf(stderr, " % 3d:[__][__]", i);1952 if (info.registerFormat() == DataFormatDouble)1953 fprintf(stderr, ":fpr%d\n", info.fpr());1954 else if (info.registerFormat() != DataFormatNone && !(info.registerFormat() & DataFormatJS)) {1955 ASSERT(info.gpr() != InvalidGPRReg);1956 fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));1957 } else1958 fprintf(stderr, "\n");1959 }1960 if (label)1961 fprintf(stderr, "</%s>\n", label);1962 }1963 1596 #endif 1964 1597 1965 1966 #if ENABLE(DFG_CONSISTENCY_CHECK) 1967 void JITCodeGenerator::checkConsistency() 1968 { 1969 bool failed = false; 1970 1971 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 1972 if (iter.isLocked()) { 1973 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName()); 1974 failed = true; 1975 } 1976 } 1977 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 1978 if (iter.isLocked()) { 1979 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName()); 1980 failed = true; 1981 } 1982 } 1983 1984 for (unsigned i = 0; i < m_generationInfo.size(); ++i) { 1985 VirtualRegister virtualRegister = (VirtualRegister)i; 1986 GenerationInfo& info = m_generationInfo[virtualRegister]; 1987 if (!info.alive()) 1988 continue; 1989 switch (info.registerFormat()) { 1990 case DataFormatNone: 1991 case DataFormatJS: 1992 case DataFormatJSInteger: 1993 case DataFormatJSDouble: 1994 case DataFormatJSCell: 1995 break; 1996 case DataFormatInteger: 1997 case DataFormatCell: { 1998 GPRReg gpr = info.gpr(); 1999 ASSERT(gpr != InvalidGPRReg); 2000 if (m_gprs.name(gpr) != virtualRegister) { 2001 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr)); 2002 failed = true; 2003 } 2004 break; 2005 } 2006 case DataFormatDouble: { 2007 FPRReg fpr = info.fpr(); 2008 ASSERT(fpr != InvalidFPRReg); 2009 if (m_fprs.name(fpr) != virtualRegister) { 2010 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr)); 2011 failed = true; 2012 } 2013 break; 2014 } 2015 } 2016 } 2017 2018 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 2019 VirtualRegister virtualRegister = iter.name(); 2020 if (virtualRegister == InvalidVirtualRegister) 2021 continue; 2022 2023 GenerationInfo& info = m_generationInfo[virtualRegister]; 2024 if (!(info.registerFormat() & DataFormatJS)) { 2025 if (iter.regID() != info.gpr()) { 2026 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 2027 failed = true; 2028 } 2029 } else { 2030 if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) { 2031 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 2032 failed = true; 2033 } 2034 } 2035 } 2036 2037 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 2038 VirtualRegister virtualRegister = iter.name(); 2039 if (virtualRegister == InvalidVirtualRegister) 2040 continue; 2041 2042 GenerationInfo& info = m_generationInfo[virtualRegister]; 2043 if (iter.regID() != info.fpr()) { 2044 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 2045 failed = true; 2046 } 2047 } 2048 2049 if (failed) { 2050 dump(); 2051 CRASH(); 2052 } 2053 } 1598 } } // namespace JSC::DFG 1599 2054 1600 #endif 2055 2056 GPRTemporary::GPRTemporary()2057 : m_jit(0)2058 , m_gpr(InvalidGPRReg)2059 {2060 }2061 2062 GPRTemporary::GPRTemporary(JITCodeGenerator* jit)2063 : m_jit(jit)2064 , m_gpr(InvalidGPRReg)2065 {2066 // we currenty lazily allocate the reg, as the number of regs on X86 is limited.2067 }2068 2069 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, GPRReg specific)2070 : m_jit(jit)2071 , m_gpr(InvalidGPRReg)2072 {2073 m_gpr = m_jit->allocate(specific);2074 }2075 2076 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)2077 : m_jit(jit)2078 , m_gpr(InvalidGPRReg)2079 {2080 if (m_jit->canReuse(op1.index()))2081 m_gpr = m_jit->reuse(op1.gpr());2082 else2083 m_gpr = m_jit->allocate();2084 }2085 2086 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)2087 : m_jit(jit)2088 , m_gpr(InvalidGPRReg)2089 {2090 if (m_jit->canReuse(op1.index()))2091 m_gpr = m_jit->reuse(op1.gpr());2092 else if (m_jit->canReuse(op2.index()))2093 m_gpr = m_jit->reuse(op2.gpr());2094 else2095 m_gpr = m_jit->allocate();2096 }2097 2098 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateStrictInt32Operand& op1)2099 : m_jit(jit)2100 , m_gpr(InvalidGPRReg)2101 {2102 if (m_jit->canReuse(op1.index()))2103 m_gpr = m_jit->reuse(op1.gpr());2104 else2105 m_gpr = m_jit->allocate();2106 }2107 2108 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)2109 : m_jit(jit)2110 , m_gpr(InvalidGPRReg)2111 {2112 if (m_jit->canReuse(op1.index()))2113 m_gpr = m_jit->reuse(op1.gpr());2114 else2115 m_gpr = m_jit->allocate();2116 }2117 2118 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)2119 : m_jit(jit)2120 , m_gpr(InvalidGPRReg)2121 {2122 if (m_jit->canReuse(op1.index()))2123 m_gpr = m_jit->reuse(op1.gpr());2124 else if (m_jit->canReuse(op2.index()))2125 m_gpr = m_jit->reuse(op2.gpr());2126 else2127 m_gpr = m_jit->allocate();2128 }2129 2130 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)2131 : m_jit(jit)2132 , m_gpr(InvalidGPRReg)2133 {2134 if (m_jit->canReuse(op1.index()))2135 m_gpr = m_jit->reuse(op1.gpr());2136 else2137 m_gpr = m_jit->allocate();2138 }2139 2140 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateBooleanOperand& op1)2141 : m_jit(jit)2142 , m_gpr(InvalidGPRReg)2143 {2144 if (m_jit->canReuse(op1.index()))2145 m_gpr = m_jit->reuse(op1.gpr());2146 else2147 m_gpr = m_jit->allocate();2148 }2149 2150 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1, bool tag)2151 : m_jit(jit)2152 , m_gpr(InvalidGPRReg)2153 {2154 if (!op1.isDouble() && m_jit->canReuse(op1.index()))2155 m_gpr = m_jit->reuse(tag ? op1.tagGPR() : op1.payloadGPR());2156 else2157 m_gpr = m_jit->allocate();2158 }2159 2160 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, StorageOperand& op1)2161 : m_jit(jit)2162 , m_gpr(InvalidGPRReg)2163 {2164 if (m_jit->canReuse(op1.index()))2165 m_gpr = m_jit->reuse(op1.gpr());2166 else2167 m_gpr = m_jit->allocate();2168 }2169 2170 void GPRTemporary::adopt(GPRTemporary& other)2171 {2172 ASSERT(!m_jit);2173 ASSERT(m_gpr == InvalidGPRReg);2174 ASSERT(other.m_jit);2175 ASSERT(other.m_gpr != InvalidGPRReg);2176 m_jit = other.m_jit;2177 m_gpr = other.m_gpr;2178 other.m_jit = 0;2179 other.m_gpr = InvalidGPRReg;2180 }2181 2182 FPRTemporary::FPRTemporary(JITCodeGenerator* jit)2183 : m_jit(jit)2184 , m_fpr(InvalidFPRReg)2185 {2186 m_fpr = m_jit->fprAllocate();2187 }2188 2189 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)2190 : m_jit(jit)2191 , m_fpr(InvalidFPRReg)2192 {2193 if (m_jit->canReuse(op1.index()))2194 m_fpr = m_jit->reuse(op1.fpr());2195 else2196 m_fpr = m_jit->fprAllocate();2197 }2198 2199 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)2200 : m_jit(jit)2201 , m_fpr(InvalidFPRReg)2202 {2203 if (m_jit->canReuse(op1.index()))2204 m_fpr = m_jit->reuse(op1.fpr());2205 else if (m_jit->canReuse(op2.index()))2206 m_fpr = m_jit->reuse(op2.fpr());2207 else2208 m_fpr = m_jit->fprAllocate();2209 }2210 2211 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1)2212 : m_jit(jit)2213 , m_fpr(InvalidFPRReg)2214 {2215 if (m_jit->canReuse(op1.index()))2216 m_fpr = m_jit->reuse(op1.fpr());2217 else2218 m_fpr = m_jit->fprAllocate();2219 }2220 2221 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)2222 : m_jit(jit)2223 , m_fpr(InvalidFPRReg)2224 {2225 if (m_jit->canReuse(op1.index()))2226 m_fpr = m_jit->reuse(op1.fpr());2227 else if (m_jit->canReuse(op2.index()))2228 m_fpr = m_jit->reuse(op2.fpr());2229 else2230 m_fpr = m_jit->fprAllocate();2231 }2232 2233 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)2234 : m_jit(jit)2235 , m_fpr(InvalidFPRReg)2236 {2237 if (op1.isDouble() && m_jit->canReuse(op1.index()))2238 m_fpr = m_jit->reuse(op1.fpr());2239 else2240 m_fpr = m_jit->fprAllocate();2241 }2242 2243 } } // namespace JSC::DFG2244 2245 #endif2246 #endif -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator64.cpp
r96363 r96377 28 28 29 29 #if ENABLE(DFG_JIT) 30 #if USE(JSVALUE64) 31 30 31 #include "DFGJITCompilerInlineMethods.h" 32 32 #include "DFGSpeculativeJIT.h" 33 33 #include "LinkBuffer.h" … … 35 35 namespace JSC { namespace DFG { 36 36 37 const double JITCodeGenerator::twoToThe32 = (double)0x100000000ull; 38 39 void JITCodeGenerator::clearGenerationInfo() 40 { 41 for (unsigned i = 0; i < m_generationInfo.size(); ++i) 42 m_generationInfo[i] = GenerationInfo(); 43 m_gprs = RegisterBank<GPRInfo>(); 44 m_fprs = RegisterBank<FPRInfo>(); 45 } 37 #if USE(JSVALUE64) 46 38 47 39 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat) … … 329 321 } 330 322 331 GPRReg JITCodeGenerator::fillStorage(NodeIndex nodeIndex)332 {333 Node& node = m_jit.graph()[nodeIndex];334 VirtualRegister virtualRegister = node.virtualRegister();335 GenerationInfo& info = m_generationInfo[virtualRegister];336 337 switch (info.registerFormat()) {338 case DataFormatNone: {339 GPRReg gpr = allocate();340 ASSERT(info.spillFormat() == DataFormatStorage);341 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);342 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);343 info.fillStorage(gpr);344 return gpr;345 }346 347 case DataFormatStorage: {348 GPRReg gpr = info.gpr();349 m_gprs.lock(gpr);350 return gpr;351 }352 353 default:354 ASSERT_NOT_REACHED();355 }356 357 return InvalidGPRReg;358 }359 360 void JITCodeGenerator::useChildren(Node& node)361 {362 if (node.op & NodeHasVarArgs) {363 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)364 use(m_jit.graph().m_varArgChildren[childIdx]);365 } else {366 NodeIndex child1 = node.child1();367 if (child1 == NoNode) {368 ASSERT(node.child2() == NoNode && node.child3() == NoNode);369 return;370 }371 use(child1);372 373 NodeIndex child2 = node.child2();374 if (child2 == NoNode) {375 ASSERT(node.child3() == NoNode);376 return;377 }378 use(child2);379 380 NodeIndex child3 = node.child3();381 if (child3 == NoNode)382 return;383 use(child3);384 }385 }386 387 bool JITCodeGenerator::isStrictInt32(NodeIndex nodeIndex)388 {389 if (isInt32Constant(nodeIndex))390 return true;391 392 Node& node = m_jit.graph()[nodeIndex];393 GenerationInfo& info = m_generationInfo[node.virtualRegister()];394 395 return info.registerFormat() == DataFormatInteger;396 }397 398 bool JITCodeGenerator::isKnownInteger(NodeIndex nodeIndex)399 {400 if (isInt32Constant(nodeIndex))401 return true;402 403 Node& node = m_jit.graph()[nodeIndex];404 405 if (node.hasInt32Result())406 return true;407 408 GenerationInfo& info = m_generationInfo[node.virtualRegister()];409 410 return info.isJSInteger();411 }412 413 bool JITCodeGenerator::isKnownNumeric(NodeIndex nodeIndex)414 {415 if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))416 return true;417 418 Node& node = m_jit.graph()[nodeIndex];419 420 if (node.hasNumberResult())421 return true;422 423 GenerationInfo& info = m_generationInfo[node.virtualRegister()];424 425 return info.isJSInteger() || info.isJSDouble();426 }427 428 bool JITCodeGenerator::isKnownCell(NodeIndex nodeIndex)429 {430 return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();431 }432 433 bool JITCodeGenerator::isKnownNotCell(NodeIndex nodeIndex)434 {435 Node& node = m_jit.graph()[nodeIndex];436 VirtualRegister virtualRegister = node.virtualRegister();437 GenerationInfo& info = m_generationInfo[virtualRegister];438 if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell())439 return true;440 return !(info.isJSCell() || info.isUnknownJS());441 }442 443 bool JITCodeGenerator::isKnownNotInteger(NodeIndex nodeIndex)444 {445 Node& node = m_jit.graph()[nodeIndex];446 VirtualRegister virtualRegister = node.virtualRegister();447 GenerationInfo& info = m_generationInfo[virtualRegister];448 449 return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()450 || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());451 }452 453 bool JITCodeGenerator::isKnownNotNumber(NodeIndex nodeIndex)454 {455 Node& node = m_jit.graph()[nodeIndex];456 VirtualRegister virtualRegister = node.virtualRegister();457 GenerationInfo& info = m_generationInfo[virtualRegister];458 459 return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())460 || (node.hasConstant() && !isNumberConstant(nodeIndex));461 }462 463 bool JITCodeGenerator::isKnownBoolean(NodeIndex nodeIndex)464 {465 Node& node = m_jit.graph()[nodeIndex];466 if (node.hasBooleanResult())467 return true;468 469 if (isBooleanConstant(nodeIndex))470 return true;471 472 VirtualRegister virtualRegister = node.virtualRegister();473 GenerationInfo& info = m_generationInfo[virtualRegister];474 475 return info.isJSBoolean();476 }477 478 323 void JITCodeGenerator::nonSpeculativeValueToNumber(Node& node) 479 324 { … … 1176 1021 1177 1022 return functionCall; 1178 }1179 1180 void JITCodeGenerator::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)1181 {1182 UNUSED_PARAM(jit);1183 UNUSED_PARAM(owner);1184 UNUSED_PARAM(scratch1);1185 UNUSED_PARAM(scratch2);1186 UNUSED_PARAM(useKind);1187 ASSERT(owner != scratch1);1188 ASSERT(owner != scratch2);1189 ASSERT(scratch1 != scratch2);1190 1191 #if ENABLE(WRITE_BARRIER_PROFILING)1192 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));1193 #endif1194 markCellCard(jit, owner, scratch1, scratch2);1195 }1196 1197 void JITCodeGenerator::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2)1198 {1199 UNUSED_PARAM(jit);1200 UNUSED_PARAM(owner);1201 UNUSED_PARAM(scratch1);1202 UNUSED_PARAM(scratch2);1203 1204 #if ENABLE(GGC)1205 jit.move(owner, scratch1);1206 jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1);1207 jit.move(owner, scratch2);1208 jit.andPtr(TrustedImm32(static_cast<int32_t>(~MarkedBlock::blockMask)), scratch2);1209 jit.rshift32(TrustedImm32(MarkedBlock::log2CardSize), scratch2);1210 jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards()));1211 #endif1212 }1213 1214 void JITCodeGenerator::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)1215 {1216 UNUSED_PARAM(ownerGPR);1217 UNUSED_PARAM(valueGPR);1218 UNUSED_PARAM(scratch1);1219 UNUSED_PARAM(scratch2);1220 UNUSED_PARAM(useKind);1221 1222 if (isKnownNotCell(valueIndex))1223 return;1224 1225 #if ENABLE(WRITE_BARRIER_PROFILING)1226 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));1227 #endif1228 1229 #if ENABLE(GGC)1230 JITCompiler::Jump rhsNotCell;1231 bool hadCellCheck = false;1232 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) {1233 hadCellCheck = true;1234 rhsNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);1235 }1236 1237 GPRTemporary temp1;1238 GPRTemporary temp2;1239 if (scratch1 == InvalidGPRReg) {1240 GPRTemporary scratchGPR(this);1241 temp1.adopt(scratchGPR);1242 scratch1 = temp1.gpr();1243 }1244 if (scratch2 == InvalidGPRReg) {1245 GPRTemporary scratchGPR(this);1246 temp2.adopt(scratchGPR);1247 scratch2 = temp2.gpr();1248 }1249 1250 markCellCard(m_jit, ownerGPR, scratch1, scratch2);1251 if (hadCellCheck)1252 rhsNotCell.link(&m_jit);1253 #endif1254 }1255 1256 void JITCodeGenerator::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch)1257 {1258 UNUSED_PARAM(owner);1259 UNUSED_PARAM(valueGPR);1260 UNUSED_PARAM(scratch);1261 UNUSED_PARAM(useKind);1262 1263 if (isKnownNotCell(valueIndex))1264 return;1265 1266 #if ENABLE(WRITE_BARRIER_PROFILING)1267 JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));1268 #endif1269 1270 #if ENABLE(GGC)1271 JITCompiler::Jump rhsNotCell;1272 bool hadCellCheck = false;1273 if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) {1274 hadCellCheck = true;1275 rhsNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);1276 }1277 1278 GPRTemporary temp;1279 if (scratch == InvalidGPRReg) {1280 GPRTemporary scratchGPR(this);1281 temp.adopt(scratchGPR);1282 scratch = temp.gpr();1283 }1284 1285 uint8_t* cardAddress = Heap::addressOfCardFor(owner);1286 m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch);1287 m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch));1288 1289 if (hadCellCheck)1290 rhsNotCell.link(&m_jit);1291 #endif1292 1023 } 1293 1024 … … 1588 1319 } 1589 1320 1590 bool JITCodeGenerator::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)1591 {1592 NodeIndex branchNodeIndex = detectPeepHoleBranch();1593 if (branchNodeIndex != NoNode) {1594 ASSERT(node.adjustedRefCount() == 1);1595 1596 nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);1597 1598 m_compileIndex = branchNodeIndex;1599 1600 return true;1601 }1602 1603 nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);1604 1605 return false;1606 }1607 1608 1321 void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert) 1609 1322 { … … 1749 1462 } 1750 1463 1751 bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert)1752 {1753 if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())))1754 return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);1755 1756 NodeIndex branchNodeIndex = detectPeepHoleBranch();1757 if (branchNodeIndex != NoNode) {1758 ASSERT(node.adjustedRefCount() == 1);1759 1760 nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);1761 1762 m_compileIndex = branchNodeIndex;1763 1764 return true;1765 }1766 1767 nonSpeculativeNonPeepholeStrictEq(node, invert);1768 1769 return false;1770 }1771 1772 1464 void JITCodeGenerator::emitBranch(Node& node) 1773 1465 { … … 1948 1640 } 1949 1641 1950 void JITCodeGenerator::speculationCheck(MacroAssembler::Jump jumpToFail)1951 {1952 ASSERT(m_isSpeculative);1953 static_cast<SpeculativeJIT*>(this)->speculationCheck(jumpToFail);1954 }1955 1956 #ifndef NDEBUG1957 static const char* dataFormatString(DataFormat format)1958 {1959 // These values correspond to the DataFormat enum.1960 const char* strings[] = {1961 "[ ]",1962 "[ i]",1963 "[ d]",1964 "[ c]",1965 "Err!",1966 "Err!",1967 "Err!",1968 "Err!",1969 "[J ]",1970 "[Ji]",1971 "[Jd]",1972 "[Jc]",1973 "Err!",1974 "Err!",1975 "Err!",1976 "Err!",1977 };1978 return strings[format];1979 }1980 1981 void JITCodeGenerator::dump(const char* label)1982 {1983 if (label)1984 fprintf(stderr, "<%s>\n", label);1985 1986 fprintf(stderr, " gprs:\n");1987 m_gprs.dump();1988 fprintf(stderr, " fprs:\n");1989 m_fprs.dump();1990 fprintf(stderr, " VirtualRegisters:\n");1991 for (unsigned i = 0; i < m_generationInfo.size(); ++i) {1992 GenerationInfo& info = m_generationInfo[i];1993 if (info.alive())1994 fprintf(stderr, " % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));1995 else1996 fprintf(stderr, " % 3d:[__][__]", i);1997 if (info.registerFormat() == DataFormatDouble)1998 fprintf(stderr, ":fpr%d\n", info.fpr());1999 else if (info.registerFormat() != DataFormatNone) {2000 ASSERT(info.gpr() != InvalidGPRReg);2001 fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));2002 } else2003 fprintf(stderr, "\n");2004 }2005 if (label)2006 fprintf(stderr, "</%s>\n", label);2007 }2008 1642 #endif 2009 1643 2010 2011 #if ENABLE(DFG_CONSISTENCY_CHECK) 2012 void JITCodeGenerator::checkConsistency() 2013 { 2014 bool failed = false; 2015 2016 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 2017 if (iter.isLocked()) { 2018 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName()); 2019 failed = true; 2020 } 2021 } 2022 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 2023 if (iter.isLocked()) { 2024 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName()); 2025 failed = true; 2026 } 2027 } 2028 2029 for (unsigned i = 0; i < m_generationInfo.size(); ++i) { 2030 VirtualRegister virtualRegister = (VirtualRegister)i; 2031 GenerationInfo& info = m_generationInfo[virtualRegister]; 2032 if (!info.alive()) 2033 continue; 2034 switch (info.registerFormat()) { 2035 case DataFormatNone: 2036 break; 2037 case DataFormatInteger: 2038 case DataFormatCell: 2039 case DataFormatJS: 2040 case DataFormatJSInteger: 2041 case DataFormatJSDouble: 2042 case DataFormatJSCell: { 2043 GPRReg gpr = info.gpr(); 2044 ASSERT(gpr != InvalidGPRReg); 2045 if (m_gprs.name(gpr) != virtualRegister) { 2046 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr)); 2047 failed = true; 2048 } 2049 break; 2050 } 2051 case DataFormatDouble: { 2052 FPRReg fpr = info.fpr(); 2053 ASSERT(fpr != InvalidFPRReg); 2054 if (m_fprs.name(fpr) != virtualRegister) { 2055 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr)); 2056 failed = true; 2057 } 2058 break; 2059 } 2060 } 2061 } 2062 2063 for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { 2064 VirtualRegister virtualRegister = iter.name(); 2065 if (virtualRegister == InvalidVirtualRegister) 2066 continue; 2067 2068 GenerationInfo& info = m_generationInfo[virtualRegister]; 2069 if (iter.regID() != info.gpr()) { 2070 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 2071 failed = true; 2072 } 2073 } 2074 2075 for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { 2076 VirtualRegister virtualRegister = iter.name(); 2077 if (virtualRegister == InvalidVirtualRegister) 2078 continue; 2079 2080 GenerationInfo& info = m_generationInfo[virtualRegister]; 2081 if (iter.regID() != info.fpr()) { 2082 fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); 2083 failed = true; 2084 } 2085 } 2086 2087 if (failed) { 2088 dump(); 2089 CRASH(); 2090 } 2091 } 1644 } } // namespace JSC::DFG 1645 2092 1646 #endif 2093 2094 GPRTemporary::GPRTemporary()2095 : m_jit(0)2096 , m_gpr(InvalidGPRReg)2097 {2098 }2099 2100 GPRTemporary::GPRTemporary(JITCodeGenerator* jit)2101 : m_jit(jit)2102 , m_gpr(InvalidGPRReg)2103 {2104 m_gpr = m_jit->allocate();2105 }2106 2107 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, GPRReg specific)2108 : m_jit(jit)2109 , m_gpr(InvalidGPRReg)2110 {2111 m_gpr = m_jit->allocate(specific);2112 }2113 2114 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)2115 : m_jit(jit)2116 , m_gpr(InvalidGPRReg)2117 {2118 if (m_jit->canReuse(op1.index()))2119 m_gpr = m_jit->reuse(op1.gpr());2120 else2121 m_gpr = m_jit->allocate();2122 }2123 2124 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)2125 : m_jit(jit)2126 , m_gpr(InvalidGPRReg)2127 {2128 if (m_jit->canReuse(op1.index()))2129 m_gpr = m_jit->reuse(op1.gpr());2130 else if (m_jit->canReuse(op2.index()))2131 m_gpr = m_jit->reuse(op2.gpr());2132 else2133 m_gpr = m_jit->allocate();2134 }2135 2136 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateStrictInt32Operand& op1)2137 : m_jit(jit)2138 , m_gpr(InvalidGPRReg)2139 {2140 if (m_jit->canReuse(op1.index()))2141 m_gpr = m_jit->reuse(op1.gpr());2142 else2143 m_gpr = m_jit->allocate();2144 }2145 2146 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)2147 : m_jit(jit)2148 , m_gpr(InvalidGPRReg)2149 {2150 if (m_jit->canReuse(op1.index()))2151 m_gpr = m_jit->reuse(op1.gpr());2152 else2153 m_gpr = m_jit->allocate();2154 }2155 2156 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)2157 : m_jit(jit)2158 , m_gpr(InvalidGPRReg)2159 {2160 if (m_jit->canReuse(op1.index()))2161 m_gpr = m_jit->reuse(op1.gpr());2162 else if (m_jit->canReuse(op2.index()))2163 m_gpr = m_jit->reuse(op2.gpr());2164 else2165 m_gpr = m_jit->allocate();2166 }2167 2168 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)2169 : m_jit(jit)2170 , m_gpr(InvalidGPRReg)2171 {2172 if (m_jit->canReuse(op1.index()))2173 m_gpr = m_jit->reuse(op1.gpr());2174 else2175 m_gpr = m_jit->allocate();2176 }2177 2178 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateBooleanOperand& op1)2179 : m_jit(jit)2180 , m_gpr(InvalidGPRReg)2181 {2182 if (m_jit->canReuse(op1.index()))2183 m_gpr = m_jit->reuse(op1.gpr());2184 else2185 m_gpr = m_jit->allocate();2186 }2187 2188 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)2189 : m_jit(jit)2190 , m_gpr(InvalidGPRReg)2191 {2192 if (m_jit->canReuse(op1.index()))2193 m_gpr = m_jit->reuse(op1.gpr());2194 else2195 m_gpr = m_jit->allocate();2196 }2197 2198 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, StorageOperand& op1)2199 : m_jit(jit)2200 , m_gpr(InvalidGPRReg)2201 {2202 if (m_jit->canReuse(op1.index()))2203 m_gpr = m_jit->reuse(op1.gpr());2204 else2205 m_gpr = m_jit->allocate();2206 }2207 2208 void GPRTemporary::adopt(GPRTemporary& other)2209 {2210 ASSERT(!m_jit);2211 ASSERT(m_gpr == InvalidGPRReg);2212 ASSERT(other.m_jit);2213 ASSERT(other.m_gpr != InvalidGPRReg);2214 m_jit = other.m_jit;2215 m_gpr = other.m_gpr;2216 other.m_jit = 0;2217 other.m_gpr = InvalidGPRReg;2218 }2219 2220 FPRTemporary::FPRTemporary(JITCodeGenerator* jit)2221 : m_jit(jit)2222 , m_fpr(InvalidFPRReg)2223 {2224 m_fpr = m_jit->fprAllocate();2225 }2226 2227 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)2228 : m_jit(jit)2229 , m_fpr(InvalidFPRReg)2230 {2231 if (m_jit->canReuse(op1.index()))2232 m_fpr = m_jit->reuse(op1.fpr());2233 else2234 m_fpr = m_jit->fprAllocate();2235 }2236 2237 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)2238 : m_jit(jit)2239 , m_fpr(InvalidFPRReg)2240 {2241 if (m_jit->canReuse(op1.index()))2242 m_fpr = m_jit->reuse(op1.fpr());2243 else if (m_jit->canReuse(op2.index()))2244 m_fpr = m_jit->reuse(op2.fpr());2245 else2246 m_fpr = m_jit->fprAllocate();2247 }2248 2249 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1)2250 : m_jit(jit)2251 , m_fpr(InvalidFPRReg)2252 {2253 if (m_jit->canReuse(op1.index()))2254 m_fpr = m_jit->reuse(op1.fpr());2255 else2256 m_fpr = m_jit->fprAllocate();2257 }2258 2259 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)2260 : m_jit(jit)2261 , m_fpr(InvalidFPRReg)2262 {2263 if (m_jit->canReuse(op1.index()))2264 m_fpr = m_jit->reuse(op1.fpr());2265 else if (m_jit->canReuse(op2.index()))2266 m_fpr = m_jit->reuse(op2.fpr());2267 else2268 m_fpr = m_jit->fprAllocate();2269 }2270 2271 } } // namespace JSC::DFG2272 2273 #endif2274 #endif -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r96375 r96377 166 166 #endif 167 167 168 Jump branchIfNotCell(GPRReg reg) 169 { 170 #if USE(JSVALUE64) 171 return branchTestPtr(MacroAssembler::NonZero, reg, GPRInfo::tagMaskRegister); 172 #else 173 return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag)); 174 #endif 175 } 176 168 177 static Address addressForGlobalVar(GPRReg global, int32_t varNumber) 169 178 { -
trunk/Source/JavaScriptCore/dfg/DFGJITCompilerInlineMethods.h
r95902 r96377 5 5 6 6 #if ENABLE(DFG_JIT) 7 #if USE(JSVALUE32_64)8 7 9 8 namespace JSC { namespace DFG { 9 10 #if USE(JSVALUE32_64) 10 11 11 12 inline void JITCompiler::emitLoadTag(NodeIndex index, GPRReg tag) … … 135 136 } 136 137 138 #endif // USE(JSVALUE32_64) 139 137 140 } } // namespace JSC::DFG 138 141 139 #endif // USE(JSVALUE32_64)140 142 #endif // ENABLE_DFG_JIT 141 143
Note: See TracChangeset
for help on using the changeset viewer.