Changeset 230517 in webkit
- Timestamp:
- Apr 11, 2018 12:44:58 AM (6 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r230516 r230517 1 2018-04-11 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DFG] Remove duplicate 32bit code more 4 https://bugs.webkit.org/show_bug.cgi?id=184236 5 6 Reviewed by Mark Lam. 7 8 Remove duplicate 32bit code more aggressively part 2. 9 10 * JavaScriptCore.xcodeproj/project.pbxproj: 11 * dfg/DFGCompareSlowPathGenerator.h: Added. 12 (JSC::DFG::CompareSlowPathGenerator::CompareSlowPathGenerator): 13 Drop boxing part. Use unblessedBooleanResult in DFGSpeculativeJIT side instead. 14 15 * dfg/DFGOperations.cpp: 16 * dfg/DFGOperations.h: 17 * dfg/DFGSpeculativeJIT.cpp: 18 (JSC::DFG::SpeculativeJIT::compileOverridesHasInstance): 19 (JSC::DFG::SpeculativeJIT::compileLoadVarargs): 20 (JSC::DFG::SpeculativeJIT::compileIsObject): 21 (JSC::DFG::SpeculativeJIT::compileCheckNotEmpty): 22 (JSC::DFG::SpeculativeJIT::compilePutByIdFlush): 23 (JSC::DFG::SpeculativeJIT::compilePutById): 24 (JSC::DFG::SpeculativeJIT::compilePutByIdDirect): 25 (JSC::DFG::SpeculativeJIT::compileNewArrayWithSize): 26 (JSC::DFG::SpeculativeJIT::compileMiscStrictEq): 27 (JSC::DFG::SpeculativeJIT::emitInitializeButterfly): 28 (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): 29 (JSC::DFG::SpeculativeJIT::compileHasIndexedProperty): 30 (JSC::DFG::SpeculativeJIT::compileGetDirectPname): 31 (JSC::DFG::SpeculativeJIT::compileExtractCatchLocal): 32 (JSC::DFG::SpeculativeJIT::cachedPutById): 33 (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): 34 (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): 35 (JSC::DFG::SpeculativeJIT::nonSpeculativeCompare): Deleted. 36 * dfg/DFGSpeculativeJIT.h: 37 (JSC::DFG::SpeculativeJIT::selectScratchGPR): Deleted. 38 * dfg/DFGSpeculativeJIT32_64.cpp: 39 (JSC::DFG::SpeculativeJIT::compile): 40 (JSC::DFG::SpeculativeJIT::cachedPutById): Deleted. 41 (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): Deleted. 42 (JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::CompareAndBoxBooleanSlowPathGenerator): Deleted. 43 (JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::generateInternal): Deleted. 44 (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted. 45 (JSC::DFG::SpeculativeJIT::compileMiscStrictEq): Deleted. 46 (JSC::DFG::SpeculativeJIT::emitInitializeButterfly): Deleted. 47 (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): Deleted. 48 * dfg/DFGSpeculativeJIT64.cpp: 49 (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq): 50 (JSC::DFG::SpeculativeJIT::compile): 51 (JSC::DFG::SpeculativeJIT::cachedPutById): Deleted. 52 (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): Deleted. 53 (JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::CompareAndBoxBooleanSlowPathGenerator): Deleted. 54 (): Deleted. 55 (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted. 56 (JSC::DFG::SpeculativeJIT::compileMiscStrictEq): Deleted. 57 (JSC::DFG::SpeculativeJIT::emitInitializeButterfly): Deleted. 58 (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): Deleted. 59 * ftl/FTLLowerDFGToB3.cpp: 60 (JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty): 61 operationHasIndexedPropertyByInt starts returning unblessed boolean with size_t. 62 63 * jit/AssemblyHelpers.h: 64 (JSC::AssemblyHelpers::loadValue): 65 (JSC::AssemblyHelpers::selectScratchGPR): 66 (JSC::AssemblyHelpers::constructRegisterSet): 67 * jit/RegisterSet.h: 68 (JSC::RegisterSet::setAny): 69 Clean up selectScratchGPR code to pass JSValueRegs. 70 1 71 2018-04-10 Caio Lima <ticaiolima@gmail.com> 2 72 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r230488 r230517 1707 1707 E3555B8A1DAE03A500F36921 /* DOMJITCallDOMGetterSnippet.h in Headers */ = {isa = PBXBuildFile; fileRef = E3555B891DAE03A200F36921 /* DOMJITCallDOMGetterSnippet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1708 1708 E355F3531B7DC85300C50DC5 /* ModuleLoaderPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */; }; 1709 E356D86420728381005AC750 /* DFGCompareSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = E356D86320728381005AC750 /* DFGCompareSlowPathGenerator.h */; }; 1709 1710 E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1521DBC3A5600F83516 /* DOMJITHeapRange.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1710 1711 E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4556 4557 E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleLoaderPrototype.cpp; sourceTree = "<group>"; }; 4557 4558 E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleLoaderPrototype.h; sourceTree = "<group>"; }; 4559 E356D86320728381005AC750 /* DFGCompareSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCompareSlowPathGenerator.h; path = dfg/DFGCompareSlowPathGenerator.h; sourceTree = "<group>"; }; 4558 4560 E35CA14F1DBC3A5600F83516 /* DOMJITAbstractHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITAbstractHeap.cpp; sourceTree = "<group>"; }; 4559 4561 E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAbstractHeap.h; sourceTree = "<group>"; }; … … 7161 7163 0FEA0A2D170D40BF00BB722C /* DFGCommonData.cpp */, 7162 7164 0FEA0A2E170D40BF00BB722C /* DFGCommonData.h */, 7165 E356D86320728381005AC750 /* DFGCompareSlowPathGenerator.h */, 7163 7166 0F38B01317CFE75500B144D3 /* DFGCompilationKey.cpp */, 7164 7167 0F38B01417CFE75500B144D3 /* DFGCompilationKey.h */, … … 8510 8513 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */, 8511 8514 0FEA0A32170D40BF00BB722C /* DFGCommonData.h in Headers */, 8515 E356D86420728381005AC750 /* DFGCompareSlowPathGenerator.h in Headers */, 8512 8516 0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */, 8513 8517 0F38B01A17CFE75500B144D3 /* DFGCompilationMode.h in Headers */, … … 9035 9039 7013CA8C1B491A9400CAE613 /* JSJob.h in Headers */, 9036 9040 BC18C4160E16F5CD00B34460 /* JSLexicalEnvironment.h in Headers */, 9037 7A9774A8206B82E4008D03D0 /* JSWeakValue.h in Headers */,9038 9041 BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */, 9039 9042 C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */, … … 9107 9110 0F0B286B1EB8E6CF000EB5D2 /* JSWeakPrivate.h in Headers */, 9108 9111 709FB8681AE335C60039D069 /* JSWeakSet.h in Headers */, 9112 7A9774A8206B82E4008D03D0 /* JSWeakValue.h in Headers */, 9109 9113 AD5C36EB1F75AD73000BCAAF /* JSWebAssembly.h in Headers */, 9110 9114 AD9E852F1E8A0C7C008DE39E /* JSWebAssemblyCodeBlock.h in Headers */, -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r230516 r230517 1898 1898 } 1899 1899 1900 EncodedJSValueJIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)1900 size_t JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType) 1901 1901 { 1902 1902 VM& vm = exec->vm(); … … 1905 1905 if (UNLIKELY(subscript < 0)) { 1906 1906 // Go the slowest way possible because negative indices don't use indexed storage. 1907 return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType))));1908 } 1909 return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType))));1907 return object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType)); 1908 } 1909 return object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType)); 1910 1910 } 1911 1911 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r230516 r230517 81 81 EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState*, JSObject*) WTF_INTERNAL; 82 82 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*); 83 EncodedJSValueJIT_OPERATION operationHasIndexedPropertyByInt(ExecState*, JSCell*, int32_t, int32_t);83 size_t JIT_OPERATION operationHasIndexedPropertyByInt(ExecState*, JSCell*, int32_t, int32_t); 84 84 JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState*, EncodedJSValue); 85 85 JSCell* JIT_OPERATION operationGetPropertyEnumeratorCell(ExecState*, JSCell*); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r230516 r230517 35 35 #include "DFGCallCreateDirectArgumentsSlowPathGenerator.h" 36 36 #include "DFGCapabilities.h" 37 #include "DFGCompareSlowPathGenerator.h" 37 38 #include "DFGMayExit.h" 38 39 #include "DFGOSRExitFuzz.h" … … 1183 1184 } 1184 1185 1185 bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)1186 {1187 unsigned branchIndexInBlock = detectPeepHoleBranch();1188 if (branchIndexInBlock != UINT_MAX) {1189 Node* branchNode = m_block->at(branchIndexInBlock);1190 1191 ASSERT(node->adjustedRefCount() == 1);1192 1193 nonSpeculativePeepholeBranch(node, branchNode, cond, helperFunction);1194 1195 m_indexInBlock = branchIndexInBlock;1196 m_currentNode = branchNode;1197 1198 return true;1199 }1200 1201 nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);1202 1203 return false;1204 }1205 1206 1186 bool SpeculativeJIT::nonSpeculativeStrictEq(Node* node, bool invert) 1207 1187 { … … 3465 3445 m_jit.exceptionCheck(); 3466 3446 jsValueResult(resultRegs, node); 3447 } 3448 3449 void SpeculativeJIT::compileOverridesHasInstance(Node* node) 3450 { 3451 Node* hasInstanceValueNode = node->child2().node(); 3452 JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value()); 3453 3454 MacroAssembler::JumpList notDefault; 3455 SpeculateCellOperand base(this, node->child1()); 3456 JSValueOperand hasInstanceValue(this, node->child2()); 3457 GPRTemporary result(this); 3458 3459 GPRReg baseGPR = base.gpr(); 3460 GPRReg resultGPR = result.gpr(); 3461 3462 // It would be great if constant folding handled automatically the case where we knew the hasInstance function 3463 // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase 3464 // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832 3465 if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) { 3466 JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs(); 3467 #if USE(JSVALUE64) 3468 notDefault.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.gpr(), TrustedImmPtr(node->cellOperand()))); 3469 #else 3470 notDefault.append(m_jit.branchIfNotCell(hasInstanceValueRegs)); 3471 notDefault.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(node->cellOperand()))); 3472 #endif 3473 } 3474 3475 // Check that base 'ImplementsDefaultHasInstance'. 3476 m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR); 3477 MacroAssembler::Jump done = m_jit.jump(); 3478 3479 if (!notDefault.empty()) { 3480 notDefault.link(&m_jit); 3481 m_jit.move(TrustedImm32(1), resultGPR); 3482 } 3483 3484 done.link(&m_jit); 3485 unblessedBooleanResult(resultGPR, node); 3467 3486 } 3468 3487 … … 6925 6944 } 6926 6945 6946 void SpeculativeJIT::compileLoadVarargs(Node* node) 6947 { 6948 LoadVarargsData* data = node->loadVarargsData(); 6949 6950 JSValueRegs argumentsRegs; 6951 { 6952 JSValueOperand arguments(this, node->child1()); 6953 argumentsRegs = arguments.jsValueRegs(); 6954 flushRegisters(); 6955 } 6956 6957 callOperation(operationSizeOfVarargs, GPRInfo::returnValueGPR, argumentsRegs, data->offset); 6958 m_jit.exceptionCheck(); 6959 6960 lock(GPRInfo::returnValueGPR); 6961 { 6962 JSValueOperand arguments(this, node->child1()); 6963 argumentsRegs = arguments.jsValueRegs(); 6964 flushRegisters(); 6965 } 6966 unlock(GPRInfo::returnValueGPR); 6967 6968 // FIXME: There is a chance that we will call an effectful length property twice. This is safe 6969 // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance 6970 // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right 6971 // past the sizing. 6972 // https://bugs.webkit.org/show_bug.cgi?id=141448 6973 6974 GPRReg argCountIncludingThisGPR = 6975 JITCompiler::selectScratchGPR(GPRInfo::returnValueGPR, argumentsRegs); 6976 6977 m_jit.add32(TrustedImm32(1), GPRInfo::returnValueGPR, argCountIncludingThisGPR); 6978 6979 speculationCheck( 6980 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 6981 MacroAssembler::Above, 6982 GPRInfo::returnValueGPR, 6983 argCountIncludingThisGPR)); 6984 6985 speculationCheck( 6986 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 6987 MacroAssembler::Above, 6988 argCountIncludingThisGPR, 6989 TrustedImm32(data->limit))); 6990 6991 m_jit.store32(argCountIncludingThisGPR, JITCompiler::payloadFor(data->machineCount)); 6992 6993 callOperation(operationLoadVarargs, data->machineStart.offset(), argumentsRegs, data->offset, GPRInfo::returnValueGPR, data->mandatoryMinimum); 6994 m_jit.exceptionCheck(); 6995 6996 noResult(node); 6997 } 6998 6927 6999 void SpeculativeJIT::compileForwardVarargs(Node* node) 6928 7000 { … … 8510 8582 } 8511 8583 8584 void SpeculativeJIT::compileIsObject(Node* node) 8585 { 8586 JSValueOperand value(this, node->child1()); 8587 #if USE(JSVALUE64) 8588 GPRTemporary result(this, Reuse, value); 8589 #else 8590 GPRTemporary result(this, Reuse, value, TagWord); 8591 #endif 8592 8593 JSValueRegs valueRegs = value.jsValueRegs(); 8594 GPRReg resultGPR = result.gpr(); 8595 8596 JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs); 8597 8598 m_jit.compare8(JITCompiler::AboveOrEqual, 8599 JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()), 8600 TrustedImm32(ObjectType), 8601 resultGPR); 8602 JITCompiler::Jump done = m_jit.jump(); 8603 8604 isNotCell.link(&m_jit); 8605 m_jit.move(TrustedImm32(0), resultGPR); 8606 8607 done.link(&m_jit); 8608 unblessedBooleanResult(resultGPR, node); 8609 } 8610 8512 8611 void SpeculativeJIT::compileIsObjectOrNull(Node* node) 8513 8612 { … … 8665 8764 SpeculateCellOperand cell(this, node->child1()); 8666 8765 speculationCheck(BadCell, JSValueSource::unboxedCell(cell.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, cell.gpr(), node->cellOperand()->cell())); 8766 noResult(node); 8767 } 8768 8769 void SpeculativeJIT::compileCheckNotEmpty(Node* node) 8770 { 8771 JSValueOperand operand(this, node->child1()); 8772 JSValueRegs regs = operand.jsValueRegs(); 8773 speculationCheck(TDZFailure, JSValueSource(), nullptr, m_jit.branchIfEmpty(regs)); 8667 8774 noResult(node); 8668 8775 } … … 11555 11662 m_jit.exceptionCheck(); 11556 11663 cellResult(resultGPR, node); 11664 } 11665 11666 void SpeculativeJIT::compilePutByIdFlush(Node* node) 11667 { 11668 SpeculateCellOperand base(this, node->child1()); 11669 JSValueOperand value(this, node->child2()); 11670 GPRTemporary scratch(this); 11671 11672 GPRReg baseGPR = base.gpr(); 11673 JSValueRegs valueRegs = value.jsValueRegs(); 11674 GPRReg scratchGPR = scratch.gpr(); 11675 flushRegisters(); 11676 11677 cachedPutById(node->origin.semantic, baseGPR, valueRegs, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill); 11678 11679 noResult(node); 11680 } 11681 11682 void SpeculativeJIT::compilePutById(Node* node) 11683 { 11684 SpeculateCellOperand base(this, node->child1()); 11685 JSValueOperand value(this, node->child2()); 11686 GPRTemporary scratch(this); 11687 11688 GPRReg baseGPR = base.gpr(); 11689 JSValueRegs valueRegs = value.jsValueRegs(); 11690 GPRReg scratchGPR = scratch.gpr(); 11691 11692 cachedPutById(node->origin.semantic, baseGPR, valueRegs, scratchGPR, node->identifierNumber(), NotDirect); 11693 11694 noResult(node); 11695 } 11696 11697 void SpeculativeJIT::compilePutByIdDirect(Node* node) 11698 { 11699 SpeculateCellOperand base(this, node->child1()); 11700 JSValueOperand value(this, node->child2()); 11701 GPRTemporary scratch(this); 11702 11703 GPRReg baseGPR = base.gpr(); 11704 JSValueRegs valueRegs = value.jsValueRegs(); 11705 GPRReg scratchGPR = scratch.gpr(); 11706 11707 cachedPutById(node->origin.semantic, baseGPR, valueRegs, scratchGPR, node->identifierNumber(), Direct); 11708 11709 noResult(node); 11557 11710 } 11558 11711 … … 11861 12014 GPRFlushedCallResult result(this); 11862 12015 GPRReg resultGPR = result.gpr(); 11863 GPRReg structureGPR = selectScratchGPR(sizeGPR);12016 GPRReg structureGPR = AssemblyHelpers::selectScratchGPR(sizeGPR); 11864 12017 MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)); 11865 12018 m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()))), structureGPR); … … 12410 12563 } 12411 12564 12565 void SpeculativeJIT::compileMiscStrictEq(Node* node) 12566 { 12567 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 12568 JSValueOperand op2(this, node->child2(), ManualOperandSpeculation); 12569 GPRTemporary result(this); 12570 12571 if (node->child1().useKind() == MiscUse) 12572 speculateMisc(node->child1(), op1.jsValueRegs()); 12573 if (node->child2().useKind() == MiscUse) 12574 speculateMisc(node->child2(), op2.jsValueRegs()); 12575 12576 #if USE(JSVALUE64) 12577 m_jit.compare64(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr()); 12578 #else 12579 m_jit.move(TrustedImm32(0), result.gpr()); 12580 JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR()); 12581 m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr()); 12582 notEqual.link(&m_jit); 12583 #endif 12584 unblessedBooleanResult(result.gpr(), node); 12585 } 12586 12587 void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR) 12588 { 12589 m_jit.zeroExtend32ToPtr(sizeGPR, scratchGPR); 12590 MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR); 12591 MacroAssembler::Label loop = m_jit.label(); 12592 m_jit.sub32(TrustedImm32(1), scratchGPR); 12593 m_jit.storeValue(emptyValueRegs, MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight)); 12594 m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit); 12595 done.link(&m_jit); 12596 } 12597 12598 void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage) 12599 { 12600 GPRTemporary storage(this); 12601 GPRTemporary scratch(this); 12602 GPRTemporary scratch2(this); 12603 12604 GPRReg storageGPR = storage.gpr(); 12605 GPRReg scratchGPR = scratch.gpr(); 12606 GPRReg scratch2GPR = scratch2.gpr(); 12607 12608 m_jit.move(TrustedImmPtr(nullptr), storageGPR); 12609 12610 MacroAssembler::JumpList slowCases; 12611 if (shouldConvertLargeSizeToArrayStorage) 12612 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH))); 12613 12614 // We can use resultGPR as a scratch right now. 12615 emitAllocateButterfly(storageGPR, sizeGPR, scratchGPR, scratch2GPR, resultGPR, slowCases); 12616 12617 #if USE(JSVALUE64) 12618 JSValueRegs emptyValueRegs(scratchGPR); 12619 if (hasDouble(indexingType)) 12620 m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), emptyValueRegs.gpr()); 12621 else 12622 m_jit.move(TrustedImm64(JSValue::encode(JSValue())), emptyValueRegs.gpr()); 12623 #else 12624 JSValueRegs emptyValueRegs(scratchGPR, scratch2GPR); 12625 if (hasDouble(indexingType)) 12626 m_jit.moveValue(JSValue(JSValue::EncodeAsDouble, PNaN), emptyValueRegs); 12627 else 12628 m_jit.moveValue(JSValue(), emptyValueRegs); 12629 #endif 12630 emitInitializeButterfly(storageGPR, sizeGPR, emptyValueRegs, resultGPR); 12631 12632 RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)); 12633 12634 emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases); 12635 12636 m_jit.mutatorFence(*m_jit.vm()); 12637 12638 addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>( 12639 slowCases, this, operationNewArrayWithSize, resultGPR, 12640 structure, 12641 shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure, 12642 sizeGPR, storageGPR)); 12643 } 12644 12645 void SpeculativeJIT::compileHasIndexedProperty(Node* node) 12646 { 12647 SpeculateCellOperand base(this, node->child1()); 12648 SpeculateStrictInt32Operand index(this, node->child2()); 12649 GPRTemporary result(this); 12650 12651 GPRReg baseGPR = base.gpr(); 12652 GPRReg indexGPR = index.gpr(); 12653 GPRReg resultGPR = result.gpr(); 12654 12655 MacroAssembler::JumpList slowCases; 12656 ArrayMode mode = node->arrayMode(); 12657 switch (mode.type()) { 12658 case Array::Int32: 12659 case Array::Contiguous: { 12660 ASSERT(!!node->child3()); 12661 StorageOperand storage(this, node->child3()); 12662 GPRTemporary scratch(this); 12663 12664 GPRReg storageGPR = storage.gpr(); 12665 GPRReg scratchGPR = scratch.gpr(); 12666 12667 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 12668 if (mode.isInBounds()) 12669 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds); 12670 else 12671 slowCases.append(outOfBounds); 12672 12673 #if USE(JSVALUE64) 12674 m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchGPR); 12675 slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR)); 12676 #else 12677 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR); 12678 slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag))); 12679 #endif 12680 m_jit.move(TrustedImm32(1), resultGPR); 12681 break; 12682 } 12683 case Array::Double: { 12684 ASSERT(!!node->child3()); 12685 StorageOperand storage(this, node->child3()); 12686 FPRTemporary scratch(this); 12687 FPRReg scratchFPR = scratch.fpr(); 12688 GPRReg storageGPR = storage.gpr(); 12689 12690 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 12691 if (mode.isInBounds()) 12692 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds); 12693 else 12694 slowCases.append(outOfBounds); 12695 12696 m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR); 12697 slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR)); 12698 m_jit.move(TrustedImm32(1), resultGPR); 12699 break; 12700 } 12701 case Array::ArrayStorage: { 12702 ASSERT(!!node->child3()); 12703 StorageOperand storage(this, node->child3()); 12704 GPRTemporary scratch(this); 12705 12706 GPRReg storageGPR = storage.gpr(); 12707 GPRReg scratchGPR = scratch.gpr(); 12708 12709 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 12710 if (mode.isInBounds()) 12711 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds); 12712 else 12713 slowCases.append(outOfBounds); 12714 12715 #if USE(JSVALUE64) 12716 m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), scratchGPR); 12717 slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR)); 12718 #else 12719 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR); 12720 slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag))); 12721 #endif 12722 m_jit.move(TrustedImm32(1), resultGPR); 12723 break; 12724 } 12725 default: { 12726 slowCases.append(m_jit.jump()); 12727 break; 12728 } 12729 } 12730 12731 addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, HasPropertyPtrTag, resultGPR, baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType()))); 12732 12733 unblessedBooleanResult(resultGPR, node); 12734 } 12735 12736 void SpeculativeJIT::compileGetDirectPname(Node* node) 12737 { 12738 Edge& baseEdge = m_jit.graph().varArgChild(node, 0); 12739 Edge& propertyEdge = m_jit.graph().varArgChild(node, 1); 12740 12741 SpeculateCellOperand base(this, baseEdge); 12742 SpeculateCellOperand property(this, propertyEdge); 12743 GPRReg baseGPR = base.gpr(); 12744 GPRReg propertyGPR = property.gpr(); 12745 12746 #if CPU(X86) 12747 // Not enough registers on X86 for this code, so always use the slow path. 12748 flushRegisters(); 12749 JSValueRegsFlushedCallResult result(this); 12750 JSValueRegs resultRegs = result.regs(); 12751 callOperation(operationGetByValCell, resultRegs, baseGPR, JSValue::JSCellType, propertyGPR); 12752 m_jit.exceptionCheck(); 12753 jsValueResult(resultRegs, node); 12754 #else 12755 Edge& indexEdge = m_jit.graph().varArgChild(node, 2); 12756 Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3); 12757 SpeculateStrictInt32Operand index(this, indexEdge); 12758 SpeculateCellOperand enumerator(this, enumeratorEdge); 12759 GPRTemporary scratch(this); 12760 JSValueRegsTemporary result(this); 12761 12762 GPRReg indexGPR = index.gpr(); 12763 GPRReg enumeratorGPR = enumerator.gpr(); 12764 GPRReg scratchGPR = scratch.gpr(); 12765 JSValueRegs resultRegs = result.regs(); 12766 12767 MacroAssembler::JumpList slowPath; 12768 12769 // Check the structure 12770 m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR); 12771 slowPath.append( 12772 m_jit.branch32( 12773 MacroAssembler::NotEqual, 12774 scratchGPR, 12775 MacroAssembler::Address( 12776 enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()))); 12777 12778 // Compute the offset 12779 // If index is less than the enumerator's cached inline storage, then it's an inline access 12780 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual, 12781 indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset())); 12782 12783 m_jit.loadValue(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs); 12784 12785 MacroAssembler::Jump done = m_jit.jump(); 12786 12787 // Otherwise it's out of line 12788 outOfLineAccess.link(&m_jit); 12789 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultRegs.gpr()); 12790 m_jit.move(indexGPR, scratchGPR); 12791 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR); 12792 m_jit.neg32(scratchGPR); 12793 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR); 12794 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 12795 m_jit.loadValue(MacroAssembler::BaseIndex(resultRegs.gpr(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs); 12796 12797 done.link(&m_jit); 12798 12799 #if USE(JSVALUE64) 12800 addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, GetPropertyPtrTag, resultRegs, baseGPR, propertyGPR)); 12801 #else 12802 addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, GetPropertyPtrTag, resultRegs, baseGPR, JSValue::JSCellType, propertyGPR)); 12803 #endif 12804 12805 jsValueResult(resultRegs, node); 12806 #endif 12807 } 12808 12809 void SpeculativeJIT::compileExtractCatchLocal(Node* node) 12810 { 12811 JSValueRegsTemporary result(this); 12812 JSValueRegs resultRegs = result.regs(); 12813 12814 JSValue* ptr = &reinterpret_cast<JSValue*>(m_jit.jitCode()->common.catchOSREntryBuffer->dataBuffer())[node->catchOSREntryIndex()]; 12815 m_jit.loadValue(ptr, resultRegs); 12816 jsValueResult(resultRegs, node); 12817 } 12818 12819 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode) 12820 { 12821 RegisterSet usedRegisters = this->usedRegisters(); 12822 if (spillMode == DontSpill) { 12823 // We've already flushed registers to the stack, we don't need to spill these. 12824 usedRegisters.set(baseGPR, false); 12825 usedRegisters.set(valueRegs, false); 12826 } 12827 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size()); 12828 JITPutByIdGenerator gen( 12829 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, 12830 JSValueRegs::payloadOnly(baseGPR), valueRegs, 12831 scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind); 12832 12833 gen.generateFastPath(m_jit); 12834 12835 JITCompiler::JumpList slowCases; 12836 if (slowPathTarget.isSet()) 12837 slowCases.append(slowPathTarget); 12838 slowCases.append(gen.slowPathJump()); 12839 12840 #if USE(JSVALUE64) 12841 auto slowPath = slowPathCall( 12842 slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueRegs, 12843 baseGPR, identifierUID(identifierNumber)); 12844 #else 12845 auto slowPath = slowPathCall( 12846 slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueRegs, 12847 JSValue::JSCellType, baseGPR, identifierUID(identifierNumber)); 12848 #endif 12849 12850 m_jit.addPutById(gen, slowPath.get()); 12851 addSlowPathGenerator(WTFMove(slowPath)); 12852 } 12853 12854 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction) 12855 { 12856 ASSERT(node->isBinaryUseKind(UntypedUse)); 12857 JSValueOperand arg1(this, node->child1()); 12858 JSValueOperand arg2(this, node->child2()); 12859 12860 JSValueRegs arg1Regs = arg1.jsValueRegs(); 12861 JSValueRegs arg2Regs = arg2.jsValueRegs(); 12862 12863 JITCompiler::JumpList slowPath; 12864 12865 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) { 12866 GPRFlushedCallResult result(this); 12867 GPRReg resultGPR = result.gpr(); 12868 12869 arg1.use(); 12870 arg2.use(); 12871 12872 flushRegisters(); 12873 callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs); 12874 m_jit.exceptionCheck(); 12875 12876 unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly); 12877 return; 12878 } 12879 12880 #if USE(JSVALUE64) 12881 GPRTemporary result(this, Reuse, arg1); 12882 #else 12883 GPRTemporary result(this, Reuse, arg1, TagWord); 12884 #endif 12885 GPRReg resultGPR = result.gpr(); 12886 12887 arg1.use(); 12888 arg2.use(); 12889 12890 if (!isKnownInteger(node->child1().node())) 12891 slowPath.append(m_jit.branchIfNotInt32(arg1Regs)); 12892 if (!isKnownInteger(node->child2().node())) 12893 slowPath.append(m_jit.branchIfNotInt32(arg2Regs)); 12894 12895 m_jit.compare32(cond, arg1Regs.payloadGPR(), arg2Regs.payloadGPR(), resultGPR); 12896 12897 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) { 12898 addSlowPathGenerator(std::make_unique<CompareSlowPathGenerator<JITCompiler::JumpList>>( 12899 slowPath, this, helperFunction, resultGPR, arg1Regs, arg2Regs)); 12900 } 12901 12902 unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly); 12903 } 12904 12905 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction) 12906 { 12907 BasicBlock* taken = branchNode->branchData()->taken.block; 12908 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 12909 12910 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero; 12911 12912 // The branch instruction will branch to the taken block. 12913 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through. 12914 if (taken == nextBlock()) { 12915 cond = JITCompiler::invert(cond); 12916 callResultCondition = JITCompiler::Zero; 12917 BasicBlock* tmp = taken; 12918 taken = notTaken; 12919 notTaken = tmp; 12920 } 12921 12922 JSValueOperand arg1(this, node->child1()); 12923 JSValueOperand arg2(this, node->child2()); 12924 JSValueRegs arg1Regs = arg1.jsValueRegs(); 12925 JSValueRegs arg2Regs = arg2.jsValueRegs(); 12926 12927 JITCompiler::JumpList slowPath; 12928 12929 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) { 12930 GPRFlushedCallResult result(this); 12931 GPRReg resultGPR = result.gpr(); 12932 12933 arg1.use(); 12934 arg2.use(); 12935 12936 flushRegisters(); 12937 callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs); 12938 m_jit.exceptionCheck(); 12939 12940 branchTest32(callResultCondition, resultGPR, taken); 12941 } else { 12942 #if USE(JSVALUE64) 12943 GPRTemporary result(this, Reuse, arg2); 12944 #else 12945 GPRTemporary result(this, Reuse, arg2, TagWord); 12946 #endif 12947 GPRReg resultGPR = result.gpr(); 12948 12949 arg1.use(); 12950 arg2.use(); 12951 12952 if (!isKnownInteger(node->child1().node())) 12953 slowPath.append(m_jit.branchIfNotInt32(arg1Regs)); 12954 if (!isKnownInteger(node->child2().node())) 12955 slowPath.append(m_jit.branchIfNotInt32(arg2Regs)); 12956 12957 branch32(cond, arg1Regs.payloadGPR(), arg2Regs.payloadGPR(), taken); 12958 12959 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) { 12960 jump(notTaken, ForceJump); 12961 12962 slowPath.link(&m_jit); 12963 12964 silentSpillAllRegisters(resultGPR); 12965 callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs); 12966 silentFillAllRegisters(); 12967 m_jit.exceptionCheck(); 12968 12969 branchTest32(callResultCondition, resultGPR, taken); 12970 } 12971 } 12972 12973 jump(notTaken); 12974 12975 m_indexInBlock = m_block->size() - 1; 12976 m_currentNode = branchNode; 12977 } 12412 12978 12413 12979 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r230516 r230517 346 346 void compileStoreBarrier(Node*); 347 347 348 static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)349 {350 return AssemblyHelpers::selectScratchGPR(preserve1, preserve2, preserve3, preserve4);351 }352 353 348 // Called by the speculative operand types, below, to fill operand to 354 349 // machine registers, implicitly generating speculation checks as needed. … … 726 721 727 722 void cachedGetById(CodeOrigin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType); 723 void cachedPutById(CodeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); 728 724 729 725 #if USE(JSVALUE64) 730 726 void cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType); 731 void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);732 727 void cachedGetByIdWithThis(CodeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList()); 733 728 #elif USE(JSVALUE32_64) 734 729 void cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType); 735 void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);736 730 void cachedGetByIdWithThis(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPROrNone, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList()); 737 731 #endif … … 749 743 void nonSpeculativePeepholeBranch(Node*, Node* branchNode, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction); 750 744 void nonSpeculativeNonPeepholeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction); 751 bool nonSpeculativeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);752 745 753 746 void nonSpeculativePeepholeStrictEq(Node*, Node* branchNode, bool invert = false); … … 758 751 void compileInstanceOf(Node*); 759 752 void compileInstanceOfCustom(Node*); 753 void compileOverridesHasInstance(Node*); 760 754 761 755 void compileIsCellWithType(Node*); … … 1443 1437 void compileNewRegexp(Node*); 1444 1438 void compileForwardVarargs(Node*); 1439 void compileLoadVarargs(Node*); 1445 1440 void compileCreateActivation(Node*); 1446 1441 void compileCreateDirectArguments(Node*); … … 1465 1460 void compileRegExpTest(Node*); 1466 1461 void compileStringReplace(Node*); 1462 void compileIsObject(Node*); 1467 1463 void compileIsObjectOrNull(Node*); 1468 1464 void compileIsFunction(Node*); 1469 1465 void compileTypeOf(Node*); 1470 1466 void compileCheckCell(Node*); 1467 void compileCheckNotEmpty(Node*); 1471 1468 void compileCheckStructure(Node*); 1472 1469 void emitStructureCheck(Node*, GPRReg cellGPR, GPRReg tempGPR); … … 1498 1495 void compileHasGenericProperty(Node*); 1499 1496 void compileToIndexString(Node*); 1497 void compilePutByIdFlush(Node*); 1498 void compilePutById(Node*); 1499 void compilePutByIdDirect(Node*); 1500 1500 void compilePutByIdWithThis(Node*); 1501 1501 void compileHasStructureProperty(Node*); 1502 void compileGetDirectPname(Node*); 1502 1503 void compileGetPropertyEnumerator(Node*); 1503 1504 void compileGetEnumeratorPname(Node*); … … 1518 1519 void compileLogShadowChickenPrologue(Node*); 1519 1520 void compileLogShadowChickenTail(Node*); 1521 void compileHasIndexedProperty(Node*); 1522 void compileExtractCatchLocal(Node*); 1520 1523 1521 1524 void moveTrueTo(GPRReg); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r230516 r230517 266 266 } 267 267 268 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)269 {270 RegisterSet usedRegisters = this->usedRegisters();271 if (spillMode == DontSpill) {272 // We've already flushed registers to the stack, we don't need to spill these.273 usedRegisters.set(basePayloadGPR, false);274 usedRegisters.set(JSValueRegs(valueTagGPR, valuePayloadGPR), false);275 }276 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());277 JITPutByIdGenerator gen(278 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters,279 JSValueRegs::payloadOnly(basePayloadGPR), JSValueRegs(valueTagGPR, valuePayloadGPR),280 scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);281 282 gen.generateFastPath(m_jit);283 284 JITCompiler::JumpList slowCases;285 if (slowPathTarget.isSet())286 slowCases.append(slowPathTarget);287 slowCases.append(gen.slowPathJump());288 289 auto slowPath = slowPathCall(290 slowCases, this, gen.slowPathFunction(), NoResult, gen.stubInfo(), JSValueRegs(valueTagGPR, valuePayloadGPR),291 JSValue::JSCellType, basePayloadGPR, identifierUID(identifierNumber));292 293 m_jit.addPutById(gen, slowPath.get());294 addSlowPathGenerator(WTFMove(slowPath));295 }296 297 268 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand) 298 269 { … … 413 384 } 414 385 415 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)416 {417 BasicBlock* taken = branchNode->branchData()->taken.block;418 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;419 420 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;421 422 // The branch instruction will branch to the taken block.423 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.424 if (taken == nextBlock()) {425 cond = JITCompiler::invert(cond);426 callResultCondition = JITCompiler::Zero;427 BasicBlock* tmp = taken;428 taken = notTaken;429 notTaken = tmp;430 }431 432 JSValueOperand arg1(this, node->child1());433 JSValueOperand arg2(this, node->child2());434 JSValueRegs arg1Regs = arg1.jsValueRegs();435 JSValueRegs arg2Regs = arg2.jsValueRegs();436 GPRReg arg1TagGPR = arg1.tagGPR();437 GPRReg arg1PayloadGPR = arg1.payloadGPR();438 GPRReg arg2TagGPR = arg2.tagGPR();439 GPRReg arg2PayloadGPR = arg2.payloadGPR();440 441 JITCompiler::JumpList slowPath;442 443 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {444 GPRFlushedCallResult result(this);445 GPRReg resultGPR = result.gpr();446 447 arg1.use();448 arg2.use();449 450 flushRegisters();451 callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);452 m_jit.exceptionCheck();453 454 branchTest32(callResultCondition, resultGPR, taken);455 } else {456 GPRTemporary result(this);457 GPRReg resultGPR = result.gpr();458 459 arg1.use();460 arg2.use();461 462 if (!isKnownInteger(node->child1().node()))463 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));464 if (!isKnownInteger(node->child2().node()))465 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));466 467 branch32(cond, arg1PayloadGPR, arg2PayloadGPR, taken);468 469 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {470 jump(notTaken, ForceJump);471 472 slowPath.link(&m_jit);473 474 silentSpillAllRegisters(resultGPR);475 callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);476 m_jit.exceptionCheck();477 silentFillAllRegisters();478 479 branchTest32(callResultCondition, resultGPR, taken);480 }481 }482 483 jump(notTaken);484 485 m_indexInBlock = m_block->size() - 1;486 m_currentNode = branchNode;487 }488 489 template<typename JumpType>490 class CompareAndBoxBooleanSlowPathGenerator491 : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {492 public:493 CompareAndBoxBooleanSlowPathGenerator(494 JumpType from, SpeculativeJIT* jit,495 S_JITOperation_EJJ function, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload,496 GPRReg arg2Tag, GPRReg arg2Payload)497 : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(498 from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result)499 , m_arg1Tag(arg1Tag)500 , m_arg1Payload(arg1Payload)501 , m_arg2Tag(arg2Tag)502 , m_arg2Payload(arg2Payload)503 {504 }505 506 protected:507 virtual void generateInternal(SpeculativeJIT* jit)508 {509 this->setUp(jit);510 this->recordCall(511 jit->callOperation(512 this->m_function, this->m_result, JSValueRegs(m_arg1Tag, m_arg1Payload), JSValueRegs(m_arg2Tag, m_arg2Payload)));513 jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);514 this->tearDown(jit);515 }516 517 private:518 GPRReg m_arg1Tag;519 GPRReg m_arg1Payload;520 GPRReg m_arg2Tag;521 GPRReg m_arg2Payload;522 };523 524 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)525 {526 JSValueOperand arg1(this, node->child1());527 JSValueOperand arg2(this, node->child2());528 GPRReg arg1TagGPR = arg1.tagGPR();529 GPRReg arg1PayloadGPR = arg1.payloadGPR();530 GPRReg arg2TagGPR = arg2.tagGPR();531 GPRReg arg2PayloadGPR = arg2.payloadGPR();532 533 JITCompiler::JumpList slowPath;534 535 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {536 GPRFlushedCallResult result(this);537 GPRReg resultPayloadGPR = result.gpr();538 539 arg1.use();540 arg2.use();541 542 flushRegisters();543 callOperation(helperFunction, resultPayloadGPR, arg1.jsValueRegs(), arg2.jsValueRegs());544 m_jit.exceptionCheck();545 546 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);547 } else {548 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);549 GPRReg resultPayloadGPR = resultPayload.gpr();550 551 arg1.use();552 arg2.use();553 554 if (!isKnownInteger(node->child1().node()))555 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));556 if (!isKnownInteger(node->child2().node()))557 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));558 559 m_jit.compare32(cond, arg1PayloadGPR, arg2PayloadGPR, resultPayloadGPR);560 561 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {562 addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>>(563 slowPath, this, helperFunction, resultPayloadGPR, arg1TagGPR,564 arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR));565 }566 567 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);568 }569 }570 571 386 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert) 572 387 { … … 667 482 668 483 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 669 }670 671 void SpeculativeJIT::compileMiscStrictEq(Node* node)672 {673 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);674 JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);675 GPRTemporary result(this);676 677 if (node->child1().useKind() == MiscUse)678 speculateMisc(node->child1(), op1.jsValueRegs());679 if (node->child2().useKind() == MiscUse)680 speculateMisc(node->child2(), op2.jsValueRegs());681 682 m_jit.move(TrustedImm32(0), result.gpr());683 JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR());684 m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr());685 notEqual.link(&m_jit);686 booleanResult(result.gpr(), node);687 484 } 688 485 … … 3581 3378 3582 3379 case CheckNotEmpty: { 3583 JSValueOperand operand(this, node->child1()); 3584 GPRReg tagGPR = operand.tagGPR(); 3585 speculationCheck(TDZFailure, JSValueSource(), nullptr, m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::EmptyValueTag))); 3586 noResult(node); 3380 compileCheckNotEmpty(node); 3587 3381 break; 3588 3382 } … … 3692 3486 3693 3487 case PutByIdFlush: { 3694 SpeculateCellOperand base(this, node->child1()); 3695 JSValueOperand value(this, node->child2()); 3696 GPRTemporary scratch(this); 3697 3698 GPRReg baseGPR = base.gpr(); 3699 GPRReg valueTagGPR = value.tagGPR(); 3700 GPRReg valuePayloadGPR = value.payloadGPR(); 3701 GPRReg scratchGPR = scratch.gpr(); 3702 flushRegisters(); 3703 3704 cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill); 3705 3706 noResult(node); 3707 break; 3708 } 3709 3488 compilePutByIdFlush(node); 3489 break; 3490 } 3491 3710 3492 case PutById: { 3711 SpeculateCellOperand base(this, node->child1()); 3712 JSValueOperand value(this, node->child2()); 3713 GPRTemporary scratch(this); 3714 3715 GPRReg baseGPR = base.gpr(); 3716 GPRReg valueTagGPR = value.tagGPR(); 3717 GPRReg valuePayloadGPR = value.payloadGPR(); 3718 GPRReg scratchGPR = scratch.gpr(); 3719 3720 cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect); 3721 3722 noResult(node); 3493 compilePutById(node); 3723 3494 break; 3724 3495 } 3725 3496 3726 3497 case PutByIdDirect: { 3727 SpeculateCellOperand base(this, node->child1()); 3728 JSValueOperand value(this, node->child2()); 3729 GPRTemporary scratch(this); 3730 3731 GPRReg baseGPR = base.gpr(); 3732 GPRReg valueTagGPR = value.tagGPR(); 3733 GPRReg valuePayloadGPR = value.payloadGPR(); 3734 GPRReg scratchGPR = scratch.gpr(); 3735 3736 cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), Direct); 3737 3738 noResult(node); 3498 compilePutByIdDirect(node); 3739 3499 break; 3740 3500 } … … 3799 3559 3800 3560 case OverridesHasInstance: { 3801 3802 Node* hasInstanceValueNode = node->child2().node(); 3803 JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value()); 3804 3805 MacroAssembler::JumpList notDefaultHasInstanceValue; 3806 SpeculateCellOperand base(this, node->child1()); 3807 JSValueOperand hasInstanceValue(this, node->child2()); 3808 GPRTemporary result(this); 3809 3810 GPRReg baseGPR = base.gpr(); 3811 GPRReg resultGPR = result.gpr(); 3812 3813 // It would be great if constant folding handled automatically the case where we knew the hasInstance function 3814 // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase 3815 // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832 3816 if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) { 3817 JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs(); 3818 notDefaultHasInstanceValue.append(m_jit.branchIfNotCell(hasInstanceValueRegs)); 3819 notDefaultHasInstanceValue.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(node->cellOperand()))); 3820 } 3821 3822 // Check that constructor 'ImplementsDefaultHasInstance'. 3823 m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR); 3824 MacroAssembler::Jump done = m_jit.jump(); 3825 3826 if (!notDefaultHasInstanceValue.empty()) { 3827 notDefaultHasInstanceValue.link(&m_jit); 3828 moveTrueTo(resultGPR); 3829 } 3830 3831 done.link(&m_jit); 3832 booleanResult(resultGPR, node); 3561 compileOverridesHasInstance(node); 3833 3562 break; 3834 3563 } … … 3922 3651 3923 3652 case IsObject: { 3924 JSValueOperand value(this, node->child1()); 3925 GPRTemporary result(this, Reuse, value, TagWord); 3926 3927 JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(value.jsValueRegs()); 3928 3929 m_jit.compare8(JITCompiler::AboveOrEqual, 3930 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()), 3931 TrustedImm32(ObjectType), 3932 result.gpr()); 3933 JITCompiler::Jump done = m_jit.jump(); 3934 3935 isNotCell.link(&m_jit); 3936 m_jit.move(TrustedImm32(0), result.gpr()); 3937 3938 done.link(&m_jit); 3939 booleanResult(result.gpr(), node); 3653 compileIsObject(node); 3940 3654 break; 3941 3655 } … … 4077 3791 4078 3792 case LoadVarargs: { 4079 LoadVarargsData* data = node->loadVarargsData(); 4080 4081 GPRReg argumentsTagGPR; 4082 GPRReg argumentsPayloadGPR; 4083 JSValueRegs argumentsRegs; 4084 { 4085 JSValueOperand arguments(this, node->child1()); 4086 argumentsRegs = arguments.jsValueRegs(); 4087 flushRegisters(); 4088 } 4089 4090 callOperation(operationSizeOfVarargs, GPRInfo::returnValueGPR, argumentsRegs, data->offset); 4091 m_jit.exceptionCheck(); 4092 4093 lock(GPRInfo::returnValueGPR); 4094 { 4095 JSValueOperand arguments(this, node->child1()); 4096 argumentsTagGPR = arguments.tagGPR(); 4097 argumentsPayloadGPR = arguments.payloadGPR(); 4098 argumentsRegs = arguments.jsValueRegs(); 4099 flushRegisters(); 4100 } 4101 unlock(GPRInfo::returnValueGPR); 4102 4103 // FIXME: There is a chance that we will call an effectful length property twice. This is safe 4104 // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance 4105 // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right 4106 // past the sizing. 4107 // https://bugs.webkit.org/show_bug.cgi?id=141448 4108 4109 GPRReg argCountIncludingThisGPR = 4110 JITCompiler::selectScratchGPR(GPRInfo::returnValueGPR, argumentsTagGPR, argumentsPayloadGPR); 4111 4112 m_jit.add32(TrustedImm32(1), GPRInfo::returnValueGPR, argCountIncludingThisGPR); 4113 4114 speculationCheck( 4115 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 4116 MacroAssembler::Above, 4117 GPRInfo::returnValueGPR, 4118 argCountIncludingThisGPR)); 4119 4120 speculationCheck( 4121 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 4122 MacroAssembler::Above, 4123 argCountIncludingThisGPR, 4124 TrustedImm32(data->limit))); 4125 4126 m_jit.store32(argCountIncludingThisGPR, JITCompiler::payloadFor(data->machineCount)); 4127 4128 callOperation(operationLoadVarargs, data->machineStart.offset(), argumentsRegs, data->offset, GPRInfo::returnValueGPR, data->mandatoryMinimum); 4129 m_jit.exceptionCheck(); 4130 4131 noResult(node); 3793 compileLoadVarargs(node); 4132 3794 break; 4133 3795 } … … 4341 4003 } 4342 4004 case HasIndexedProperty: { 4343 SpeculateCellOperand base(this, node->child1()); 4344 SpeculateInt32Operand index(this, node->child2()); 4345 GPRTemporary resultPayload(this); 4346 GPRTemporary resultTag(this); 4347 4348 GPRReg baseGPR = base.gpr(); 4349 GPRReg indexGPR = index.gpr(); 4350 GPRReg resultPayloadGPR = resultPayload.gpr(); 4351 GPRReg resultTagGPR = resultTag.gpr(); 4352 4353 MacroAssembler::JumpList slowCases; 4354 ArrayMode mode = node->arrayMode(); 4355 switch (mode.type()) { 4356 case Array::Int32: 4357 case Array::Contiguous: { 4358 ASSERT(!!node->child3()); 4359 StorageOperand storage(this, node->child3()); 4360 GPRTemporary scratch(this); 4361 4362 GPRReg storageGPR = storage.gpr(); 4363 GPRReg scratchGPR = scratch.gpr(); 4364 4365 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()))); 4366 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR); 4367 slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag))); 4368 break; 4369 } 4370 case Array::Double: { 4371 ASSERT(!!node->child3()); 4372 StorageOperand storage(this, node->child3()); 4373 FPRTemporary scratch(this); 4374 FPRReg scratchFPR = scratch.fpr(); 4375 GPRReg storageGPR = storage.gpr(); 4376 4377 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()))); 4378 m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR); 4379 slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR)); 4380 break; 4381 } 4382 case Array::ArrayStorage: { 4383 ASSERT(!!node->child3()); 4384 StorageOperand storage(this, node->child3()); 4385 GPRTemporary scratch(this); 4386 4387 GPRReg storageGPR = storage.gpr(); 4388 GPRReg scratchGPR = scratch.gpr(); 4389 4390 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()))); 4391 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR); 4392 slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag))); 4393 break; 4394 } 4395 default: { 4396 slowCases.append(m_jit.jump()); 4397 break; 4398 } 4399 } 4400 4401 moveTrueTo(resultPayloadGPR); 4402 MacroAssembler::Jump done = m_jit.jump(); 4403 4404 addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, JSValueRegs(resultTagGPR, resultPayloadGPR), baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType()))); 4405 4406 done.link(&m_jit); 4407 booleanResult(resultPayloadGPR, node); 4005 compileHasIndexedProperty(node); 4408 4006 break; 4409 4007 } 4410 4008 case GetDirectPname: { 4411 Edge& baseEdge = m_jit.graph().varArgChild(node, 0); 4412 Edge& propertyEdge = m_jit.graph().varArgChild(node, 1); 4413 4414 SpeculateCellOperand base(this, baseEdge); 4415 SpeculateCellOperand property(this, propertyEdge); 4416 GPRReg baseGPR = base.gpr(); 4417 GPRReg propertyGPR = property.gpr(); 4418 4419 #if CPU(X86) 4420 GPRTemporary scratch(this); 4421 4422 GPRReg scratchGPR = scratch.gpr(); 4423 4424 // Not enough registers on X86 for this code, so always use the slow path. 4425 flushRegisters(); 4426 JSValueRegsFlushedCallResult result(this); 4427 JSValueRegs resultRegs = result.regs(); 4428 m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), scratchGPR); 4429 callOperation(operationGetByValCell, resultRegs, baseGPR, JSValueRegs(scratchGPR, propertyGPR)); 4430 m_jit.exceptionCheck(); 4431 #else 4432 GPRTemporary scratch(this); 4433 JSValueRegsTemporary result(this); 4434 4435 GPRReg scratchGPR = scratch.gpr(); 4436 JSValueRegs resultRegs = result.regs(); 4437 4438 Edge& indexEdge = m_jit.graph().varArgChild(node, 2); 4439 Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3); 4440 4441 SpeculateInt32Operand index(this, indexEdge); 4442 SpeculateCellOperand enumerator(this, enumeratorEdge); 4443 4444 GPRReg indexGPR = index.gpr(); 4445 GPRReg enumeratorGPR = enumerator.gpr(); 4446 4447 MacroAssembler::JumpList slowPath; 4448 4449 // Check the structure 4450 m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR); 4451 slowPath.append( 4452 m_jit.branch32( 4453 MacroAssembler::NotEqual, 4454 scratchGPR, 4455 MacroAssembler::Address( 4456 enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()))); 4457 4458 // Compute the offset 4459 // If index is less than the enumerator's cached inline storage, then it's an inline access 4460 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual, 4461 indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset())); 4462 4463 m_jit.move(indexGPR, scratchGPR); 4464 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR); 4465 m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR()); 4466 m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR()); 4467 4468 MacroAssembler::Jump done = m_jit.jump(); 4469 4470 // Otherwise it's out of line 4471 outOfLineAccess.link(&m_jit); 4472 m_jit.move(indexGPR, scratchGPR); 4473 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR); 4474 m_jit.neg32(scratchGPR); 4475 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR); 4476 // We use resultRegs.payloadGPR() as a temporary here. We have to make sure clobber it after getting the 4477 // value out of indexGPR and enumeratorGPR because resultRegs.payloadGPR() could reuse either of those registers. 4478 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultRegs.payloadGPR()); 4479 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 4480 m_jit.load32(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR()); 4481 m_jit.load32(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR()); 4482 4483 done.link(&m_jit); 4484 4485 addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, resultRegs, baseGPR, JSValue::JSCellType, propertyGPR)); 4486 #endif 4487 4488 jsValueResult(resultRegs, node); 4009 compileGetDirectPname(node); 4489 4010 break; 4490 4011 } … … 4651 4172 4652 4173 case ExtractCatchLocal: { 4653 GPRTemporary temp(this); 4654 GPRTemporary tag(this); 4655 GPRTemporary payload(this); 4656 4657 GPRReg tempGPR = temp.gpr(); 4658 GPRReg tagGPR = tag.gpr(); 4659 GPRReg payloadGPR = payload.gpr(); 4660 4661 JSValue* ptr = &reinterpret_cast<JSValue*>(m_jit.jitCode()->common.catchOSREntryBuffer->dataBuffer())[node->catchOSREntryIndex()]; 4662 m_jit.move(CCallHelpers::TrustedImmPtr(ptr), tempGPR); 4663 m_jit.load32(CCallHelpers::Address(tempGPR, TagOffset), tagGPR); 4664 m_jit.load32(CCallHelpers::Address(tempGPR, PayloadOffset), payloadGPR); 4665 jsValueResult(tagGPR, payloadGPR, node); 4174 compileExtractCatchLocal(node); 4666 4175 break; 4667 4176 } … … 4795 4304 } 4796 4305 4797 void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)4798 {4799 m_jit.move(sizeGPR, scratchGPR);4800 MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);4801 MacroAssembler::Label loop = m_jit.label();4802 m_jit.sub32(TrustedImm32(1), scratchGPR);4803 m_jit.store32(emptyValueRegs.tagGPR(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));4804 m_jit.store32(emptyValueRegs.payloadGPR(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));4805 m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);4806 done.link(&m_jit);4807 }4808 4809 void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)4810 {4811 GPRTemporary storage(this);4812 GPRTemporary scratch(this);4813 GPRTemporary scratch2(this);4814 4815 GPRReg storageGPR = storage.gpr();4816 GPRReg scratchGPR = scratch.gpr();4817 GPRReg scratch2GPR = scratch2.gpr();4818 4819 m_jit.move(TrustedImmPtr(nullptr), storageGPR);4820 4821 MacroAssembler::JumpList slowCases;4822 if (shouldConvertLargeSizeToArrayStorage)4823 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));4824 4825 // We can use result as a scratch for this.4826 emitAllocateButterfly(storageGPR, sizeGPR, scratchGPR, scratch2GPR, resultGPR, slowCases);4827 4828 JSValue hole;4829 if (hasDouble(indexingType))4830 hole = JSValue(JSValue::EncodeAsDouble, PNaN);4831 else4832 hole = JSValue();4833 JSValueRegs emptyValueRegs(scratchGPR, scratch2GPR);4834 m_jit.move(TrustedImm32(hole.tag()), emptyValueRegs.tagGPR());4835 m_jit.move(TrustedImm32(hole.payload()), emptyValueRegs.payloadGPR());4836 // We can use result as a scratch for this.4837 emitInitializeButterfly(storageGPR, sizeGPR, emptyValueRegs, resultGPR);4838 4839 RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));4840 4841 emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);4842 4843 addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(4844 slowCases, this, operationNewArrayWithSize, resultGPR,4845 structure,4846 shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,4847 sizeGPR, storageGPR));4848 }4849 4850 4306 #endif 4851 4307 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r230516 r230517 217 217 } 218 218 219 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)220 {221 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());222 RegisterSet usedRegisters = this->usedRegisters();223 if (spillMode == DontSpill) {224 // We've already flushed registers to the stack, we don't need to spill these.225 usedRegisters.set(baseGPR, false);226 usedRegisters.set(valueGPR, false);227 }228 229 JITPutByIdGenerator gen(230 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, JSValueRegs(baseGPR),231 JSValueRegs(valueGPR), scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);232 233 gen.generateFastPath(m_jit);234 235 JITCompiler::JumpList slowCases;236 if (slowPathTarget.isSet())237 slowCases.append(slowPathTarget);238 slowCases.append(gen.slowPathJump());239 240 auto slowPath = slowPathCall(241 slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueGPR, baseGPR,242 identifierUID(identifierNumber));243 244 m_jit.addPutById(gen, slowPath.get());245 addSlowPathGenerator(WTFMove(slowPath));246 }247 248 219 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand) 249 220 { … … 358 329 } 359 330 360 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)361 {362 BasicBlock* taken = branchNode->branchData()->taken.block;363 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;364 365 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;366 367 // The branch instruction will branch to the taken block.368 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.369 if (taken == nextBlock()) {370 cond = JITCompiler::invert(cond);371 callResultCondition = JITCompiler::Zero;372 BasicBlock* tmp = taken;373 taken = notTaken;374 notTaken = tmp;375 }376 377 JSValueOperand arg1(this, node->child1());378 JSValueOperand arg2(this, node->child2());379 GPRReg arg1GPR = arg1.gpr();380 GPRReg arg2GPR = arg2.gpr();381 382 JITCompiler::JumpList slowPath;383 384 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {385 GPRFlushedCallResult result(this);386 GPRReg resultGPR = result.gpr();387 388 arg1.use();389 arg2.use();390 391 flushRegisters();392 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);393 m_jit.exceptionCheck();394 395 branchTest32(callResultCondition, resultGPR, taken);396 } else {397 GPRTemporary result(this, Reuse, arg2);398 GPRReg resultGPR = result.gpr();399 400 arg1.use();401 arg2.use();402 403 if (!isKnownInteger(node->child1().node()))404 slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));405 if (!isKnownInteger(node->child2().node()))406 slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));407 408 branch32(cond, arg1GPR, arg2GPR, taken);409 410 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {411 jump(notTaken, ForceJump);412 413 slowPath.link(&m_jit);414 415 silentSpillAllRegisters(resultGPR);416 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);417 silentFillAllRegisters();418 m_jit.exceptionCheck();419 420 branchTest32(callResultCondition, resultGPR, taken);421 }422 }423 424 jump(notTaken);425 426 m_indexInBlock = m_block->size() - 1;427 m_currentNode = branchNode;428 }429 430 template<typename JumpType>431 class CompareAndBoxBooleanSlowPathGenerator432 : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {433 public:434 CompareAndBoxBooleanSlowPathGenerator(435 JumpType from, SpeculativeJIT* jit,436 S_JITOperation_EJJ function, GPRReg result, GPRReg arg1, GPRReg arg2)437 : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(438 from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result)439 , m_arg1(arg1)440 , m_arg2(arg2)441 {442 }443 444 protected:445 void generateInternal(SpeculativeJIT* jit) override446 {447 this->setUp(jit);448 this->recordCall(jit->callOperation(this->m_function, this->m_result, m_arg1, m_arg2));449 jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);450 jit->m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), this->m_result);451 this->tearDown(jit);452 }453 454 private:455 GPRReg m_arg1;456 GPRReg m_arg2;457 };458 459 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)460 {461 ASSERT(node->isBinaryUseKind(UntypedUse));462 JSValueOperand arg1(this, node->child1());463 JSValueOperand arg2(this, node->child2());464 GPRReg arg1GPR = arg1.gpr();465 GPRReg arg2GPR = arg2.gpr();466 467 JITCompiler::JumpList slowPath;468 469 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {470 GPRFlushedCallResult result(this);471 GPRReg resultGPR = result.gpr();472 473 arg1.use();474 arg2.use();475 476 flushRegisters();477 callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);478 m_jit.exceptionCheck();479 480 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);481 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);482 } else {483 GPRTemporary result(this, Reuse, arg2);484 GPRReg resultGPR = result.gpr();485 486 arg1.use();487 arg2.use();488 489 if (!isKnownInteger(node->child1().node()))490 slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));491 if (!isKnownInteger(node->child2().node()))492 slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));493 494 m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);495 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);496 497 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {498 addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>>(499 slowPath, this, helperFunction, resultGPR, arg1GPR, arg2GPR));500 }501 502 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);503 }504 }505 506 331 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert) 507 332 { … … 576 401 JSValueOperand arg1(this, node->child1()); 577 402 JSValueOperand arg2(this, node->child2()); 578 GPRReg arg1GPR = arg1.gpr();579 GPRReg arg2GPR = arg2.gpr();403 JSValueRegs arg1Regs = arg1.jsValueRegs(); 404 JSValueRegs arg2Regs = arg2.jsValueRegs(); 580 405 581 406 GPRTemporary result(this); … … 589 414 // cell, then they must be strictly equal. 590 415 // FIXME: this should flush registers instead of silent spill/fill. 591 JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1 GPR, arg2GPR);592 593 m_jit.move(JITCompiler::TrustedImm64( JSValue::encode(jsBoolean(!invert))), resultGPR);416 JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr()); 417 418 m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR); 594 419 595 420 JITCompiler::Jump done = m_jit.jump(); … … 598 423 599 424 silentSpillAllRegisters(resultGPR); 600 callOperation(operationCompareStrictEqCell, resultGPR, arg1 GPR, arg2GPR);425 callOperation(operationCompareStrictEqCell, resultGPR, arg1Regs, arg2Regs); 601 426 silentFillAllRegisters(); 602 427 m_jit.exceptionCheck(); 603 428 604 m_jit.and64(JITCompiler::TrustedImm32(1), resultGPR);605 m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);606 607 429 done.link(&m_jit); 608 } else { 609 m_jit.or64(arg1GPR, arg2GPR, resultGPR); 610 611 JITCompiler::JumpList slowPathCases; 612 613 JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister); 614 615 JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister); 616 slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister)); 617 leftOK.link(&m_jit); 618 JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister); 619 slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister)); 620 rightOK.link(&m_jit); 621 622 m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR); 623 m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR); 624 625 JITCompiler::Jump done = m_jit.jump(); 626 627 twoCellsCase.link(&m_jit); 628 slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR)); 629 630 m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR); 631 632 addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<MacroAssembler::JumpList>>( 633 slowPathCases, this, operationCompareStrictEq, resultGPR, arg1GPR, 634 arg2GPR)); 635 636 done.link(&m_jit); 637 } 638 639 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly); 640 } 641 642 void SpeculativeJIT::compileMiscStrictEq(Node* node) 643 { 644 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 645 JSValueOperand op2(this, node->child2(), ManualOperandSpeculation); 646 GPRTemporary result(this); 647 648 if (node->child1().useKind() == MiscUse) 649 speculateMisc(node->child1(), op1.jsValueRegs()); 650 if (node->child2().useKind() == MiscUse) 651 speculateMisc(node->child2(), op2.jsValueRegs()); 652 653 m_jit.compare64(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr()); 654 m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); 655 jsValueResult(result.gpr(), node, DataFormatJSBoolean); 430 unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly); 431 return; 432 } 433 434 m_jit.or64(arg1Regs.gpr(), arg2Regs.gpr(), resultGPR); 435 436 JITCompiler::JumpList slowPathCases; 437 438 JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister); 439 440 JITCompiler::Jump leftOK = m_jit.branchIfInt32(arg1Regs); 441 slowPathCases.append(m_jit.branchIfNumber(arg1Regs, InvalidGPRReg)); 442 leftOK.link(&m_jit); 443 JITCompiler::Jump rightOK = m_jit.branchIfInt32(arg2Regs); 444 slowPathCases.append(m_jit.branchIfNumber(arg2Regs, InvalidGPRReg)); 445 rightOK.link(&m_jit); 446 447 m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1Regs.gpr(), arg2Regs.gpr(), resultGPR); 448 449 JITCompiler::Jump done = m_jit.jump(); 450 451 twoCellsCase.link(&m_jit); 452 slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr())); 453 454 m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR); 455 456 addSlowPathGenerator(std::make_unique<CompareSlowPathGenerator<MacroAssembler::JumpList>>( 457 slowPathCases, this, operationCompareStrictEq, resultGPR, arg1Regs, arg2Regs)); 458 459 done.link(&m_jit); 460 461 unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly); 656 462 } 657 463 … … 3797 3603 3798 3604 case CheckNotEmpty: { 3799 JSValueOperand operand(this, node->child1()); 3800 GPRReg gpr = operand.gpr(); 3801 speculationCheck(TDZFailure, JSValueSource(), nullptr, m_jit.branchTest64(JITCompiler::Zero, gpr)); 3802 noResult(node); 3605 compileCheckNotEmpty(node); 3803 3606 break; 3804 3607 } … … 3922 3725 3923 3726 case PutByIdFlush: { 3924 SpeculateCellOperand base(this, node->child1()); 3925 JSValueOperand value(this, node->child2()); 3926 GPRTemporary scratch(this); 3927 3928 GPRReg baseGPR = base.gpr(); 3929 GPRReg valueGPR = value.gpr(); 3930 GPRReg scratchGPR = scratch.gpr(); 3931 flushRegisters(); 3932 3933 cachedPutById(node->origin.semantic, baseGPR, valueGPR, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill); 3934 3935 noResult(node); 3727 compilePutByIdFlush(node); 3936 3728 break; 3937 3729 } 3938 3730 3939 3731 case PutById: { 3940 SpeculateCellOperand base(this, node->child1()); 3941 JSValueOperand value(this, node->child2()); 3942 GPRTemporary scratch(this); 3943 3944 GPRReg baseGPR = base.gpr(); 3945 GPRReg valueGPR = value.gpr(); 3946 GPRReg scratchGPR = scratch.gpr(); 3947 3948 cachedPutById(node->origin.semantic, baseGPR, valueGPR, scratchGPR, node->identifierNumber(), NotDirect); 3949 3950 noResult(node); 3732 compilePutById(node); 3951 3733 break; 3952 3734 } … … 3976 3758 3977 3759 case PutByIdDirect: { 3978 SpeculateCellOperand base(this, node->child1()); 3979 JSValueOperand value(this, node->child2()); 3980 GPRTemporary scratch(this); 3981 3982 GPRReg baseGPR = base.gpr(); 3983 GPRReg valueGPR = value.gpr(); 3984 GPRReg scratchGPR = scratch.gpr(); 3985 3986 cachedPutById(node->origin.semantic, baseGPR, valueGPR, scratchGPR, node->identifierNumber(), Direct); 3987 3988 noResult(node); 3760 compilePutByIdDirect(node); 3989 3761 break; 3990 3762 } … … 4064 3836 4065 3837 case OverridesHasInstance: { 4066 4067 Node* hasInstanceValueNode = node->child2().node(); 4068 JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value()); 4069 4070 MacroAssembler::Jump notDefault; 4071 SpeculateCellOperand base(this, node->child1()); 4072 JSValueOperand hasInstanceValue(this, node->child2()); 4073 GPRTemporary result(this); 4074 4075 GPRReg resultGPR = result.gpr(); 4076 GPRReg baseGPR = base.gpr(); 4077 4078 // It would be great if constant folding handled automatically the case where we knew the hasInstance function 4079 // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase 4080 // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832 4081 if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) { 4082 GPRReg hasInstanceValueGPR = hasInstanceValue.gpr(); 4083 notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueGPR, TrustedImmPtr(node->cellOperand())); 4084 } 4085 4086 // Check that base 'ImplementsDefaultHasInstance'. 4087 m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR); 4088 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 4089 MacroAssembler::Jump done = m_jit.jump(); 4090 4091 if (notDefault.isSet()) { 4092 notDefault.link(&m_jit); 4093 moveTrueTo(resultGPR); 4094 } 4095 4096 done.link(&m_jit); 4097 jsValueResult(resultGPR, node, DataFormatJSBoolean); 3838 compileOverridesHasInstance(node); 4098 3839 break; 4099 3840 } … … 4109 3850 } 4110 3851 4111 case IsEmpty: { 3852 case IsEmpty: { 4112 3853 JSValueOperand value(this, node->child1()); 4113 3854 GPRTemporary result(this, Reuse, value); … … 4530 4271 4531 4272 case IsObject: { 4532 JSValueOperand value(this, node->child1()); 4533 GPRTemporary result(this, Reuse, value); 4534 4535 JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(value.jsValueRegs()); 4536 4537 m_jit.compare8(JITCompiler::AboveOrEqual, 4538 JITCompiler::Address(value.gpr(), JSCell::typeInfoTypeOffset()), 4539 TrustedImm32(ObjectType), 4540 result.gpr()); 4541 m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); 4542 JITCompiler::Jump done = m_jit.jump(); 4543 4544 isNotCell.link(&m_jit); 4545 m_jit.move(TrustedImm32(ValueFalse), result.gpr()); 4546 4547 done.link(&m_jit); 4548 jsValueResult(result.gpr(), node, DataFormatJSBoolean); 4273 compileIsObject(node); 4549 4274 break; 4550 4275 } … … 4599 4324 4600 4325 case LoadVarargs: { 4601 LoadVarargsData* data = node->loadVarargsData(); 4602 4603 GPRReg argumentsGPR; 4604 { 4605 JSValueOperand arguments(this, node->child1()); 4606 argumentsGPR = arguments.gpr(); 4607 flushRegisters(); 4608 } 4609 4610 callOperation(operationSizeOfVarargs, GPRInfo::returnValueGPR, argumentsGPR, data->offset); 4611 m_jit.exceptionCheck(); 4612 4613 lock(GPRInfo::returnValueGPR); 4614 { 4615 JSValueOperand arguments(this, node->child1()); 4616 argumentsGPR = arguments.gpr(); 4617 flushRegisters(); 4618 } 4619 unlock(GPRInfo::returnValueGPR); 4620 4621 // FIXME: There is a chance that we will call an effectful length property twice. This is safe 4622 // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance 4623 // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right 4624 // past the sizing. 4625 // https://bugs.webkit.org/show_bug.cgi?id=141448 4626 4627 GPRReg argCountIncludingThisGPR = 4628 JITCompiler::selectScratchGPR(GPRInfo::returnValueGPR, argumentsGPR); 4629 4630 m_jit.add32(TrustedImm32(1), GPRInfo::returnValueGPR, argCountIncludingThisGPR); 4631 4632 speculationCheck( 4633 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 4634 MacroAssembler::Above, 4635 GPRInfo::returnValueGPR, 4636 argCountIncludingThisGPR)); 4637 4638 speculationCheck( 4639 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 4640 MacroAssembler::Above, 4641 argCountIncludingThisGPR, 4642 TrustedImm32(data->limit))); 4643 4644 m_jit.store32(argCountIncludingThisGPR, JITCompiler::payloadFor(data->machineCount)); 4645 4646 callOperation(operationLoadVarargs, data->machineStart.offset(), argumentsGPR, data->offset, GPRInfo::returnValueGPR, data->mandatoryMinimum); 4647 m_jit.exceptionCheck(); 4648 4649 noResult(node); 4326 compileLoadVarargs(node); 4650 4327 break; 4651 4328 } … … 4879 4556 } 4880 4557 case HasIndexedProperty: { 4881 SpeculateCellOperand base(this, node->child1()); 4882 SpeculateStrictInt32Operand index(this, node->child2()); 4883 GPRTemporary result(this); 4884 4885 GPRReg baseGPR = base.gpr(); 4886 GPRReg indexGPR = index.gpr(); 4887 GPRReg resultGPR = result.gpr(); 4888 4889 MacroAssembler::JumpList slowCases; 4890 ArrayMode mode = node->arrayMode(); 4891 switch (mode.type()) { 4892 case Array::Int32: 4893 case Array::Contiguous: { 4894 ASSERT(!!node->child3()); 4895 StorageOperand storage(this, node->child3()); 4896 GPRTemporary scratch(this); 4897 4898 GPRReg storageGPR = storage.gpr(); 4899 GPRReg scratchGPR = scratch.gpr(); 4900 4901 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 4902 if (mode.isInBounds()) 4903 speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds); 4904 else 4905 slowCases.append(outOfBounds); 4906 4907 m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchGPR); 4908 slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR)); 4909 moveTrueTo(resultGPR); 4910 break; 4911 } 4912 case Array::Double: { 4913 ASSERT(!!node->child3()); 4914 StorageOperand storage(this, node->child3()); 4915 FPRTemporary scratch(this); 4916 FPRReg scratchFPR = scratch.fpr(); 4917 GPRReg storageGPR = storage.gpr(); 4918 4919 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 4920 if (mode.isInBounds()) 4921 speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds); 4922 else 4923 slowCases.append(outOfBounds); 4924 4925 m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR); 4926 slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR)); 4927 moveTrueTo(resultGPR); 4928 break; 4929 } 4930 case Array::ArrayStorage: { 4931 ASSERT(!!node->child3()); 4932 StorageOperand storage(this, node->child3()); 4933 GPRTemporary scratch(this); 4934 4935 GPRReg storageGPR = storage.gpr(); 4936 GPRReg scratchGPR = scratch.gpr(); 4937 4938 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 4939 if (mode.isInBounds()) 4940 speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds); 4941 else 4942 slowCases.append(outOfBounds); 4943 4944 m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), scratchGPR); 4945 slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR)); 4946 moveTrueTo(resultGPR); 4947 break; 4948 } 4949 default: { 4950 slowCases.append(m_jit.jump()); 4951 break; 4952 } 4953 } 4954 4955 addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, HasPropertyPtrTag, resultGPR, baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType()))); 4956 4957 jsValueResult(resultGPR, node, DataFormatJSBoolean); 4558 compileHasIndexedProperty(node); 4958 4559 break; 4959 4560 } 4960 4561 case GetDirectPname: { 4961 Edge& baseEdge = m_jit.graph().varArgChild(node, 0); 4962 Edge& propertyEdge = m_jit.graph().varArgChild(node, 1); 4963 Edge& indexEdge = m_jit.graph().varArgChild(node, 2); 4964 Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3); 4965 4966 SpeculateCellOperand base(this, baseEdge); 4967 SpeculateCellOperand property(this, propertyEdge); 4968 SpeculateStrictInt32Operand index(this, indexEdge); 4969 SpeculateCellOperand enumerator(this, enumeratorEdge); 4970 GPRTemporary result(this); 4971 GPRTemporary scratch1(this); 4972 GPRTemporary scratch2(this); 4973 4974 GPRReg baseGPR = base.gpr(); 4975 GPRReg propertyGPR = property.gpr(); 4976 GPRReg indexGPR = index.gpr(); 4977 GPRReg enumeratorGPR = enumerator.gpr(); 4978 GPRReg resultGPR = result.gpr(); 4979 GPRReg scratch1GPR = scratch1.gpr(); 4980 GPRReg scratch2GPR = scratch2.gpr(); 4981 4982 MacroAssembler::JumpList slowPath; 4983 4984 // Check the structure 4985 m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratch1GPR); 4986 slowPath.append( 4987 m_jit.branch32( 4988 MacroAssembler::NotEqual, 4989 scratch1GPR, 4990 MacroAssembler::Address( 4991 enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()))); 4992 4993 // Compute the offset 4994 // If index is less than the enumerator's cached inline storage, then it's an inline access 4995 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual, 4996 indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset())); 4997 4998 m_jit.load64(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultGPR); 4999 5000 MacroAssembler::Jump done = m_jit.jump(); 5001 5002 // Otherwise it's out of line 5003 outOfLineAccess.link(&m_jit); 5004 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratch2GPR); 5005 m_jit.move(indexGPR, scratch1GPR); 5006 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratch1GPR); 5007 m_jit.neg32(scratch1GPR); 5008 m_jit.signExtend32ToPtr(scratch1GPR, scratch1GPR); 5009 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 5010 m_jit.load64(MacroAssembler::BaseIndex(scratch2GPR, scratch1GPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultGPR); 5011 5012 done.link(&m_jit); 5013 5014 addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByVal, GetPropertyPtrTag, resultGPR, baseGPR, propertyGPR)); 5015 5016 jsValueResult(resultGPR, node); 4562 compileGetDirectPname(node); 5017 4563 break; 5018 4564 } … … 5135 4681 5136 4682 case ExtractCatchLocal: { 5137 JSValue* ptr = &reinterpret_cast<JSValue*>(m_jit.jitCode()->common.catchOSREntryBuffer->dataBuffer())[node->catchOSREntryIndex()]; 5138 GPRTemporary temp(this); 5139 GPRReg tempGPR = temp.gpr(); 5140 m_jit.move(CCallHelpers::TrustedImmPtr(ptr), tempGPR); 5141 m_jit.load64(CCallHelpers::Address(tempGPR), tempGPR); 5142 jsValueResult(tempGPR, node); 4683 compileExtractCatchLocal(node); 5143 4684 break; 5144 4685 } … … 5368 4909 } 5369 4910 5370 void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)5371 {5372 m_jit.zeroExtend32ToPtr(sizeGPR, scratchGPR);5373 MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);5374 MacroAssembler::Label loop = m_jit.label();5375 m_jit.sub32(TrustedImm32(1), scratchGPR);5376 m_jit.store64(emptyValueRegs.gpr(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight));5377 m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);5378 done.link(&m_jit);5379 }5380 5381 4911 void SpeculativeJIT::compileBigIntEquality(Node* node) 5382 4912 { … … 5416 4946 } 5417 4947 5418 void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)5419 {5420 GPRTemporary storage(this);5421 GPRTemporary scratch(this);5422 GPRTemporary scratch2(this);5423 5424 GPRReg storageGPR = storage.gpr();5425 GPRReg scratchGPR = scratch.gpr();5426 GPRReg scratch2GPR = scratch2.gpr();5427 5428 m_jit.move(TrustedImmPtr(nullptr), storageGPR);5429 5430 MacroAssembler::JumpList slowCases;5431 if (shouldConvertLargeSizeToArrayStorage)5432 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));5433 5434 // We can use resultGPR as a scratch right now.5435 emitAllocateButterfly(storageGPR, sizeGPR, resultGPR, scratchGPR, scratch2GPR, slowCases);5436 5437 if (hasDouble(indexingType))5438 m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);5439 else5440 m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);5441 emitInitializeButterfly(storageGPR, sizeGPR, JSValueRegs(scratchGPR), scratch2GPR);5442 5443 RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));5444 5445 emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);5446 5447 m_jit.mutatorFence(*m_jit.vm());5448 5449 addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(5450 slowCases, this, operationNewArrayWithSize, resultGPR,5451 structure,5452 shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,5453 sizeGPR, storageGPR));5454 }5455 5456 4948 #endif 5457 4949 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r230516 r230517 10024 10024 10025 10025 m_out.appendTo(slowCase, continuation); 10026 ValueFromBlock slowResult = m_out.anchor(m_out.equal( 10027 m_out.constInt64(JSValue::encode(jsBoolean(true))), 10028 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10026 ValueFromBlock slowResult = m_out.anchor( 10027 m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10029 10028 m_out.jump(continuation); 10030 10029 … … 10061 10060 10062 10061 m_out.appendTo(slowCase, continuation); 10063 ValueFromBlock slowResult = m_out.anchor(m_out.equal( 10064 m_out.constInt64(JSValue::encode(jsBoolean(true))), 10065 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10062 ValueFromBlock slowResult = m_out.anchor( 10063 m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10066 10064 m_out.jump(continuation); 10067 10065 … … 10097 10095 10098 10096 m_out.appendTo(slowCase, continuation); 10099 ValueFromBlock slowResult = m_out.anchor(m_out.equal( 10100 m_out.constInt64(JSValue::encode(jsBoolean(true))), 10101 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10097 ValueFromBlock slowResult = m_out.anchor( 10098 m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10102 10099 m_out.jump(continuation); 10103 10100 … … 10111 10108 LValue index = lowInt32(m_node->child2()); 10112 10109 LValue internalMethodType = m_out.constInt32(static_cast<int32_t>(m_node->internalMethodType())); 10113 setBoolean(m_out.equal( 10114 m_out.constInt64(JSValue::encode(jsBoolean(true))), 10115 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10110 setBoolean(m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType))); 10116 10111 break; 10117 10112 } -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r230516 r230517 165 165 load64(address, regs.gpr()); 166 166 #else 167 load32(bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + PayloadOffset), regs.payloadGPR());168 load 32(bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + TagOffset), regs.tagGPR());167 move(TrustedImmPtr(address), regs.payloadGPR()); 168 loadValue(Address(regs.payloadGPR()), regs); 169 169 #endif 170 170 } … … 1012 1012 } 1013 1013 1014 static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg, GPRReg preserve5 = InvalidGPRReg) 1015 { 1016 if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0 && preserve5 != GPRInfo::regT0) 1017 return GPRInfo::regT0; 1018 1019 if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1 && preserve5 != GPRInfo::regT1) 1020 return GPRInfo::regT1; 1021 1022 if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2 && preserve5 != GPRInfo::regT2) 1023 return GPRInfo::regT2; 1024 1025 if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3 && preserve5 != GPRInfo::regT3) 1026 return GPRInfo::regT3; 1027 1028 if (preserve1 != GPRInfo::regT4 && preserve2 != GPRInfo::regT4 && preserve3 != GPRInfo::regT4 && preserve4 != GPRInfo::regT4 && preserve5 != GPRInfo::regT4) 1029 return GPRInfo::regT4; 1030 1031 return GPRInfo::regT5; 1014 static GPRReg selectScratchGPR(RegisterSet preserved) 1015 { 1016 GPRReg registers[] = { 1017 GPRInfo::regT0, 1018 GPRInfo::regT1, 1019 GPRInfo::regT2, 1020 GPRInfo::regT3, 1021 GPRInfo::regT4, 1022 GPRInfo::regT5, 1023 }; 1024 1025 for (GPRReg reg : registers) { 1026 if (!preserved.contains(reg)) 1027 return reg; 1028 } 1029 RELEASE_ASSERT_NOT_REACHED(); 1030 return InvalidGPRReg; 1031 } 1032 1033 template<typename... Regs> 1034 static GPRReg selectScratchGPR(Regs... args) 1035 { 1036 RegisterSet set; 1037 constructRegisterSet(set, args...); 1038 return selectScratchGPR(set); 1039 } 1040 1041 static void constructRegisterSet(RegisterSet&) 1042 { 1043 } 1044 1045 template<typename... Regs> 1046 static void constructRegisterSet(RegisterSet& set, JSValueRegs regs, Regs... args) 1047 { 1048 if (regs.tagGPR() != InvalidGPRReg) 1049 set.set(regs.tagGPR()); 1050 if (regs.payloadGPR() != InvalidGPRReg) 1051 set.set(regs.payloadGPR()); 1052 constructRegisterSet(set, args...); 1053 } 1054 1055 template<typename... Regs> 1056 static void constructRegisterSet(RegisterSet& set, GPRReg reg, Regs... args) 1057 { 1058 if (reg != InvalidGPRReg) 1059 set.set(reg); 1060 constructRegisterSet(set, args...); 1032 1061 } 1033 1062 -
trunk/Source/JavaScriptCore/jit/RegisterSet.h
r229391 r230517 208 208 private: 209 209 void setAny(Reg reg) { set(reg); } 210 void setAny(JSValueRegs regs) { set(regs); } 210 211 void setAny(const RegisterSet& set) { merge(set); } 211 212 void setMany() { }
Note: See TracChangeset
for help on using the changeset viewer.