Commit 779540c6 authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

Move feedback for BigIntTooBig from deoptimizer to interpreter

Feedback shall not be updated by the deoptimizer. Although this
mechanism exists, it shall not be used if possible. This CL changes
how V8 learns from BigInt deopts: Previously we updated feedback on
the BinaryOperations in the deoptimizer, now we let the interpreter
widen the feedback type from BigInt to Any after the deopt has occurred.

Bug: v8:9407
Change-Id: I92e5e733085b433fd8ab452674d02404b81b2796
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1687419Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@google.com>
Cr-Commit-Position: refs/heads/master@{#62548}
parent 7e0f961e
...@@ -4217,7 +4217,6 @@ Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) { ...@@ -4217,7 +4217,6 @@ Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
Node* EffectControlLinearizer::LowerSpeculativeBigIntAdd(Node* node, Node* EffectControlLinearizer::LowerSpeculativeBigIntAdd(Node* node,
Node* frame_state) { Node* frame_state) {
const auto& p = BigIntOperationParametersOf(node->op());
Node* lhs = node->InputAt(0); Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1); Node* rhs = node->InputAt(1);
...@@ -4232,7 +4231,7 @@ Node* EffectControlLinearizer::LowerSpeculativeBigIntAdd(Node* node, ...@@ -4232,7 +4231,7 @@ Node* EffectControlLinearizer::LowerSpeculativeBigIntAdd(Node* node,
rhs, __ NoContextConstant()); rhs, __ NoContextConstant());
// Check for exception sentinel: Smi is returned to signal BigIntTooBig. // Check for exception sentinel: Smi is returned to signal BigIntTooBig.
__ DeoptimizeIf(DeoptimizeReason::kBigIntTooBig, p.feedback(), __ DeoptimizeIf(DeoptimizeReason::kBigIntTooBig, VectorSlotPair{},
ObjectIsSmi(value), frame_state); ObjectIsSmi(value), frame_state);
return value; return value;
......
...@@ -162,11 +162,10 @@ class JSSpeculativeBinopBuilder final { ...@@ -162,11 +162,10 @@ class JSSpeculativeBinopBuilder final {
UNREACHABLE(); UNREACHABLE();
} }
const Operator* SpeculativeBigIntOp(BigIntOperationHint hint, const Operator* SpeculativeBigIntOp(BigIntOperationHint hint) {
const VectorSlotPair& feedback) {
switch (op_->opcode()) { switch (op_->opcode()) {
case IrOpcode::kJSAdd: case IrOpcode::kJSAdd:
return simplified()->SpeculativeBigIntAdd(hint, feedback); return simplified()->SpeculativeBigIntAdd(hint);
default: default:
break; break;
} }
...@@ -217,9 +216,7 @@ class JSSpeculativeBinopBuilder final { ...@@ -217,9 +216,7 @@ class JSSpeculativeBinopBuilder final {
Node* TryBuildBigIntBinop() { Node* TryBuildBigIntBinop() {
BigIntOperationHint hint; BigIntOperationHint hint;
if (GetBinaryBigIntOperationHint(&hint)) { if (GetBinaryBigIntOperationHint(&hint)) {
FeedbackNexus nexus{feedback_vector(), slot_}; const Operator* op = SpeculativeBigIntOp(hint);
VectorSlotPair feedback{feedback_vector(), slot_, nexus.ic_state()};
const Operator* op = SpeculativeBigIntOp(hint, feedback);
Node* node = BuildSpeculativeOperation(op); Node* node = BuildSpeculativeOperation(op);
return node; return node;
} }
......
...@@ -2642,8 +2642,8 @@ class RepresentationSelector { ...@@ -2642,8 +2642,8 @@ class RepresentationSelector {
return; return;
} }
case IrOpcode::kSpeculativeBigIntAdd: { case IrOpcode::kSpeculativeBigIntAdd: {
const auto& p = BigIntOperationParametersOf(node->op()); VisitBinop(node,
VisitBinop(node, UseInfo::CheckedBigIntAsTaggedPointer(p.feedback()), UseInfo::CheckedBigIntAsTaggedPointer(VectorSlotPair{}),
MachineRepresentation::kTaggedPointer); MachineRepresentation::kTaggedPointer);
return; return;
} }
......
...@@ -504,25 +504,6 @@ size_t hash_value(BigIntOperationHint hint) { ...@@ -504,25 +504,6 @@ size_t hash_value(BigIntOperationHint hint) {
return static_cast<uint8_t>(hint); return static_cast<uint8_t>(hint);
} }
bool operator==(const BigIntOperationParameters& lhs,
const BigIntOperationParameters& rhs) {
return lhs.hint() == rhs.hint() && lhs.feedback() == rhs.feedback();
}
size_t hash_value(const BigIntOperationParameters& p) {
return base::hash_combine(p.hint(), p.feedback());
}
std::ostream& operator<<(std::ostream& os, const BigIntOperationParameters& p) {
return os << p.hint() << " " << p.feedback();
}
const BigIntOperationParameters& BigIntOperationParametersOf(
const Operator* op) {
DCHECK_EQ(IrOpcode::kSpeculativeBigIntAdd, op->opcode());
return OpParameter<BigIntOperationParameters>(op);
}
std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) { std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
switch (hint) { switch (hint) {
case NumberOperationHint::kSignedSmall: case NumberOperationHint::kSignedSmall:
...@@ -1446,11 +1427,10 @@ const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole( ...@@ -1446,11 +1427,10 @@ const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
} }
const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAdd( const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAdd(
BigIntOperationHint hint, const VectorSlotPair& feedback) { BigIntOperationHint hint) {
return new (zone()) Operator1<BigIntOperationParameters>( return new (zone()) Operator1<BigIntOperationHint>(
IrOpcode::kSpeculativeBigIntAdd, Operator::kFoldable | Operator::kNoThrow, IrOpcode::kSpeculativeBigIntAdd, Operator::kFoldable | Operator::kNoThrow,
"SpeculativeBigIntAdd", 2, 1, 1, 1, 1, 0, "SpeculativeBigIntAdd", 2, 1, 1, 1, 1, 0, hint);
BigIntOperationParameters{hint, feedback});
} }
const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber( const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
......
...@@ -487,28 +487,6 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BigIntOperationHint); ...@@ -487,28 +487,6 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BigIntOperationHint);
V8_EXPORT_PRIVATE NumberOperationHint NumberOperationHintOf(const Operator* op) V8_EXPORT_PRIVATE NumberOperationHint NumberOperationHintOf(const Operator* op)
V8_WARN_UNUSED_RESULT; V8_WARN_UNUSED_RESULT;
class BigIntOperationParameters {
public:
BigIntOperationParameters(BigIntOperationHint hint,
const VectorSlotPair& feedback)
: hint_(hint), feedback_(feedback) {}
BigIntOperationHint hint() const { return hint_; }
const VectorSlotPair& feedback() const { return feedback_; }
private:
BigIntOperationHint hint_;
VectorSlotPair feedback_;
};
size_t hash_value(const BigIntOperationParameters&);
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
const BigIntOperationParameters&);
bool operator==(const BigIntOperationParameters& lhs,
const BigIntOperationParameters& rhs);
const BigIntOperationParameters& BigIntOperationParametersOf(const Operator* op)
V8_WARN_UNUSED_RESULT;
class NumberOperationParameters { class NumberOperationParameters {
public: public:
NumberOperationParameters(NumberOperationHint hint, NumberOperationParameters(NumberOperationHint hint,
...@@ -680,8 +658,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -680,8 +658,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* SpeculativeNumberLessThanOrEqual(NumberOperationHint hint); const Operator* SpeculativeNumberLessThanOrEqual(NumberOperationHint hint);
const Operator* SpeculativeNumberEqual(NumberOperationHint hint); const Operator* SpeculativeNumberEqual(NumberOperationHint hint);
const Operator* SpeculativeBigIntAdd(BigIntOperationHint hint, const Operator* SpeculativeBigIntAdd(BigIntOperationHint hint);
const VectorSlotPair& feedback);
const Operator* BigIntAsUintN(int bits); const Operator* BigIntAsUintN(int bits);
const Operator* ReferenceEqual(); const Operator* ReferenceEqual();
......
...@@ -4030,21 +4030,10 @@ void TranslatedState::VerifyMaterializedObjects() { ...@@ -4030,21 +4030,10 @@ void TranslatedState::VerifyMaterializedObjects() {
bool TranslatedState::DoUpdateFeedback() { bool TranslatedState::DoUpdateFeedback() {
if (!feedback_vector_handle_.is_null()) { if (!feedback_vector_handle_.is_null()) {
CHECK(!feedback_slot_.IsInvalid()); CHECK(!feedback_slot_.IsInvalid());
isolate()->CountUsage(v8::Isolate::kDeoptimizerDisableSpeculation);
FeedbackNexus nexus(feedback_vector_handle_, feedback_slot_); FeedbackNexus nexus(feedback_vector_handle_, feedback_slot_);
nexus.SetSpeculationMode(SpeculationMode::kDisallowSpeculation);
const auto kind = feedback_vector_handle_->GetKind(feedback_slot_); return true;
if (kind == FeedbackSlotKind::kCall) {
isolate()->CountUsage(v8::Isolate::kDeoptimizerDisableSpeculation);
nexus.SetSpeculationMode(SpeculationMode::kDisallowSpeculation);
return true;
} else if (kind == FeedbackSlotKind::kBinaryOp) {
// To prevent a deopt loop for binary operations (like speculative
// addition of BigInts), we generalize feedback to Any.
return nexus.SetBinaryOpFeedbackToAny();
} else {
UNREACHABLE();
}
} }
return false; return false;
} }
......
...@@ -176,15 +176,28 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs, ...@@ -176,15 +176,28 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
Node* rhs_instance_type = LoadInstanceType(rhs); Node* rhs_instance_type = LoadInstanceType(rhs);
Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE); Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
GotoIf(rhs_is_oddball, &call_with_oddball_feedback); GotoIf(rhs_is_oddball, &call_with_oddball_feedback);
Branch(IsBigIntInstanceType(rhs_instance_type), &bigint, Goto(&call_with_any_feedback);
&call_with_any_feedback);
} }
BIND(&bigint); BIND(&bigint);
{ {
// Both {lhs} and {rhs} are of BigInt type.
Label bigint_too_big(this);
var_result.Bind(
CallBuiltin(Builtins::kBigIntAddNoThrow, context, lhs, rhs));
// Check for sentinel that signals BigIntTooBig exception.
GotoIf(TaggedIsSmi(var_result.value()), &bigint_too_big);
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt)); var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
var_result.Bind(CallBuiltin(Builtins::kBigIntAdd, context, lhs, rhs));
Goto(&end); Goto(&end);
BIND(&bigint_too_big);
{
// Update feedback to prevent deopt loop.
UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
feedback_vector, slot_id);
ThrowRangeError(context, MessageTemplate::kBigIntTooBig);
}
} }
BIND(&call_with_oddball_feedback); BIND(&call_with_oddball_feedback);
......
...@@ -894,16 +894,6 @@ float FeedbackNexus::ComputeCallFrequency() { ...@@ -894,16 +894,6 @@ float FeedbackNexus::ComputeCallFrequency() {
return static_cast<float>(call_count / invocation_count); return static_cast<float>(call_count / invocation_count);
} }
bool FeedbackNexus::SetBinaryOpFeedbackToAny() {
DCHECK_EQ(kind(), FeedbackSlotKind::kBinaryOp);
int feedback = GetFeedback().ToSmi().value();
if (feedback == BinaryOperationFeedback::kAny) {
return false;
}
SetFeedback(Smi::FromInt(BinaryOperationFeedback::kAny));
return true;
}
void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name, void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
Handle<Map> receiver_map, Handle<Map> receiver_map,
const MaybeObjectHandle& handler) { const MaybeObjectHandle& handler) {
......
...@@ -673,7 +673,6 @@ class V8_EXPORT_PRIVATE FeedbackNexus final { ...@@ -673,7 +673,6 @@ class V8_EXPORT_PRIVATE FeedbackNexus final {
inline Isolate* GetIsolate() const; inline Isolate* GetIsolate() const;
bool SetBinaryOpFeedbackToAny();
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
const MaybeObjectHandle& handler); const MaybeObjectHandle& handler);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment