• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14 
15 namespace {
TryGetConstant(JSGraph * jsgraph,Node * node)16 Node* 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 
IsAlreadyBeingFolded(Node * node)44 bool 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 
ConstantFoldingReducer(Editor * editor,JSGraph * jsgraph,JSHeapBroker * broker)60 ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph,
61                                                JSHeapBroker* broker)
62     : AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {}
63 
64 ConstantFoldingReducer::~ConstantFoldingReducer() = default;
65 
Reduce(Node * node)66 Reduction 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