Title: [272405] trunk
Revision
272405
Author
[email protected]
Date
2021-02-05 00:45:09 -0800 (Fri, 05 Feb 2021)

Log Message

[JSC] Atomics.store in DFG / FTL should return ToNumber(input) value
https://bugs.webkit.org/show_bug.cgi?id=221438
<rdar://problem/73973264>

Reviewed by Filip Pizlo.

JSTests:

* stress/atomic-store-result-type-in-ai.js: Added.
* stress/atomics-store-result-double-nan.js: Added.
(shouldBe):
(test):
* stress/atomics-store-result-double-negative-zero.js: Added.
(shouldBe):
(test):
* stress/atomics-store-result-double.js: Added.
(shouldBe):
(test):
* stress/atomics-store-result-int52.js: Added.
(shouldBe):
* stress/atomics-store-result.js: Added.
(shouldBe):

Source/_javascript_Core:

Atomics.store is different from the other ReadModifyWrite atomics. It returns the input value without truncating it into TypedArray's requirement.
For example,

    var u8 = new Uint8Array(8);
    Atomics.store(u8, 0, 0xffff) === 0xffff // Not 0xff.

However DFG and FTL implementations do not handle it correctly.
This patch fixes AI, fixup, and code generations to handle this.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::getIntTypedArrayStoreOperandForAtomics):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileAtomicsReadModifyWrite):
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::setIntTypedArrayLoadResult):
(JSC::FTL::DFG::LowerDFGToB3::toIntegerOrInfinity):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (272404 => 272405)


--- trunk/JSTests/ChangeLog	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/JSTests/ChangeLog	2021-02-05 08:45:09 UTC (rev 272405)
@@ -1,3 +1,26 @@
+2021-02-05  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Atomics.store in DFG / FTL should return ToNumber(input) value
+        https://bugs.webkit.org/show_bug.cgi?id=221438
+        <rdar://problem/73973264>
+
+        Reviewed by Filip Pizlo.
+
+        * stress/atomic-store-result-type-in-ai.js: Added.
+        * stress/atomics-store-result-double-nan.js: Added.
+        (shouldBe):
+        (test):
+        * stress/atomics-store-result-double-negative-zero.js: Added.
+        (shouldBe):
+        (test):
+        * stress/atomics-store-result-double.js: Added.
+        (shouldBe):
+        (test):
+        * stress/atomics-store-result-int52.js: Added.
+        (shouldBe):
+        * stress/atomics-store-result.js: Added.
+        (shouldBe):
+
 2021-02-03  Yusuke Suzuki  <[email protected]>
 
         [JSC] Update test262

Added: trunk/JSTests/stress/atomic-store-result-type-in-ai.js (0 => 272405)


--- trunk/JSTests/stress/atomic-store-result-type-in-ai.js	                        (rev 0)
+++ trunk/JSTests/stress/atomic-store-result-type-in-ai.js	2021-02-05 08:45:09 UTC (rev 272405)
@@ -0,0 +1,5 @@
+//@ runDefault("--forceDebuggerBytecodeGeneration=1", "--useConcurrentJIT=0")
+let a = new Uint8Array(1);
+for (let i = 0; i < 10000; ++i) {
+  Atomics.store(a, 0, i);
+}

Added: trunk/JSTests/stress/atomics-store-result-double-nan.js (0 => 272405)


--- trunk/JSTests/stress/atomics-store-result-double-nan.js	                        (rev 0)
+++ trunk/JSTests/stress/atomics-store-result-double-nan.js	2021-02-05 08:45:09 UTC (rev 272405)
@@ -0,0 +1,13 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(i8, double) {
+    shouldBe(Atomics.store(i8, 0, double), 0);
+}
+noInline(test);
+
+var i8 = new Int8Array(new SharedArrayBuffer(8));
+for (var i = 0; i < 1e4; ++i)
+    test(i8, NaN);

Added: trunk/JSTests/stress/atomics-store-result-double-negative-zero.js (0 => 272405)


--- trunk/JSTests/stress/atomics-store-result-double-negative-zero.js	                        (rev 0)
+++ trunk/JSTests/stress/atomics-store-result-double-negative-zero.js	2021-02-05 08:45:09 UTC (rev 272405)
@@ -0,0 +1,13 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(i8, double) {
+    shouldBe(Math.sign(Atomics.store(i8, 0, double)), 0);
+}
+noInline(test);
+
+var i8 = new Int8Array(new SharedArrayBuffer(8));
+for (var i = 0; i < 1e4; ++i)
+    test(i8, -0.0);

Added: trunk/JSTests/stress/atomics-store-result-double.js (0 => 272405)


