[turbofan] Use the right comparison for constant field store.

This uses the same comparison as the ICs to make sure that ICs learn
after deoptimization (see
https://chromium-review.googlesource.com/c/v8/v8/+/1561319 for the IC
fix).

Bug: v8:9139
Change-Id: I67a361d85ee0c8a4ad4a6abc2d33ac4ca5fa22bc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1569438
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60917}
This commit is contained in:
Jaroslav Sevcik 2019-04-18 11:56:16 +02:00 committed by Commit Bot
parent 45a6503ca6
commit 2c5f11fba2
14 changed files with 82 additions and 1 deletions

View File

@ -752,6 +752,7 @@ namespace internal {
TFC(GreaterThanOrEqual, Compare) \
TFC(Equal, Compare) \
TFC(SameValue, Compare) \
TFC(SameValueNumbersOnly, Compare) \
TFC(StrictEqual, Compare) \
TFS(BitwiseNot, kValue) \
TFS(Decrement, kValue) \

View File

@ -646,6 +646,20 @@ TF_BUILTIN(SameValue, CodeStubAssembler) {
Return(FalseConstant());
}
TF_BUILTIN(SameValueNumbersOnly, CodeStubAssembler) {
Node* lhs = Parameter(Descriptor::kLeft);
Node* rhs = Parameter(Descriptor::kRight);
Label if_true(this), if_false(this);
BranchIfSameValue(lhs, rhs, &if_true, &if_false, SameValueMode::kNumbersOnly);
BIND(&if_true);
Return(TrueConstant());
BIND(&if_false);
Return(FalseConstant());
}
class InternalBuiltinsAssembler : public CodeStubAssembler {
public:
explicit InternalBuiltinsAssembler(compiler::CodeAssemblerState* state)

View File

@ -905,6 +905,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kSameValue:
result = LowerSameValue(node);
break;
case IrOpcode::kSameValueNumbersOnly:
result = LowerSameValueNumbersOnly(node);
break;
case IrOpcode::kNumberSameValue:
result = LowerNumberSameValue(node);
break;
@ -3443,6 +3446,21 @@ Node* EffectControlLinearizer::LowerSameValue(Node* node) {
__ NoContextConstant());
}
Node* EffectControlLinearizer::LowerSameValueNumbersOnly(Node* node) {
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kSameValueNumbersOnly);
Operator::Properties properties = Operator::kEliminatable;
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
auto call_descriptor = Linkage::GetStubCallDescriptor(
graph()->zone(), callable.descriptor(),
callable.descriptor().GetStackParameterCount(), flags, properties);
return __ Call(call_descriptor, __ HeapConstant(callable.code()), lhs, rhs,
__ NoContextConstant());
}
Node* EffectControlLinearizer::LowerNumberSameValue(Node* node) {
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);

View File

@ -146,6 +146,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerNewConsTwoByteString(Node* node);
Node* LowerNewConsString(Node* node);
Node* LowerSameValue(Node* node);
Node* LowerSameValueNumbersOnly(Node* node);
Node* LowerNumberSameValue(Node* node);
Node* LowerDeadValue(Node* node);
Node* LowerStringConcat(Node* node);

View File

