1// Copyright 2018 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/compiler/constant-folding-reducer.h" 6 7#include "src/compiler/js-graph.h" 8#include "src/compiler/js-heap-broker.h" 9#include "src/objects/objects-inl.h" 10 11namespace v8 { 12namespace internal { 13namespace compiler { 14 15namespace { 16Node* TryGetConstant(JSGraph* jsgraph, Node* node) { 17 Type type = NodeProperties::GetType(node); 18 Node* result; 19 if (type.IsNone()) { 20 result = nullptr; 21 } else if (type.Is(Type::Null())) { 22 result = jsgraph->NullConstant(); 23 } else if (type.Is(Type::Undefined())) { 24 result = jsgraph->UndefinedConstant(); 25 } else if (type.Is(Type::MinusZero())) { 26 result = jsgraph->MinusZeroConstant(); 27 } else if (type.Is(Type::NaN())) { 28 result = jsgraph->NaNConstant(); 29 } else if (type.Is(Type::Hole())) { 30 result = jsgraph->TheHoleConstant(); 31 } else if (type.IsHeapConstant()) { 32 result = jsgraph->Constant(type.AsHeapConstant()->Ref()); 33 } else if (type.Is(Type::PlainNumber()) && type.Min() == type.Max()) { 34 result = jsgraph->Constant(type.Min()); 35 } else { 36 result = nullptr; 37 } 38 DCHECK_EQ(result != nullptr, type.IsSingleton()); 39 DCHECK_IMPLIES(result != nullptr, 40 type.Equals(NodeProperties::GetType(result))); 41 return result; 42} 43 44bool IsAlreadyBeingFolded(Node* node) { 45 DCHECK(FLAG_assert_types); 46 if (node->opcode() == IrOpcode::kFoldConstant) return true; 47 for (Edge edge : node->use_edges()) { 48 if (NodeProperties::IsValueEdge(edge) && 49 edge.from()->opcode() == IrOpcode::kFoldConstant) { 50 // Note: {node} may have gained new value uses since the time it was 51 // "constant-folded", and theses uses should ideally be rewritten as well. 52 // For simplicity, we ignore them here. 53 return true; 54 } 55 } 56 return false; 57} 58} // namespace 59 60ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph, 61 JSHeapBroker* broker) 62 : AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {} 63 64ConstantFoldingReducer::~ConstantFoldingReducer() = default; 65 66Reduction ConstantFoldingReducer::Reduce(Node* node) { 67 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && 68 node->op()->HasProperty(Operator::kEliminatable) && 69 node->opcode() != IrOpcode::kFinishRegion) { 70 Node* constant = TryGetConstant(jsgraph(), node); 71 if (constant != nullptr) { 72 DCHECK(NodeProperties::IsTyped(constant)); 73 if (!FLAG_assert_types) { 74 DCHECK_EQ(node->op()->ControlOutputCount(), 0); 75 ReplaceWithValue(node, constant); 76 return Replace(constant); 77 } else if (!IsAlreadyBeingFolded(node)) { 78 // Delay the constant folding (by inserting a FoldConstant operation 79 // instead) in order to keep type assertions meaningful. 80 Node* fold_constant = jsgraph()->graph()->NewNode( 81 jsgraph()->common()->FoldConstant(), node, constant); 82 DCHECK(NodeProperties::IsTyped(fold_constant)); 83 ReplaceWithValue(node, fold_constant, node, node); 84 fold_constant->ReplaceInput(0, node); 85 DCHECK(IsAlreadyBeingFolded(node)); 86 DCHECK(IsAlreadyBeingFolded(fold_constant)); 87 return Changed(node); 88 } 89 } 90 } 91 return NoChange(); 92} 93 94} // namespace compiler 95} // namespace internal 96} // namespace v8 97