[turbofan] Add feedback to SpeculativeToNumber

Bug: v8:7250
Change-Id: If4c9d0b32939a06993d3ffb39ac4b19edbad422f
Reviewed-on: https://chromium-review.googlesource.com/906731
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51184}
This commit is contained in:
Sigurd Schneider 2018-02-08 03:59:54 +01:00 committed by Commit Bot
parent 13d67667cc
commit 922d14b4fe
9 changed files with 139 additions and 82 deletions

View File

@ -1935,7 +1935,8 @@ Node* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
Node* frame_state) {
CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
CheckTaggedInputParameters const& p =
CheckTaggedInputParametersOf(node->op());
Node* value = node->InputAt(0);
auto if_smi = __ MakeLabel();
@ -1947,7 +1948,7 @@ Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
// In the Smi case, just convert to int32 and then float64.
// Otherwise, check heap numberness and load the number.
Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
mode, VectorSlotPair(), value, frame_state);
p.mode(), p.feedback(), value, frame_state);
__ Goto(&done, number);
__ Bind(&if_smi);

View File

@ -2173,9 +2173,9 @@ JSNativeContextSpecialization::BuildElementAccess(
case AccessMode::kStore: {
// Ensure that the {value} is actually a Number or an Oddball,
// and truncate it to a Number appropriately.
value = effect =
graph()->NewNode(simplified()->SpeculativeToNumber(
NumberOperationHint::kNumberOrOddball),
value = effect = graph()->NewNode(
simplified()->SpeculativeToNumber(
NumberOperationHint::kNumberOrOddball, VectorSlotPair()),
value, effect, control);
// Introduce the appropriate truncation for {value}. Currently we

View File

@ -390,8 +390,8 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceToNumberOperation(
if (BinaryOperationHintToNumberOperationHint(
nexus.GetBinaryOperationFeedback(), &hint)) {
Node* node = jsgraph()->graph()->NewNode(
jsgraph()->simplified()->SpeculativeToNumber(hint), input, effect,
control);
jsgraph()->simplified()->SpeculativeToNumber(hint, VectorSlotPair()),
input, effect, control);
return LoweringResult::SideEffectFree(node, node, control);
}
return LoweringResult::NoChange();

View File

@ -588,10 +588,11 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
} else if (use_info.type_check() == TypeCheckKind::kNumber ||
(use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
!output_type->Maybe(Type::BooleanOrNullOrNumber()))) {
op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber);
op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
use_info.feedback());
} else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
op = simplified()->CheckedTaggedToFloat64(
CheckTaggedInputMode::kNumberOrOddball);
CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
}
} else if (output_rep == MachineRepresentation::kFloat32) {
op = machine()->ChangeFloat32ToFloat64();

View File

@ -209,21 +209,23 @@ class UseInfo {
Truncation::Any(identify_zeros), TypeCheckKind::kSigned32,
feedback);
}
static UseInfo CheckedNumberAsFloat64() {
static UseInfo CheckedNumberAsFloat64(const VectorSlotPair& feedback) {
return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
TypeCheckKind::kNumber);
TypeCheckKind::kNumber, feedback);
}
static UseInfo CheckedNumberAsWord32() {
static UseInfo CheckedNumberAsWord32(const VectorSlotPair& feedback) {
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
TypeCheckKind::kNumber);
TypeCheckKind::kNumber, feedback);
}
static UseInfo CheckedNumberOrOddballAsFloat64() {
static UseInfo CheckedNumberOrOddballAsFloat64(
const VectorSlotPair& feedback) {
return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
TypeCheckKind::kNumberOrOddball);
TypeCheckKind::kNumberOrOddball, feedback);
}
static UseInfo CheckedNumberOrOddballAsWord32() {
static UseInfo CheckedNumberOrOddballAsWord32(
const VectorSlotPair& feedback) {
return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
TypeCheckKind::kNumberOrOddball);
TypeCheckKind::kNumberOrOddball, feedback);
}
// Undetermined representation.

View File

