Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (284699 => 284700)
--- trunk/Source/_javascript_Core/ChangeLog 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-10-22 18:31:50 UTC (rev 284700)
@@ -1,3 +1,33 @@
+2021-10-22 Mikhail R. Gadelha <[email protected]>
+
+ [JSC][32bit] Re-enable compileEnumeratorGetByVal fast path
+ https://bugs.webkit.org/show_bug.cgi?id=232052
+
+ Reviewed by Yusuke Suzuki.
+
+ In https://bugs.webkit.org/show_bug.cgi?id=229543, the compileEnumeratorGetByVal
+ fast path had to be disabled in 32 bits due to not having enough registers.
+ There are enough registers available now, so we can re-enable the fast path and
+ removed the speculation that the baseEdge of both enumeratorGetByVal and
+ getByVal is a Cell in 32 bits.
+
+ I've also updated the 32 bits version of compileGetByVal to be closer to the 64
+ bits version: using DFG_CRASH instead of RELEASE_ASSERT_NOT_REACHED, using nullptr
+ instead of 0, and removed some whitespaces.
+
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compileGetByVal):
+ (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): Deleted.
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): Deleted.
+
2021-10-22 Saam Barati <[email protected]>
canDoFastSpread should also check that the Structure is from the global object we're watching
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (284699 => 284700)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2021-10-22 18:31:50 UTC (rev 284700)
@@ -1124,9 +1124,6 @@
break;
}
}
-#if USE(JSVALUE32_64)
- fixEdge<CellUse>(m_graph.varArgChild(node, 0)); // Speculating cell due to register pressure on 32-bit.
-#endif
break;
case Array::ForceExit:
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (284699 => 284700)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-10-22 18:31:50 UTC (rev 284700)
@@ -749,35 +749,6 @@
return JSValue::encode(jsNumber(truncatedValueOfArgument));
}
-JSC_DEFINE_JIT_OPERATION(operationGetByValCell, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, EncodedJSValue encodedProperty))
-{
- VM& vm = globalObject->vm();
- CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
- JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- JSValue property = JSValue::decode(encodedProperty);
-
- if (std::optional<uint32_t> index = property.tryGetAsUint32Index())
- RELEASE_AND_RETURN(scope, getByValWithIndex(globalObject, base, *index));
-
- if (property.isString()) {
- Structure& structure = *base->structure(vm);
- if (JSCell::canUseFastGetOwnProperty(structure)) {
- RefPtr<AtomStringImpl> existingAtomString = asString(property)->toExistingAtomString(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (existingAtomString) {
- if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomString.get()))
- return JSValue::encode(result);
- }
- }
- }
-
- auto propertyName = property.toPropertyKey(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- RELEASE_AND_RETURN(scope, JSValue::encode(JSValue(base).get(globalObject, propertyName)));
-}
-
ALWAYS_INLINE EncodedJSValue getByValCellInt(JSGlobalObject* globalObject, VM& vm, JSCell* base, int32_t index)
{
if (index < 0) {
@@ -2507,7 +2478,7 @@
return result;
}
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))
+JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, uint32_t index, JSPropertyNameEnumerator* enumerator))
{
VM& vm = globalObject->vm();
CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
@@ -2518,7 +2489,8 @@
PropertyName propertyName = string->toIdentifier(globalObject);
// This should only really return for TerminationException since we know string is backed by a UUID.
RETURN_IF_EXCEPTION(scope, { });
- JSObject* object = base->toObject(globalObject);
+ JSValue base = JSValue::decode(baseValue);
+ JSObject* object = base.toObject(globalObject);
RETURN_IF_EXCEPTION(scope, { });
RELEASE_AND_RETURN(scope, JSValue::encode(object->get(globalObject, propertyName)));
@@ -2539,19 +2511,6 @@
RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, propertyName))));
}
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
-{
- VM& vm = globalObject->vm();
- CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
- JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- JSValue property = JSValue::decode(propertyNameValue);
- JSPropertyNameEnumerator::Flag mode = static_cast<JSPropertyNameEnumerator::Flag>(modeNumber);
- JSValue base = JSValue::decode(baseValue);
- RELEASE_AND_RETURN(scope, JSValue::encode(CommonSlowPaths::opEnumeratorGetByVal(globalObject, base, property, index, mode, enumerator)));
-}
-
JSC_DEFINE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber))
{
VM& vm = globalObject->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (284699 => 284700)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2021-10-22 18:31:50 UTC (rev 284700)
@@ -90,7 +90,6 @@
JSC_DECLARE_JIT_OPERATION(operationArithFloor, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationArithCeil, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationArithTrunc, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
-JSC_DECLARE_JIT_OPERATION(operationGetByValCell, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue encodedProperty));
JSC_DECLARE_JIT_OPERATION(operationGetByValObjectInt, EncodedJSValue, (JSGlobalObject*, JSObject*, int32_t));
JSC_DECLARE_JIT_OPERATION(operationGetByValStringInt, EncodedJSValue, (JSGlobalObject*, JSString*, int32_t));
JSC_DECLARE_JIT_OPERATION(operationGetByValObjectString, EncodedJSValue, (JSGlobalObject*, JSCell*, JSCell* string));
@@ -111,8 +110,7 @@
JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
+JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, JSPropertyNameEnumerator*));
JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationNewArray, char*, (JSGlobalObject*, Structure*, void*, size_t));
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (284699 => 284700)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-10-22 18:31:50 UTC (rev 284700)
@@ -15854,6 +15854,118 @@
#endif
}
+void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
+{
+ Edge baseEdge = m_graph.varArgChild(node, 0);
+ auto generate = [&] (JSValueRegs baseRegs) {
+ MacroAssembler::JumpList doneCases;
+ JSValueRegsTemporary result;
+ JSValueRegs resultRegs;
+ GPRReg indexGPR;
+ GPRReg enumeratorGPR;
+ MacroAssembler::Jump badStructureSlowPath;
+
+ compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
+ Edge storageEdge = m_graph.varArgChild(node, 2);
+ StorageOperand storage;
+ if (storageEdge)
+ storage.emplace(this, storageEdge);
+ SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
+ SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
+ SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
+
+ GPRReg modeGPR = mode.gpr();
+ indexGPR = index.gpr();
+ enumeratorGPR = enumerator.gpr();
+
+ bool haveStorage = !!storageEdge;
+ GPRTemporary storageTemporary;
+ GPRReg storageGPR;
+ if (!haveStorage) {
+ storageTemporary = GPRTemporary(this, Reuse, enumerator);
+ storageGPR = storageTemporary.gpr();
+ } else
+ storageGPR = storage.gpr();
+
+ result = JSValueRegsTemporary(this);
+ resultRegs = result.regs();
+ GPRReg scratchGPR = resultRegs.payloadGPR();
+
+ MacroAssembler::JumpList notFastNamedCases;
+
+ // FIXME: We shouldn't generate this code if we know base is not an object.
+ notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
+ {
+ if (!m_state.forNode(baseEdge).isType(SpecCell))
+ notFastNamedCases.append(m_jit.branchIfNotCell(baseRegs));
+
+ // Check the structure
+ // FIXME: If we know there's only one structure for base we can just embed it here.
+ m_jit.load32(MacroAssembler::Address(baseRegs.payloadGPR(), JSCell::structureIDOffset()), scratchGPR);
+
+ auto badStructure = m_jit.branch32(
+ MacroAssembler::NotEqual,
+ scratchGPR,
+ MacroAssembler::Address(
+ enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
+
+ // FIXME: Maybe we should have a better way to represent Indexed+Named?
+ if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
+ badStructureSlowPath = badStructure;
+ else
+ notFastNamedCases.append(badStructure);
+
+ // Compute the offset
+ // If index is less than the enumerator's cached inline storage, then it's an inline access
+ MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
+ indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+
+ m_jit.loadValue(MacroAssembler::BaseIndex(baseRegs.payloadGPR(), indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
+
+ doneCases.append(m_jit.jump());
+
+ // Otherwise it's out of line
+ outOfLineAccess.link(&m_jit);
+ m_jit.move(indexGPR, scratchGPR);
+ m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
+ m_jit.neg32(scratchGPR);
+ m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
+ if (!haveStorage)
+ m_jit.loadPtr(MacroAssembler::Address(baseRegs.payloadGPR(), JSObject::butterflyOffset()), storageGPR);
+ constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
+ m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
+ doneCases.append(m_jit.jump());
+ }
+
+ notFastNamedCases.link(&m_jit);
+ return std::make_pair(resultRegs, DataFormatJS);
+ }));
+
+ // We rely on compileGetByVal to call jsValueResult for us.
+ // FIXME: This is kinda hacky...
+ ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
+
+ if (badStructureSlowPath.isSet()) {
+ if (baseRegs.tagGPR() == InvalidGPRReg)
+ addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), CCallHelpers::CellValue(baseRegs.payloadGPR()), indexGPR, enumeratorGPR));
+ else
+ addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, indexGPR, enumeratorGPR));
+ }
+
+ doneCases.link(&m_jit);
+ };
+
+ if (isCell(baseEdge.useKind())) {
+ // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
+ SpeculateCellOperand base(this, baseEdge, ManualOperandSpeculation);
+ speculate(node, baseEdge);
+ generate(JSValueRegs::payloadOnly(base.gpr()));
+ } else {
+ JSValueOperand base(this, baseEdge);
+ generate(base.regs());
+ }
+}
+
} } // namespace JSC::DFG
#endif
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (284699 => 284700)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2021-10-22 18:31:50 UTC (rev 284700)
@@ -1818,12 +1818,14 @@
void SpeculativeJIT::compileGetByVal(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
{
switch (node->arrayMode().type()) {
+ case Array::AnyTypedArray:
+ case Array::ForceExit:
+ case Array::SelectUsingArguments:
case Array::SelectUsingPredictions:
- case Array::ForceExit:
- RELEASE_ASSERT_NOT_REACHED();
-#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
- terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
-#endif
+ case Array::Unprofiled:
+ case Array::BigInt64Array:
+ case Array::BigUint64Array:
+ DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
break;
case Array::Undecided: {
SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
@@ -1846,18 +1848,18 @@
if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
compileGetByValForObjectWithString(node, prefix);
- break;
+ return;
}
if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
compileGetByValForObjectWithSymbol(node, prefix);
- break;
+ return;
}
}
- SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
+ JSValueOperand base(this, m_graph.varArgChild(node, 0));
JSValueOperand property(this, m_graph.varArgChild(node, 1));
- GPRReg baseGPR = base.gpr();
+ JSValueRegs baseGPR = base.jsValueRegs();
JSValueRegs propertyRegs = property.jsValueRegs();
JSValueRegs resultRegs;
@@ -1864,56 +1866,70 @@
std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
flushRegisters();
- callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
+ callOperation(operationGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
m_jit.exceptionCheck();
jsValueResult(resultRegs, node);
- break;
+ return;
}
- speculate(node, m_graph.varArgChild(node, 0));
+ JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
+ JSValueRegs propertyRegs = property.jsValueRegs();
speculate(node, m_graph.varArgChild(node, 1));
- JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
- JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
+ auto generate = [&] (JSValueRegs baseRegs) {
+ JSValueRegs resultRegs;
+ std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
- JSValueRegs baseRegs = base.jsValueRegs();
- JSValueRegs propertyRegs = property.jsValueRegs();
+ CodeOrigin codeOrigin = node->origin.semantic;
+ CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
+ RegisterSet usedRegisters = this->usedRegisters();
- JSValueRegs resultRegs;
- std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
+ JITCompiler::JumpList slowCases;
+ if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
+ slowCases.append(m_jit.branchIfNotCell(baseRegs));
- CodeOrigin codeOrigin = node->origin.semantic;
- CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
- RegisterSet usedRegisters = this->usedRegisters();
+ JITGetByValGenerator gen(
+ m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
+ baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
- JITCompiler::JumpList slowCases;
- if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
- slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR()));
+ if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
+ gen.stubInfo()->propertyIsString = true;
+ else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
+ gen.stubInfo()->propertyIsInt32 = true;
+ else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
+ gen.stubInfo()->propertyIsSymbol = true;
- JITGetByValGenerator gen(
- m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
- baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
+ gen.generateFastPath(m_jit);
- if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
- gen.stubInfo()->propertyIsString = true;
- else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
- gen.stubInfo()->propertyIsInt32 = true;
- else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
- gen.stubInfo()->propertyIsSymbol = true;
+ slowCases.append(gen.slowPathJump());
- gen.generateFastPath(m_jit);
+ std::unique_ptr<SlowPathGenerator> slowPath;
+ if (baseRegs.tagGPR() == InvalidGPRReg) {
+ slowPath = slowPathCall(
+ slowCases, this, operationGetByValOptimize,
+ resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, CCallHelpers::CellValue(baseRegs.payloadGPR()), propertyRegs);
+ } else {
+ slowPath = slowPathCall(
+ slowCases, this, operationGetByValOptimize,
+ resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
+ }
- slowCases.append(gen.slowPathJump());
+ m_jit.addGetByVal(gen, slowPath.get());
+ addSlowPathGenerator(WTFMove(slowPath));
- std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
- slowCases, this, operationGetByValOptimize,
- resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
+ jsValueResult(resultRegs, node);
+ };
- m_jit.addGetByVal(gen, slowPath.get());
- addSlowPathGenerator(WTFMove(slowPath));
-
- jsValueResult(resultRegs, node);
+ if (isCell(m_graph.varArgChild(node, 0).useKind())) {
+ SpeculateCellOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
+ speculate(node, m_graph.varArgChild(node, 0));
+ generate(JSValueRegs::payloadOnly(base.gpr()));
+ } else {
+ JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
+ speculate(node, m_graph.varArgChild(node, 0));
+ generate(base.jsValueRegs());
+ }
break;
}
case Array::Int32:
@@ -1932,7 +1948,7 @@
DataFormat format;
std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatInt32 : DataFormatJS);
- speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+ speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
if (format == DataFormatInt32) {
ASSERT(!node->arrayMode().isInBoundsSaneChain());
@@ -1994,8 +2010,8 @@
slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
m_jit.loadValue(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultRegs);
+
slowCases.append(m_jit.branchIfEmpty(resultRegs.tagGPR()));
-
addSlowPathGenerator(
slowPathCall(
slowCases, this, operationGetByValObjectInt,
@@ -2016,22 +2032,23 @@
return;
FPRTemporary result(this);
+ FPRReg resultReg = result.fpr();
JSValueRegs resultRegs;
DataFormat format;
std::tie(resultRegs, format) = prefix(DataFormatDouble);
- speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+ speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
- m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
+ m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
if (!node->arrayMode().isInBoundsSaneChain())
- speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
+ speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg));
if (format == DataFormatJS) {
- boxDouble(result.fpr(), resultRegs);
+ boxDouble(resultReg, resultRegs);
jsValueResult(resultRegs, node);
} else {
ASSERT(format == DataFormatDouble && !resultRegs);
- doubleResult(result.fpr(), node);
+ doubleResult(resultReg, node);
}
break;
}
@@ -2083,7 +2100,7 @@
JSValueRegs resultRegs;
std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
- speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
+ speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultRegs.tagGPR()));
@@ -2096,9 +2113,10 @@
SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
StorageOperand storage(this, m_graph.varArgChild(node, 2));
+
+ GPRReg baseReg = base.gpr();
GPRReg propertyReg = property.gpr();
GPRReg storageReg = storage.gpr();
- GPRReg baseReg = base.gpr();
if (!m_compileOkay)
return;
@@ -2120,8 +2138,7 @@
addSlowPathGenerator(
slowPathCall(
slowCases, this, operationGetByValObjectInt,
- resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)),
- baseReg, propertyReg));
+ resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
jsValueResult(resultRegs, node);
break;
@@ -2135,8 +2152,15 @@
case Array::ScopedArguments:
compileGetByValOnScopedArguments(node, prefix);
break;
- default: {
- ASSERT(node->arrayMode().isSomeTypedArrayView());
+ case Array::Int8Array:
+ case Array::Int16Array:
+ case Array::Int32Array:
+ case Array::Uint8Array:
+ case Array::Uint8ClampedArray:
+ case Array::Uint16Array:
+ case Array::Uint32Array:
+ case Array::Float32Array:
+ case Array::Float64Array: {
TypedArrayType type = node->arrayMode().typedArrayType();
if (isInt(type))
compileGetByValOnIntTypedArray(node, type, prefix);
@@ -4498,43 +4522,6 @@
doubleResult(result.fpr(), node);
}
-// FIXME: we are always taking the slow path here, we should be able to do the equivalent to the 64bit version if we add more available (callee-save registers) to ARMv7 and/or if we reduce the number of registers compileEnumeratorGetByVal uses. See bug #230189.
-void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
-{
- Edge baseEdge = m_graph.varArgChild(node, 0);
- auto generate = [&] (JSValueRegs baseRegs) {
- JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
- SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
- SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
- SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
- JSValueRegs propertyRegs = property.jsValueRegs();
- GPRReg indexGPR = index.gpr();
- GPRReg modeGPR = mode.gpr();
- GPRReg enumeratorGPR = enumerator.gpr();
-
- flushRegisters();
-
- JSValueRegsFlushedCallResult result(this);
- JSValueRegs resultRegs = result.regs();
-
- if (baseRegs.tagGPR() == InvalidGPRReg)
- callOperation(operationEnumeratorGetByValGeneric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), CCallHelpers::CellValue(baseRegs.payloadGPR()), propertyRegs, indexGPR, modeGPR, enumeratorGPR);
- else
- callOperation(operationEnumeratorGetByValGeneric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyRegs, indexGPR, modeGPR, enumeratorGPR);
- m_jit.exceptionCheck();
- jsValueResult(resultRegs, node);
- };
-
- if (isCell(baseEdge.useKind())) {
- // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
- speculate(node, baseEdge);
- SpeculateCellOperand base(this, baseEdge, ManualOperandSpeculation);
- generate(JSValueRegs::payloadOnly(base.gpr()));
- } else {
- JSValueOperand base(this, baseEdge);
- generate(base.regs());
- }
-}
#endif
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (284699 => 284700)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2021-10-22 18:31:50 UTC (rev 284700)
@@ -6466,114 +6466,6 @@
}
}
-void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
-{
- Edge baseEdge = m_graph.varArgChild(node, 0);
- auto generate = [&] (GPRReg baseCellGPR) {
- MacroAssembler::JumpList doneCases;
- JSValueRegsTemporary result;
- JSValueRegs resultRegs;
- GPRReg indexGPR;
- GPRReg enumeratorGPR;
- MacroAssembler::Jump badStructureSlowPath;
-
- compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
- Edge storageEdge = m_graph.varArgChild(node, 2);
- StorageOperand storage;
- if (storageEdge)
- storage.emplace(this, storageEdge);
- SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
- SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
- SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
-
- GPRReg modeGPR = mode.gpr();
- indexGPR = index.gpr();
- enumeratorGPR = enumerator.gpr();
-
- result = JSValueRegsTemporary(this);
- resultRegs = result.regs();
- GPRReg scratchGPR = resultRegs.payloadGPR();
-
- bool haveStorage = !!storageEdge;
- GPRTemporary storageTemporary;
- GPRReg storageGPR;
- if (!haveStorage) {
- storageTemporary = GPRTemporary(this, Reuse, enumerator);
- storageGPR = storageTemporary.gpr();
- } else
- storageGPR = storage.gpr();
-
- MacroAssembler::JumpList notFastNamedCases;
-
- // FIXME: We shouldn't generate this code if we know base is not an object.
- notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
- {
- if (!m_state.forNode(baseEdge).isType(SpecCell))
- notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
-
- // Check the structure
- // FIXME: If we know there's only one structure for base we can just embed it here.
- m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
-
- auto badStructure = m_jit.branch32(
- MacroAssembler::NotEqual,
- scratchGPR,
- MacroAssembler::Address(
- enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
-
- // FIXME: Maybe we should have a better way to represent Indexed+Named?
- if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
- badStructureSlowPath = badStructure;
- else
- notFastNamedCases.append(badStructure);
-
- // Compute the offset
- // If index is less than the enumerator's cached inline storage, then it's an inline access
- MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
- indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
-
- m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
-
- doneCases.append(m_jit.jump());
-
- // Otherwise it's out of line
- outOfLineAccess.link(&m_jit);
- m_jit.move(indexGPR, scratchGPR);
- m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
- m_jit.neg32(scratchGPR);
- m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
- if (!haveStorage)
- m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
- constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
- m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
- doneCases.append(m_jit.jump());
- }
-
- notFastNamedCases.link(&m_jit);
- return std::make_pair(resultRegs, DataFormatJS);
- }));
-
- // We rely on compileGetByVal to call jsValueResult for us.
- // FIXME: This is kinda hacky...
- ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
-
- if (badStructureSlowPath.isSet())
- addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
-
- doneCases.link(&m_jit);
- };
-
- if (isCell(baseEdge.useKind())) {
- // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
- speculate(node, baseEdge);
- SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
- generate(baseOperand.gpr());
- } else {
- JSValueOperand baseOperand(this, baseEdge);
- generate(baseOperand.gpr());
- }
-}
-
#endif
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (284699 => 284700)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2021-10-22 18:31:50 UTC (rev 284700)
@@ -118,21 +118,6 @@
case JSPropertyNameEnumerator::GenericMode: {
if (arrayProfile && baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
arrayProfile->observeStructureID(baseValue.asCell()->structureID());
-#if USE(JSVALUE32_64)
- if (!propertyNameValue.isCell()) {
- // This branch is only needed because we use this method
- // both as a slow_path and as a DFG call op. We'll end up
- // here if propertyName is not a cell then we are in
- // index+named mode, so do what RecoverNameAndGetVal
- // does. This can probably be removed if we re-enable the
- // optimizations for enumeratorGetByVal in DFG, see bug
- // #230189.
- JSString* string = enumerator->propertyNameAtIndex(index);
- auto propertyName = string->toIdentifier(globalObject);
- RETURN_IF_EXCEPTION(scope, { });
- RELEASE_AND_RETURN(scope, baseValue.get(globalObject, propertyName));
- }
-#endif
JSString* string = asString(propertyNameValue);
auto propertyName = string->toIdentifier(globalObject);
RETURN_IF_EXCEPTION(scope, { });