| // Copyright 2018 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/constant-folding-reducer.h" |
| |
| #include "src/compiler/js-graph.h" |
| #include "src/objects/objects-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace compiler { |
| |
| ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph, |
| JSHeapBroker* broker) |
| : AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {} |
| |
| 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); |
| } |
| } |
| } |
| return NoChange(); |
| } |
| |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |