Title: [285167] trunk
Revision
285167
Author
sbar...@apple.com
Date
2021-11-02 10:25:46 -0700 (Tue, 02 Nov 2021)

Log Message

EnumeratorGetByVal for IndexedMode+OwnStructureMode doesn't always recover the property name
https://bugs.webkit.org/show_bug.cgi?id=231321
<rdar://problem/84211697>

Reviewed by Yusuke Suzuki.

JSTests:

* stress/enumerator-get-by-val-needs-to-recover-property-name.js: Added.

Source/_javascript_Core:

When running an EnumeratorGetByVal in IndexedMode+OwnStructureMode, we may
go to the slow path. However, we were incorrectly going to the slow path
before recovering the actual property name. Instead, we were passing in
the integer index value to the get by val.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (285166 => 285167)


--- trunk/JSTests/ChangeLog	2021-11-02 17:11:54 UTC (rev 285166)
+++ trunk/JSTests/ChangeLog	2021-11-02 17:25:46 UTC (rev 285167)
@@ -1,3 +1,13 @@
+2021-11-02  Saam Barati  <sbar...@apple.com>
+
+        EnumeratorGetByVal for IndexedMode+OwnStructureMode doesn't always recover the property name
+        https://bugs.webkit.org/show_bug.cgi?id=231321
+        <rdar://problem/84211697>
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/enumerator-get-by-val-needs-to-recover-property-name.js: Added.
+
 2021-11-01  Saam Barati  <sbar...@apple.com>
 
         ArrayBuffer species watchpoint being invalidated doesn't mean it's not an ArrayBuffer constructor from the same global object

Added: trunk/JSTests/stress/enumerator-get-by-val-needs-to-recover-property-name.js (0 => 285167)


--- trunk/JSTests/stress/enumerator-get-by-val-needs-to-recover-property-name.js	                        (rev 0)
+++ trunk/JSTests/stress/enumerator-get-by-val-needs-to-recover-property-name.js	2021-11-02 17:25:46 UTC (rev 285167)
@@ -0,0 +1,32 @@
+//@ runDefault("--validateOptions=true", "--useConcurrentJIT=false", "--useConcurrentGC=false", "--thresholdForJITSoon=10", "--thresholdForJITAfterWarmUp=10", "--thresholdForOptimizeAfterWarmUp=100", "--thresholdForOptimizeAfterLongWarmUp=100", "--thresholdForOptimizeSoon=100", "--thresholdForFTLOptimizeAfterWarmUp=1000", "--thresholdForFTLOptimizeSoon=1000", "--validateBCE=true", "--useFTLJIT=true")
+
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+function main() {
+    let result;
+    const v35 = [0, 0, {b:"AAAAA"}];
+    
+    async function v36(arr) {
+        edenGC();  // This is needed
+        for (let i = 0; i < 2; i++) {
+            const v201 = ` 
+                var someVar; // this is needed
+
+                for (let j = 0; j < 60000; j++) { }
+
+                const v222 = {"__proto__":[[]], "a":0, "b":0};
+                for (const prop in v222) {
+                    result = arr[prop];
+                    v222.__proto__ = {};
+                }
+            `;
+            eval(v201); // moving code out of eval breaks differential
+        }
+    }
+    v35.filter(v36);
+    assert(result === "AAAAA");
+}
+main();

Modified: trunk/Source/_javascript_Core/ChangeLog (285166 => 285167)


--- trunk/Source/_javascript_Core/ChangeLog	2021-11-02 17:11:54 UTC (rev 285166)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-11-02 17:25:46 UTC (rev 285167)
@@ -1,3 +1,21 @@
+2021-11-02  Saam Barati  <sbar...@apple.com>
+
+        EnumeratorGetByVal for IndexedMode+OwnStructureMode doesn't always recover the property name
+        https://bugs.webkit.org/show_bug.cgi?id=231321
+        <rdar://problem/84211697>
+
+        Reviewed by Yusuke Suzuki.
+
+        When running an EnumeratorGetByVal in IndexedMode+OwnStructureMode, we may
+        go to the slow path. However, we were incorrectly going to the slow path
+        before recovering the actual property name. Instead, we were passing in
+        the integer index value to the get by val.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+
 2021-11-02  Patrick Angle  <pan...@apple.com>
 
         WebDriver: [Cocoa] support `acceptInsecureCerts` capability

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (285166 => 285167)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-11-02 17:11:54 UTC (rev 285166)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-11-02 17:25:46 UTC (rev 285167)
@@ -15875,7 +15875,7 @@
         JSValueRegs resultRegs;
         GPRReg indexGPR;
         GPRReg enumeratorGPR;