--- trunk/JSTests/stress/atomics-store-result-double.js	                        (rev 0)
+++ trunk/JSTests/stress/atomics-store-result-double.js	2021-02-05 08:45:09 UTC (rev 272405)
@@ -0,0 +1,15 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test(i8, double) {
+    shouldBe(Atomics.store(i8, 0, double), double);
+}
+noInline(test);
+
+var i8 = new Int8Array(32);
+for (var i = 0; i < 1e4; ++i) {
+    test(i8, Infinity);
+    test(i8, -Infinity);
+}

Added: trunk/JSTests/stress/atomics-store-result-int52.js (0 => 272405)


--- trunk/JSTests/stress/atomics-store-result-int52.js	                        (rev 0)
+++ trunk/JSTests/stress/atomics-store-result-int52.js	2021-02-05 08:45:09 UTC (rev 272405)
@@ -0,0 +1,8 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var i8 = new Int8Array(32);
+for (var i = 0; i < 1e4; ++i)
+    shouldBe(Atomics.store(i8, 0, 0xffffffff00 + i), 0xffffffff00 + i);

Added: trunk/JSTests/stress/atomics-store-result.js (0 => 272405)


--- trunk/JSTests/stress/atomics-store-result.js	                        (rev 0)
+++ trunk/JSTests/stress/atomics-store-result.js	2021-02-05 08:45:09 UTC (rev 272405)
@@ -0,0 +1,8 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var i8 = new Int8Array(32);
+for (var i = 0; i < 1e4; ++i)
+    shouldBe(Atomics.store(i8, 0, 0xff00 + i), 0xff00 + i);

Modified: trunk/Source/_javascript_Core/ChangeLog (272404 => 272405)


--- trunk/Source/_javascript_Core/ChangeLog	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-02-05 08:45:09 UTC (rev 272405)
@@ -1,3 +1,36 @@
+2021-02-05  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Atomics.store in DFG / FTL should return ToNumber(input) value
+        https://bugs.webkit.org/show_bug.cgi?id=221438
+        <rdar://problem/73973264>
+
+        Reviewed by Filip Pizlo.
+
+        Atomics.store is different from the other ReadModifyWrite atomics. It returns the input value without truncating it into TypedArray's requirement.
+        For example,
+
+            var u8 = new Uint8Array(8);
+            Atomics.store(u8, 0, 0xffff) === 0xffff // Not 0xff.
+
+        However DFG and FTL implementations do not handle it correctly.
+        This patch fixes AI, fixup, and code generations to handle this.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
+        (JSC::DFG::SpeculativeJIT::getIntTypedArrayStoreOperandForAtomics):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileAtomicsReadModifyWrite):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
+        (JSC::FTL::DFG::LowerDFGToB3::setIntTypedArrayLoadResult):
+        (JSC::FTL::DFG::LowerDFGToB3::toIntegerOrInfinity):
+
 2021-02-04  Yusuke Suzuki  <[email protected]>
 
         [JSC] Implement Object.entries in C++

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (272404 => 272405)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2021-02-05 08:45:09 UTC (rev 272405)
@@ -2324,6 +2324,44 @@
             if (!storageEdge)
                 clobberWorld();
         }
+
+        if (node->op() == AtomicsStore) {
+            // The returned value from Atomics.store does not rely on typed array types. It is relying
+            // on input's UseKind. For example,
+            //
+            //     Atomics.store(uint8Array, /* index */ 0, Infinity) // => returned value is Infinity
+            //
+            // Since the other ReadModifyWrite atomics return values stored in the typed array previously,
+            // the returned values rely on the typed array types. On the other hand, Atomics.store's
+            // returned value is input value. This means that Atomics.store + Uint8Array can return doubles
+            // while the typed array is Uint8Array (the above one is the example).
+            switch (node->arrayMode().type()) {
+            case Array::Generic:
+                clobberWorld();
+                makeHeapTopForNode(node);
+                break;
+            default: {
+                Edge operand = m_graph.child(node, 2);
+                switch (operand.useKind()) {
+                case Int32Use:
+                    setNonCellTypeForNode(node, SpecInt32Only);
+                    break;
+                case Int52RepUse:
+                    setNonCellTypeForNode(node, SpecInt52Any);
+                    break;
+                case DoubleRepUse:
+                    setNonCellTypeForNode(node, SpecFullDouble);
+                    break;
+                default:
+                    DFG_CRASH(m_graph, node, "Bad use kind");
+                    break;
+                }
+                break;
+            }
+            }
+            break;
+        }
+
         switch (node->arrayMode().type()) {
         case Array::SelectUsingPredictions:
         case Array::Unprofiled:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (272404 => 272405)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2021-02-05 08:45:09 UTC (rev 272405)
@@ -1379,10 +1379,26 @@
                 }
 
                 blessArrayOperation(base, index, m_graph.child(node, 2 + numExtraAtomicsArgs(node->op())));
