Commit 5c8ac0f3 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Add feedback to CheckMaps and Deoptimize nodes

Bug: v8:7127
Change-Id: I79be6acaa04623fe9a5d314de5cb10811724db5f
Reviewed-on: https://chromium-review.googlesource.com/814401
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49996}
parent 4b949591
......@@ -103,8 +103,9 @@ Reduction BranchElimination::ReduceDeoptimizeConditional(Node* node) {
// with the {control} node that already contains the right information.
ReplaceWithValue(node, dead(), effect, control);
} else {
control = graph()->NewNode(common()->Deoptimize(p.kind(), p.reason()),
frame_state, effect, control);
control = graph()->NewNode(
common()->Deoptimize(p.kind(), p.reason(), VectorSlotPair()),
frame_state, effect, control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), control);
Revisit(graph()->end());
......
......@@ -138,9 +138,10 @@ Reduction CommonOperatorReducer::ReduceDeoptimizeConditional(Node* node) {
if (condition->opcode() == IrOpcode::kBooleanNot) {
NodeProperties::ReplaceValueInput(node, condition->InputAt(0), 0);
NodeProperties::ChangeOp(
node, condition_is_true
? common()->DeoptimizeIf(p.kind(), p.reason())
: common()->DeoptimizeUnless(p.kind(), p.reason()));
node, condition_is_true ? common()->DeoptimizeIf(p.kind(), p.reason(),
VectorSlotPair())
: common()->DeoptimizeUnless(
p.kind(), p.reason(), VectorSlotPair()));
return Changed(node);
}
Decision const decision = DecideCondition(condition);
......@@ -148,8 +149,9 @@ Reduction CommonOperatorReducer::ReduceDeoptimizeConditional(Node* node) {
if (condition_is_true == (decision == Decision::kTrue)) {
ReplaceWithValue(node, dead(), effect, control);
} else {
control = graph()->NewNode(common()->Deoptimize(p.kind(), p.reason()),
frame_state, effect, control);
control = graph()->NewNode(
common()->Deoptimize(p.kind(), p.reason(), VectorSlotPair()),
frame_state, effect, control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), control);
Revisit(graph()->end());
......
......@@ -43,7 +43,8 @@ int ValueInputCountOfReturn(Operator const* const op) {
}
bool operator==(DeoptimizeParameters lhs, DeoptimizeParameters rhs) {
return lhs.kind() == rhs.kind() && lhs.reason() == rhs.reason();
return lhs.kind() == rhs.kind() && lhs.reason() == rhs.reason() &&
lhs.feedback() == rhs.feedback();
}
bool operator!=(DeoptimizeParameters lhs, DeoptimizeParameters rhs) {
......@@ -51,11 +52,15 @@ bool operator!=(DeoptimizeParameters lhs, DeoptimizeParameters rhs) {
}
size_t hash_value(DeoptimizeParameters p) {
return base::hash_combine(p.kind(), p.reason());
return base::hash_combine(p.kind(), p.reason(), p.feedback());
}
std::ostream& operator<<(std::ostream& os, DeoptimizeParameters p) {
return os << p.kind() << ":" << p.reason();
os << p.kind() << ":" << p.reason();
if (p.feedback().IsValid()) {
os << "; " << p.feedback();
}
return os;
}
DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const op) {
......@@ -606,7 +611,7 @@ struct CommonOperatorGlobalCache final {
Operator::kFoldable | Operator::kNoThrow, // properties
"Deoptimize", // name
1, 1, 1, 0, 0, 1, // counts
DeoptimizeParameters(kKind, kReason)) {} // parameter
DeoptimizeParameters(kKind, kReason, VectorSlotPair())) {}
};
#define CACHED_DEOPTIMIZE(Kind, Reason) \
DeoptimizeOperator<DeoptimizeKind::k##Kind, DeoptimizeReason::k##Reason> \
......@@ -622,7 +627,7 @@ struct CommonOperatorGlobalCache final {
Operator::kFoldable | Operator::kNoThrow, // properties
"DeoptimizeIf", // name
2, 1, 1, 0, 1, 1, // counts
DeoptimizeParameters(kKind, kReason)) {} // parameter
DeoptimizeParameters(kKind, kReason, VectorSlotPair())) {}
};
#define CACHED_DEOPTIMIZE_IF(Kind, Reason) \
DeoptimizeIfOperator<DeoptimizeKind::k##Kind, DeoptimizeReason::k##Reason> \
......@@ -639,7 +644,7 @@ struct CommonOperatorGlobalCache final {
Operator::kFoldable | Operator::kNoThrow, // properties
"DeoptimizeUnless", // name
2, 1, 1, 0, 1, 1, // counts
DeoptimizeParameters(kKind, kReason)) {} // parameter
DeoptimizeParameters(kKind, kReason, VectorSlotPair())) {}
};
#define CACHED_DEOPTIMIZE_UNLESS(Kind, Reason) \
DeoptimizeUnlessOperator<DeoptimizeKind::k##Kind, \
......@@ -817,8 +822,9 @@ const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
UNREACHABLE();
}
const Operator* CommonOperatorBuilder::Deoptimize(DeoptimizeKind kind,
DeoptimizeReason reason) {
const Operator* CommonOperatorBuilder::Deoptimize(
DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback) {
#define CACHED_DEOPTIMIZE(Kind, Reason) \
if (kind == DeoptimizeKind::k##Kind && \
reason == DeoptimizeReason::k##Reason) { \
......@@ -827,7 +833,7 @@ const Operator* CommonOperatorBuilder::Deoptimize(DeoptimizeKind kind,
CACHED_DEOPTIMIZE_LIST(CACHED_DEOPTIMIZE)
#undef CACHED_DEOPTIMIZE
// Uncached
DeoptimizeParameters parameter(kind, reason);
DeoptimizeParameters parameter(kind, reason, feedback);
return new (zone()) Operator1<DeoptimizeParameters>( // --
IrOpcode::kDeoptimize, // opcodes
Operator::kFoldable | Operator::kNoThrow, // properties
......@@ -836,8 +842,9 @@ const Operator* CommonOperatorBuilder::Deoptimize(DeoptimizeKind kind,
parameter); // parameter
}
const Operator* CommonOperatorBuilder::DeoptimizeIf(DeoptimizeKind kind,
DeoptimizeReason reason) {
const Operator* CommonOperatorBuilder::DeoptimizeIf(
DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback) {
#define CACHED_DEOPTIMIZE_IF(Kind, Reason) \
if (kind == DeoptimizeKind::k##Kind && \
reason == DeoptimizeReason::k##Reason) { \
......@@ -846,7 +853,7 @@ const Operator* CommonOperatorBuilder::DeoptimizeIf(DeoptimizeKind kind,
CACHED_DEOPTIMIZE_IF_LIST(CACHED_DEOPTIMIZE_IF)
#undef CACHED_DEOPTIMIZE_IF
// Uncached
DeoptimizeParameters parameter(kind, reason);
DeoptimizeParameters parameter(kind, reason, feedback);
return new (zone()) Operator1<DeoptimizeParameters>( // --
IrOpcode::kDeoptimizeIf, // opcode
Operator::kFoldable | Operator::kNoThrow, // properties
......@@ -856,7 +863,8 @@ const Operator* CommonOperatorBuilder::DeoptimizeIf(DeoptimizeKind kind,
}
const Operator* CommonOperatorBuilder::DeoptimizeUnless(
DeoptimizeKind kind, DeoptimizeReason reason) {
DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback) {
#define CACHED_DEOPTIMIZE_UNLESS(Kind, Reason) \
if (kind == DeoptimizeKind::k##Kind && \
reason == DeoptimizeReason::k##Reason) { \
......@@ -865,7 +873,7 @@ const Operator* CommonOperatorBuilder::DeoptimizeUnless(
CACHED_DEOPTIMIZE_UNLESS_LIST(CACHED_DEOPTIMIZE_UNLESS)
#undef CACHED_DEOPTIMIZE_UNLESS
// Uncached
DeoptimizeParameters parameter(kind, reason);
DeoptimizeParameters parameter(kind, reason, feedback);
return new (zone()) Operator1<DeoptimizeParameters>( // --
IrOpcode::kDeoptimizeUnless, // opcode
Operator::kFoldable | Operator::kNoThrow, // properties
......
......@@ -11,6 +11,7 @@
#include "src/deoptimize-reason.h"
#include "src/globals.h"
#include "src/machine-type.h"
#include "src/vector-slot-pair.h"
#include "src/zone/zone-containers.h"
#include "src/zone/zone-handle-set.h"
......@@ -52,15 +53,18 @@ int ValueInputCountOfReturn(Operator const* const op);
// Parameters for the {Deoptimize} operator.
class DeoptimizeParameters final {
public:
DeoptimizeParameters(DeoptimizeKind kind, DeoptimizeReason reason)
: kind_(kind), reason_(reason) {}
DeoptimizeParameters(DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback)
: kind_(kind), reason_(reason), feedback_(feedback) {}
DeoptimizeKind kind() const { return kind_; }
DeoptimizeReason reason() const { return reason_; }
const VectorSlotPair& feedback() const { return feedback_; }
private:
DeoptimizeKind const kind_;
DeoptimizeReason const reason_;
VectorSlotPair const feedback_;
};
bool operator==(DeoptimizeParameters, DeoptimizeParameters);
......@@ -358,10 +362,12 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
const Operator* IfValue(int32_t value);
const Operator* IfDefault();
const Operator* Throw();
const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason);
const Operator* DeoptimizeIf(DeoptimizeKind kind, DeoptimizeReason reason);
const Operator* DeoptimizeUnless(DeoptimizeKind kind,
DeoptimizeReason reason);
const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback);
const Operator* DeoptimizeIf(DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback);
const Operator* DeoptimizeUnless(DeoptimizeKind kind, DeoptimizeReason reason,
VectorSlotPair const& feedback);
const Operator* TrapIf(int32_t trap_id);
const Operator* TrapUnless(int32_t trap_id);
const Operator* Return(int value_input_count = 1);
......
......@@ -1355,7 +1355,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
__ Int32Constant(Map::IsDeprecatedBit::kMask)),
__ Int32Constant(0));
__ DeoptimizeIf(DeoptimizeReason::kWrongMap, if_not_deprecated,
frame_state);
frame_state, p.feedback());
Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
Runtime::FunctionId id = Runtime::kTryMigrateInstance;
......@@ -1367,7 +1367,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
__ Int32Constant(1), __ NoContextConstant());
Node* check = ObjectIsSmi(result);
__ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check,
frame_state);
frame_state, p.feedback());
}
// Reload the current map of the {value}.
......@@ -1378,7 +1378,8 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* map = __ HeapConstant(maps[i]);
Node* check = __ WordEqual(value_map, map);
if (i == map_count - 1) {
__ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, check, frame_state);
__ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, check, frame_state,
p.feedback());
} else {
__ GotoIf(check, &done);
}
......@@ -1396,7 +1397,8 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* map = __ HeapConstant(maps[i]);
Node* check = __ WordEqual(value_map, map);
if (i == map_count - 1) {
__ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, check, frame_state);
__ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, check, frame_state,
p.feedback());
} else {
__ GotoIf(check, &done);
}
......@@ -1524,7 +1526,7 @@ Node* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
void EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) {
Node* value = node->InputAt(0);
__ DeoptimizeIfNot(DeoptimizeKind::kEager, DeoptimizeReasonOf(node->op()),
value, frame_state);
value, frame_state, VectorSlotPair());
}
Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node,
......
......@@ -165,24 +165,27 @@ Node* GraphAssembler::ToNumber(Node* value) {
}
Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason, Node* condition,
Node* frame_state) {
Node* frame_state,
VectorSlotPair const& feedback) {
return current_control_ = current_effect_ = graph()->NewNode(
common()->DeoptimizeIf(DeoptimizeKind::kEager, reason), condition,
frame_state, current_effect_, current_control_);
common()->DeoptimizeIf(DeoptimizeKind::kEager, reason, feedback),
condition, frame_state, current_effect_, current_control_);
}
Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeKind kind,
DeoptimizeReason reason, Node* condition,
Node* frame_state) {
Node* frame_state,
VectorSlotPair const& feedback) {
return current_control_ = current_effect_ = graph()->NewNode(
common()->DeoptimizeUnless(kind, reason), condition, frame_state,
current_effect_, current_control_);
common()->DeoptimizeUnless(kind, reason, feedback), condition,
frame_state, current_effect_, current_control_);
}
Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason, Node* condition,
Node* frame_state) {
return DeoptimizeIfNot(DeoptimizeKind::kEager, reason, condition,
frame_state);
Node* frame_state,
VectorSlotPair const& feedback) {
return DeoptimizeIfNot(DeoptimizeKind::kEager, reason, condition, frame_state,
feedback);
}
void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
......
......@@ -8,6 +8,7 @@
#include "src/compiler/js-graph.h"
#include "src/compiler/node.h"
#include "src/compiler/simplified-operator.h"
#include "src/vector-slot-pair.h"
namespace v8 {
namespace internal {
......@@ -209,11 +210,14 @@ class GraphAssembler {
Node* UnsafePointerAdd(Node* base, Node* external);
Node* DeoptimizeIf(DeoptimizeReason reason, Node* condition,
Node* frame_state);
Node* frame_state,
VectorSlotPair const& feedback = VectorSlotPair());
Node* DeoptimizeIfNot(DeoptimizeKind kind, DeoptimizeReason reason,
Node* condition, Node* frame_state);
Node* condition, Node* frame_state,
VectorSlotPair const& feedback);
Node* DeoptimizeIfNot(DeoptimizeReason reason, Node* condition,
Node* frame_state);
Node* frame_state,
VectorSlotPair const& feedback = VectorSlotPair());
template <typename... Args>
Node* Call(const CallDescriptor* desc, Args... args);
template <typename... Args>
......
......@@ -2485,9 +2485,9 @@ Reduction JSCallReducer::ReduceSoftDeoptimize(Node* node,
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kSoft, reason),
frame_state, effect, control);
Node* deoptimize = graph()->NewNode(
common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
frame_state, effect, control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
Revisit(graph()->end());
......
......@@ -135,7 +135,8 @@ Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
// TODO(bmeurer): Move MergeControlToEnd() to the AdvancedReducer.
Node* deoptimize = graph()->NewNode(
common()->Deoptimize(DeoptimizeKind::kEager, DeoptimizeReason::kNoReason),
common()->Deoptimize(DeoptimizeKind::kEager, DeoptimizeReason::kNoReason,
VectorSlotPair()),
frame_state, effect, control);
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
Revisit(graph()->end());
......
......@@ -1424,9 +1424,9 @@ Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kSoft, reason),
frame_state, effect, control);
Node* deoptimize = graph()->NewNode(
common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
frame_state, effect, control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
Revisit(graph()->end());
......
......@@ -493,7 +493,8 @@ Node* JSTypeHintLowering::TryBuildSoftDeopt(FeedbackNexus& nexus, Node* effect,
DeoptimizeReason reason) const {
if ((flags() & kBailoutOnUninitialized) && nexus.IsUninitialized()) {
Node* deoptimize = jsgraph()->graph()->NewNode(
jsgraph()->common()->Deoptimize(DeoptimizeKind::kSoft, reason),
jsgraph()->common()->Deoptimize(DeoptimizeKind::kSoft, reason,
VectorSlotPair()),
jsgraph()->Dead(), effect, control);
Node* frame_state = NodeProperties::FindFrameStateBefore(deoptimize);
deoptimize->ReplaceInput(0, frame_state);
......
......@@ -215,15 +215,20 @@ size_t hash_value(MapsParameterInfo const& p) { return hash_value(p.maps()); }
bool operator==(CheckMapsParameters const& lhs,
CheckMapsParameters const& rhs) {
return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps();
return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps() &&
lhs.feedback() == rhs.feedback();
}
size_t hash_value(CheckMapsParameters const& p) {
return base::hash_combine(p.flags(), p.maps());
return base::hash_combine(p.flags(), p.maps(), p.feedback());
}
std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
return os << p.flags() << p.maps_info();
os << p.flags() << p.maps_info();
if (p.feedback().IsValid()) {
os << "; " << p.feedback();
}
return os;
}
CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
......@@ -1021,9 +1026,10 @@ const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
UNREACHABLE();
}
const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags,
ZoneHandleSet<Map> maps) {
CheckMapsParameters const parameters(flags, maps);
const Operator* SimplifiedOperatorBuilder::CheckMaps(
CheckMapsFlags flags, ZoneHandleSet<Map> maps,
const VectorSlotPair& feedback) {
CheckMapsParameters const parameters(flags, maps, feedback);
return new (zone()) Operator1<CheckMapsParameters>( // --
IrOpcode::kCheckMaps, // opcode
Operator::kNoThrow | Operator::kNoWrite, // flags
......
......@@ -16,6 +16,7 @@
#include "src/machine-type.h"
#include "src/objects.h"
#include "src/type-hints.h"
#include "src/vector-slot-pair.h"
#include "src/zone/zone-handle-set.h"
namespace v8 {
......@@ -155,19 +156,24 @@ bool operator!=(MapsParameterInfo const&, MapsParameterInfo const&);
size_t hash_value(MapsParameterInfo const&);
// A descriptor for map checks.
// A descriptor for map checks. The {feedback} parameter is optional.
// If {feedback} references a valid CallIC slot and this MapCheck fails,
// then speculation on that CallIC slot will be disabled.
class CheckMapsParameters final {
public:
CheckMapsParameters(CheckMapsFlags flags, ZoneHandleSet<Map> const& maps)
: flags_(flags), maps_info_(maps) {}
CheckMapsParameters(CheckMapsFlags flags, ZoneHandleSet<Map> const& maps,
const VectorSlotPair& feedback)
: flags_(flags), maps_info_(maps), feedback_(feedback) {}
CheckMapsFlags flags() const { return flags_; }
ZoneHandleSet<Map> const& maps() const { return maps_info_.maps(); }
MapsParameterInfo const& maps_info() const { return maps_info_; }
VectorSlotPair const& feedback() const { return feedback_; }
private:
CheckMapsFlags const flags_;
MapsParameterInfo const maps_info_;
VectorSlotPair const feedback_;
};
bool operator==(CheckMapsParameters const&, CheckMapsParameters const&);
......@@ -438,7 +444,8 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* CheckIf(DeoptimizeReason deoptimize_reason);
const Operator* CheckBounds();
const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet<Map>);
const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet<Map>,
const VectorSlotPair& = VectorSlotPair());
const Operator* CompareMaps(ZoneHandleSet<Map>);
const Operator* MapGuard(ZoneHandleSet<Map> maps);
......
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