Modified: trunk/JSTests/ChangeLog (282211 => 282212)
--- trunk/JSTests/ChangeLog 2021-09-09 13:59:41 UTC (rev 282211)
+++ trunk/JSTests/ChangeLog 2021-09-09 15:30:01 UTC (rev 282212)
@@ -1,3 +1,24 @@
+2021-09-09 Justin Michaud <[email protected]>
+
+ Differential testing: incorrect constant propagation around Uint8ClampedArray
+ https://bugs.webkit.org/show_bug.cgi?id=229869
+
+ Reviewed by Saam Barati.
+
+ * stress/Uint8ClampedArrayClampsInt52Positive.js: Added.
+ (let.x.123.test):
+ (noInline.test.int32pos1):
+ (255.int32pos2):
+ (1.int32neg1):
+ (0.int32neg2):
+ (0.int52pos1):
+ (255.int52pos2):
+ (255.int52neg1):
+ (0.int52neg2):
+ (0.int52neg3):
+ (0.int52pos3):
+ (255.int8):
+
2021-09-09 Robin Morisset <[email protected]>
Optimize compareStrictEq when neither side is a double and at least one is not a BigInt
Added: trunk/JSTests/stress/Uint8ClampedArrayClampsInt52Positive.js (0 => 282212)
--- trunk/JSTests/stress/Uint8ClampedArrayClampsInt52Positive.js (rev 0)
+++ trunk/JSTests/stress/Uint8ClampedArrayClampsInt52Positive.js 2021-09-09 15:30:01 UTC (rev 282212)
@@ -0,0 +1,79 @@
+let x = 123
+
+function test(fn, expected) {
+ for (let i = 0; i < 10000; i++) {
+ const arr = new Uint8ClampedArray(1)
+ fn(arr)
+ x = arr[0]
+ }
+
+ if (x != expected)
+ throw new Error(`Clamping was done incorrectly ${x}, expected ${expected} in ${fn}`)
+}
+noInline(test)
+
+function int32pos1(arr) {
+ arr[0] = 0x70000001|0
+}
+noInline(int32pos1)
+test(int32pos1, 255)
+
+function int32pos2(arr) {
+ arr[0] = 0x800000001|0
+}
+noInline(int32pos2)
+test(int32pos2, 1)
+
+function int32neg1(arr) {
+ arr[0] = 0x80000001|0
+}
+noInline(int32neg1)
+test(int32neg1, 0)
+
+function int32neg2(arr) {
+ arr[0] = 0x80000000|0
+}
+noInline(int32neg2)
+test(int32neg2, 0)
+
+function int52pos1(arr) {
+ arr[0] = 0x80000001
+}
+noInline(int52pos1)
+test(int52pos1, 255)
+
+function int52pos2(arr) {
+ arr[0] = 0x80000000
+}
+noInline(int52pos2)
+test(int52pos2, 255)
+
+function int52neg1(arr) {
+ arr[0] = -0x80000001
+}
+noInline(int52neg1)
+test(int52neg1, 0)
+
+function int52neg2(arr) {
+ arr[0] = -0x80000000
+}
+noInline(int52neg2)
+test(int52neg2, 0)
+
+function int52neg3(arr) {
+ arr[0] = -0x0008_0000_0000_0000
+}
+noInline(int52neg3)
+test(int52neg3, 0)
+
+function int52pos3(arr) {
+ arr[0] = 0x0007_FFFF_FFFF_FFFF
+}
+noInline(int52pos3)
+test(int52pos3, 255)
+
+function int8(arr) {
+ arr[0] = 0x8000000fe - 0x800000000
+}
+noInline(int8)
+test(int8, 254)
\ No newline at end of file
Modified: trunk/Source/_javascript_Core/ChangeLog (282211 => 282212)
--- trunk/Source/_javascript_Core/ChangeLog 2021-09-09 13:59:41 UTC (rev 282211)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-09-09 15:30:01 UTC (rev 282212)
@@ -1,3 +1,16 @@
+2021-09-09 Justin Michaud <[email protected]>
+
+ Differential testing: incorrect constant propagation around Uint8ClampedArray
+ https://bugs.webkit.org/show_bug.cgi?id=229869
+
+ We casted int52 values to int32 before clamping, which caused any value with the 32nd bit
+ set to be interpreted as negative. The fix is to check the full-size value when deciding to clamp.
+
+ Reviewed by Saam Barati.
+
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+
2021-09-09 Robin Morisset <[email protected]>
Optimize compareStrictEq when neither side is a double and at least one is not a BigInt
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (282211 => 282212)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2021-09-09 13:59:41 UTC (rev 282211)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2021-09-09 15:30:01 UTC (rev 282212)
@@ -17797,15 +17797,26 @@
LValue getIntTypedArrayStoreOperand(Edge edge, bool isClamped = false)
{
- LValue intValue;
+ LValue valueAsInt32;
+ LValue value;
+ LValue zero;
+ LValue byteMax;
+
switch (edge.useKind()) {
case Int52RepUse:
case Int32Use: {
- if (edge.useKind() == Int32Use)
- intValue = lowInt32(edge);
- else
- intValue = m_out.castToInt32(lowStrictInt52(edge));
-
+ if (edge.useKind() == Int32Use) {
+ value = lowInt32(edge);
+ valueAsInt32 = value;
+ zero = m_out.int32Zero;
+ byteMax = m_out.constInt32(255);
+ } else {
+ value = lowStrictInt52(edge);
+ valueAsInt32 = m_out.castToInt32(value);
+ zero = m_out.int64Zero;
+ byteMax = m_out.constInt64(255);
+ }
+
if (isClamped) {
LBasicBlock atLeastZero = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();
@@ -17813,19 +17824,19 @@
Vector<ValueFromBlock, 2> intValues;
intValues.append(m_out.anchor(m_out.int32Zero));
m_out.branch(
- m_out.lessThan(intValue, m_out.int32Zero),
+ m_out.lessThan(value, zero),
unsure(continuation), unsure(atLeastZero));
LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
intValues.append(m_out.anchor(m_out.select(
- m_out.greaterThan(intValue, m_out.constInt32(255)),
+ m_out.greaterThan(value, byteMax),
m_out.constInt32(255),
- intValue)));
+ valueAsInt32)));
m_out.jump(continuation);
m_out.appendTo(continuation, lastNext);
- intValue = m_out.phi(Int32, intValues);
+ valueAsInt32 = m_out.phi(Int32, intValues);
}
break;
}
@@ -17855,9 +17866,9 @@
m_out.jump(continuation);
m_out.appendTo(continuation, lastNext);
- intValue = m_out.phi(Int32, intValues);
+ valueAsInt32 = m_out.phi(Int32, intValues);
} else
- intValue = doubleToInt32(doubleValue);
+ valueAsInt32 = doubleToInt32(doubleValue);
break;
}
@@ -17865,7 +17876,7 @@
DFG_CRASH(m_graph, m_node, "Bad use kind");
}
- return intValue;
+ return valueAsInt32;
}
LValue doubleToInt32(LValue doubleValue, double low, double high, bool isSigned = true)