Commit f3b4841d authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

Revert "[turbofan] Prune control flow based on failed map checks and comparisons."

This reverts commit 37b4b2f1.

Reason for revert: Likely breaking canary.

Original change's description:
> [turbofan] Prune control flow based on failed map checks and comparisons.
> 
> This introduces unreachable state into load elimination. We mark state
> as unreachable if we know statically that a map check would fail.
> When processing effect phis, we disconnect unreachable state's
> control from the effect phi's merge, and point it to RuntimeAbort.
> The control input to the merge is then updated with Dead. Dead
> code elimination prunes the merge, phis and effect phis.
> 
> Bug: v8:6396
> Change-Id: I01874b576e548747a915c7b645b96ebaa6f6700d
> Reviewed-on: https://chromium-review.googlesource.com/730754
> Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#48810}

TBR=jarin@chromium.org,bmeurer@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: v8:6396, chromium:777843
Change-Id: I6fac6f86e138f33756e688ec30424cb940690dae
Reviewed-on: https://chromium-review.googlesource.com/737829Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48918}
parent 1a70805a
......@@ -141,7 +141,6 @@ namespace internal {
V(kUnexpectedReturnFromFrameDropper, \
"Unexpectedly returned from dropping frames") \
V(kUnexpectedReturnFromThrow, "Unexpectedly returned from a throw") \
V(kUnreachableCodeReached, "Reached unreachable code") \
V(kVariableResolvedToWithContext, "Variable resolved to with context") \
V(kWithStatement, "WithStatement") \
V(kWrongFunctionContext, "Wrong context passed to function") \
......
......@@ -525,8 +525,6 @@ Node* LoadElimination::AbstractState::LookupCheck(Node* node) const {
LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck(
Node* node, Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this);
if (that->checks_) {
that->checks_ = that->checks_->Extend(node, zone);
......@@ -543,8 +541,6 @@ bool LoadElimination::AbstractState::LookupMaps(
LoadElimination::AbstractState const* LoadElimination::AbstractState::SetMaps(
Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this);
if (that->maps_) {
that->maps_ = that->maps_->Extend(object, maps, zone);
......@@ -556,8 +552,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::SetMaps(
LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
const AliasStateInfo& alias_info, Zone* zone) const {
if (is_unreachable()) return this;
if (this->maps_) {
AbstractMaps const* that_maps = this->maps_->Kill(alias_info, zone);
if (this->maps_ != that_maps) {
......@@ -588,8 +582,6 @@ LoadElimination::AbstractState::AddElement(Node* object, Node* index,
Node* value,
MachineRepresentation representation,
Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this);
if (that->elements_) {
that->elements_ =
......@@ -604,8 +596,6 @@ LoadElimination::AbstractState::AddElement(Node* object, Node* index,
LoadElimination::AbstractState const*
LoadElimination::AbstractState::KillElement(Node* object, Node* index,
Zone* zone) const {
if (is_unreachable()) return this;
if (this->elements_) {
AbstractElements const* that_elements =
this->elements_->Kill(object, index, zone);
......@@ -621,8 +611,6 @@ LoadElimination::AbstractState::KillElement(Node* object, Node* index,
LoadElimination::AbstractState const* LoadElimination::AbstractState::AddField(
Node* object, size_t index, Node* value, MaybeHandle<Name> name,
Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this);
if (that->fields_[index]) {
that->fields_[index] =
......@@ -642,8 +630,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
const AliasStateInfo& alias_info, size_t index, MaybeHandle<Name> name,
Zone* zone) const {
if (is_unreachable()) return this;
if (AbstractField const* this_field = this->fields_[index]) {
this_field = this_field->Kill(alias_info, name, zone);
if (this->fields_[index] != this_field) {
......@@ -658,8 +644,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
LoadElimination::AbstractState const*
LoadElimination::AbstractState::KillFields(Node* object, MaybeHandle<Name> name,
Zone* zone) const {
if (is_unreachable()) return this;
AliasStateInfo alias_info(this, object);
for (size_t i = 0;; ++i) {
if (i == arraysize(fields_)) return this;
......@@ -707,10 +691,6 @@ bool LoadElimination::AliasStateInfo::MayAlias(Node* other) const {
}
void LoadElimination::AbstractState::Print() const {
if (is_unreachable()) {
PrintF(" Unreachable\n");
}
if (checks_) {
PrintF(" checks:\n");
checks_->Print();
......@@ -731,18 +711,6 @@ void LoadElimination::AbstractState::Print() const {
}
}
// static
LoadElimination::AbstractState LoadElimination::AbstractState::Empty() {
return AbstractState();
}
// static
LoadElimination::AbstractState LoadElimination::AbstractState::Unreachable() {
AbstractState unreachable;
unreachable.is_unreachable_ = true;
return unreachable;
}
LoadElimination::AbstractState const*
LoadElimination::AbstractStateForEffectNodes::Get(Node* node) const {
size_t const id = node->id();
......@@ -769,27 +737,6 @@ Reduction LoadElimination::ReduceArrayBufferWasNeutered(Node* node) {
return UpdateState(node, state);
}
// static
LoadElimination::MapSetComparisonResult LoadElimination::CompareMapSets(
ZoneHandleSet<Map> const& lhs, ZoneHandleSet<Map> const& rhs) {
DCHECK(!lhs.is_empty());
DCHECK(!rhs.is_empty());
MapSetComparisonResult result = rhs.contains(ZoneHandleSet<Map>(lhs.at(0)))
? MapSetComparisonResult::kSubset
: MapSetComparisonResult::kDisjoint;
for (size_t i = 1; i < lhs.size(); i++) {
MapSetComparisonResult current = rhs.contains(ZoneHandleSet<Map>(lhs.at(i)))
? MapSetComparisonResult::kSubset
: MapSetComparisonResult::kDisjoint;
if (current != result) {
return MapSetComparisonResult::kOther;
}
}
return result;
}
Reduction LoadElimination::ReduceMapGuard(Node* node) {
ZoneHandleSet<Map> const maps = MapGuardMapsOf(node->op()).maps();
Node* const object = NodeProperties::GetValueInput(node, 0);
......@@ -798,15 +745,7 @@ Reduction LoadElimination::ReduceMapGuard(Node* node) {
if (state == nullptr) return NoChange();
ZoneHandleSet<Map> object_maps;
if (state->LookupMaps(object, &object_maps)) {
switch (CompareMapSets(object_maps, maps)) {
case MapSetComparisonResult::kSubset:
return Replace(effect);
case MapSetComparisonResult::kDisjoint:
state = unreachable_state();
break;
case MapSetComparisonResult::kOther:
break;
}
if (maps.contains(object_maps)) return Replace(effect);
// TODO(turbofan): Compute the intersection.
}
state = state->SetMaps(object, maps, zone());
......@@ -821,15 +760,7 @@ Reduction LoadElimination::ReduceCheckMaps(Node* node) {
if (state == nullptr) return NoChange();
ZoneHandleSet<Map> object_maps;
if (state->LookupMaps(object, &object_maps)) {
switch (CompareMapSets(object_maps, maps)) {
case MapSetComparisonResult::kSubset:
return Replace(effect);
case MapSetComparisonResult::kDisjoint:
state = unreachable_state();
break;
case MapSetComparisonResult::kOther:
break;
}
if (maps.contains(object_maps)) return Replace(effect);
// TODO(turbofan): Compute the intersection.
}
state = state->SetMaps(object, maps, zone());
......@@ -844,20 +775,12 @@ Reduction LoadElimination::ReduceCompareMaps(Node* node) {
if (state == nullptr) return NoChange();
ZoneHandleSet<Map> object_maps;
if (state->LookupMaps(object, &object_maps)) {
switch (CompareMapSets(object_maps, maps)) {
case MapSetComparisonResult::kSubset: {
Node* value = jsgraph()->TrueConstant();
ReplaceWithValue(node, value, effect);
return Replace(value);
}
case MapSetComparisonResult::kDisjoint: {
Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value, effect);
return Replace(value);
}
case MapSetComparisonResult::kOther:
break;
if (maps.contains(object_maps)) {
Node* value = jsgraph()->TrueConstant();
ReplaceWithValue(node, value, effect);
return Replace(value);
}
// TODO(turbofan): Compute the intersection.
}
return UpdateState(node, state);
}
......@@ -1183,29 +1106,9 @@ Reduction LoadElimination::ReduceEffectPhi(Node* node) {
// Shortcut for the case when we do not know anything about some input.
int const input_count = node->op()->EffectInputCount();
for (int i = 0; i < input_count; ++i) {
Node* effect = NodeProperties::GetEffectInput(node, i);
AbstractState const* input_state = node_states_.Get(effect);
if (input_state == nullptr) return NoChange();
if (input_state->is_unreachable()) {
// The state is unreachable, so we connect the control to the
// end.
Node* input_control = NodeProperties::GetControlInput(control, i);
effect = graph()->NewNode(jsgraph()->simplified()->RuntimeAbort(
BailoutReason::kUnreachableCodeReached),
effect, input_control);
input_control =
graph()->NewNode(common()->Throw(), effect, input_control);
NodeProperties::MergeControlToEnd(graph(), common(), input_control);
Revisit(graph()->end());
// Update the merge node with unreachable control input, and trigger
// revisit so that dead code elimination prunes the merge and its phis.
control->ReplaceInput(i, jsgraph()->Dead());
Revisit(control);
return NoChange();
}
for (int i = 1; i < input_count; ++i) {
Node* const effect = NodeProperties::GetEffectInput(node, i);
if (node_states_.Get(effect) == nullptr) return NoChange();
}
// Make a copy of the first input's state and merge with the state
......@@ -1228,13 +1131,6 @@ Reduction LoadElimination::ReduceEffectPhi(Node* node) {
return UpdateState(node, state_with_phis);
}
LoadElimination::LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone)
: AdvancedReducer(editor),
empty_state_(AbstractState::Empty()),
unreachable_state_(AbstractState::Unreachable()),
node_states_(zone),
jsgraph_(jsgraph) {}
Reduction LoadElimination::ReduceStart(Node* node) {
return UpdateState(node, empty_state());
}
......
......@@ -28,7 +28,8 @@ class JSGraph;
class V8_EXPORT_PRIVATE LoadElimination final
: public NON_EXPORTED_BASE(AdvancedReducer) {
public:
LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone);
LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone)
: AdvancedReducer(editor), node_states_(zone), jsgraph_(jsgraph) {}
~LoadElimination() final {}
const char* reducer_name() const override { return "LoadElimination"; }
......@@ -187,15 +188,6 @@ class V8_EXPORT_PRIVATE LoadElimination final
static size_t const kMaxTrackedFields = 32;
enum class MapSetComparisonResult {
kSubset,
kDisjoint,
kOther,
};
static MapSetComparisonResult CompareMapSets(ZoneHandleSet<Map> const& lhs,
ZoneHandleSet<Map> const& rhs);
// Abstract state to approximate the current map of an object along the
// effect paths through the graph.
class AbstractMaps final : public ZoneObject {
......@@ -221,6 +213,12 @@ class V8_EXPORT_PRIVATE LoadElimination final
class AbstractState final : public ZoneObject {
public:
AbstractState() {
for (size_t i = 0; i < arraysize(fields_); ++i) {
fields_[i] = nullptr;
}
}
bool Equals(AbstractState const* that) const;
void Merge(AbstractState const* that, Zone* zone);
......@@ -253,26 +251,13 @@ class V8_EXPORT_PRIVATE LoadElimination final
AbstractState const* AddCheck(Node* node, Zone* zone) const;
Node* LookupCheck(Node* node) const;
bool is_unreachable() const { return is_unreachable_; }
void Print() const;
static AbstractState Unreachable();
static AbstractState Empty();
private:
AbstractState() {
for (size_t i = 0; i < arraysize(fields_); ++i) {
fields_[i] = nullptr;
}
}
AbstractChecks const* checks_ = nullptr;
AbstractElements const* elements_ = nullptr;
AbstractField const* fields_[kMaxTrackedFields];
AbstractMaps const* maps_ = nullptr;
bool is_unreachable_ = false;
};
class AbstractStateForEffectNodes final : public ZoneObject {
......@@ -316,14 +301,12 @@ class V8_EXPORT_PRIVATE LoadElimination final
CommonOperatorBuilder* common() const;
AbstractState const* empty_state() const { return &empty_state_; }
AbstractState const* unreachable_state() const { return &unreachable_state_; }
Factory* factory() const;
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
Zone* zone() const { return node_states_.zone(); }
AbstractState const empty_state_;
AbstractState const unreachable_state_;
AbstractStateForEffectNodes node_states_;
JSGraph* const jsgraph_;
......
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