diff --git a/JSTests/stress/array-sort-inline-int32-double-comparator.js b/JSTests/stress/array-sort-inline-int32-double-comparator.js new file mode 100644 index 000000000000..583f227c9871 --- /dev/null +++ b/JSTests/stress/array-sort-inline-int32-double-comparator.js @@ -0,0 +1,14 @@ +function shouldBe(actual, expected) { + if (actual !== expected) + throw new Error("bad value: " + actual + " expected: " + expected); +} + +// Double arithmetic on the comparator's first parameter must not make the inlined sort store its pivot +// back into the Int32 array as a double. +function test(a, b, c, d) { + return [a, b, c, d].sort((x, y) => (x + 0.5) - (y + 0.5)); +} +noInline(test); + +for (var i = 0; i < testLoopCount; ++i) + shouldBe(test(17, 8, 1, 1).join(), "1,1,8,17"); diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index 497043256389..95fde70338e5 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -932,6 +932,16 @@ class PredictionPropagationPhase : public Phase { break; } + case PutCellButterflySlot: { + // The inlined sort reads the scratch of an Int32 array back with no check, and ArraySortCommit + // copies it into the array as is. A pivot in the double format would be stored as a boxed double. + m_graph.voteChildren(node, VoteValue, weight); + Node* value = node->child3().node(); + if (value->op() == GetLocal) + value->variableAccessData()->mergeDoubleFormatState(CantUseDoubleFormat); + break; + } + case DataViewSet: { DataViewData data = node->dataViewData(); if (data.isFloatingPoint)