Title: [254716] trunk
Revision
254716
Author
[email protected]
Date
2020-01-16 15:53:19 -0800 (Thu, 16 Jan 2020)

Log Message

Teach the bytecode that arithmetic operations can return bigints
https://bugs.webkit.org/show_bug.cgi?id=205416

Reviewed by Yusuke Suzuki.

JSTests:

This file crashes in debug mode without the fix.

* stress/big-int-arithmetic-return-big-int.js: Added.
(fooAdd):
(fooSub):
(fooMul):
(fooDiv):

Source/_javascript_Core:

Add already has the correct ResultType, but previously Sub/Mult/Div/Mod/Pow/Negate were always claimed to return Number,
and when BigInt is enabled they can also return BigInt.
UnaryPlus is left unchanged as it is invalid on a BigInt (to keep asm.js working as intended).

* parser/NodeConstructors.h:
(JSC::NegateNode::NegateNode):
(JSC::PowNode::PowNode):
(JSC::MultNode::MultNode):
(JSC::DivNode::DivNode):
(JSC::ModNode::ModNode):
(JSC::SubNode::SubNode):
* parser/ResultType.h:
(JSC::ResultType::bigIntOrNumberType): Added.
(JSC::ResultType::forNonAddArith):
(JSC::ResultType::forUnaryArith):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (254715 => 254716)


--- trunk/JSTests/ChangeLog	2020-01-16 23:26:10 UTC (rev 254715)
+++ trunk/JSTests/ChangeLog	2020-01-16 23:53:19 UTC (rev 254716)
@@ -1,3 +1,18 @@
+2020-01-16  Robin Morisset  <[email protected]>
+
+        Teach the bytecode that arithmetic operations can return bigints
+        https://bugs.webkit.org/show_bug.cgi?id=205416
+
+        Reviewed by Yusuke Suzuki.
+
+        This file crashes in debug mode without the fix.
+
+        * stress/big-int-arithmetic-return-big-int.js: Added.
+        (fooAdd):
+        (fooSub):
+        (fooMul):
+        (fooDiv):
+
 2020-01-16  Mark Lam  <[email protected]>
 
         operationToObject() should check for a null errorMessage.

Added: trunk/JSTests/stress/big-int-arithmetic-return-big-int.js (0 => 254716)


--- trunk/JSTests/stress/big-int-arithmetic-return-big-int.js	                        (rev 0)
+++ trunk/JSTests/stress/big-int-arithmetic-return-big-int.js	2020-01-16 23:53:19 UTC (rev 254716)
@@ -0,0 +1,33 @@
+//@ runBigIntEnabled
+
+function fooAdd()
+{
+    return (1n+1n) / 1;
+}
+function fooSub()
+{
+    return (1n-1n) / 1;
+}
+function fooMul()
+{
+    return (1n*1n) / 1;
+}
+function fooDiv()
+{
+    return (1n/1n) / 1;
+}
+
+for (var i = 0; i < 10000 ; ++i) {
+    try {
+        fooAdd()
+    } catch {}
+    try {
+        fooSub()
+    } catch {}
+    try {
+        fooMul()
+    } catch {}
+    try {
+        fooDiv()
+    } catch {}
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (254715 => 254716)


--- trunk/Source/_javascript_Core/ChangeLog	2020-01-16 23:26:10 UTC (rev 254715)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-01-16 23:53:19 UTC (rev 254716)
@@ -1,5 +1,28 @@
 2020-01-16  Robin Morisset  <[email protected]>
 
+        Teach the bytecode that arithmetic operations can return bigints
+        https://bugs.webkit.org/show_bug.cgi?id=205416
+
+        Reviewed by Yusuke Suzuki.
+
+        Add already has the correct ResultType, but previously Sub/Mult/Div/Mod/Pow/Negate were always claimed to return Number,
+        and when BigInt is enabled they can also return BigInt.
+        UnaryPlus is left unchanged as it is invalid on a BigInt (to keep asm.js working as intended).
+
+        * parser/NodeConstructors.h:
+        (JSC::NegateNode::NegateNode):
+        (JSC::PowNode::PowNode):
+        (JSC::MultNode::MultNode):
+        (JSC::DivNode::DivNode):
+        (JSC::ModNode::ModNode):
+        (JSC::SubNode::SubNode):
+        * parser/ResultType.h:
+        (JSC::ResultType::bigIntOrNumberType): Added.
+        (JSC::ResultType::forNonAddArith):
+        (JSC::ResultType::forUnaryArith):
+
+2020-01-16  Robin Morisset  <[email protected]>
+
         Use dataLogIf more regularly
         https://bugs.webkit.org/show_bug.cgi?id=206332
 

Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (254715 => 254716)


--- trunk/Source/_javascript_Core/parser/NodeConstructors.h	2020-01-16 23:26:10 UTC (rev 254715)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h	2020-01-16 23:53:19 UTC (rev 254716)
@@ -516,6 +516,8 @@
     {
     }
 
+    // UnaryPlus is guaranteed to always return a number, never a BigInt.
+    // See https://tc39.es/ecma262/#sec-unary-plus-operator-runtime-semantics-evaluation
     inline UnaryPlusNode::UnaryPlusNode(const JSTokenLocation& location, ExpressionNode* expr)
         : UnaryOpNode(location, ResultType::numberType(), expr, op_to_number)
     {
@@ -522,7 +524,7 @@
     }
 
     inline NegateNode::NegateNode(const JSTokenLocation& location, ExpressionNode* expr)
-        : UnaryOpNode(location, ResultType::numberType(), expr, op_negate)
+        : UnaryOpNode(location, ResultType::forUnaryArith(expr->resultDescriptor()), expr, op_negate)
     {
     }
 
@@ -555,23 +557,23 @@
     }
 
     inline PowNode::PowNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_pow, rightHasAssignments)
