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:
Nico Hartmann 2020-05-28 13:44:41 +02:00 committed by Commit Bot
parent 120d433345
commit fd5cc8837a
2 changed files with 27 additions and 1 deletions

View File

@ -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();
} }

View 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);