Fix feedback loss when builtins throw
In BinaryOpAssembler::Generate_BinaryOperationWithFeedback, the feedback is stored only after the respective builtin/runtime call. If this call throws an exception, the feedback is lost, leading to a deopt loop in some cases. This CL fixes that issue by writing the gathered feedback before passing control to the builtin. Bug: chromium:1077197, v8:9441 Change-Id: I20e4b14815520224e2c6f8af1af6a89f754ccddf Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2202904 Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Mythri Alle <mythria@chromium.org> Auto-Submit: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/master@{#68038}
This commit is contained in:
parent
120d433345
commit
fd5cc8837a
@ -279,6 +279,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
|
|||||||
{
|
{
|
||||||
Comment("perform smi operation");
|
Comment("perform smi operation");
|
||||||
var_result = smiOperation(lhs_smi, CAST(rhs), &var_type_feedback);
|
var_result = smiOperation(lhs_smi, CAST(rhs), &var_type_feedback);
|
||||||
|
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
|
||||||
Goto(&end);
|
Goto(&end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,6 +322,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
|
|||||||
BIND(&do_float_operation);
|
BIND(&do_float_operation);
|
||||||
{
|
{
|
||||||
var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
|
var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
|
||||||
|
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
|
||||||
TNode<Float64T> lhs_value = var_float_lhs.value();
|
TNode<Float64T> lhs_value = var_float_lhs.value();
|
||||||
TNode<Float64T> rhs_value = var_float_rhs.value();
|
TNode<Float64T> rhs_value = var_float_rhs.value();
|
||||||
TNode<Float64T> value = floatOperation(lhs_value, rhs_value);
|
TNode<Float64T> value = floatOperation(lhs_value, rhs_value);
|
||||||
@ -384,6 +386,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
|
|||||||
BIND(&if_both_bigint);
|
BIND(&if_both_bigint);
|
||||||
{
|
{
|
||||||
var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
|
var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
|
||||||
|
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
|
||||||
if (op == Operation::kSubtract) {
|
if (op == Operation::kSubtract) {
|
||||||
Label bigint_too_big(this);
|
Label bigint_too_big(this);
|
||||||
var_result =
|
var_result =
|
||||||
@ -415,6 +418,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
|
|||||||
|
|
||||||
BIND(&call_stub);
|
BIND(&call_stub);
|
||||||
{
|
{
|
||||||
|
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
|
||||||
TNode<Object> result;
|
TNode<Object> result;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Operation::kSubtract:
|
case Operation::kSubtract:
|
||||||
@ -437,7 +441,6 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
BIND(&end);
|
BIND(&end);
|
||||||
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
|
|
||||||
return var_result.value();
|
return var_result.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
test/mjsunit/regress/regress-9441.js
Normal file
23
test/mjsunit/regress/regress-9441.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2020 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --allow-natives-syntax --opt --no-always-opt
|
||||||
|
|
||||||
|
function foo(a, b) {
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
%PrepareFunctionForOptimization(foo);
|
||||||
|
assertEquals(-1n, foo(1n, 2n));
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
assertEquals(1n, foo(2n, 1n));
|
||||||
|
assertOptimized(foo);
|
||||||
|
assertThrows(() => foo(2n, undefined));
|
||||||
|
assertUnoptimized(foo);
|
||||||
|
%PrepareFunctionForOptimization(foo);
|
||||||
|
%OptimizeFunctionOnNextCall(foo);
|
||||||
|
assertEquals(-1n, foo(1n, 2n));
|
||||||
|
assertOptimized(foo);
|
||||||
|
assertThrows(() => foo(undefined, 2n));
|
||||||
|
assertOptimized(foo);
|
Loading…
Reference in New Issue
Block a user