[turbofan] Move MapInference into its own files

Bug: v8:9197
Change-Id: If72dbf1507f68fa344db389c08ad8614bca6667e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1593337
Auto-Submit: Georg Neis <neis@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61199}
This commit is contained in:
Georg Neis 2019-05-02 19:41:08 +02:00 committed by Commit Bot
parent b09146832c
commit 3460e02064
4 changed files with 239 additions and 187 deletions

View File

@ -1811,6 +1811,8 @@ v8_compiler_sources = [
"src/compiler/machine-operator-reducer.h",
"src/compiler/machine-operator.cc",
"src/compiler/machine-operator.h",
"src/compiler/map-inference.cc",
"src/compiler/map-inference.h",
"src/compiler/memory-optimizer.cc",
"src/compiler/memory-optimizer.h",
"src/compiler/node-aux-data.h",

View File

@ -16,6 +16,7 @@
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/map-inference.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/property-access-builder.h"
#include "src/compiler/simplified-operator.h"
@ -35,193 +36,6 @@ namespace v8 {
namespace internal {
namespace compiler {
// The MapInference class provides access to the "inferred" maps of an
// {object}. This information can be either "reliable", meaning that the object
// is guaranteed to have one of these maps at runtime, or "unreliable", meaning
// that the object is guaranteed to have HAD one of these maps.
//
// The MapInference class does not expose whether or not the information is
// reliable. A client is expected to eventually make the information reliable by
// calling one of several methods that will either insert map checks, or record
// stability dependencies (or do nothing if the information was already
// reliable).
class MapInference {
public:
MapInference(JSHeapBroker* broker, Node* object, Node* effect);
// The destructor checks that the information has been made reliable (if
// necessary) and force-crashes if not.
~MapInference();
// Is there any information at all?
V8_WARN_UNUSED_RESULT bool HaveMaps() const;
// These queries don't require a guard.
//
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypesAreJSReceiver() const;
// Here, {type} must not be a String type.
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypesAre(InstanceType type) const;
// These queries require a guard. (Even instance types are generally not
// reliable because of how the representation of a string can change.)
V8_WARN_UNUSED_RESULT MapHandles const& GetMaps();
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypes(
std::function<bool(InstanceType)> f);
// These methods provide a guard.
//
// Returns true iff maps were already reliable or stability dependencies were
// successfully recorded.
V8_WARN_UNUSED_RESULT bool RelyOnMapsViaStability(
CompilationDependencies* dependencies);
// Records stability dependencies if possible, otherwise it inserts map
// checks. Does nothing if maps were already reliable. Returns true iff
// dependencies were taken.
bool RelyOnMapsPreferStability(CompilationDependencies* dependencies,
JSGraph* jsgraph, Node** effect, Node* control,
const VectorSlotPair& feedback);
// Inserts map checks even if maps were already reliable.
void InsertMapChecks(JSGraph* jsgraph, Node** effect, Node* control,
const VectorSlotPair& feedback);
// Internally marks the maps as reliable (thus bypassing the safety check) and
// returns the NoChange reduction. USE THIS ONLY WHEN RETURNING, e.g.:
// if (foo) return inference.NoChange();
V8_WARN_UNUSED_RESULT Reduction NoChange();
private:
JSHeapBroker* const broker_;
Node* const object_;
MapHandles maps_;
enum {
kReliableOrGuarded,
kUnreliableDontNeedGuard,
kUnreliableNeedGuard
} maps_state_;
bool Safe() const;
void SetNeedGuardIfUnreliable();
void SetGuarded();
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypesUnsafe(
std::function<bool(InstanceType)> f) const;
V8_WARN_UNUSED_RESULT bool RelyOnMapsHelper(
CompilationDependencies* dependencies, JSGraph* jsgraph, Node** effect,
Node* control, const VectorSlotPair& feedback);
};
MapInference::MapInference(JSHeapBroker* broker, Node* object, Node* effect)
: broker_(broker), object_(object) {
ZoneHandleSet<Map> maps;
auto result =
NodeProperties::InferReceiverMaps(broker_, object_, effect, &maps);
maps_.insert(maps_.end(), maps.begin(), maps.end());
maps_state_ = (result == NodeProperties::kUnreliableReceiverMaps)
? kUnreliableDontNeedGuard
: kReliableOrGuarded;
DCHECK_EQ(maps_.empty(), result == NodeProperties::kNoReceiverMaps);
}
bool MapInference::Safe() const { return maps_state_ != kUnreliableNeedGuard; }
void MapInference::SetNeedGuardIfUnreliable() {
CHECK(HaveMaps());
if (maps_state_ == kUnreliableDontNeedGuard) {
maps_state_ = kUnreliableNeedGuard;
}
}
void MapInference::SetGuarded() { maps_state_ = kReliableOrGuarded; }
MapInference::~MapInference() { CHECK(Safe()); }
bool MapInference::HaveMaps() const { return !maps_.empty(); }
bool MapInference::AllOfInstanceTypesAreJSReceiver() const {
return AllOfInstanceTypesUnsafe(InstanceTypeChecker::IsJSReceiver);
}
bool MapInference::AllOfInstanceTypesAre(InstanceType type) const {
CHECK(!InstanceTypeChecker::IsString(type));
return AllOfInstanceTypesUnsafe(
[type](InstanceType other) { return type == other; });
}
bool MapInference::AllOfInstanceTypes(std::function<bool(InstanceType)> f) {
SetNeedGuardIfUnreliable();
return AllOfInstanceTypesUnsafe(f);
}
bool MapInference::AllOfInstanceTypesUnsafe(
std::function<bool(InstanceType)> f) const {
CHECK(HaveMaps());
return std::all_of(maps_.begin(), maps_.end(),
[f](Handle<Map> map) { return f(map->instance_type()); });
}
MapHandles const& MapInference::GetMaps() {
SetNeedGuardIfUnreliable();
return maps_;
}
void MapInference::InsertMapChecks(JSGraph* jsgraph, Node** effect,
Node* control,
const VectorSlotPair& feedback) {
CHECK(HaveMaps());
CHECK(feedback.IsValid());
ZoneHandleSet<Map> maps;
for (Handle<Map> map : maps_) maps.insert(map, jsgraph->graph()->zone());
*effect = jsgraph->graph()->NewNode(
jsgraph->simplified()->CheckMaps(CheckMapsFlag::kNone, maps, feedback),
object_, *effect, control);
SetGuarded();
}
bool MapInference::RelyOnMapsViaStability(
CompilationDependencies* dependencies) {
CHECK(HaveMaps());
return RelyOnMapsHelper(dependencies, nullptr, nullptr, nullptr, {});
}
bool MapInference::RelyOnMapsPreferStability(
CompilationDependencies* dependencies, JSGraph* jsgraph, Node** effect,
Node* control, const VectorSlotPair& feedback) {
CHECK(HaveMaps());
if (Safe()) return false;
if (RelyOnMapsViaStability(dependencies)) return true;
CHECK(RelyOnMapsHelper(nullptr, jsgraph, effect, control, feedback));
return false;
}
bool MapInference::RelyOnMapsHelper(CompilationDependencies* dependencies,
JSGraph* jsgraph, Node** effect,
Node* control,
const VectorSlotPair& feedback) {
if (Safe()) return true;
auto is_stable = [](Handle<Map> map) { return map->is_stable(); };
if (dependencies != nullptr &&
std::all_of(maps_.cbegin(), maps_.cend(), is_stable)) {
for (Handle<Map> map : maps_) {
dependencies->DependOnStableMap(MapRef(broker_, map));
}
SetGuarded();
return true;
} else if (feedback.IsValid()) {
InsertMapChecks(jsgraph, effect, control, feedback);
return true;
} else {
return false;
}
}
Reduction MapInference::NoChange() {
SetGuarded();
maps_.clear(); // Just to make some CHECKs fail if {this} gets used after.
return Reducer::NoChange();
}
Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {

View File

@ -0,0 +1,131 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/map-inference.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/simplified-operator.h"
#include "src/objects/map-inl.h"
#include "src/vector-slot-pair.h"
#include "src/zone/zone-handle-set.h"
namespace v8 {
namespace internal {
namespace compiler {
MapInference::MapInference(JSHeapBroker* broker, Node* object, Node* effect)
: broker_(broker), object_(object) {
ZoneHandleSet<Map> maps;
auto result =
NodeProperties::InferReceiverMaps(broker_, object_, effect, &maps);
maps_.insert(maps_.end(), maps.begin(), maps.end());
maps_state_ = (result == NodeProperties::kUnreliableReceiverMaps)
? kUnreliableDontNeedGuard
: kReliableOrGuarded;
DCHECK_EQ(maps_.empty(), result == NodeProperties::kNoReceiverMaps);
}
MapInference::~MapInference() { CHECK(Safe()); }
bool MapInference::Safe() const { return maps_state_ != kUnreliableNeedGuard; }
void MapInference::SetNeedGuardIfUnreliable() {
CHECK(HaveMaps());
if (maps_state_ == kUnreliableDontNeedGuard) {
maps_state_ = kUnreliableNeedGuard;
}
}
void MapInference::SetGuarded() { maps_state_ = kReliableOrGuarded; }
bool MapInference::HaveMaps() const { return !maps_.empty(); }
bool MapInference::AllOfInstanceTypesAreJSReceiver() const {
return AllOfInstanceTypesUnsafe(InstanceTypeChecker::IsJSReceiver);
}
bool MapInference::AllOfInstanceTypesAre(InstanceType type) const {
CHECK(!InstanceTypeChecker::IsString(type));
return AllOfInstanceTypesUnsafe(
[type](InstanceType other) { return type == other; });
}
bool MapInference::AllOfInstanceTypes(std::function<bool(InstanceType)> f) {
SetNeedGuardIfUnreliable();
return AllOfInstanceTypesUnsafe(f);
}
bool MapInference::AllOfInstanceTypesUnsafe(
std::function<bool(InstanceType)> f) const {
CHECK(HaveMaps());
return std::all_of(maps_.begin(), maps_.end(),
[f](Handle<Map> map) { return f(map->instance_type()); });
}
MapHandles const& MapInference::GetMaps() {
SetNeedGuardIfUnreliable();
return maps_;
}
void MapInference::InsertMapChecks(JSGraph* jsgraph, Node** effect,
Node* control,
const VectorSlotPair& feedback) {
CHECK(HaveMaps());
CHECK(feedback.IsValid());
ZoneHandleSet<Map> maps;
for (Handle<Map> map : maps_) maps.insert(map, jsgraph->graph()->zone());
*effect = jsgraph->graph()->NewNode(
jsgraph->simplified()->CheckMaps(CheckMapsFlag::kNone, maps, feedback),
object_, *effect, control);
SetGuarded();
}
bool MapInference::RelyOnMapsViaStability(
CompilationDependencies* dependencies) {
CHECK(HaveMaps());
return RelyOnMapsHelper(dependencies, nullptr, nullptr, nullptr, {});
}
bool MapInference::RelyOnMapsPreferStability(
CompilationDependencies* dependencies, JSGraph* jsgraph, Node** effect,
Node* control, const VectorSlotPair& feedback) {
CHECK(HaveMaps());
if (Safe()) return false;
if (RelyOnMapsViaStability(dependencies)) return true;
CHECK(RelyOnMapsHelper(nullptr, jsgraph, effect, control, feedback));
return false;
}
bool MapInference::RelyOnMapsHelper(CompilationDependencies* dependencies,
JSGraph* jsgraph, Node** effect,
Node* control,
const VectorSlotPair& feedback) {
if (Safe()) return true;
auto is_stable = [](Handle<Map> map) { return map->is_stable(); };
if (dependencies != nullptr &&
std::all_of(maps_.cbegin(), maps_.cend(), is_stable)) {
for (Handle<Map> map : maps_) {
dependencies->DependOnStableMap(MapRef(broker_, map));
}
SetGuarded();
return true;
} else if (feedback.IsValid()) {
InsertMapChecks(jsgraph, effect, control, feedback);
return true;
} else {
return false;
}
}
Reduction MapInference::NoChange() {
SetGuarded();
maps_.clear(); // Just to make some CHECKs fail if {this} gets used after.
return Reducer::NoChange();
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,105 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_MAP_INFERENCE_H_
#define V8_COMPILER_MAP_INFERENCE_H_
#include "include/v8config.h"
#include "src/compiler/graph-reducer.h"
#include "src/objects/instance-type.h"
#include "src/objects/map.h"
namespace v8 {
namespace internal {
class VectorSlotPair;
namespace compiler {
class CompilationDependencies;
class JSGraph;
class JSHeapBroker;
class Node;
// The MapInference class provides access to the "inferred" maps of an
// {object}. This information can be either "reliable", meaning that the object
// is guaranteed to have one of these maps at runtime, or "unreliable", meaning
// that the object is guaranteed to have HAD one of these maps.
//
// The MapInference class does not expose whether or not the information is
// reliable. A client is expected to eventually make the information reliable by
// calling one of several methods that will either insert map checks, or record
// stability dependencies (or do nothing if the information was already
// reliable).
class MapInference {
public:
MapInference(JSHeapBroker* broker, Node* object, Node* effect);
// The destructor checks that the information has been made reliable (if
// necessary) and force-crashes if not.
~MapInference();
// Is there any information at all?
V8_WARN_UNUSED_RESULT bool HaveMaps() const;
// These queries don't require a guard.
//
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypesAreJSReceiver() const;
// Here, {type} must not be a String type.
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypesAre(InstanceType type) const;
// These queries require a guard. (Even instance types are generally not
// reliable because of how the representation of a string can change.)
V8_WARN_UNUSED_RESULT MapHandles const& GetMaps();
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypes(
std::function<bool(InstanceType)> f);
// These methods provide a guard.
//
// Returns true iff maps were already reliable or stability dependencies were
// successfully recorded.
V8_WARN_UNUSED_RESULT bool RelyOnMapsViaStability(
CompilationDependencies* dependencies);
// Records stability dependencies if possible, otherwise it inserts map
// checks. Does nothing if maps were already reliable. Returns true iff
// dependencies were taken.
bool RelyOnMapsPreferStability(CompilationDependencies* dependencies,
JSGraph* jsgraph, Node** effect, Node* control,
const VectorSlotPair& feedback);
// Inserts map checks even if maps were already reliable.
void InsertMapChecks(JSGraph* jsgraph, Node** effect, Node* control,
const VectorSlotPair& feedback);
// Internally marks the maps as reliable (thus bypassing the safety check) and
// returns the NoChange reduction. USE THIS ONLY WHEN RETURNING, e.g.:
// if (foo) return inference.NoChange();
V8_WARN_UNUSED_RESULT Reduction NoChange();
private:
JSHeapBroker* const broker_;
Node* const object_;
MapHandles maps_;
enum {
kReliableOrGuarded,
kUnreliableDontNeedGuard,
kUnreliableNeedGuard
} maps_state_;
bool Safe() const;
void SetNeedGuardIfUnreliable();
void SetGuarded();
V8_WARN_UNUSED_RESULT bool AllOfInstanceTypesUnsafe(
std::function<bool(InstanceType)> f) const;
V8_WARN_UNUSED_RESULT bool RelyOnMapsHelper(
CompilationDependencies* dependencies, JSGraph* jsgraph, Node** effect,
Node* control, const VectorSlotPair& feedback);
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_MAP_INFERENCE_H_