OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/verifier.h" | 5 #include "src/compiler/verifier.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 #include <queue> | 9 #include <queue> |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 24 matching lines...) Expand all Loading... |
35 | 35 |
36 | 36 |
37 static bool IsUseDefChainLinkPresent(Node* def, Node* use) { | 37 static bool IsUseDefChainLinkPresent(Node* def, Node* use) { |
38 const Node::Inputs inputs = use->inputs(); | 38 const Node::Inputs inputs = use->inputs(); |
39 return std::find(inputs.begin(), inputs.end(), def) != inputs.end(); | 39 return std::find(inputs.begin(), inputs.end(), def) != inputs.end(); |
40 } | 40 } |
41 | 41 |
42 | 42 |
43 class Verifier::Visitor { | 43 class Verifier::Visitor { |
44 public: | 44 public: |
45 Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {} | 45 Visitor(Zone* z, Typing typed, CheckInputs check_inputs) |
| 46 : zone(z), typing(typed), check_inputs(check_inputs) {} |
46 | 47 |
47 void Check(Node* node); | 48 void Check(Node* node); |
48 | 49 |
49 Zone* zone; | 50 Zone* zone; |
50 Typing typing; | 51 Typing typing; |
| 52 CheckInputs check_inputs; |
51 | 53 |
52 private: | 54 private: |
53 void CheckNotTyped(Node* node) { | 55 void CheckNotTyped(Node* node) { |
54 if (NodeProperties::IsTyped(node)) { | 56 if (NodeProperties::IsTyped(node)) { |
55 std::ostringstream str; | 57 std::ostringstream str; |
56 str << "TypeError: node #" << node->id() << ":" << *node->op() | 58 str << "TypeError: node #" << node->id() << ":" << *node->op() |
57 << " should never have a type"; | 59 << " should never have a type"; |
58 FATAL(str.str().c_str()); | 60 FATAL(str.str().c_str()); |
59 } | 61 } |
60 } | 62 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 | 109 |
108 void Verifier::Visitor::Check(Node* node) { | 110 void Verifier::Visitor::Check(Node* node) { |
109 int value_count = node->op()->ValueInputCount(); | 111 int value_count = node->op()->ValueInputCount(); |
110 int context_count = OperatorProperties::GetContextInputCount(node->op()); | 112 int context_count = OperatorProperties::GetContextInputCount(node->op()); |
111 int frame_state_count = | 113 int frame_state_count = |
112 OperatorProperties::GetFrameStateInputCount(node->op()); | 114 OperatorProperties::GetFrameStateInputCount(node->op()); |
113 int effect_count = node->op()->EffectInputCount(); | 115 int effect_count = node->op()->EffectInputCount(); |
114 int control_count = node->op()->ControlInputCount(); | 116 int control_count = node->op()->ControlInputCount(); |
115 | 117 |
116 // Verify number of inputs matches up. | 118 // Verify number of inputs matches up. |
117 int input_count = value_count + context_count + frame_state_count + | 119 int input_count = value_count + context_count + frame_state_count; |
118 effect_count + control_count; | 120 if (check_inputs == kAll) { |
| 121 input_count += effect_count + control_count; |
| 122 } |
119 CHECK_EQ(input_count, node->InputCount()); | 123 CHECK_EQ(input_count, node->InputCount()); |
120 | 124 |
121 // Verify that frame state has been inserted for the nodes that need it. | 125 // Verify that frame state has been inserted for the nodes that need it. |
122 for (int i = 0; i < frame_state_count; i++) { | 126 for (int i = 0; i < frame_state_count; i++) { |
123 Node* frame_state = NodeProperties::GetFrameStateInput(node, i); | 127 Node* frame_state = NodeProperties::GetFrameStateInput(node, i); |
124 CHECK(frame_state->opcode() == IrOpcode::kFrameState || | 128 CHECK(frame_state->opcode() == IrOpcode::kFrameState || |
125 // kFrameState uses Start as a sentinel. | 129 // kFrameState uses Start as a sentinel. |
126 (node->opcode() == IrOpcode::kFrameState && | 130 (node->opcode() == IrOpcode::kFrameState && |
127 frame_state->opcode() == IrOpcode::kStart)); | 131 frame_state->opcode() == IrOpcode::kStart)); |
128 CHECK(IsDefUseChainLinkPresent(frame_state, node)); | 132 CHECK(IsDefUseChainLinkPresent(frame_state, node)); |
(...skipping 14 matching lines...) Expand all Loading... |
143 } | 147 } |
144 | 148 |
145 // Verify all context inputs are value nodes. | 149 // Verify all context inputs are value nodes. |
146 for (int i = 0; i < context_count; ++i) { | 150 for (int i = 0; i < context_count; ++i) { |
147 Node* context = NodeProperties::GetContextInput(node); | 151 Node* context = NodeProperties::GetContextInput(node); |
148 CheckOutput(context, node, context->op()->ValueOutputCount(), "context"); | 152 CheckOutput(context, node, context->op()->ValueOutputCount(), "context"); |
149 CHECK(IsDefUseChainLinkPresent(context, node)); | 153 CHECK(IsDefUseChainLinkPresent(context, node)); |
150 CHECK(IsUseDefChainLinkPresent(context, node)); | 154 CHECK(IsUseDefChainLinkPresent(context, node)); |
151 } | 155 } |
152 | 156 |
153 // Verify all effect inputs actually have an effect. | 157 if (check_inputs == kAll) { |
154 for (int i = 0; i < effect_count; ++i) { | 158 // Verify all effect inputs actually have an effect. |
155 Node* effect = NodeProperties::GetEffectInput(node); | 159 for (int i = 0; i < effect_count; ++i) { |
156 CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect"); | 160 Node* effect = NodeProperties::GetEffectInput(node); |
157 CHECK(IsDefUseChainLinkPresent(effect, node)); | 161 CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect"); |
158 CHECK(IsUseDefChainLinkPresent(effect, node)); | 162 CHECK(IsDefUseChainLinkPresent(effect, node)); |
159 } | 163 CHECK(IsUseDefChainLinkPresent(effect, node)); |
| 164 } |
160 | 165 |
161 // Verify all control inputs are control nodes. | 166 // Verify all control inputs are control nodes. |
162 for (int i = 0; i < control_count; ++i) { | 167 for (int i = 0; i < control_count; ++i) { |
163 Node* control = NodeProperties::GetControlInput(node, i); | 168 Node* control = NodeProperties::GetControlInput(node, i); |
164 CheckOutput(control, node, control->op()->ControlOutputCount(), "control"); | 169 CheckOutput(control, node, control->op()->ControlOutputCount(), |
165 CHECK(IsDefUseChainLinkPresent(control, node)); | 170 "control"); |
166 CHECK(IsUseDefChainLinkPresent(control, node)); | 171 CHECK(IsDefUseChainLinkPresent(control, node)); |
| 172 CHECK(IsUseDefChainLinkPresent(control, node)); |
| 173 } |
167 } | 174 } |
168 | 175 |
169 switch (node->opcode()) { | 176 switch (node->opcode()) { |
170 case IrOpcode::kStart: | 177 case IrOpcode::kStart: |
171 // Start has no inputs. | 178 // Start has no inputs. |
172 CHECK_EQ(0, input_count); | 179 CHECK_EQ(0, input_count); |
173 // Type is a tuple. | 180 // Type is a tuple. |
174 // TODO(rossberg): Multiple outputs are currently typed as Internal. | 181 // TODO(rossberg): Multiple outputs are currently typed as Internal. |
175 CheckUpperIs(node, Type::Internal()); | 182 CheckUpperIs(node, Type::Internal()); |
176 break; | 183 break; |
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 case IrOpcode::kLoadFramePointer: | 1010 case IrOpcode::kLoadFramePointer: |
1004 case IrOpcode::kLoadParentFramePointer: | 1011 case IrOpcode::kLoadParentFramePointer: |
1005 case IrOpcode::kCheckedLoad: | 1012 case IrOpcode::kCheckedLoad: |
1006 case IrOpcode::kCheckedStore: | 1013 case IrOpcode::kCheckedStore: |
1007 case IrOpcode::kAtomicLoad: | 1014 case IrOpcode::kAtomicLoad: |
1008 // TODO(rossberg): Check. | 1015 // TODO(rossberg): Check. |
1009 break; | 1016 break; |
1010 } | 1017 } |
1011 } // NOLINT(readability/fn_size) | 1018 } // NOLINT(readability/fn_size) |
1012 | 1019 |
1013 | 1020 void Verifier::Run(Graph* graph, Typing typing, CheckInputs check_inputs) { |
1014 void Verifier::Run(Graph* graph, Typing typing) { | |
1015 CHECK_NOT_NULL(graph->start()); | 1021 CHECK_NOT_NULL(graph->start()); |
1016 CHECK_NOT_NULL(graph->end()); | 1022 CHECK_NOT_NULL(graph->end()); |
1017 Zone zone(graph->zone()->allocator()); | 1023 Zone zone(graph->zone()->allocator()); |
1018 Visitor visitor(&zone, typing); | 1024 Visitor visitor(&zone, typing, check_inputs); |
1019 AllNodes all(&zone, graph); | 1025 AllNodes all(&zone, graph); |
1020 for (Node* node : all.live) visitor.Check(node); | 1026 for (Node* node : all.live) visitor.Check(node); |
1021 | 1027 |
1022 // Check the uniqueness of projections. | 1028 // Check the uniqueness of projections. |
1023 for (Node* proj : all.live) { | 1029 for (Node* proj : all.live) { |
1024 if (proj->opcode() != IrOpcode::kProjection) continue; | 1030 if (proj->opcode() != IrOpcode::kProjection) continue; |
1025 Node* node = proj->InputAt(0); | 1031 Node* node = proj->InputAt(0); |
1026 for (Node* other : node->uses()) { | 1032 for (Node* other : node->uses()) { |
1027 if (all.IsLive(other) && other != proj && | 1033 if (all.IsLive(other) && other != proj && |
1028 other->opcode() == IrOpcode::kProjection && | 1034 other->opcode() == IrOpcode::kProjection && |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 replacement->op()->EffectOutputCount() > 0); | 1334 replacement->op()->EffectOutputCount() > 0); |
1329 DCHECK(!NodeProperties::IsFrameStateEdge(edge) || | 1335 DCHECK(!NodeProperties::IsFrameStateEdge(edge) || |
1330 replacement->opcode() == IrOpcode::kFrameState); | 1336 replacement->opcode() == IrOpcode::kFrameState); |
1331 } | 1337 } |
1332 | 1338 |
1333 #endif // DEBUG | 1339 #endif // DEBUG |
1334 | 1340 |
1335 } // namespace compiler | 1341 } // namespace compiler |
1336 } // namespace internal | 1342 } // namespace internal |
1337 } // namespace v8 | 1343 } // namespace v8 |
OLD | NEW |