-        MacroAssembler::Jump badStructureSlowPath;
+        MacroAssembler::JumpList recoverGenericCase;
 
         compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat, CanUseFlush>(DataFormat)>([&] (DataFormat) {
             Edge storageEdge = m_graph.varArgChild(node, 2);
@@ -15904,12 +15904,15 @@
             GPRReg scratchGPR = resultRegs.payloadGPR();
 
             MacroAssembler::JumpList notFastNamedCases;
+            // FIXME: Maybe we should have a better way to represent IndexedMode+OwnStructureMode?
+            bool indexedAndOwnStructureMode = m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node();
+            MacroAssembler::JumpList& genericOrRecoverCase = indexedAndOwnStructureMode ? recoverGenericCase : 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));
+                    genericOrRecoverCase.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.
@@ -15920,13 +15923,8 @@
                     scratchGPR,
                     MacroAssembler::Address(
                         enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
+                genericOrRecoverCase.append(badStructure);
 
-                // 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,
@@ -15957,11 +15955,11 @@
         // FIXME: This is kinda hacky...
         ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
 
-        if (badStructureSlowPath.isSet()) {
+        if (!recoverGenericCase.empty()) {
             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));
+                addSlowPathGenerator(slowPathCall(recoverGenericCase, 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));
+                addSlowPathGenerator(slowPathCall(recoverGenericCase, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, indexGPR, enumeratorGPR));
         }
 
         doneCases.link(&m_jit);

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (285166 => 285167)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-11-02 17:11:54 UTC (rev 285166)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-11-02 17:25:46 UTC (rev 285167)
@@ -13681,7 +13681,15 @@
         LBasicBlock outOfLineLoadBlock = m_out.newBlock();
         LBasicBlock genericICBlock = m_out.newBlock();
         LBasicBlock continuation = m_out.newBlock();
+        LBasicBlock genericOrRecover;
 
+        // FIXME: This is not the cleanest way to say we're using IndexedMode+OwnStructureMode mode. 
+        bool indexedAndOwnStructureMode = indexEdge.node() == propertyNameEdge.node();
+        if (indexedAndOwnStructureMode)
+            genericOrRecover = m_out.newBlock();
+        else
+            genericOrRecover = genericICBlock;
+
         Vector<ValueFromBlock, 4> results;
 
         LValue isNotNamed = m_out.testNonZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode));
@@ -13688,7 +13696,7 @@
         m_out.branch(isNotNamed, unsure(genericICBlock), unsure(checkIsCellBlock));
 
         m_out.appendTo(checkIsCellBlock);
-        m_out.branch(isCell(base, provenType(baseEdge)), usually(checkStructureBlock), rarely(genericICBlock));
+        m_out.branch(isCell(base, provenType(baseEdge)), usually(checkStructureBlock), rarely(genericOrRecover));
 
         m_out.appendTo(checkStructureBlock);
         LValue structureID;
@@ -13700,16 +13708,8 @@
 
         LValue hasEnumeratorStructure = m_out.equal(structureID, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID));
 
-        if (indexEdge.node() == propertyNameEdge.node()) {
-            JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
-            LBasicBlock badStructureSlowPath = m_out.newBlock();
-            m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericICBlock));
+        m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericOrRecover));
 
-            m_out.appendTo(badStructureSlowPath);
-            results.append(m_out.anchor(vmCall(Int64, operationEnumeratorRecoverNameAndGetByVal, weakPointer(globalObject), base, index, enumerator)));
-        } else
-            m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericICBlock));
-
         m_out.appendTo(checkInlineOrOutOfLineBlock);
         LValue inlineCapacity = nullptr;
         bool hasNoOutOfLineProperties = false;
@@ -13753,6 +13753,12 @@
         results.append(m_out.anchor(genericResult));
         m_out.jump(continuation);
 
+        if (indexedAndOwnStructureMode) {
+            m_out.appendTo(genericOrRecover);
+            results.append(m_out.anchor(vmCall(Int64, operationEnumeratorRecoverNameAndGetByVal, weakPointer(m_graph.globalObjectFor(m_origin.semantic)), base, index, enumerator)));
+            m_out.jump(continuation);
+        }
+
         m_out.appendTo(continuation);
         ASSERT(results.size());
         LValue result = m_out.phi(Int64, results);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to