+        : BinaryOpNode(location, ResultType::forNonAddArith(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_pow, rightHasAssignments)
     {
     }
 
     inline MultNode::MultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments)
+        : BinaryOpNode(location, ResultType::forNonAddArith(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_mul, rightHasAssignments)
     {
     }
 
     inline DivNode::DivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_div, rightHasAssignments)
+        : BinaryOpNode(location, ResultType::forNonAddArith(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_div, rightHasAssignments)
     {
     }
 
 
     inline ModNode::ModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_mod, rightHasAssignments)
+        : BinaryOpNode(location, ResultType::forNonAddArith(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_mod, rightHasAssignments)
     {
     }
 
@@ -581,7 +583,7 @@
     }
 
     inline SubNode::SubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_sub, rightHasAssignments)
+        : BinaryOpNode(location, ResultType::forNonAddArith(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_sub, rightHasAssignments)
     {
     }
 

Modified: trunk/Source/_javascript_Core/parser/ResultType.h (254715 => 254716)


--- trunk/Source/_javascript_Core/parser/ResultType.h	2020-01-16 23:26:10 UTC (rev 254715)
+++ trunk/Source/_javascript_Core/parser/ResultType.h	2020-01-16 23:53:19 UTC (rev 254716)
@@ -157,6 +157,11 @@
             return ResultType(TypeMaybeBigInt | TypeInt32 | TypeMaybeNumber);
         }
 
+        static constexpr ResultType bigIntOrNumberType()
+        {
+            return ResultType(TypeMaybeBigInt | TypeMaybeNumber);
+        }
+
         static constexpr ResultType unknownType()
         {
             return ResultType(TypeBits);
@@ -173,6 +178,24 @@
             return addResultType();
         }
 
+        static constexpr ResultType forNonAddArith(ResultType op1, ResultType op2)
+        {
+            if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
+                return numberType();
+            if (op1.definitelyIsBigInt() && op2.definitelyIsBigInt())
+                return bigIntType();
+            return bigIntOrNumberType();
+        }
+
+        static constexpr ResultType forUnaryArith(ResultType op)
+        {
+            if (op.definitelyIsNumber())
+                return numberType();
+            if (op.definitelyIsBigInt())
+                return bigIntType();
+            return bigIntOrNumberType();
+        }
+
         // Unlike in C, a logical op produces the value of the
         // last _expression_ evaluated (and not true or false).
         static constexpr ResultType forLogicalOp(ResultType op1, ResultType op2)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to