[turbofan] Generalize optimization on CallWithArrayLike when target is Math.min/max
With this change, ReduceJSCallMathMinMaxWithArrayLike will work on both PACKED_DOUBLE_ELEMENTS and HOLEY_DOUBLE_ELEMETNS kind. It will also work when the opcode of arguments_list is JSCreateEmptyLiteralArray to deal with following use cases. var array = []; array.push(num1); // add elements array.push(num2); console.log(Math.min.apply(Math, array)); Change-Id: I39840a17607c31baea2c6b1d33218700f723d760 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4007927 Commit-Queue: Fanchen Kong <fanchen.kong@intel.com> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#84079}
This commit is contained in:
parent
1d28608ec0
commit
f8e7c7ad7a
@ -398,6 +398,12 @@ TNode<Number> JSGraphAssembler::NumberBitwiseAnd(TNode<Number> lhs,
|
||||
graph()->NewNode(simplified()->NumberBitwiseAnd(), lhs, rhs));
|
||||
}
|
||||
|
||||
TNode<Number> JSGraphAssembler::NumberBitwiseOr(TNode<Number> lhs,
|
||||
TNode<Number> rhs) {
|
||||
return AddNode<Number>(
|
||||
graph()->NewNode(simplified()->NumberBitwiseOr(), lhs, rhs));
|
||||
}
|
||||
|
||||
TNode<String> JSGraphAssembler::StringSubstring(TNode<String> string,
|
||||
TNode<Number> from,
|
||||
TNode<Number> to) {
|
||||
|
@ -1008,6 +1008,7 @@ class V8_EXPORT_PRIVATE JSGraphAssembler : public GraphAssembler {
|
||||
TNode<Number> NumberSubtract(TNode<Number> lhs, TNode<Number> rhs);
|
||||
TNode<Number> NumberShiftRightLogical(TNode<Number> lhs, TNode<Number> rhs);
|
||||
TNode<Number> NumberBitwiseAnd(TNode<Number> lhs, TNode<Number> rhs);
|
||||
TNode<Number> NumberBitwiseOr(TNode<Number> lhs, TNode<Number> rhs);
|
||||
TNode<Number> NumberDivide(TNode<Number> lhs, TNode<Number> rhs);
|
||||
TNode<Number> NumberFloor(TNode<Number> value);
|
||||
TNode<String> StringSubstring(TNode<String> string, TNode<Number> from,
|
||||
|
@ -1077,12 +1077,17 @@ TNode<Object> JSCallReducerAssembler::ReduceJSCallMathMinMaxWithArrayLike(
|
||||
NumberEqual(arguments_list_instance_type, NumberConstant(JS_ARRAY_TYPE));
|
||||
GotoIfNot(check_instance_type, &call_builtin);
|
||||
|
||||
// Check if {arguments_list} has PACKED_DOUBLE_ELEMENTS.
|
||||
// Check if {arguments_list} has PACKED_DOUBLE_ELEMENTS or
|
||||
// HOLEY_DOUBLE_ELEMENTS.
|
||||
TNode<Number> arguments_list_elements_kind =
|
||||
LoadMapElementsKind(arguments_list_map);
|
||||
auto check_element_kind = NumberEqual(arguments_list_elements_kind,
|
||||
NumberConstant(PACKED_DOUBLE_ELEMENTS));
|
||||
GotoIfNot(check_element_kind, &call_builtin);
|
||||
|
||||
static_assert(PACKED_DOUBLE_ELEMENTS == 4);
|
||||
static_assert(HOLEY_DOUBLE_ELEMENTS == 5);
|
||||
auto check_elements_kind = NumberEqual(
|
||||
NumberBitwiseOr(arguments_list_elements_kind, NumberConstant(1)),
|
||||
NumberConstant(HOLEY_DOUBLE_ELEMENTS));
|
||||
GotoIfNot(check_elements_kind, &call_builtin);
|
||||
|
||||
// If {arguments_list} is a JSArray with PACKED_DOUBLE_ELEMENTS, calculate the
|
||||
// result with inlined loop.
|
||||
@ -8345,10 +8350,15 @@ base::Optional<Reduction> JSCallReducer::TryReduceJSCallMathMinMaxWithArrayLike(
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
if (!dependencies()->DependOnNoElementsProtector()) {
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
// These ops are handled by ReduceCallOrConstructWithArrayLikeOrSpread.
|
||||
// IrOpcode::kJSCreateEmptyLiteralArray is not included, since arguments_list
|
||||
// for Math.min/min is not likely to keep empty.
|
||||
Node* arguments_list = n.Argument(0);
|
||||
if (arguments_list->opcode() == IrOpcode::kJSCreateLiteralArray ||
|
||||
arguments_list->opcode() == IrOpcode::kJSCreateEmptyLiteralArray ||
|
||||
arguments_list->opcode() == IrOpcode::kJSCreateArguments) {
|
||||
return base::nullopt;
|
||||
}
|
||||
|
@ -248,6 +248,34 @@
|
||||
|
||||
})();
|
||||
|
||||
// Test with holey double array and Math.min/max.
|
||||
(function () {
|
||||
"use strict";
|
||||
function arrayMin(val) {
|
||||
return Math.min.apply(Math, val);
|
||||
}
|
||||
function arrayMax(val) {
|
||||
return Math.max.apply(Math, val);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(arrayMin);
|
||||
%PrepareFunctionForOptimization(arrayMin);
|
||||
assertEquals(NaN, arrayMin([11.03, 16.11, , 26.06]));
|
||||
|
||||
%PrepareFunctionForOptimization(arrayMax);
|
||||
%PrepareFunctionForOptimization(arrayMax);
|
||||
assertEquals(NaN, arrayMax([11.03, 16.11, , 26.06]));
|
||||
%OptimizeFunctionOnNextCall(arrayMin);
|
||||
%OptimizeFunctionOnNextCall(arrayMax);
|
||||
|
||||
assertEquals(NaN, arrayMin([11.03, 16.11, , 26.06]));
|
||||
assertEquals(NaN, arrayMax([11.03, 16.11, , 26.06]));
|
||||
|
||||
assertOptimized(arrayMin);
|
||||
assertOptimized(arrayMax);
|
||||
|
||||
})();
|
||||
|
||||
// Test Reflect.apply().
|
||||
(function () {
|
||||
"use strict";
|
||||
|
Loading…
Reference in New Issue
Block a user