diff options
Diffstat (limited to 'deps/v8/src/compiler/constant-folding-reducer.cc')
-rw-r--r-- | deps/v8/src/compiler/constant-folding-reducer.cc | 101 |
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); } } } |