@ -87,24 +87,24 @@ MachineRepresentation MachineRepresentationFromArrayType(
}
UseInfo CheckedUseInfoAsWord32FromHint(
NumberOperationHint hint,
NumberOperationHint hint, const VectorSlotPair& feedback = VectorSlotPair(),
IdentifyZeros identify_zeros = kDistinguishZeros) {
switch (hint) {
case NumberOperationHint::kSignedSmall:
case NumberOperationHint::kSignedSmallInputs:
return UseInfo::CheckedSignedSmallAsWord32(identify_zeros,
VectorSlotPair());
return UseInfo::CheckedSignedSmallAsWord32(identify_zeros, feedback);
case NumberOperationHint::kSigned32:
return UseInfo::CheckedSigned32AsWord32(identify_zeros, VectorSlotPair());
return UseInfo::CheckedSigned32AsWord32(identify_zeros, feedback);
case NumberOperationHint::kNumber:
return UseInfo::CheckedNumberAsWord32();
return UseInfo::CheckedNumberAsWord32(feedback);
case NumberOperationHint::kNumberOrOddball:
return UseInfo::CheckedNumberOrOddballAsWord32();
return UseInfo::CheckedNumberOrOddballAsWord32(feedback);
}
UNREACHABLE();
}
UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) {
UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint,
const VectorSlotPair& feedback) {
switch (hint) {
case NumberOperationHint::kSignedSmall:
case NumberOperationHint::kSignedSmallInputs:
@ -113,9 +113,9 @@ UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) {
UNREACHABLE();
break;
case NumberOperationHint::kNumber:
return UseInfo::CheckedNumberAsFloat64();
return UseInfo::CheckedNumberAsFloat64(feedback);
case NumberOperationHint::kNumberOrOddball:
return UseInfo::CheckedNumberOrOddballAsFloat64();
return UseInfo::CheckedNumberOrOddballAsFloat64(feedback);
}
UNREACHABLE();
}
@ -1321,13 +1321,14 @@ class RepresentationSelector {
!right_feedback_type->Maybe(Type::MinusZero())) {
left_identify_zeros = kIdentifyZeros;
}
UseInfo left_use =
CheckedUseInfoAsWord32FromHint(hint, left_identify_zeros);
UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(),
left_identify_zeros);
// For CheckedInt32Add and CheckedInt32Sub, we don't need to do
// a minus zero check for the right hand side, since we already
// know that the left hand side is a proper Signed32 value,
// potentially guarded by a check.
UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros);
UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(),
kIdentifyZeros);
VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32,
Type::Signed32());
}
@ -1357,7 +1358,7 @@ class RepresentationSelector {
}
// default case => Float64Add/Sub
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()),
MachineRepresentation::kFloat64, Type::Number());
if (lower()) {
ChangeToPureOp(node, Float64Op(node));
@ -1456,7 +1457,7 @@ class RepresentationSelector {
return;
}
// default case => Float64Mod
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()),
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
@ -1719,7 +1720,8 @@ class RepresentationSelector {
DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
// Fallthrough
case NumberOperationHint::kNumber:
VisitBinop(node, CheckedUseInfoAsFloat64FromHint(hint),
VisitBinop(node,
CheckedUseInfoAsFloat64FromHint(hint, VectorSlotPair()),
MachineRepresentation::kBit);
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
@ -1792,7 +1794,8 @@ class RepresentationSelector {
}
// Checked float64 x float64 => float64
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
VisitBinop(node,
UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()),
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
@ -1886,7 +1889,8 @@ class RepresentationSelector {
}
// default case => Float64Div
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
VisitBinop(node,
UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()),
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
@ -2709,17 +2713,20 @@ class RepresentationSelector {
return;
}
case IrOpcode::kSpeculativeToNumber: {
NumberOperationHint const hint = NumberOperationHintOf(node->op());
switch (hint) {
NumberOperationParameters const& p =
NumberOperationParametersOf(node->op());
switch (p.hint()) {
case NumberOperationHint::kSigned32:
case NumberOperationHint::kSignedSmall:
case NumberOperationHint::kSignedSmallInputs:
VisitUnop(node, CheckedUseInfoAsWord32FromHint(hint),
VisitUnop(node,
CheckedUseInfoAsWord32FromHint(p.hint(), p.feedback()),
MachineRepresentation::kWord32, Type::Signed32());
break;
case NumberOperationHint::kNumber:
case NumberOperationHint::kNumberOrOddball:
VisitUnop(node, CheckedUseInfoAsFloat64FromHint(hint),
VisitUnop(node,
CheckedUseInfoAsFloat64FromHint(p.hint(), p.feedback()),
MachineRepresentation::kFloat64);
break;
}

View File

@ -258,11 +258,6 @@ std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
UNREACHABLE();
}
CheckTaggedInputMode CheckTaggedInputModeOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kCheckedTaggedToFloat64);
return OpParameter<CheckTaggedInputMode>(op);
}
std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) {
switch (mode) {
case GrowFastElementsMode::kDoubleElements:
@ -487,8 +482,7 @@ size_t hash_value(NumberOperationHint hint) {
}
NumberOperationHint NumberOperationHintOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kSpeculativeToNumber ||
op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
@ -507,6 +501,25 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) {
return OpParameter<NumberOperationHint>(op);
}
bool operator==(NumberOperationParameters const& lhs,
NumberOperationParameters const& rhs) {
return lhs.hint() == rhs.hint() && lhs.feedback() == rhs.feedback();
}
size_t hash_value(NumberOperationParameters const& p) {
return base::hash_combine(p.hint(), p.feedback());
}
std::ostream& operator<<(std::ostream& os, NumberOperationParameters const& p) {
return os << p.hint() << " " << p.feedback();
}
NumberOperationParameters const& NumberOperationParametersOf(
Operator const* op) {
DCHECK_EQ(IrOpcode::kSpeculativeToNumber, op->opcode());
return OpParameter<NumberOperationParameters>(op);
}
size_t hash_value(AllocateParameters info) {
return base::hash_combine(info.type(), info.pretenure());
}
@ -555,7 +568,8 @@ DeoptimizeReason DeoptimizeReasonOf(const Operator* op) {
const CheckTaggedInputParameters& CheckTaggedInputParametersOf(
const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32);
DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32 ||
op->opcode() == IrOpcode::kCheckedTaggedToFloat64);
return OpParameter<CheckTaggedInputParameters>(op);
}
@ -934,12 +948,13 @@ struct SimplifiedOperatorGlobalCache final {
template <CheckTaggedInputMode kMode>
struct CheckedTaggedToFloat64Operator final
: public Operator1<CheckTaggedInputMode> {
: public Operator1<CheckTaggedInputParameters> {
CheckedTaggedToFloat64Operator()
: Operator1<CheckTaggedInputMode>(
: Operator1<CheckTaggedInputParameters>(
IrOpcode::kCheckedTaggedToFloat64,
Operator::kFoldable | Operator::kNoThrow,
"CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0, kMode) {}
"CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0,
CheckTaggedInputParameters(kMode, VectorSlotPair())) {}
};
CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
kCheckedTaggedToFloat64NumberOperator;
@ -1047,14 +1062,13 @@ struct SimplifiedOperatorGlobalCache final {
template <NumberOperationHint kHint>
struct SpeculativeToNumberOperator final
: public Operator1<NumberOperationHint> {
: public Operator1<NumberOperationParameters> {
SpeculativeToNumberOperator()
: Operator1<NumberOperationHint>(
IrOpcode::kSpeculativeToNumber, // opcode
Operator::kFoldable | Operator::kNoThrow, // flags
"SpeculativeToNumber", // name
1, 1, 1, 1, 1, 0, // counts
kHint) {} // parameter
: Operator1<NumberOperationParameters>(
IrOpcode::kSpeculativeToNumber,
Operator::kFoldable | Operator::kNoThrow, "SpeculativeToNumber",
1, 1, 1, 1, 1, 0,
NumberOperationParameters(kHint, VectorSlotPair())) {}
};
SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
kSpeculativeToNumberSignedSmallOperator;
@ -1184,14 +1198,19 @@ const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
}
const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
CheckTaggedInputMode mode) {
CheckTaggedInputMode mode, const VectorSlotPair& feedback) {
if (!feedback.IsValid()) {
switch (mode) {
case CheckTaggedInputMode::kNumber:
return &cache_.kCheckedTaggedToFloat64NumberOperator;
case CheckTaggedInputMode::kNumberOrOddball:
return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
}
UNREACHABLE();
}
return new (zone()) Operator1<CheckTaggedInputParameters>(
IrOpcode::kCheckedTaggedToFloat64,
Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToFloat64", 1, 1,
1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
}
const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
@ -1266,7 +1285,8 @@ const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
}
const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
NumberOperationHint hint) {
NumberOperationHint hint, const VectorSlotPair& feedback) {
if (!feedback.IsValid()) {
switch (hint) {
case NumberOperationHint::kSignedSmall:
return &cache_.kSpeculativeToNumberSignedSmallOperator;
@ -1279,7 +1299,11 @@ const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
case NumberOperationHint::kNumberOrOddball:
return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
}
UNREACHABLE();
}
return new (zone()) Operator1<NumberOperationParameters>(
IrOpcode::kSpeculativeToNumber, Operator::kFoldable | Operator::kNoThrow,
"SpeculativeToNumber", 1, 1, 1, 1, 1, 0,
NumberOperationParameters(hint, feedback));
}
const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {

View File

@ -134,8 +134,6 @@ size_t hash_value(CheckTaggedInputMode);
std::ostream& operator<<(std::ostream&, CheckTaggedInputMode);
CheckTaggedInputMode CheckTaggedInputModeOf(const Operator*);
class CheckTaggedInputParameters {
public:
CheckTaggedInputParameters(CheckTaggedInputMode mode,
@ -353,6 +351,28 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, NumberOperationHint);
NumberOperationHint NumberOperationHintOf(const Operator* op)
WARN_UNUSED_RESULT;
class NumberOperationParameters {
public:
NumberOperationParameters(NumberOperationHint hint,
const VectorSlotPair& feedback)
: hint_(hint), feedback_(feedback) {}
NumberOperationHint hint() const { return hint_; }
const VectorSlotPair& feedback() const { return feedback_; }
private:
NumberOperationHint hint_;
VectorSlotPair feedback_;
};
size_t hash_value(NumberOperationParameters const&);
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
const NumberOperationParameters&);
bool operator==(NumberOperationParameters const&,
NumberOperationParameters const&);
const NumberOperationParameters& NumberOperationParametersOf(const Operator* op)
WARN_UNUSED_RESULT;
int FormalParameterCountOf(const Operator* op) WARN_UNUSED_RESULT;
bool IsRestLengthOf(const Operator* op) WARN_UNUSED_RESULT;
@ -516,7 +536,8 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* FindOrderedHashMapEntry();
const Operator* FindOrderedHashMapEntryForInt32Key();
const Operator* SpeculativeToNumber(NumberOperationHint hint);
const Operator* SpeculativeToNumber(NumberOperationHint hint,
const VectorSlotPair& feedback);
const Operator* StringToNumber();
const Operator* PlainPrimitiveToNumber();
@ -570,7 +591,8 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* CheckedInt32Sub();
const Operator* CheckedInt32ToTaggedSigned(const VectorSlotPair& feedback);
const Operator* CheckedTaggedSignedToInt32(const VectorSlotPair& feedback);
const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode);
const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode,
const VectorSlotPair& feedback);
const Operator* CheckedTaggedToInt32(CheckForMinusZeroMode,
const VectorSlotPair& feedback);
const Operator* CheckedTaggedToTaggedPointer(const VectorSlotPair& feedback);

View File

@ -429,7 +429,7 @@ TEST(SignednessInWord32) {
CheckChange(IrOpcode::kCheckedTruncateTaggedToWord32,
MachineRepresentation::kTagged, Type::NonInternal(),
MachineRepresentation::kWord32,
UseInfo::CheckedNumberOrOddballAsWord32());
UseInfo::CheckedNumberOrOddballAsWord32(VectorSlotPair()));
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
IrOpcode::kTruncateFloat64ToFloat32,