summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/constant-folding-reducer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/constant-folding-reducer.cc')
-rw-r--r--deps/v8/src/compiler/constant-folding-reducer.cc101
1 files changed, 65 insertions, 36 deletions
diff --git a/deps/v8/src/compiler/constant-folding-reducer.cc b/deps/v8/src/compiler/constant-folding-reducer.cc
index 5a903273ed..9649dbda08 100644
--- a/deps/v8/src/compiler/constant-folding-reducer.cc
+++ b/deps/v8/src/compiler/constant-folding-reducer.cc
@@ -11,6 +11,51 @@ namespace v8 {
namespace internal {
namespace compiler {
+namespace {
+Node* TryGetConstant(JSGraph* jsgraph, Node* node) {
+ Type type = NodeProperties::GetType(node);
+ Node* result;
+ if (type.IsNone()) {
+ result = nullptr;
+ } else if (type.Is(Type::Null())) {
+ result = jsgraph->NullConstant();
+ } else if (type.Is(Type::Undefined())) {
+ result = jsgraph->UndefinedConstant();
+ } else if (type.Is(Type::MinusZero())) {
+ result = jsgraph->MinusZeroConstant();
+ } else if (type.Is(Type::NaN())) {
+ result = jsgraph->NaNConstant();
+ } else if (type.Is(Type::Hole())) {
+ result = jsgraph->TheHoleConstant();
+ } else if (type.IsHeapConstant()) {
+ result = jsgraph->Constant(type.AsHeapConstant()->Ref());
+ } else if (type.Is(Type::PlainNumber()) && type.Min() == type.Max()) {
+ result = jsgraph->Constant(type.Min());
+ } else {
+ result = nullptr;
+ }
+ DCHECK_EQ(result != nullptr, type.IsSingleton());
+ DCHECK_IMPLIES(result != nullptr,
+ type.Equals(NodeProperties::GetType(result)));
+ return result;
+}
+
+bool IsAlreadyBeingFolded(Node* node) {
+ DCHECK(FLAG_assert_types);
+ if (node->opcode() == IrOpcode::kFoldConstant) return true;
+ for (Edge edge : node->use_edges()) {
+ if (NodeProperties::IsValueEdge(edge) &&
+ edge.from()->opcode() == IrOpcode::kFoldConstant) {
+ // Note: {node} may have gained new value uses since the time it was
+ // "constant-folded", and theses uses should ideally be rewritten as well.
+ // For simplicity, we ignore them here.
+ return true;
+ }
+ }
+ return false;
+}
+} // namespace
+
ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph,
JSHeapBroker* broker)
: AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {}
@@ -19,43 +64,27 @@ ConstantFoldingReducer::~ConstantFoldingReducer() = default;
Reduction ConstantFoldingReducer::Reduce(Node* node) {
DisallowHeapAccess no_heap_access;
- // Check if the output type is a singleton. In that case we already know the
- // result value and can simply replace the node if it's eliminable.
if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
- node->op()->HasProperty(Operator::kEliminatable)) {
- // TODO(v8:5303): We must not eliminate FinishRegion here. This special
- // case can be removed once we have separate operators for value and
- // effect regions.
- if (node->opcode() == IrOpcode::kFinishRegion) return NoChange();
- // We can only constant-fold nodes here, that are known to not cause any
- // side-effect, may it be a JavaScript observable side-effect or a possible
- // eager deoptimization exit (i.e. {node} has an operator that doesn't have
- // the Operator::kNoDeopt property).
- Type upper = NodeProperties::GetType(node);
- if (!upper.IsNone()) {
- Node* replacement = nullptr;
- if (upper.IsHeapConstant()) {
- replacement = jsgraph()->Constant(upper.AsHeapConstant()->Ref());
- } else if (upper.Is(Type::MinusZero())) {
- Factory* factory = jsgraph()->isolate()->factory();
- ObjectRef minus_zero(broker(), factory->minus_zero_value());
- replacement = jsgraph()->Constant(minus_zero);
- } else if (upper.Is(Type::NaN())) {
- replacement = jsgraph()->NaNConstant();
- } else if (upper.Is(Type::Null())) {
- replacement = jsgraph()->NullConstant();
- } else if (upper.Is(Type::PlainNumber()) && upper.Min() == upper.Max()) {
- replacement = jsgraph()->Constant(upper.Min());
- } else if (upper.Is(Type::Undefined())) {
- replacement = jsgraph()->UndefinedConstant();
- }
- if (replacement) {
- // Make sure the node has a type.
- if (!NodeProperties::IsTyped(replacement)) {
- NodeProperties::SetType(replacement, upper);
- }
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
+ node->op()->HasProperty(Operator::kEliminatable) &&
+ node->opcode() != IrOpcode::kFinishRegion) {
+ Node* constant = TryGetConstant(jsgraph(), node);
+ if (constant != nullptr) {
+ DCHECK(NodeProperties::IsTyped(constant));
+ if (!FLAG_assert_types) {
+ DCHECK_EQ(node->op()->ControlOutputCount(), 0);
+ ReplaceWithValue(node, constant);
+ return Replace(constant);
+ } else if (!IsAlreadyBeingFolded(node)) {
+ // Delay the constant folding (by inserting a FoldConstant operation
+ // instead) in order to keep type assertions meaningful.
+ Node* fold_constant = jsgraph()->graph()->NewNode(
+ jsgraph()->common()->FoldConstant(), node, constant);
+ DCHECK(NodeProperties::IsTyped(fold_constant));
+ ReplaceWithValue(node, fold_constant, node, node);
+ fold_constant->ReplaceInput(0, node);
+ DCHECK(IsAlreadyBeingFolded(node));
+ DCHECK(IsAlreadyBeingFolded(fold_constant));
+ return Changed(node);
}
}
}