Commit 8f09a751 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

Revert "[turbofan] Load elimination prunes control flow based on instance type."

This reverts commit 71bcc1d9.

Reason for revert: Regresses Octane/Box2D, among other things.

Original change's description:
> [turbofan] Load elimination prunes control flow based on instance type.
> 
> Changes:
> - introduce the notion of unreachable abstract states.
> 
> - reconnect unreachables states to runtime abort in effect phis (so that
>   the merged states are not polluted by unreachable branches while
>   preserving SSA).
> 
> - mark states with failed map checks, unreachable map guars as unreachable.
> 
> - add instance type to AbstractMaps, only invalidate instance type on
>   mismatched effect merges.
> 
> 
> This results in 2-3% improvement on ARES/ML steady state.
> 
> Bug: v8:6396
> Change-Id: I35b0d4482fa400ba7ee9a754f8ef1b2663ebc7dc
> Reviewed-on: https://chromium-review.googlesource.com/727761
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#48742}

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

Change-Id: I6302b37dbf5ea781c64815ef1900681531ad7d71
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6396
Reviewed-on: https://chromium-review.googlesource.com/728440Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48763}
parent ff8b937f
...@@ -141,7 +141,6 @@ namespace internal { ...@@ -141,7 +141,6 @@ namespace internal {
V(kUnexpectedReturnFromFrameDropper, \ V(kUnexpectedReturnFromFrameDropper, \
"Unexpectedly returned from dropping frames") \ "Unexpectedly returned from dropping frames") \
V(kUnexpectedReturnFromThrow, "Unexpectedly returned from a throw") \ V(kUnexpectedReturnFromThrow, "Unexpectedly returned from a throw") \
V(kUnreachableCodeReached, "Reached unreachable code") \
V(kVariableResolvedToWithContext, "Variable resolved to with context") \ V(kVariableResolvedToWithContext, "Variable resolved to with context") \
V(kWithStatement, "WithStatement") \ V(kWithStatement, "WithStatement") \
V(kWrongFunctionContext, "Wrong context passed to function") \ V(kWrongFunctionContext, "Wrong context passed to function") \
......
...@@ -297,6 +297,11 @@ RegionObservability RegionObservabilityOf(Operator const* op) { ...@@ -297,6 +297,11 @@ RegionObservability RegionObservabilityOf(Operator const* op) {
return OpParameter<RegionObservability>(op); return OpParameter<RegionObservability>(op);
} }
ZoneHandleSet<Map> MapGuardMapsOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
return OpParameter<ZoneHandleSet<Map>>(op);
}
Type* TypeGuardTypeOf(Operator const* op) { Type* TypeGuardTypeOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode()); DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode());
return OpParameter<Type*>(op); return OpParameter<Type*>(op);
...@@ -1125,6 +1130,14 @@ const Operator* CommonOperatorBuilder::Phi(MachineRepresentation rep, ...@@ -1125,6 +1130,14 @@ const Operator* CommonOperatorBuilder::Phi(MachineRepresentation rep,
rep); // parameter rep); // parameter
} }
const Operator* CommonOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
return new (zone()) Operator1<ZoneHandleSet<Map>>( // --
IrOpcode::kMapGuard, Operator::kEliminatable, // opcode
"MapGuard", // name
1, 1, 1, 0, 1, 0, // counts
maps); // parameter
}
const Operator* CommonOperatorBuilder::TypeGuard(Type* type) { const Operator* CommonOperatorBuilder::TypeGuard(Type* type) {
return new (zone()) Operator1<Type*>( // -- return new (zone()) Operator1<Type*>( // --
IrOpcode::kTypeGuard, Operator::kPure, // opcode IrOpcode::kTypeGuard, Operator::kPure, // opcode
......
...@@ -304,6 +304,8 @@ RegionObservability RegionObservabilityOf(Operator const*) WARN_UNUSED_RESULT; ...@@ -304,6 +304,8 @@ RegionObservability RegionObservabilityOf(Operator const*) WARN_UNUSED_RESULT;
std::ostream& operator<<(std::ostream& os, std::ostream& operator<<(std::ostream& os,
const ZoneVector<MachineType>* types); const ZoneVector<MachineType>* types);
ZoneHandleSet<Map> MapGuardMapsOf(Operator const*) WARN_UNUSED_RESULT;
Type* TypeGuardTypeOf(Operator const*) WARN_UNUSED_RESULT; Type* TypeGuardTypeOf(Operator const*) WARN_UNUSED_RESULT;
int OsrValueIndexOf(Operator const*); int OsrValueIndexOf(Operator const*);
...@@ -417,6 +419,7 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final ...@@ -417,6 +419,7 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
const Operator* TailCall(const CallDescriptor* descriptor); const Operator* TailCall(const CallDescriptor* descriptor);
const Operator* Projection(size_t index); const Operator* Projection(size_t index);
const Operator* Retain(); const Operator* Retain();
const Operator* MapGuard(ZoneHandleSet<Map> maps);
const Operator* TypeGuard(Type* type); const Operator* TypeGuard(Type* type);
// Constructs a new merge or phi operator with the same opcode as {op}, but // Constructs a new merge or phi operator with the same opcode as {op}, but
......
...@@ -1330,7 +1330,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { ...@@ -1330,7 +1330,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
} }
Node* EffectControlLinearizer::LowerCompareMaps(Node* node) { Node* EffectControlLinearizer::LowerCompareMaps(Node* node) {
ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op()).maps(); ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op());
size_t const map_count = maps.size(); size_t const map_count = maps.size();
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
......
...@@ -661,8 +661,8 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current, ...@@ -661,8 +661,8 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
if (Node* map = current->Get(map_field)) { if (Node* map = current->Get(map_field)) {
Type* const map_type = NodeProperties::GetType(map); Type* const map_type = NodeProperties::GetType(map);
if (map_type->IsHeapConstant() && if (map_type->IsHeapConstant() &&
params.maps().contains( params.maps().contains(ZoneHandleSet<Map>(bit_cast<Handle<Map>>(
bit_cast<Handle<Map>>(map_type->AsHeapConstant()->Value()))) { map_type->AsHeapConstant()->Value())))) {
current->MarkForDeletion(); current->MarkForDeletion();
break; break;
} }
...@@ -683,7 +683,7 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current, ...@@ -683,7 +683,7 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
vobject->FieldAt(HeapObject::kMapOffset).To(&map_field)) { vobject->FieldAt(HeapObject::kMapOffset).To(&map_field)) {
if (Node* object_map = current->Get(map_field)) { if (Node* object_map = current->Get(map_field)) {
current->SetReplacement(LowerCompareMapsWithoutLoad( current->SetReplacement(LowerCompareMapsWithoutLoad(
object_map, CompareMapsParametersOf(op).maps(), jsgraph)); object_map, CompareMapsParametersOf(op), jsgraph));
break; break;
} else { } else {
// If the variable has no value, we have not reached the fixed-point // If the variable has no value, we have not reached the fixed-point
......
...@@ -840,7 +840,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -840,7 +840,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
for (auto receiver_map : receiver_maps) { for (auto receiver_map : receiver_maps) {
maps.insert(receiver_map, graph()->zone()); maps.insert(receiver_map, graph()->zone());
} }
this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver, this_effect = graph()->NewNode(common()->MapGuard(maps), receiver,
this_effect, this_control); this_effect, this_control);
} }
} }
...@@ -1196,7 +1196,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -1196,7 +1196,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
this_control = graph()->NewNode(common()->IfTrue(), branch); this_control = graph()->NewNode(common()->IfTrue(), branch);
// Introduce a MapGuard to learn from this on the effect chain. // Introduce a MapGuard to learn from this on the effect chain.
this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver, this_effect = graph()->NewNode(common()->MapGuard(maps), receiver,
this_effect, this_control); this_effect, this_control);
} }
......
...@@ -373,20 +373,9 @@ void LoadElimination::AbstractField::Print() const { ...@@ -373,20 +373,9 @@ void LoadElimination::AbstractField::Print() const {
bool LoadElimination::AbstractMaps::Lookup( bool LoadElimination::AbstractMaps::Lookup(
Node* object, ZoneHandleSet<Map>* object_maps) const { Node* object, ZoneHandleSet<Map>* object_maps) const {
for (auto pair : info_for_node_) {
if (MustAlias(object, pair.first) && pair.second.maps_valid()) {
*object_maps = pair.second.maps();
return true;
}
}
return false;
}
bool LoadElimination::AbstractMaps::Lookup(Node* object,
AbstractMapInfo* maps_info) const {
for (auto pair : info_for_node_) { for (auto pair : info_for_node_) {
if (MustAlias(object, pair.first)) { if (MustAlias(object, pair.first)) {
*maps_info = pair.second; *object_maps = pair.second;
return true; return true;
} }
} }
...@@ -396,18 +385,10 @@ bool LoadElimination::AbstractMaps::Lookup(Node* object, ...@@ -396,18 +385,10 @@ bool LoadElimination::AbstractMaps::Lookup(Node* object,
LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill( LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
const AliasStateInfo& alias_info, Zone* zone) const { const AliasStateInfo& alias_info, Zone* zone) const {
for (auto pair : this->info_for_node_) { for (auto pair : this->info_for_node_) {
if (alias_info.MayAlias(pair.first) && pair.second.maps_valid()) { if (alias_info.MayAlias(pair.first)) {
AbstractMaps* that = new (zone) AbstractMaps(zone); AbstractMaps* that = new (zone) AbstractMaps(zone);
for (auto pair : this->info_for_node_) { for (auto pair : this->info_for_node_) {
if (!alias_info.MayAlias(pair.first)) { if (!alias_info.MayAlias(pair.first)) that->info_for_node_.insert(pair);
// Keep the elements that cannto alias.
that->info_for_node_.insert(pair);
} else if (pair.second.instance_type_valid()) {
// Instance type information cannot be invalidated, so we just
// throw away the map part.
that->info_for_node_.insert(std::make_pair(
pair.first, AbstractMapInfo(pair.second.instance_type())));
}
} }
return that; return that;
} }
...@@ -415,137 +396,36 @@ LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill( ...@@ -415,137 +396,36 @@ LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
return this; return this;
} }
LoadElimination::AbstractMapInfo::AbstractMapInfo()
: instance_type_(FIRST_TYPE), info_validity_(0) {}
LoadElimination::AbstractMapInfo::AbstractMapInfo(
ZoneHandleSet<Map> const& maps)
: maps_(maps), instance_type_(FIRST_TYPE), info_validity_(kMapsValid) {
DCHECK(!maps.is_empty());
}
LoadElimination::AbstractMapInfo::AbstractMapInfo(InstanceType instance_type)
: instance_type_(instance_type), info_validity_(kInstanceTypeValid) {}
LoadElimination::AbstractMapInfo::AbstractMapInfo(MapsParameterInfo const& info)
: maps_(info.maps()),
instance_type_(FIRST_TYPE),
info_validity_(kMapsValid) {
InstanceType instance_type;
if (info.instance_type().To(&instance_type)) {
instance_type_ = instance_type;
info_validity_ |= kInstanceTypeValid;
}
}
LoadElimination::AbstractMapInfo::AbstractMapInfo(
ZoneHandleSet<Map> const& maps, InstanceType instance_type,
Validity validity)
: maps_(maps), instance_type_(instance_type), info_validity_(validity) {}
bool LoadElimination::AbstractMapInfo::operator==(
AbstractMapInfo const& other) const {
return info_validity_ == other.info_validity_ &&
instance_type_ == other.instance_type_ && maps_ == other.maps_;
}
bool LoadElimination::AbstractMapInfo::operator!=(
AbstractMapInfo const& other) const {
return !(*this == other);
}
ZoneHandleSet<Map> const& LoadElimination::AbstractMapInfo::maps() const {
DCHECK(info_validity_ & kMapsValid);
return maps_;
}
InstanceType LoadElimination::AbstractMapInfo::instance_type() const {
DCHECK(info_validity_ & kInstanceTypeValid);
return instance_type_;
}
LoadElimination::AbstractMapInfo LoadElimination::AbstractMapInfo::Merge(
AbstractMapInfo const& other) const {
// Merge the map information and the instance type information.
Validity validity = info_validity_ & other.info_validity_;
ZoneHandleSet<Map> merged_maps;
InstanceType merged_instance_type = FIRST_TYPE;
if ((validity & kInstanceTypeValid) &&
instance_type() == other.instance_type()) {
merged_instance_type = instance_type_;
} else {
validity &= ~Validity(kInstanceTypeValid);
}
if ((validity & kMapsValid) && maps() == other.maps()) {
merged_maps = maps_;
} else {
validity &= ~Validity(kMapsValid);
}
return AbstractMapInfo(merged_maps, merged_instance_type, validity);
}
LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Merge( LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Merge(
AbstractMaps const* that, Zone* zone) const { AbstractMaps const* that, Zone* zone) const {
if (this->Equals(that)) return this; if (this->Equals(that)) return this;
AbstractMaps* copy = new (zone) AbstractMaps(zone); AbstractMaps* copy = new (zone) AbstractMaps(zone);
for (auto this_it : this->info_for_node_) { for (auto this_it : this->info_for_node_) {
Node* this_object = this_it.first; Node* this_object = this_it.first;
AbstractMapInfo const& this_maps_info = this_it.second; ZoneHandleSet<Map> this_maps = this_it.second;
auto that_it = that->info_for_node_.find(this_object); auto that_it = that->info_for_node_.find(this_object);
if (that_it == that->info_for_node_.end()) continue; if (that_it != that->info_for_node_.end() && that_it->second == this_maps) {
AbstractMapInfo const& that_maps_info = that_it->second; copy->info_for_node_.insert(this_it);
// Merge the map information and the instance type information.
AbstractMapInfo merged = this_maps_info.Merge(that_maps_info);
if (!merged.empty()) {
copy->info_for_node_.insert({this_object, merged});
} }
} }
return copy; return copy;
} }
LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Extend( LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Extend(
Node* object, AbstractMapInfo const& map_info, Zone* zone) const { Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
AbstractMaps* that = new (zone) AbstractMaps(zone); AbstractMaps* that = new (zone) AbstractMaps(zone);
that->info_for_node_ = this->info_for_node_; that->info_for_node_ = this->info_for_node_;
that->info_for_node_[object] = map_info; that->info_for_node_.insert(std::make_pair(object, maps));
return that; return that;
} }
LoadElimination::AbstractMaps const*
LoadElimination::AbstractMaps::KillMutableState(Zone* zone) const {
for (auto pair : this->info_for_node_) {
if (pair.second.maps_valid()) {
// We have the map part valid, so we have to invalidate.
AbstractMaps* that = nullptr; // Allocated lazily.
for (auto pair : this->info_for_node_) {
if (pair.second.instance_type_valid()) {
if (that == nullptr) {
that = new (zone) AbstractMaps(zone);
}
that->info_for_node_.insert(std::make_pair(
pair.first, AbstractMapInfo(pair.second.instance_type())));
}
}
return that;
}
}
return this;
}
void LoadElimination::AbstractMaps::Print() const { void LoadElimination::AbstractMaps::Print() const {
for (auto pair : info_for_node_) { for (auto pair : info_for_node_) {
PrintF(" #%d:%s\n", pair.first->id(), pair.first->op()->mnemonic());
OFStream os(stdout); OFStream os(stdout);
os << " #" << pair.first->id() << ":" << pair.first->op()->mnemonic() ZoneHandleSet<Map> const& maps = pair.second;
<< std::endl;
if (pair.second.maps_valid()) {
ZoneHandleSet<Map> const& maps = pair.second.maps();
for (size_t i = 0; i < maps.size(); ++i) { for (size_t i = 0; i < maps.size(); ++i) {
os << " - " << Brief(*maps.at(i)) << std::endl; os << " - " << Brief(*maps[i]) << "\n";
}
}
if (pair.second.instance_type_valid()) {
os << " Instance type: " << pair.second.instance_type() << std::endl;
} }
} }
} }
...@@ -620,34 +500,8 @@ Node* LoadElimination::AbstractState::LookupCheck(Node* node) const { ...@@ -620,34 +500,8 @@ Node* LoadElimination::AbstractState::LookupCheck(Node* node) const {
return this->checks_ ? this->checks_->Lookup(node) : nullptr; return this->checks_ ? this->checks_->Lookup(node) : nullptr;
} }
LoadElimination::AbstractState const*
LoadElimination::AbstractState::KillMutableState(Zone* zone) const {
if (is_unreachable()) return this;
AbstractMaps const* new_maps =
maps_ ? maps_->KillMutableState(zone) : nullptr;
// If the state is unchanged, just return the existing one.
if (new_maps == maps_ && checks_ == nullptr && elements_ == nullptr) {
bool all_fields_empty = true;
for (size_t i = 0; i < arraysize(fields_); ++i) {
if (fields_[i] != nullptr) {
all_fields_empty = false;
break;
}
}
if (all_fields_empty) return this;
}
AbstractState* new_state = new (zone) AbstractState();
new_state->maps_ = new_maps;
return new_state;
}
LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck( LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck(
Node* node, Zone* zone) const { Node* node, Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this); AbstractState* that = new (zone) AbstractState(*this);
if (that->checks_) { if (that->checks_) {
that->checks_ = that->checks_->Extend(node, zone); that->checks_ = that->checks_->Extend(node, zone);
...@@ -662,35 +516,19 @@ bool LoadElimination::AbstractState::LookupMaps( ...@@ -662,35 +516,19 @@ bool LoadElimination::AbstractState::LookupMaps(
return this->maps_ && this->maps_->Lookup(object, object_map); return this->maps_ && this->maps_->Lookup(object, object_map);
} }
bool LoadElimination::AbstractState::LookupMaps(
Node* object, AbstractMapInfo* map_info) const {
return this->maps_ && this->maps_->Lookup(object, map_info);
}
LoadElimination::AbstractState const* LoadElimination::AbstractState::AddMaps( LoadElimination::AbstractState const* LoadElimination::AbstractState::AddMaps(
Node* object, ZoneHandleSet<Map> maps, Zone* zone) const { Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
if (is_unreachable()) return this;
AbstractMapInfo map_info(maps);
return AddMaps(object, map_info, zone);
}
LoadElimination::AbstractState const* LoadElimination::AbstractState::AddMaps(
Node* object, AbstractMapInfo const& map_info, Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this); AbstractState* that = new (zone) AbstractState(*this);
if (that->maps_) { if (that->maps_) {
that->maps_ = that->maps_->Extend(object, map_info, zone); that->maps_ = that->maps_->Extend(object, maps, zone);
} else { } else {
that->maps_ = new (zone) AbstractMaps(object, map_info, zone); that->maps_ = new (zone) AbstractMaps(object, maps, zone);
} }
return that; return that;
} }
LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps( LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
const AliasStateInfo& alias_info, Zone* zone) const { const AliasStateInfo& alias_info, Zone* zone) const {
if (is_unreachable()) return this;
if (this->maps_) { if (this->maps_) {
AbstractMaps const* that_maps = this->maps_->Kill(alias_info, zone); AbstractMaps const* that_maps = this->maps_->Kill(alias_info, zone);
if (this->maps_ != that_maps) { if (this->maps_ != that_maps) {
...@@ -704,8 +542,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps( ...@@ -704,8 +542,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps( LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
Node* object, Zone* zone) const { Node* object, Zone* zone) const {
if (is_unreachable()) return this;
AliasStateInfo alias_info(this, object); AliasStateInfo alias_info(this, object);
return KillMaps(alias_info, zone); return KillMaps(alias_info, zone);
} }
...@@ -723,8 +559,6 @@ LoadElimination::AbstractState::AddElement(Node* object, Node* index, ...@@ -723,8 +559,6 @@ LoadElimination::AbstractState::AddElement(Node* object, Node* index,
Node* value, Node* value,
MachineRepresentation representation, MachineRepresentation representation,
Zone* zone) const { Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this); AbstractState* that = new (zone) AbstractState(*this);
if (that->elements_) { if (that->elements_) {
that->elements_ = that->elements_ =
...@@ -739,8 +573,6 @@ LoadElimination::AbstractState::AddElement(Node* object, Node* index, ...@@ -739,8 +573,6 @@ LoadElimination::AbstractState::AddElement(Node* object, Node* index,
LoadElimination::AbstractState const* LoadElimination::AbstractState const*
LoadElimination::AbstractState::KillElement(Node* object, Node* index, LoadElimination::AbstractState::KillElement(Node* object, Node* index,
Zone* zone) const { Zone* zone) const {
if (is_unreachable()) return this;
if (this->elements_) { if (this->elements_) {
AbstractElements const* that_elements = AbstractElements const* that_elements =
this->elements_->Kill(object, index, zone); this->elements_->Kill(object, index, zone);
...@@ -756,8 +588,6 @@ LoadElimination::AbstractState::KillElement(Node* object, Node* index, ...@@ -756,8 +588,6 @@ LoadElimination::AbstractState::KillElement(Node* object, Node* index,
LoadElimination::AbstractState const* LoadElimination::AbstractState::AddField( LoadElimination::AbstractState const* LoadElimination::AbstractState::AddField(
Node* object, size_t index, Node* value, MaybeHandle<Name> name, Node* object, size_t index, Node* value, MaybeHandle<Name> name,
Zone* zone) const { Zone* zone) const {
if (is_unreachable()) return this;
AbstractState* that = new (zone) AbstractState(*this); AbstractState* that = new (zone) AbstractState(*this);
if (that->fields_[index]) { if (that->fields_[index]) {
that->fields_[index] = that->fields_[index] =
...@@ -770,8 +600,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::AddField( ...@@ -770,8 +600,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::AddField(
LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField( LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
Node* object, size_t index, MaybeHandle<Name> name, Zone* zone) const { Node* object, size_t index, MaybeHandle<Name> name, Zone* zone) const {
if (is_unreachable()) return this;
AliasStateInfo alias_info(this, object); AliasStateInfo alias_info(this, object);
return KillField(alias_info, index, name, zone); return KillField(alias_info, index, name, zone);
} }
...@@ -779,8 +607,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField( ...@@ -779,8 +607,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField( LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
const AliasStateInfo& alias_info, size_t index, MaybeHandle<Name> name, const AliasStateInfo& alias_info, size_t index, MaybeHandle<Name> name,
Zone* zone) const { Zone* zone) const {
if (is_unreachable()) return this;
if (AbstractField const* this_field = this->fields_[index]) { if (AbstractField const* this_field = this->fields_[index]) {
this_field = this_field->Kill(alias_info, name, zone); this_field = this_field->Kill(alias_info, name, zone);
if (this->fields_[index] != this_field) { if (this->fields_[index] != this_field) {
...@@ -795,8 +621,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField( ...@@ -795,8 +621,6 @@ LoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
LoadElimination::AbstractState const* LoadElimination::AbstractState const*
LoadElimination::AbstractState::KillFields(Node* object, MaybeHandle<Name> name, LoadElimination::AbstractState::KillFields(Node* object, MaybeHandle<Name> name,
Zone* zone) const { Zone* zone) const {
if (is_unreachable()) return this;
AliasStateInfo alias_info(this, object); AliasStateInfo alias_info(this, object);
for (size_t i = 0;; ++i) { for (size_t i = 0;; ++i) {
if (i == arraysize(fields_)) return this; if (i == arraysize(fields_)) return this;
...@@ -842,10 +666,6 @@ bool LoadElimination::AliasStateInfo::MayAlias(Node* other) const { ...@@ -842,10 +666,6 @@ bool LoadElimination::AliasStateInfo::MayAlias(Node* other) const {
} }
void LoadElimination::AbstractState::Print() const { void LoadElimination::AbstractState::Print() const {
if (is_unreachable()) {
PrintF(" Unreachable\n");
}
if (checks_) { if (checks_) {
PrintF(" checks:\n"); PrintF(" checks:\n");
checks_->Print(); checks_->Print();
...@@ -866,18 +686,6 @@ void LoadElimination::AbstractState::Print() const { ...@@ -866,18 +686,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::AbstractState const*
LoadElimination::AbstractStateForEffectNodes::Get(Node* node) const { LoadElimination::AbstractStateForEffectNodes::Get(Node* node) const {
size_t const id = node->id(); size_t const id = node->id();
...@@ -904,112 +712,52 @@ Reduction LoadElimination::ReduceArrayBufferWasNeutered(Node* node) { ...@@ -904,112 +712,52 @@ Reduction LoadElimination::ReduceArrayBufferWasNeutered(Node* node) {
return UpdateState(node, state); 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(lhs.at(0))
? MapSetComparisonResult::kSubset
: MapSetComparisonResult::kDisjoint;
for (size_t i = 1; i < lhs.size(); i++) {
MapSetComparisonResult current = rhs.contains(lhs.at(i))
? MapSetComparisonResult::kSubset
: MapSetComparisonResult::kDisjoint;
if (current != result) {
return MapSetComparisonResult::kOther;
}
}
return result;
}
LoadElimination::MapSetComparisonResult
LoadElimination::AbstractMapInfo::Compare(AbstractMapInfo const& other) const {
// If we have map information, decide based on that.
if (maps_valid() && other.maps_valid()) {
return CompareMapSets(maps(), other.maps());
}
// If we do not have maps, try to use the instance types.
if (instance_type_valid() && other.instance_type_valid() &&
instance_type() != other.instance_type()) {
return MapSetComparisonResult::kDisjoint;
}
return MapSetComparisonResult::kOther;
}
Reduction LoadElimination::ReduceMapGuard(Node* node) { Reduction LoadElimination::ReduceMapGuard(Node* node) {
AbstractMapInfo guarded_maps(MapGuardMapsOf(node->op())); ZoneHandleSet<Map> const maps = MapGuardMapsOf(node->op());
Node* const object = NodeProperties::GetValueInput(node, 0); Node* const object = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node); Node* const effect = NodeProperties::GetEffectInput(node);
AbstractState const* state = node_states_.Get(effect); AbstractState const* state = node_states_.Get(effect);
if (state == nullptr) return NoChange(); if (state == nullptr) return NoChange();
AbstractMapInfo state_info; ZoneHandleSet<Map> object_maps;
if (state->LookupMaps(object, &state_info)) { if (state->LookupMaps(object, &object_maps)) {
switch (state_info.Compare(guarded_maps)) { if (maps.contains(object_maps)) return Replace(effect);
case MapSetComparisonResult::kSubset:
return Replace(effect);
case MapSetComparisonResult::kDisjoint:
state = unreachable_state();
break;
case MapSetComparisonResult::kOther:
break;
}
state = state->KillMaps(object, zone()); state = state->KillMaps(object, zone());
// TODO(turbofan): Compute the intersection. // TODO(turbofan): Compute the intersection.
} }
state = state->AddMaps(object, guarded_maps, zone()); state = state->AddMaps(object, maps, zone());
return UpdateState(node, state); return UpdateState(node, state);
} }
Reduction LoadElimination::ReduceCheckMaps(Node* node) { Reduction LoadElimination::ReduceCheckMaps(Node* node) {
AbstractMapInfo checked_maps(CheckMapsParametersOf(node->op()).maps_info()); ZoneHandleSet<Map> const maps = CheckMapsParametersOf(node->op()).maps();
Node* const object = NodeProperties::GetValueInput(node, 0); Node* const object = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node); Node* const effect = NodeProperties::GetEffectInput(node);
AbstractState const* state = node_states_.Get(effect); AbstractState const* state = node_states_.Get(effect);
if (state == nullptr) return NoChange(); if (state == nullptr) return NoChange();
AbstractMapInfo map_info; ZoneHandleSet<Map> object_maps;
if (state->LookupMaps(object, &map_info)) { if (state->LookupMaps(object, &object_maps)) {
switch (map_info.Compare(checked_maps)) { if (maps.contains(object_maps)) return Replace(effect);
case MapSetComparisonResult::kSubset:
return Replace(effect);
case MapSetComparisonResult::kDisjoint: {
state = unreachable_state();
break;
}
case MapSetComparisonResult::kOther:
break;
}
state = state->KillMaps(object, zone()); state = state->KillMaps(object, zone());
// TODO(turbofan): Compute the intersection. // TODO(turbofan): Compute the intersection.
} }
state = state->AddMaps(object, checked_maps, zone()); state = state->AddMaps(object, maps, zone());
return UpdateState(node, state); return UpdateState(node, state);
} }
Reduction LoadElimination::ReduceCompareMaps(Node* node) { Reduction LoadElimination::ReduceCompareMaps(Node* node) {
AbstractMapInfo compared_maps(CompareMapsParametersOf(node->op())); ZoneHandleSet<Map> const maps = CompareMapsParametersOf(node->op());
Node* const object = NodeProperties::GetValueInput(node, 0); Node* const object = NodeProperties::GetValueInput(node, 0);
Node* const effect = NodeProperties::GetEffectInput(node); Node* const effect = NodeProperties::GetEffectInput(node);
AbstractState const* state = node_states_.Get(effect); AbstractState const* state = node_states_.Get(effect);
if (state == nullptr) return NoChange(); if (state == nullptr) return NoChange();
AbstractMapInfo map_info; ZoneHandleSet<Map> object_maps;
if (state->LookupMaps(object, &map_info)) { if (state->LookupMaps(object, &object_maps)) {
switch (map_info.Compare(compared_maps)) { if (maps.contains(object_maps)) {
case MapSetComparisonResult::kSubset: {
Node* value = jsgraph()->TrueConstant(); Node* value = jsgraph()->TrueConstant();
ReplaceWithValue(node, value, effect); ReplaceWithValue(node, value, effect);
return Replace(value); return Replace(value);
} }
case MapSetComparisonResult::kDisjoint: { // TODO(turbofan): Compute the intersection.
Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value, effect);
return Replace(value);
}
case MapSetComparisonResult::kOther:
break;
}
} }
return UpdateState(node, state); return UpdateState(node, state);
} }
...@@ -1089,7 +837,7 @@ Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) { ...@@ -1089,7 +837,7 @@ Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
// {node} is fully redundant (independent of what {source_map} is). // {node} is fully redundant (independent of what {source_map} is).
return Replace(effect); return Replace(effect);
} }
if (object_maps.contains(source_map)) { if (object_maps.contains(ZoneHandleSet<Map>(source_map))) {
object_maps.remove(source_map, zone()); object_maps.remove(source_map, zone());
object_maps.insert(target_map, zone()); object_maps.insert(target_map, zone());
AliasStateInfo alias_info(state, object, source_map); AliasStateInfo alias_info(state, object, source_map);
...@@ -1338,29 +1086,9 @@ Reduction LoadElimination::ReduceEffectPhi(Node* node) { ...@@ -1338,29 +1086,9 @@ Reduction LoadElimination::ReduceEffectPhi(Node* node) {
// Shortcut for the case when we do not know anything about some input. // Shortcut for the case when we do not know anything about some input.
int const input_count = node->op()->EffectInputCount(); int const input_count = node->op()->EffectInputCount();
for (int i = 0; i < input_count; ++i) { for (int i = 1; i < input_count; ++i) {
Node* effect = NodeProperties::GetEffectInput(node, i); Node* const effect = NodeProperties::GetEffectInput(node, i);
AbstractState const* input_state = node_states_.Get(effect); if (node_states_.Get(effect) == nullptr) return NoChange();
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();
}
} }
// Make a copy of the first input's state and merge with the state // Make a copy of the first input's state and merge with the state
...@@ -1398,7 +1126,7 @@ Reduction LoadElimination::ReduceOtherNode(Node* node) { ...@@ -1398,7 +1126,7 @@ Reduction LoadElimination::ReduceOtherNode(Node* node) {
if (state == nullptr) return NoChange(); if (state == nullptr) return NoChange();
// Check if this {node} has some uncontrolled side effects. // Check if this {node} has some uncontrolled side effects.
if (!node->op()->HasProperty(Operator::kNoWrite)) { if (!node->op()->HasProperty(Operator::kNoWrite)) {
state = state->KillMutableState(zone()); state = empty_state();
} }
return UpdateState(node, state); return UpdateState(node, state);
} else { } else {
...@@ -1508,7 +1236,7 @@ LoadElimination::AbstractState const* LoadElimination::ComputeLoopState( ...@@ -1508,7 +1236,7 @@ LoadElimination::AbstractState const* LoadElimination::ComputeLoopState(
break; break;
} }
default: default:
return state->KillMutableState(zone()); return empty_state();
} }
} }
for (int i = 0; i < current->op()->EffectInputCount(); ++i) { for (int i = 0; i < current->op()->EffectInputCount(); ++i) {
...@@ -1607,13 +1335,6 @@ int LoadElimination::FieldIndexOf(FieldAccess const& access) { ...@@ -1607,13 +1335,6 @@ int LoadElimination::FieldIndexOf(FieldAccess const& access) {
return FieldIndexOf(access.offset); return FieldIndexOf(access.offset);
} }
LoadElimination::LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone)
: AdvancedReducer(editor),
empty_state_(AbstractState::Empty()),
unreachable_state_(AbstractState::Unreachable()),
node_states_(zone),
jsgraph_(jsgraph) {}
CommonOperatorBuilder* LoadElimination::common() const { CommonOperatorBuilder* LoadElimination::common() const {
return jsgraph()->common(); return jsgraph()->common();
} }
......
...@@ -24,12 +24,12 @@ class CommonOperatorBuilder; ...@@ -24,12 +24,12 @@ class CommonOperatorBuilder;
struct FieldAccess; struct FieldAccess;
class Graph; class Graph;
class JSGraph; class JSGraph;
class MapsParameterInfo;
class V8_EXPORT_PRIVATE LoadElimination final class V8_EXPORT_PRIVATE LoadElimination final
: public NON_EXPORTED_BASE(AdvancedReducer) { : public NON_EXPORTED_BASE(AdvancedReducer) {
public: public:
LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone); LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone)
: AdvancedReducer(editor), node_states_(zone), jsgraph_(jsgraph) {}
~LoadElimination() final {} ~LoadElimination() final {}
const char* reducer_name() const override { return "LoadElimination"; } const char* reducer_name() const override { return "LoadElimination"; }
...@@ -188,92 +188,49 @@ class V8_EXPORT_PRIVATE LoadElimination final ...@@ -188,92 +188,49 @@ class V8_EXPORT_PRIVATE LoadElimination final
static size_t const kMaxTrackedFields = 32; static size_t const kMaxTrackedFields = 32;
enum class MapSetComparisonResult {
kSubset,
kDisjoint,
kOther,
};
static MapSetComparisonResult CompareMapSets(ZoneHandleSet<Map> const& lhs,
ZoneHandleSet<Map> const& rhs);
class AbstractMapInfo {
public:
enum InfoValid { kMapsValid = 1 << 0, kInstanceTypeValid = 1 << 1 };
typedef base::Flags<InfoValid, uint8_t> Validity;
AbstractMapInfo();
explicit AbstractMapInfo(ZoneHandleSet<Map> const& maps);
explicit AbstractMapInfo(InstanceType instance_type);
explicit AbstractMapInfo(MapsParameterInfo const& info);
bool operator==(AbstractMapInfo const& other) const;
bool operator!=(AbstractMapInfo const& other) const;
ZoneHandleSet<Map> const& maps() const;
InstanceType instance_type() const;
bool maps_valid() const { return info_validity_ & kMapsValid; }
bool instance_type_valid() const {
return info_validity_ & kInstanceTypeValid;
}
bool empty() const { return info_validity_ == 0; }
AbstractMapInfo Merge(AbstractMapInfo const& other) const;
MapSetComparisonResult Compare(AbstractMapInfo const& other) const;
private:
AbstractMapInfo(ZoneHandleSet<Map> const& maps, InstanceType instance_type,
Validity validity);
ZoneHandleSet<Map> maps_;
InstanceType instance_type_;
Validity info_validity_;
};
// Abstract state to approximate the current map of an object along the // Abstract state to approximate the current map of an object along the
// effect paths through the graph. // effect paths through the graph.
class AbstractMaps final : public ZoneObject { class AbstractMaps final : public ZoneObject {
public: public:
explicit AbstractMaps(Zone* zone) : info_for_node_(zone) {} explicit AbstractMaps(Zone* zone) : info_for_node_(zone) {}
AbstractMaps(Node* object, AbstractMapInfo const& map_info, Zone* zone) AbstractMaps(Node* object, ZoneHandleSet<Map> maps, Zone* zone)
: info_for_node_(zone) { : info_for_node_(zone) {
info_for_node_.insert(std::make_pair(object, map_info)); info_for_node_.insert(std::make_pair(object, maps));
} }
AbstractMaps const* Extend(Node* object, AbstractMapInfo const& maps, AbstractMaps const* Extend(Node* object, ZoneHandleSet<Map> maps,
Zone* zone) const; Zone* zone) const;
bool Lookup(Node* object, ZoneHandleSet<Map>* object_maps) const; bool Lookup(Node* object, ZoneHandleSet<Map>* object_maps) const;
bool Lookup(Node* object, AbstractMapInfo* maps_info) const;
AbstractMaps const* Kill(const AliasStateInfo& alias_info, AbstractMaps const* Kill(const AliasStateInfo& alias_info,
Zone* zone) const; Zone* zone) const;
bool Equals(AbstractMaps const* that) const { bool Equals(AbstractMaps const* that) const {
return this == that || this->info_for_node_ == that->info_for_node_; return this == that || this->info_for_node_ == that->info_for_node_;
} }
AbstractMaps const* Merge(AbstractMaps const* that, Zone* zone) const; AbstractMaps const* Merge(AbstractMaps const* that, Zone* zone) const;
AbstractMaps const* KillMutableState(Zone* zone) const;
void Print() const; void Print() const;
private: private:
ZoneMap<Node*, AbstractMapInfo> info_for_node_; ZoneMap<Node*, ZoneHandleSet<Map>> info_for_node_;
}; };
class AbstractState final : public ZoneObject { class AbstractState final : public ZoneObject {
public: public:
AbstractState() {
for (size_t i = 0; i < arraysize(fields_); ++i) {
fields_[i] = nullptr;
}
}
bool Equals(AbstractState const* that) const; bool Equals(AbstractState const* that) const;
void Merge(AbstractState const* that, Zone* zone); void Merge(AbstractState const* that, Zone* zone);
AbstractState const* AddMaps(Node* object, ZoneHandleSet<Map> maps, AbstractState const* AddMaps(Node* object, ZoneHandleSet<Map> maps,
Zone* zone) const; Zone* zone) const;
AbstractState const* AddMaps(Node* object, AbstractMapInfo const& map_info,
Zone* zone) const;
AbstractState const* KillMaps(Node* object, Zone* zone) const; AbstractState const* KillMaps(Node* object, Zone* zone) const;
AbstractState const* KillMaps(const AliasStateInfo& alias_info, AbstractState const* KillMaps(const AliasStateInfo& alias_info,
Zone* zone) const; Zone* zone) const;
bool LookupMaps(Node* object, ZoneHandleSet<Map>* object_maps) const; bool LookupMaps(Node* object, ZoneHandleSet<Map>* object_maps) const;
bool LookupMaps(Node* object, AbstractMapInfo* object_maps) const;
AbstractState const* AddField(Node* object, size_t index, Node* value, AbstractState const* AddField(Node* object, size_t index, Node* value,
MaybeHandle<Name> name, Zone* zone) const; MaybeHandle<Name> name, Zone* zone) const;
...@@ -297,28 +254,13 @@ class V8_EXPORT_PRIVATE LoadElimination final ...@@ -297,28 +254,13 @@ class V8_EXPORT_PRIVATE LoadElimination final
AbstractState const* AddCheck(Node* node, Zone* zone) const; AbstractState const* AddCheck(Node* node, Zone* zone) const;
Node* LookupCheck(Node* node) const; Node* LookupCheck(Node* node) const;
AbstractState const* KillMutableState(Zone* zone) const;
bool is_unreachable() const { return is_unreachable_; }
void Print() const; void Print() const;
static AbstractState Unreachable();
static AbstractState Empty();
private: private:
AbstractState() : is_unreachable_(false) {
for (size_t i = 0; i < arraysize(fields_); ++i) {
fields_[i] = nullptr;
}
}
AbstractChecks const* checks_ = nullptr; AbstractChecks const* checks_ = nullptr;
AbstractElements const* elements_ = nullptr; AbstractElements const* elements_ = nullptr;
AbstractField const* fields_[kMaxTrackedFields]; AbstractField const* fields_[kMaxTrackedFields];
AbstractMaps const* maps_ = nullptr; AbstractMaps const* maps_ = nullptr;
bool is_unreachable_;
}; };
class AbstractStateForEffectNodes final : public ZoneObject { class AbstractStateForEffectNodes final : public ZoneObject {
...@@ -362,14 +304,12 @@ class V8_EXPORT_PRIVATE LoadElimination final ...@@ -362,14 +304,12 @@ class V8_EXPORT_PRIVATE LoadElimination final
CommonOperatorBuilder* common() const; CommonOperatorBuilder* common() const;
AbstractState const* empty_state() const { return &empty_state_; } AbstractState const* empty_state() const { return &empty_state_; }
AbstractState const* unreachable_state() const { return &unreachable_state_; }
Factory* factory() const; Factory* factory() const;
Graph* graph() const; Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
Zone* zone() const { return node_states_.zone(); } Zone* zone() const { return node_states_.zone(); }
AbstractState const empty_state_; AbstractState const empty_state_;
AbstractState const unreachable_state_;
AbstractStateForEffectNodes node_states_; AbstractStateForEffectNodes node_states_;
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
......
...@@ -362,7 +362,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps( ...@@ -362,7 +362,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
case IrOpcode::kMapGuard: { case IrOpcode::kMapGuard: {
Node* const object = GetValueInput(effect, 0); Node* const object = GetValueInput(effect, 0);
if (IsSame(receiver, object)) { if (IsSame(receiver, object)) {
*maps_return = MapGuardMapsOf(effect->op()).maps(); *maps_return = MapGuardMapsOf(effect->op());
return result; return result;
} }
break; break;
......
...@@ -179,40 +179,6 @@ std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) { ...@@ -179,40 +179,6 @@ std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
return os; return os;
} }
MapsParameterInfo::MapsParameterInfo(ZoneHandleSet<Map> const& maps)
: maps_(maps), instance_type_(Nothing<InstanceType>()) {
DCHECK_LT(0, maps.size());
instance_type_ = Just(maps.at(0)->instance_type());
for (size_t i = 1; i < maps.size(); ++i) {
if (instance_type_.FromJust() != maps.at(i)->instance_type()) {
instance_type_ = Nothing<InstanceType>();
break;
}
}
}
std::ostream& operator<<(std::ostream& os, MapsParameterInfo const& p) {
ZoneHandleSet<Map> const& maps = p.maps();
InstanceType instance_type;
if (p.instance_type().To(&instance_type)) {
os << ", " << instance_type;
}
for (size_t i = 0; i < maps.size(); ++i) {
os << ", " << Brief(*maps[i]);
}
return os;
}
bool operator==(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
return lhs.maps() == rhs.maps();
}
bool operator!=(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
return !(lhs == rhs);
}
size_t hash_value(MapsParameterInfo const& p) { return hash_value(p.maps()); }
bool operator==(CheckMapsParameters const& lhs, bool operator==(CheckMapsParameters const& lhs,
CheckMapsParameters const& rhs) { CheckMapsParameters const& rhs) {
return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps(); return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps();
...@@ -223,7 +189,12 @@ size_t hash_value(CheckMapsParameters const& p) { ...@@ -223,7 +189,12 @@ size_t hash_value(CheckMapsParameters const& p) {
} }
std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) { std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
return os << p.flags() << p.maps_info(); ZoneHandleSet<Map> const& maps = p.maps();
os << p.flags();
for (size_t i = 0; i < maps.size(); ++i) {
os << ", " << Brief(*maps[i]);
}
return os;
} }
CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) { CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
...@@ -231,14 +202,9 @@ CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) { ...@@ -231,14 +202,9 @@ CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
return OpParameter<CheckMapsParameters>(op); return OpParameter<CheckMapsParameters>(op);
} }
MapsParameterInfo const& CompareMapsParametersOf(Operator const* op) { ZoneHandleSet<Map> const& CompareMapsParametersOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode()); DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
return OpParameter<MapsParameterInfo>(op); return OpParameter<ZoneHandleSet<Map>>(op);
}
MapsParameterInfo const& MapGuardMapsOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
return OpParameter<MapsParameterInfo>(op);
} }
size_t hash_value(CheckTaggedInputMode mode) { size_t hash_value(CheckTaggedInputMode mode) {
...@@ -1006,22 +972,14 @@ const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags, ...@@ -1006,22 +972,14 @@ const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags,
parameters); // parameter parameters); // parameter
} }
const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
return new (zone()) Operator1<MapsParameterInfo>( // --
IrOpcode::kMapGuard, Operator::kEliminatable, // opcode
"MapGuard", // name
1, 1, 1, 0, 1, 0, // counts
MapsParameterInfo(maps)); // parameter
}
const Operator* SimplifiedOperatorBuilder::CompareMaps( const Operator* SimplifiedOperatorBuilder::CompareMaps(
ZoneHandleSet<Map> maps) { ZoneHandleSet<Map> maps) {
return new (zone()) Operator1<MapsParameterInfo>( // -- return new (zone()) Operator1<ZoneHandleSet<Map>>( // --
IrOpcode::kCompareMaps, // opcode IrOpcode::kCompareMaps, // opcode
Operator::kEliminatable, // flags Operator::kEliminatable, // flags
"CompareMaps", // name "CompareMaps", // name
1, 1, 1, 1, 1, 0, // counts 1, 1, 1, 1, 1, 0, // counts
MapsParameterInfo(maps)); // parameter maps); // parameter
} }
const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole( const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
......
...@@ -133,38 +133,18 @@ DEFINE_OPERATORS_FOR_FLAGS(CheckMapsFlags) ...@@ -133,38 +133,18 @@ DEFINE_OPERATORS_FOR_FLAGS(CheckMapsFlags)
std::ostream& operator<<(std::ostream&, CheckMapsFlags); std::ostream& operator<<(std::ostream&, CheckMapsFlags);
class MapsParameterInfo {
public:
explicit MapsParameterInfo(ZoneHandleSet<Map> const& maps);
Maybe<InstanceType> instance_type() const { return instance_type_; }
ZoneHandleSet<Map> const& maps() const { return maps_; }
private:
ZoneHandleSet<Map> const maps_;
Maybe<InstanceType> instance_type_;
};
std::ostream& operator<<(std::ostream&, MapsParameterInfo const&);
bool operator==(MapsParameterInfo const&, MapsParameterInfo const&);
bool operator!=(MapsParameterInfo const&, MapsParameterInfo const&);
size_t hash_value(MapsParameterInfo const&);
// A descriptor for map checks. // A descriptor for map checks.
class CheckMapsParameters final { class CheckMapsParameters final {
public: public:
CheckMapsParameters(CheckMapsFlags flags, ZoneHandleSet<Map> const& maps) CheckMapsParameters(CheckMapsFlags flags, ZoneHandleSet<Map> const& maps)
: flags_(flags), maps_info_(maps) {} : flags_(flags), maps_(maps) {}
CheckMapsFlags flags() const { return flags_; } CheckMapsFlags flags() const { return flags_; }
ZoneHandleSet<Map> const& maps() const { return maps_info_.maps(); } ZoneHandleSet<Map> const& maps() const { return maps_; }
MapsParameterInfo const& maps_info() const { return maps_info_; }
private: private:
CheckMapsFlags const flags_; CheckMapsFlags const flags_;
MapsParameterInfo const maps_info_; ZoneHandleSet<Map> const maps_;
}; };
bool operator==(CheckMapsParameters const&, CheckMapsParameters const&); bool operator==(CheckMapsParameters const&, CheckMapsParameters const&);
...@@ -176,10 +156,8 @@ std::ostream& operator<<(std::ostream&, CheckMapsParameters const&); ...@@ -176,10 +156,8 @@ std::ostream& operator<<(std::ostream&, CheckMapsParameters const&);
CheckMapsParameters const& CheckMapsParametersOf(Operator const*) CheckMapsParameters const& CheckMapsParametersOf(Operator const*)
WARN_UNUSED_RESULT; WARN_UNUSED_RESULT;
MapsParameterInfo const& MapGuardMapsOf(Operator const*) WARN_UNUSED_RESULT;
// Parameters for CompareMaps operator. // Parameters for CompareMaps operator.
MapsParameterInfo const& CompareMapsParametersOf(Operator const*) ZoneHandleSet<Map> const& CompareMapsParametersOf(Operator const*)
WARN_UNUSED_RESULT; WARN_UNUSED_RESULT;
// A descriptor for growing elements backing stores. // A descriptor for growing elements backing stores.
...@@ -437,7 +415,6 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -437,7 +415,6 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* CheckBounds(); const Operator* CheckBounds();
const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet<Map>); const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet<Map>);
const Operator* CompareMaps(ZoneHandleSet<Map>); const Operator* CompareMaps(ZoneHandleSet<Map>);
const Operator* MapGuard(ZoneHandleSet<Map> maps);
const Operator* CheckHeapObject(); const Operator* CheckHeapObject();
const Operator* CheckInternalizedString(); const Operator* CheckInternalizedString();
......
...@@ -96,15 +96,6 @@ class ZoneHandleSet final { ...@@ -96,15 +96,6 @@ class ZoneHandleSet final {
return true; return true;
} }
bool contains(Handle<T> other) const {
if (data_ == kEmptyTag) return false;
if ((data_ & kTagMask) == kSingletonTag) {
return singleton() == bit_cast<T**>(other.address());
}
DCHECK_EQ(kListTag, data_ & kTagMask);
return list()->Contains(bit_cast<T**>(other.address()));
}
void remove(Handle<T> handle, Zone* zone) { void remove(Handle<T> handle, Zone* zone) {
// TODO(bmeurer): Optimize this case. // TODO(bmeurer): Optimize this case.
ZoneHandleSet<T> that; ZoneHandleSet<T> that;
......
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