-                if (node->arrayMode().type() != Array::Generic) {
-                    fixEdge<CellUse>(base);
-                    fixEdge<Int32Use>(index);
+                fixEdge<CellUse>(base);
+                fixEdge<Int32Use>(index);
 
+                if (node->op() == AtomicsStore) {
+                    Edge& operand = m_graph.child(node, 2);
+                    switch (operand.useKind()) {
+                    case Int32Use:
+                        // Default result type.
+                        break;
+                    case Int52RepUse:
+                        node->setResult(NodeResultInt52);
+                        break;
+                    case DoubleRepUse:
+                        node->setResult(NodeResultDouble);
+                        break;
+                    default:
+                        DFG_CRASH(m_graph, node, "Bad use kind");
+                        break;
+                    }
+                } else {
                     if (node->arrayMode().type() == Array::Uint32Array) {
                         // NOTE: This means basically always doing Int52.
                         if (node->shouldSpeculateInt52())

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (272404 => 272405)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-02-05 08:45:09 UTC (rev 272405)
@@ -3145,7 +3145,7 @@
 
     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
     loadFromIntTypedArray(storageReg, propertyReg, resultReg, type);
-    bool canSpeculate = true;
+    constexpr bool canSpeculate = true;
     setIntTypedArrayLoadResult(node, resultReg, type, canSpeculate);
 }
 
@@ -3271,6 +3271,31 @@
     return true;
 }
 
+bool SpeculativeJIT::getIntTypedArrayStoreOperandForAtomics(
+    GPRTemporary& value,
+    GPRReg property,
+#if USE(JSVALUE32_64)
+    GPRTemporary& propertyTag,
+    GPRTemporary& valueTag,
+#endif
+    Edge valueUse)
+{
+    JITCompiler::JumpList slowPathCases;
+    constexpr bool isClamped = false;
+    bool result = getIntTypedArrayStoreOperand(
+        value,
+        property,
+#if USE(JSVALUE32_64)
+        propertyTag,
+        valueTag,
+#endif
+        valueUse,
+        slowPathCases,
+        isClamped);
+    ASSERT(slowPathCases.empty());
+    return result;
+}
+
 void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
 {
     ASSERT(isInt(type));

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (272404 => 272405)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2021-02-05 08:45:09 UTC (rev 272405)
@@ -1385,8 +1385,16 @@
         GPRTemporary& valueTag,
 #endif
         Edge valueUse, JITCompiler::JumpList& slowPathCases, bool isClamped = false);
+    bool getIntTypedArrayStoreOperandForAtomics(
+        GPRTemporary& value,
+        GPRReg property,
+#if USE(JSVALUE32_64)
+        GPRTemporary& propertyTag,
+        GPRTemporary& valueTag,
+#endif
+        Edge valueUse);
     void loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType);
