<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[284700] trunk/Source/JavaScriptCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/284700">284700</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2021-10-22 11:31:50 -0700 (Fri, 22 Oct 2021)</dd>
</dl>
<h3>Log Message</h3>
<pre>[JSC][32bit] Re-enable compileEnumeratorGetByVal fast path
https://bugs.webkit.org/show_bug.cgi?id=232052
Patch by Mikhail R. Gadelha <mikhail@igalia.com> on 2021-10-22
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.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/ChangeLog 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -1,3 +1,33 @@
</span><ins>+2021-10-22 Mikhail R. Gadelha <mikhail@igalia.com>
+
+ [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.
+
</ins><span class="cx"> 2021-10-22 Saam Barati <sbarati@apple.com>
</span><span class="cx">
</span><span class="cx"> canDoFastSpread should also check that the Structure is from the global object we're watching
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -1124,9 +1124,6 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> }
</span><del>-#if USE(JSVALUE32_64)
- fixEdge<CellUse>(m_graph.varArgChild(node, 0)); // Speculating cell due to register pressure on 32-bit.
-#endif
</del><span class="cx"> break;
</span><span class="cx"> case Array::ForceExit:
</span><span class="cx"> break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -749,35 +749,6 @@
</span><span class="cx"> return JSValue::encode(jsNumber(truncatedValueOfArgument));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-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)));
-}
-
</del><span class="cx"> ALWAYS_INLINE EncodedJSValue getByValCellInt(JSGlobalObject* globalObject, VM& vm, JSCell* base, int32_t index)
</span><span class="cx"> {
</span><span class="cx"> if (index < 0) {
</span><span class="lines">@@ -2507,7 +2478,7 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, uint32_t index, JSPropertyNameEnumerator* enumerator))
</ins><span class="cx"> {
</span><span class="cx"> VM& vm = globalObject->vm();
</span><span class="cx"> CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -2518,7 +2489,8 @@
</span><span class="cx"> PropertyName propertyName = string->toIdentifier(globalObject);
</span><span class="cx"> // This should only really return for TerminationException since we know string is backed by a UUID.
</span><span class="cx"> RETURN_IF_EXCEPTION(scope, { });
</span><del>- JSObject* object = base->toObject(globalObject);
</del><ins>+ JSValue base = JSValue::decode(baseValue);
+ JSObject* object = base.toObject(globalObject);
</ins><span class="cx"> RETURN_IF_EXCEPTION(scope, { });
</span><span class="cx">
</span><span class="cx"> RELEASE_AND_RETURN(scope, JSValue::encode(object->get(globalObject, propertyName)));
</span><span class="lines">@@ -2539,19 +2511,6 @@
</span><span class="cx"> RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, propertyName))));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-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)));
-}
-
</del><span class="cx"> JSC_DEFINE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber))
</span><span class="cx"> {
</span><span class="cx"> VM& vm = globalObject->vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -90,7 +90,6 @@
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationArithFloor, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationArithCeil, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationArithTrunc, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationGetByValCell, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue encodedProperty));
</del><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetByValObjectInt, EncodedJSValue, (JSGlobalObject*, JSObject*, int32_t));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetByValStringInt, EncodedJSValue, (JSGlobalObject*, JSString*, int32_t));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationGetByValObjectString, EncodedJSValue, (JSGlobalObject*, JSCell*, JSCell* string));
</span><span class="lines">@@ -111,8 +110,7 @@
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
</span><del>-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*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, JSPropertyNameEnumerator*));
</ins><span class="cx">
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewArray, char*, (JSGlobalObject*, Structure*, void*, size_t));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -15854,6 +15854,118 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+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());
+ }
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx">
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -1818,12 +1818,14 @@
</span><span class="cx"> void SpeculativeJIT::compileGetByVal(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix)
</span><span class="cx"> {
</span><span class="cx"> switch (node->arrayMode().type()) {
</span><ins>+ case Array::AnyTypedArray:
+ case Array::ForceExit:
+ case Array::SelectUsingArguments:
</ins><span class="cx"> case Array::SelectUsingPredictions:
</span><del>- case Array::ForceExit:
- RELEASE_ASSERT_NOT_REACHED();
-#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
- terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
-#endif
</del><ins>+ case Array::Unprofiled:
+ case Array::BigInt64Array:
+ case Array::BigUint64Array:
+ DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
</ins><span class="cx"> break;
</span><span class="cx"> case Array::Undecided: {
</span><span class="cx"> SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
</span><span class="lines">@@ -1846,18 +1848,18 @@
</span><span class="cx"> if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
</span><span class="cx"> if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
</span><span class="cx"> compileGetByValForObjectWithString(node, prefix);
</span><del>- break;
</del><ins>+ return;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
</span><span class="cx"> compileGetByValForObjectWithSymbol(node, prefix);
</span><del>- break;
</del><ins>+ return;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
</del><ins>+ JSValueOperand base(this, m_graph.varArgChild(node, 0));
</ins><span class="cx"> JSValueOperand property(this, m_graph.varArgChild(node, 1));
</span><del>- GPRReg baseGPR = base.gpr();
</del><ins>+ JSValueRegs baseGPR = base.jsValueRegs();
</ins><span class="cx"> JSValueRegs propertyRegs = property.jsValueRegs();
</span><span class="cx">
</span><span class="cx"> JSValueRegs resultRegs;
</span><span class="lines">@@ -1864,56 +1866,70 @@
</span><span class="cx"> std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
</span><span class="cx">
</span><span class="cx"> flushRegisters();
</span><del>- callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
</del><ins>+ callOperation(operationGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
</ins><span class="cx"> m_jit.exceptionCheck();
</span><span class="cx">
</span><span class="cx"> jsValueResult(resultRegs, node);
</span><del>- break;
</del><ins>+ return;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- speculate(node, m_graph.varArgChild(node, 0));
</del><ins>+ JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
+ JSValueRegs propertyRegs = property.jsValueRegs();
</ins><span class="cx"> speculate(node, m_graph.varArgChild(node, 1));
</span><span class="cx">
</span><del>- JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
- JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
</del><ins>+ auto generate = [&] (JSValueRegs baseRegs) {
+ JSValueRegs resultRegs;
+ std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
</ins><span class="cx">
</span><del>- JSValueRegs baseRegs = base.jsValueRegs();
- JSValueRegs propertyRegs = property.jsValueRegs();
</del><ins>+ CodeOrigin codeOrigin = node->origin.semantic;
+ CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
+ RegisterSet usedRegisters = this->usedRegisters();
</ins><span class="cx">
</span><del>- JSValueRegs resultRegs;
- std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
</del><ins>+ JITCompiler::JumpList slowCases;
+ if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
+ slowCases.append(m_jit.branchIfNotCell(baseRegs));
</ins><span class="cx">
</span><del>- CodeOrigin codeOrigin = node->origin.semantic;
- CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
- RegisterSet usedRegisters = this->usedRegisters();
</del><ins>+ JITGetByValGenerator gen(
+ m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
+ baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
</ins><span class="cx">
</span><del>- JITCompiler::JumpList slowCases;
- if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
- slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR()));
</del><ins>+ 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;
</ins><span class="cx">
</span><del>- JITGetByValGenerator gen(
- m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
- baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
</del><ins>+ gen.generateFastPath(m_jit);
</ins><span class="cx">
</span><del>- 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;
</del><ins>+ slowCases.append(gen.slowPathJump());
</ins><span class="cx">
</span><del>- gen.generateFastPath(m_jit);
</del><ins>+ 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);
+ }
</ins><span class="cx">
</span><del>- slowCases.append(gen.slowPathJump());
</del><ins>+ m_jit.addGetByVal(gen, slowPath.get());
+ addSlowPathGenerator(WTFMove(slowPath));
</ins><span class="cx">
</span><del>- std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
- slowCases, this, operationGetByValOptimize,
- resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
</del><ins>+ jsValueResult(resultRegs, node);
+ };
</ins><span class="cx">
</span><del>- m_jit.addGetByVal(gen, slowPath.get());
- addSlowPathGenerator(WTFMove(slowPath));
-
- jsValueResult(resultRegs, node);
</del><ins>+ 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());
+ }
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case Array::Int32:
</span><span class="lines">@@ -1932,7 +1948,7 @@
</span><span class="cx"> DataFormat format;
</span><span class="cx"> std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatInt32 : DataFormatJS);
</span><span class="cx">
</span><del>- speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
</del><ins>+ speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
</ins><span class="cx">
</span><span class="cx"> if (format == DataFormatInt32) {
</span><span class="cx"> ASSERT(!node->arrayMode().isInBoundsSaneChain());
</span><span class="lines">@@ -1994,8 +2010,8 @@
</span><span class="cx"> slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
</span><span class="cx">
</span><span class="cx"> m_jit.loadValue(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultRegs);
</span><ins>+
</ins><span class="cx"> slowCases.append(m_jit.branchIfEmpty(resultRegs.tagGPR()));
</span><del>-
</del><span class="cx"> addSlowPathGenerator(
</span><span class="cx"> slowPathCall(
</span><span class="cx"> slowCases, this, operationGetByValObjectInt,
</span><span class="lines">@@ -2016,22 +2032,23 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> FPRTemporary result(this);
</span><ins>+ FPRReg resultReg = result.fpr();
</ins><span class="cx">
</span><span class="cx"> JSValueRegs resultRegs;
</span><span class="cx"> DataFormat format;
</span><span class="cx"> std::tie(resultRegs, format) = prefix(DataFormatDouble);
</span><span class="cx">
</span><del>- speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
</del><ins>+ speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
</ins><span class="cx">
</span><del>- m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
</del><ins>+ m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
</ins><span class="cx"> if (!node->arrayMode().isInBoundsSaneChain())
</span><del>- speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
</del><ins>+ speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg));
</ins><span class="cx"> if (format == DataFormatJS) {
</span><del>- boxDouble(result.fpr(), resultRegs);
</del><ins>+ boxDouble(resultReg, resultRegs);
</ins><span class="cx"> jsValueResult(resultRegs, node);
</span><span class="cx"> } else {
</span><span class="cx"> ASSERT(format == DataFormatDouble && !resultRegs);
</span><del>- doubleResult(result.fpr(), node);
</del><ins>+ doubleResult(resultReg, node);
</ins><span class="cx"> }
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -2083,7 +2100,7 @@
</span><span class="cx"> JSValueRegs resultRegs;
</span><span class="cx"> std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
</span><span class="cx">
</span><del>- speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
</del><ins>+ speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
</ins><span class="cx">
</span><span class="cx"> m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
</span><span class="cx"> speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultRegs.tagGPR()));
</span><span class="lines">@@ -2096,9 +2113,10 @@
</span><span class="cx"> SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
</span><span class="cx"> SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
</span><span class="cx"> StorageOperand storage(this, m_graph.varArgChild(node, 2));
</span><ins>+
+ GPRReg baseReg = base.gpr();
</ins><span class="cx"> GPRReg propertyReg = property.gpr();
</span><span class="cx"> GPRReg storageReg = storage.gpr();
</span><del>- GPRReg baseReg = base.gpr();
</del><span class="cx">
</span><span class="cx"> if (!m_compileOkay)
</span><span class="cx"> return;
</span><span class="lines">@@ -2120,8 +2138,7 @@
</span><span class="cx"> addSlowPathGenerator(
</span><span class="cx"> slowPathCall(
</span><span class="cx"> slowCases, this, operationGetByValObjectInt,
</span><del>- resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)),
- baseReg, propertyReg));
</del><ins>+ resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
</ins><span class="cx">
</span><span class="cx"> jsValueResult(resultRegs, node);
</span><span class="cx"> break;
</span><span class="lines">@@ -2135,8 +2152,15 @@
</span><span class="cx"> case Array::ScopedArguments:
</span><span class="cx"> compileGetByValOnScopedArguments(node, prefix);
</span><span class="cx"> break;
</span><del>- default: {
- ASSERT(node->arrayMode().isSomeTypedArrayView());
</del><ins>+ 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: {
</ins><span class="cx"> TypedArrayType type = node->arrayMode().typedArrayType();
</span><span class="cx"> if (isInt(type))
</span><span class="cx"> compileGetByValOnIntTypedArray(node, type, prefix);
</span><span class="lines">@@ -4498,43 +4522,6 @@
</span><span class="cx"> doubleResult(result.fpr(), node);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-// 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());
- }
-}
</del><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -6466,114 +6466,6 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-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());
- }
-}
-
</del><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (284699 => 284700)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h 2021-10-22 18:23:09 UTC (rev 284699)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h 2021-10-22 18:31:50 UTC (rev 284700)
</span><span class="lines">@@ -118,21 +118,6 @@
</span><span class="cx"> case JSPropertyNameEnumerator::GenericMode: {
</span><span class="cx"> if (arrayProfile && baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
</span><span class="cx"> arrayProfile->observeStructureID(baseValue.asCell()->structureID());
</span><del>-#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
</del><span class="cx"> JSString* string = asString(propertyNameValue);
</span><span class="cx"> auto propertyName = string->toIdentifier(globalObject);
</span><span class="cx"> RETURN_IF_EXCEPTION(scope, { });
</span></span></pre>
</div>
</div>
</body>
</html>