@ -2330,7 +2330,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
Node* current_value = effect = graph()->NewNode(
simplified()->LoadField(field_access), storage, effect, control);
Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
Node* check = graph()->NewNode(simplified()->SameValueNumbersOnly(),
current_value, value);
effect = graph()->NewNode(
simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,

View File

@ -293,6 +293,7 @@
V(SpeculativeNumberLessThanOrEqual) \
V(ReferenceEqual) \
V(SameValue) \
V(SameValueNumbersOnly) \
V(NumberSameValue) \
V(StringEqual) \
V(StringLessThan) \

View File

@ -1187,6 +1187,13 @@ Type OperationTyper::SameValue(Type lhs, Type rhs) {
return Type::Boolean();
}
Type OperationTyper::SameValueNumbersOnly(Type lhs, Type rhs) {
// SameValue and SamevalueNumbersOnly only differ in treatment of
// strings and biginits. Since the SameValue typer does not do anything
// special about strings or bigints, we can just use it here.
return SameValue(lhs, rhs);
}
Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();

View File

@ -55,6 +55,7 @@ class V8_EXPORT_PRIVATE OperationTyper {
// Comparison operators.
Type SameValue(Type lhs, Type rhs);
Type SameValueNumbersOnly(Type lhs, Type rhs);
Type StrictEqual(Type lhs, Type rhs);
// String operators.

View File

@ -2585,6 +2585,11 @@ class RepresentationSelector {
}
return;
}
case IrOpcode::kSameValueNumbersOnly: {
VisitBinop(node, UseInfo::AnyTagged(),
MachineRepresentation::kTaggedPointer);
return;
}
case IrOpcode::kSameValue: {
if (truncation.IsUnused()) return VisitUnused(node);
if (BothInputsAre(node, Type::Number())) {

View File

@ -736,6 +736,7 @@ bool operator==(CheckMinusZeroParameters const& lhs,
V(ObjectIsInteger, Operator::kNoProperties, 1, 0) \
V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
V(SameValue, Operator::kCommutative, 2, 0) \
V(SameValueNumbersOnly, Operator::kCommutative, 2, 0) \
V(NumberSameValue, Operator::kCommutative, 2, 0) \
V(ReferenceEqual, Operator::kCommutative, 2, 0) \
V(StringEqual, Operator::kCommutative, 2, 0) \

View File

@ -617,6 +617,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* ReferenceEqual();
const Operator* SameValue();
const Operator* SameValueNumbersOnly();
const Operator* TypeOf();

View File

@ -317,6 +317,7 @@ class Typer::Visitor : public Reducer {
static Type NumberLessThanOrEqualTyper(Type, Type, Typer*);
static Type ReferenceEqualTyper(Type, Type, Typer*);
static Type SameValueTyper(Type, Type, Typer*);
static Type SameValueNumbersOnlyTyper(Type, Type, Typer*);
static Type StringFromSingleCharCodeTyper(Type, Typer*);
static Type StringFromSingleCodePointTyper(Type, Typer*);
@ -1992,10 +1993,19 @@ Type Typer::Visitor::SameValueTyper(Type lhs, Type rhs, Typer* t) {
return t->operation_typer()->SameValue(lhs, rhs);
}
// static
Type Typer::Visitor::SameValueNumbersOnlyTyper(Type lhs, Type rhs, Typer* t) {
return t->operation_typer()->SameValueNumbersOnly(lhs, rhs);
}
Type Typer::Visitor::TypeSameValue(Node* node) {
return TypeBinaryOp(node, SameValueTyper);
}
Type Typer::Visitor::TypeSameValueNumbersOnly(Node* node) {
return TypeBinaryOp(node, SameValueNumbersOnlyTyper);
}
Type Typer::Visitor::TypeNumberSameValue(Node* node) { UNREACHABLE(); }
Type Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); }

View File

@ -1185,6 +1185,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
CheckTypeIs(node, Type::Boolean());
break;
case IrOpcode::kSameValue:
case IrOpcode::kSameValueNumbersOnly:
// (Any, Any) -> Boolean
CheckValueInputIs(node, 0, Type::Any());
CheckValueInputIs(node, 1, Type::Any());

View File

@ -0,0 +1,20 @@
// Copyright 2019 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
let dummy = { x : {} };
let o = { x : 0.1 };
function f(o, a, b) {
o.x = a + b;
}
%PrepareFunctionForOptimization(f);
f(o, 0.05, 0.05);
f(o, 0.05, 0.05);
%OptimizeFunctionOnNextCall(f);
f(o, 0.05, 0.05);
assertOptimized(f);