-    void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate = false);
+    void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate);
     template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*);
     void compileNewFunction(Node*);
     void compileSetFunctionName(Node*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (272404 => 272405)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2021-02-05 08:45:09 UTC (rev 272405)
@@ -3243,43 +3243,43 @@
         GPRReg argGPRs[2];
         GPRReg resultGPR;
 
-        auto callSlowPath = [&] () {
-            auto globalObjectImmPtr = TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic));
-            switch (node->op()) {
-            case AtomicsAdd:
-                callOperation(operationAtomicsAdd, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            case AtomicsAnd:
-                callOperation(operationAtomicsAnd, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            case AtomicsCompareExchange:
-                callOperation(operationAtomicsCompareExchange, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
-                break;
-            case AtomicsExchange:
-                callOperation(operationAtomicsExchange, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            case AtomicsLoad:
-                callOperation(operationAtomicsLoad, resultGPR, globalObjectImmPtr, baseGPR, indexGPR);
-                break;
-            case AtomicsOr:
-                callOperation(operationAtomicsOr, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            case AtomicsStore:
-                callOperation(operationAtomicsStore, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            case AtomicsSub:
-                callOperation(operationAtomicsSub, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            case AtomicsXor:
-                callOperation(operationAtomicsXor, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            }
-        };
-        
         if (!storageEdge) {
+            auto callSlowPath = [&] () {
+                auto globalObjectImmPtr = TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic));
+                switch (node->op()) {
+                case AtomicsAdd:
+                    callOperation(operationAtomicsAdd, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                case AtomicsAnd:
+                    callOperation(operationAtomicsAnd, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                case AtomicsCompareExchange:
+                    callOperation(operationAtomicsCompareExchange, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
+                    break;
+                case AtomicsExchange:
+                    callOperation(operationAtomicsExchange, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                case AtomicsLoad:
+                    callOperation(operationAtomicsLoad, resultGPR, globalObjectImmPtr, baseGPR, indexGPR);
+                    break;
+                case AtomicsOr:
+                    callOperation(operationAtomicsOr, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                case AtomicsStore:
+                    callOperation(operationAtomicsStore, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                case AtomicsSub:
+                    callOperation(operationAtomicsSub, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                case AtomicsXor:
+                    callOperation(operationAtomicsXor, resultGPR, globalObjectImmPtr, baseGPR, indexGPR, argGPRs[0]);
+                    break;
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                    break;
+                }
+            };
+
             // We are in generic mode!
             JSValueOperand base(this, baseEdge);
             JSValueOperand index(this, indexEdge);
@@ -3313,11 +3313,9 @@
         
         GPRTemporary args[2];
         
-        JITCompiler::JumpList slowPathCases;
-        
         bool ok = true;
         for (unsigned i = numExtraArgs; i--;) {
-            if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
+            if (!getIntTypedArrayStoreOperandForAtomics(args[i], indexGPR, argEdges[i])) {
                 noResult(node);
                 ok = false;
             }
@@ -3417,21 +3415,26 @@
         }
         m_jit.jump().linkTo(loop, &m_jit);
         
-        if (!slowPathCases.empty()) {
-            slowPathCases.link(&m_jit);
-            silentSpillAllRegisters(resultGPR);
-            // Since we spilled, we can do things to registers.
-            m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
-            m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
-            for (unsigned i = numExtraArgs; i--;)
-                m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
-            callSlowPath();
-            silentFillAllRegisters();
-            m_jit.exceptionCheck();
+        success.link(&m_jit);
+
+        if (node->op() == AtomicsStore) {
+            Edge operand = argEdges[0];
+            switch (operand.useKind()) {
+            case Int32Use:
+                m_jit.zeroExtend32ToWord(resultGPR, resultGPR);
+                strictInt32Result(resultGPR, node);
+                break;
+            case Int52RepUse:
+                strictInt52Result(resultGPR, node);
+                break;
+            default:
+                DFG_CRASH(m_graph, node, "Bad result type");
+                break;
+            }
+            break;
         }
-        
-        success.link(&m_jit);
-        setIntTypedArrayLoadResult(node, resultGPR, type);
+        constexpr bool canSpeculate = false;
+        setIntTypedArrayLoadResult(node, resultGPR, type, canSpeculate);
         break;
     }
         

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (272404 => 272405)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-02-05 07:40:33 UTC (rev 272404)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-02-05 08:45:09 UTC (rev 272405)
@@ -4275,7 +4275,27 @@
 
         // We have to keep base alive since that keeps storage alive.
         ensureStillAliveHere(lowCell(baseEdge));
-        setIntTypedArrayLoadResult(result, type);
+
+        if (m_node->op() == AtomicsStore) {
+            Edge operand = argEdges[0];
+            switch (operand.useKind()) {
+            case Int32Use:
+                setInt32(lowInt32(operand));
+                break;
+            case Int52RepUse:
+                setStrictInt52(lowStrictInt52(operand));
+                break;
+            case DoubleRepUse:
+                setDouble(toIntegerOrInfinity(lowDouble(operand)));
+                break;
+            default:
+                DFG_CRASH(m_graph, m_node, "Bad result type");
+                break;
+            }
+            return;
+        }
+        constexpr bool canSpeculate = false;
+        setIntTypedArrayLoadResult(result, type, canSpeculate);
     }
     
     void compileAtomicsIsLockFree()
@@ -5247,7 +5267,7 @@
                     LValue result = loadFromIntTypedArray(pointer, type);
                     // We have to keep base alive since that keeps storage alive.
                     ensureStillAliveHere(base);
-                    bool canSpeculate = true;
+                    constexpr bool canSpeculate = true;
                     setIntTypedArrayLoadResult(result, type, canSpeculate);
                     return;
                 }
@@ -16892,7 +16912,7 @@
         }
     }
     
-    void setIntTypedArrayLoadResult(LValue result, TypedArrayType type, bool canSpeculate = false)
+    void setIntTypedArrayLoadResult(LValue result, TypedArrayType type, bool canSpeculate)
     {
         if (elementSize(type) < 4 || isSigned(type)) {
             setInt32(result);
@@ -19634,6 +19654,14 @@
         return m_out.addPtr(immutableButterfly, JSImmutableButterfly::offsetOfData());
     }
 
+    LValue toIntegerOrInfinity(LValue doubleValue)
+    {
+        // https://tc39.es/ecma262/#sec-tointegerorinfinity
+        // 1. If value is either of +0, -0, or NaN, return +0
+        // 2. Otherwise, return trunc(value)
+        return m_out.select(m_out.doubleNotEqualAndOrdered(doubleValue, m_out.doubleZero), m_out.doubleTrunc(doubleValue), m_out.doubleZero);
+    }
+
     void addWeakReference(JSCell* target)
     {
         m_graph.m_plan.weakReferences().addLazily(target);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to