Diff
Modified: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/ChangeLog (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/ChangeLog 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/ChangeLog 2021-09-17 10:33:25 UTC (rev 282651)
@@ -1,3 +1,32 @@
+2021-09-14 Xan López <x...@igalia.com>
+
+ [JSC] ASSERT failed in stress/for-in-tests.js (32bit)
+ https://bugs.webkit.org/show_bug.cgi?id=229543
+
+ Reviewed by Yusuke Suzuki.
+
+ Since r280760 DFG::SpeculativeJIT::compileEnumeratorGetByVal uses
+ too many registers for 32bit. Revert to the slow path as a
+ temporary measure to avoid crashes, we'll try to reenable the
+ optimizations later on (see bug #230189).
+
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION): define a generic call
+ operation for compileEnumeratorGetByVal.
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT.cpp: move the current version of
+ compileEnumeratorGetByVal to 64bit, since it won't work on 32bit.
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): call the generic call op always.
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): use the previous version here.
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::JSC_DEFINE_COMMON_SLOW_PATH): refactor a bit the slow path
+ for enumeratorGetByVal so it can be called from DFG as a call
+ operation.
+ * runtime/CommonSlowPaths.h:
+ (JSC::CommonSlowPaths::opEnumeratorGetByVal):
+
2021-09-13 Xan López <x...@igalia.com>
[JSC][32bit] in-by-val fails inside for-in loop after delete
Modified: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGOperations.cpp (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-09-17 10:33:25 UTC (rev 282651)
@@ -2538,6 +2538,18 @@
RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, propertyName))));
}
+JSC_DEFINE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* baseCell, 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::Mode mode = static_cast<JSPropertyNameEnumerator::Mode>(modeNumber);
+ RELEASE_AND_RETURN(scope, JSValue::encode(CommonSlowPaths::opEnumeratorGetByVal(globalObject, baseCell, 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: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGOperations.h (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGOperations.h 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGOperations.h 2021-09-17 10:33:25 UTC (rev 282651)
@@ -112,6 +112,7 @@
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*, JSCell*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationNewArray, char*, (JSGlobalObject*, Structure*, void*, size_t));
Modified: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-09-17 10:33:25 UTC (rev 282651)
@@ -13623,114 +13623,6 @@
jsValueResult(resultRegs, node);
}
-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());
- }
-}
-
template<typename SlowPathFunctionType>
void SpeculativeJIT::compileEnumeratorHasProperty(Node* node, SlowPathFunctionType slowPathFunction)
{
Modified: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2021-09-17 10:33:25 UTC (rev 282651)
@@ -4480,6 +4480,29 @@
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)
+{
+ SpeculateCellOperand baseOperand(this, m_graph.varArgChild(node, 0));
+ JSValueOperand property(this, m_graph.varArgChild(node, 1));
+ 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 baseOperandGPR = baseOperand.gpr();
+ JSValueRegs propertyRegs = property.jsValueRegs();
+ GPRReg indexGPR = index.gpr();
+ GPRReg modeGPR = mode.gpr();
+ GPRReg enumeratorGPR = enumerator.gpr();
+
+ flushRegisters();
+
+ JSValueRegsFlushedCallResult result(this);
+ JSValueRegs resultRegs = result.regs();
+
+ callOperation(operationEnumeratorGetByValGeneric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseOperandGPR, propertyRegs, indexGPR, modeGPR, enumeratorGPR);
+ m_jit.exceptionCheck();
+ jsValueResult(resultRegs, node);
+}
#endif
} } // namespace JSC::DFG
Modified: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2021-09-17 10:33:25 UTC (rev 282651)
@@ -6263,6 +6263,114 @@
}
}
+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: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2021-09-17 10:33:25 UTC (rev 282651)
@@ -1010,42 +1010,14 @@
BEGIN();
auto bytecode = pc->as<OpEnumeratorGetByVal>();
JSValue baseValue = GET_C(bytecode.m_base).jsValue();
+ JSValue propertyName = GET(bytecode.m_propertyName).jsValue();
auto& metadata = bytecode.metadata(codeBlock);
auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32());
metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
-
JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
unsigned index = GET(bytecode.m_index).jsValue().asInt32();
- switch (mode) {
- case JSPropertyNameEnumerator::IndexedMode: {
- if (LIKELY(baseValue.isCell()))
- metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID());
- RETURN_PROFILED(baseValue.get(globalObject, static_cast<unsigned>(index)));
- }
- case JSPropertyNameEnumerator::OwnStructureMode: {
- if (LIKELY(baseValue.isCell()) && baseValue.asCell()->structureID() == enumerator->cachedStructureID()) {
- // We'll only match the structure ID if the base is an object.
- ASSERT(index < enumerator->endStructurePropertyIndex());
- RETURN_PROFILED(baseValue.getObject()->getDirect(index < enumerator->cachedInlineCapacity() ? index : index - enumerator->cachedInlineCapacity() + firstOutOfLineOffset));
- } else
- metadata.m_enumeratorMetadata |= static_cast<uint8_t>(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch);
- FALLTHROUGH;
- }
- case JSPropertyNameEnumerator::GenericMode: {
- if (baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
- metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID());
- JSString* string = asString(GET(bytecode.m_propertyName).jsValue());
- auto propertyName = string->toIdentifier(globalObject);
- CHECK_EXCEPTION();
- RETURN_PROFILED(baseValue.get(globalObject, propertyName));
- }
-
- default:
- RELEASE_ASSERT_NOT_REACHED();
- break;
- };
- RELEASE_ASSERT_NOT_REACHED();
+ RETURN_PROFILED(CommonSlowPaths::opEnumeratorGetByVal(globalObject, baseValue, propertyName, index, mode, enumerator, &metadata.m_arrayProfile, &metadata.m_enumeratorMetadata));
}
JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_in_by_val)
Modified: releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/runtime/CommonSlowPaths.h (282650 => 282651)
--- releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/runtime/CommonSlowPaths.h 2021-09-17 10:33:17 UTC (rev 282650)
+++ releases/WebKitGTK/webkit-2.34/Source/_javascript_Core/runtime/CommonSlowPaths.h 2021-09-17 10:33:25 UTC (rev 282651)
@@ -31,6 +31,7 @@
#include "ExceptionHelpers.h"
#include "FunctionCodeBlock.h"
#include "JSImmutableButterfly.h"
+#include "JSPropertyNameEnumerator.h"
#include "ScopedArguments.h"
#include "SlowPathFunction.h"
#include "StackAlignment.h"
@@ -91,6 +92,60 @@
return padding;
}
+inline JSValue opEnumeratorGetByVal(JSGlobalObject* globalObject, JSValue baseValue, JSValue propertyNameValue, unsigned index, JSPropertyNameEnumerator::Mode mode, JSPropertyNameEnumerator* enumerator, ArrayProfile* arrayProfile = nullptr, uint8_t* enumeratorMetadata = nullptr)
+{
+ VM& vm = getVM(globalObject);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ switch (mode) {
+ case JSPropertyNameEnumerator::IndexedMode: {
+ if (arrayProfile && LIKELY(baseValue.isCell()))
+ arrayProfile->observeStructureID(baseValue.asCell()->structureID());
+ RELEASE_AND_RETURN(scope, baseValue.get(globalObject, static_cast<unsigned>(index)));
+ }
+ case JSPropertyNameEnumerator::OwnStructureMode: {
+ if (LIKELY(baseValue.isCell()) && baseValue.asCell()->structureID() == enumerator->cachedStructureID()) {
+ // We'll only match the structure ID if the base is an object.
+ ASSERT(index < enumerator->endStructurePropertyIndex());
+ RELEASE_AND_RETURN(scope, baseValue.getObject()->getDirect(index < enumerator->cachedInlineCapacity() ? index : index - enumerator->cachedInlineCapacity() + firstOutOfLineOffset));
+ } else {
+ if (enumeratorMetadata)
+ *enumeratorMetadata |= static_cast<uint8_t>(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch);
+ }
+ FALLTHROUGH;
+ }
+
+ 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, { });
+ RELEASE_AND_RETURN(scope, baseValue.get(globalObject, propertyName));
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ };
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
inline bool opInByVal(JSGlobalObject* globalObject, JSValue baseVal, JSValue propName, ArrayProfile* arrayProfile = nullptr)
{
VM& vm = getVM(globalObject);