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 <deque> | 7 #include <deque> |
8 #include <queue> | 8 #include <queue> |
9 #include <sstream> | 9 #include <sstream> |
10 #include <string> | 10 #include <string> |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 bounds(input).upper->PrintTo(str); | 114 bounds(input).upper->PrintTo(str); |
115 str << " is not "; | 115 str << " is not "; |
116 type->PrintTo(str); | 116 type->PrintTo(str); |
117 V8_Fatal(__FILE__, __LINE__, str.str().c_str()); | 117 V8_Fatal(__FILE__, __LINE__, str.str().c_str()); |
118 } | 118 } |
119 } | 119 } |
120 }; | 120 }; |
121 | 121 |
122 | 122 |
123 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { | 123 GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { |
124 int value_count = OperatorProperties::GetValueInputCount(node->op()); | 124 int value_count = node->op()->ValueInputCount(); |
125 int context_count = OperatorProperties::GetContextInputCount(node->op()); | 125 int context_count = OperatorProperties::GetContextInputCount(node->op()); |
126 int frame_state_count = | 126 int frame_state_count = |
127 OperatorProperties::GetFrameStateInputCount(node->op()); | 127 OperatorProperties::GetFrameStateInputCount(node->op()); |
128 int effect_count = OperatorProperties::GetEffectInputCount(node->op()); | 128 int effect_count = node->op()->EffectInputCount(); |
129 int control_count = OperatorProperties::GetControlInputCount(node->op()); | 129 int control_count = node->op()->ControlInputCount(); |
130 | 130 |
131 // Verify number of inputs matches up. | 131 // Verify number of inputs matches up. |
132 int input_count = value_count + context_count + frame_state_count + | 132 int input_count = value_count + context_count + frame_state_count + |
133 effect_count + control_count; | 133 effect_count + control_count; |
134 CHECK_EQ(input_count, node->InputCount()); | 134 CHECK_EQ(input_count, node->InputCount()); |
135 | 135 |
136 // Verify that frame state has been inserted for the nodes that need it. | 136 // Verify that frame state has been inserted for the nodes that need it. |
137 if (OperatorProperties::HasFrameStateInput(node->op())) { | 137 if (OperatorProperties::HasFrameStateInput(node->op())) { |
138 Node* frame_state = NodeProperties::GetFrameStateInput(node); | 138 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
139 CHECK(frame_state->opcode() == IrOpcode::kFrameState || | 139 CHECK(frame_state->opcode() == IrOpcode::kFrameState || |
140 // kFrameState uses undefined as a sentinel. | 140 // kFrameState uses undefined as a sentinel. |
141 (node->opcode() == IrOpcode::kFrameState && | 141 (node->opcode() == IrOpcode::kFrameState && |
142 frame_state->opcode() == IrOpcode::kHeapConstant)); | 142 frame_state->opcode() == IrOpcode::kHeapConstant)); |
143 CHECK(IsDefUseChainLinkPresent(frame_state, node)); | 143 CHECK(IsDefUseChainLinkPresent(frame_state, node)); |
144 CHECK(IsUseDefChainLinkPresent(frame_state, node)); | 144 CHECK(IsUseDefChainLinkPresent(frame_state, node)); |
145 } | 145 } |
146 | 146 |
147 // Verify all value inputs actually produce a value. | 147 // Verify all value inputs actually produce a value. |
148 for (int i = 0; i < value_count; ++i) { | 148 for (int i = 0; i < value_count; ++i) { |
149 Node* value = NodeProperties::GetValueInput(node, i); | 149 Node* value = NodeProperties::GetValueInput(node, i); |
150 CHECK(OperatorProperties::HasValueOutput(value->op())); | 150 CHECK(value->op()->ValueOutputCount() > 0); |
151 CHECK(IsDefUseChainLinkPresent(value, node)); | 151 CHECK(IsDefUseChainLinkPresent(value, node)); |
152 CHECK(IsUseDefChainLinkPresent(value, node)); | 152 CHECK(IsUseDefChainLinkPresent(value, node)); |
153 } | 153 } |
154 | 154 |
155 // Verify all context inputs are value nodes. | 155 // Verify all context inputs are value nodes. |
156 for (int i = 0; i < context_count; ++i) { | 156 for (int i = 0; i < context_count; ++i) { |
157 Node* context = NodeProperties::GetContextInput(node); | 157 Node* context = NodeProperties::GetContextInput(node); |
158 CHECK(OperatorProperties::HasValueOutput(context->op())); | 158 CHECK(context->op()->ValueOutputCount() > 0); |
159 CHECK(IsDefUseChainLinkPresent(context, node)); | 159 CHECK(IsDefUseChainLinkPresent(context, node)); |
160 CHECK(IsUseDefChainLinkPresent(context, node)); | 160 CHECK(IsUseDefChainLinkPresent(context, node)); |
161 } | 161 } |
162 | 162 |
163 // Verify all effect inputs actually have an effect. | 163 // Verify all effect inputs actually have an effect. |
164 for (int i = 0; i < effect_count; ++i) { | 164 for (int i = 0; i < effect_count; ++i) { |
165 Node* effect = NodeProperties::GetEffectInput(node); | 165 Node* effect = NodeProperties::GetEffectInput(node); |
166 CHECK(OperatorProperties::HasEffectOutput(effect->op())); | 166 CHECK(effect->op()->EffectOutputCount() > 0); |
167 CHECK(IsDefUseChainLinkPresent(effect, node)); | 167 CHECK(IsDefUseChainLinkPresent(effect, node)); |
168 CHECK(IsUseDefChainLinkPresent(effect, node)); | 168 CHECK(IsUseDefChainLinkPresent(effect, node)); |
169 } | 169 } |
170 | 170 |
171 // Verify all control inputs are control nodes. | 171 // Verify all control inputs are control nodes. |
172 for (int i = 0; i < control_count; ++i) { | 172 for (int i = 0; i < control_count; ++i) { |
173 Node* control = NodeProperties::GetControlInput(node, i); | 173 Node* control = NodeProperties::GetControlInput(node, i); |
174 CHECK(OperatorProperties::HasControlOutput(control->op())); | 174 CHECK(control->op()->ControlOutputCount() > 0); |
175 CHECK(IsDefUseChainLinkPresent(control, node)); | 175 CHECK(IsDefUseChainLinkPresent(control, node)); |
176 CHECK(IsUseDefChainLinkPresent(control, node)); | 176 CHECK(IsUseDefChainLinkPresent(control, node)); |
177 } | 177 } |
178 | 178 |
179 // Verify all successors are projections if multiple value outputs exist. | 179 // Verify all successors are projections if multiple value outputs exist. |
180 if (OperatorProperties::GetValueOutputCount(node->op()) > 1) { | 180 if (node->op()->ValueOutputCount() > 1) { |
181 Node::Uses uses = node->uses(); | 181 Node::Uses uses = node->uses(); |
182 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { | 182 for (Node::Uses::iterator it = uses.begin(); it != uses.end(); ++it) { |
183 CHECK(!NodeProperties::IsValueEdge(it.edge()) || | 183 CHECK(!NodeProperties::IsValueEdge(it.edge()) || |
184 (*it)->opcode() == IrOpcode::kProjection || | 184 (*it)->opcode() == IrOpcode::kProjection || |
185 (*it)->opcode() == IrOpcode::kParameter); | 185 (*it)->opcode() == IrOpcode::kParameter); |
186 } | 186 } |
187 } | 187 } |
188 | 188 |
189 switch (node->opcode()) { | 189 switch (node->opcode()) { |
190 case IrOpcode::kStart: | 190 case IrOpcode::kStart: |
191 // Start has no inputs. | 191 // Start has no inputs. |
192 CHECK_EQ(0, input_count); | 192 CHECK_EQ(0, input_count); |
193 // Type is a tuple. | 193 // Type is a tuple. |
194 // TODO(rossberg): Multiple outputs are currently typed as Internal. | 194 // TODO(rossberg): Multiple outputs are currently typed as Internal. |
195 CheckUpperIs(node, Type::Internal()); | 195 CheckUpperIs(node, Type::Internal()); |
196 break; | 196 break; |
197 case IrOpcode::kEnd: | 197 case IrOpcode::kEnd: |
198 // End has no outputs. | 198 // End has no outputs. |
199 CHECK(!OperatorProperties::HasValueOutput(node->op())); | 199 CHECK(node->op()->ValueOutputCount() == 0); |
200 CHECK(!OperatorProperties::HasEffectOutput(node->op())); | 200 CHECK(node->op()->EffectOutputCount() == 0); |
201 CHECK(!OperatorProperties::HasControlOutput(node->op())); | 201 CHECK(node->op()->ControlOutputCount() == 0); |
202 // Type is empty. | 202 // Type is empty. |
203 CheckNotTyped(node); | 203 CheckNotTyped(node); |
204 break; | 204 break; |
205 case IrOpcode::kDead: | 205 case IrOpcode::kDead: |
206 // Dead is never connected to the graph. | 206 // Dead is never connected to the graph. |
207 UNREACHABLE(); | 207 UNREACHABLE(); |
208 case IrOpcode::kBranch: { | 208 case IrOpcode::kBranch: { |
209 // Branch uses are IfTrue and IfFalse. | 209 // Branch uses are IfTrue and IfFalse. |
210 Node::Uses uses = node->uses(); | 210 Node::Uses uses = node->uses(); |
211 int count_true = 0, count_false = 0; | 211 int count_true = 0, count_false = 0; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 // ---------------- | 254 // ---------------- |
255 case IrOpcode::kParameter: { | 255 case IrOpcode::kParameter: { |
256 // Parameters have the start node as inputs. | 256 // Parameters have the start node as inputs. |
257 CHECK_EQ(1, input_count); | 257 CHECK_EQ(1, input_count); |
258 CHECK_EQ(IrOpcode::kStart, | 258 CHECK_EQ(IrOpcode::kStart, |
259 NodeProperties::GetValueInput(node, 0)->opcode()); | 259 NodeProperties::GetValueInput(node, 0)->opcode()); |
260 // Parameter has an input that produces enough values. | 260 // Parameter has an input that produces enough values. |
261 int index = OpParameter<int>(node); | 261 int index = OpParameter<int>(node); |
262 Node* input = NodeProperties::GetValueInput(node, 0); | 262 Node* input = NodeProperties::GetValueInput(node, 0); |
263 // Currently, parameter indices start at -1 instead of 0. | 263 // Currently, parameter indices start at -1 instead of 0. |
264 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index + 1); | 264 CHECK_GT(input->op()->ValueOutputCount(), index + 1); |
265 // Type can be anything. | 265 // Type can be anything. |
266 CheckUpperIs(node, Type::Any()); | 266 CheckUpperIs(node, Type::Any()); |
267 break; | 267 break; |
268 } | 268 } |
269 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? | 269 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant? |
270 // Constants have no inputs. | 270 // Constants have no inputs. |
271 CHECK_EQ(0, input_count); | 271 CHECK_EQ(0, input_count); |
272 // Type is a 32 bit integer, signed or unsigned. | 272 // Type is a 32 bit integer, signed or unsigned. |
273 CheckUpperIs(node, Type::Integral32()); | 273 CheckUpperIs(node, Type::Integral32()); |
274 break; | 274 break; |
(...skipping 21 matching lines...) Expand all Loading... |
296 case IrOpcode::kExternalConstant: | 296 case IrOpcode::kExternalConstant: |
297 // Constants have no inputs. | 297 // Constants have no inputs. |
298 CHECK_EQ(0, input_count); | 298 CHECK_EQ(0, input_count); |
299 // Type is considered internal. | 299 // Type is considered internal. |
300 CheckUpperIs(node, Type::Internal()); | 300 CheckUpperIs(node, Type::Internal()); |
301 break; | 301 break; |
302 case IrOpcode::kProjection: { | 302 case IrOpcode::kProjection: { |
303 // Projection has an input that produces enough values. | 303 // Projection has an input that produces enough values. |
304 int index = static_cast<int>(OpParameter<size_t>(node->op())); | 304 int index = static_cast<int>(OpParameter<size_t>(node->op())); |
305 Node* input = NodeProperties::GetValueInput(node, 0); | 305 Node* input = NodeProperties::GetValueInput(node, 0); |
306 CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index); | 306 CHECK_GT(input->op()->ValueOutputCount(), index); |
307 // Type can be anything. | 307 // Type can be anything. |
308 // TODO(rossberg): Introduce tuple types for this. | 308 // TODO(rossberg): Introduce tuple types for this. |
309 // TODO(titzer): Convince rossberg not to. | 309 // TODO(titzer): Convince rossberg not to. |
310 CheckUpperIs(node, Type::Any()); | 310 CheckUpperIs(node, Type::Any()); |
311 break; | 311 break; |
312 } | 312 } |
313 case IrOpcode::kSelect: { | 313 case IrOpcode::kSelect: { |
314 CHECK_EQ(0, effect_count); | 314 CHECK_EQ(0, effect_count); |
315 CHECK_EQ(0, control_count); | 315 CHECK_EQ(0, control_count); |
316 CHECK_EQ(3, value_count); | 316 CHECK_EQ(3, value_count); |
317 break; | 317 break; |
318 } | 318 } |
319 case IrOpcode::kPhi: { | 319 case IrOpcode::kPhi: { |
320 // Phi input count matches parent control node. | 320 // Phi input count matches parent control node. |
321 CHECK_EQ(0, effect_count); | 321 CHECK_EQ(0, effect_count); |
322 CHECK_EQ(1, control_count); | 322 CHECK_EQ(1, control_count); |
323 Node* control = NodeProperties::GetControlInput(node, 0); | 323 Node* control = NodeProperties::GetControlInput(node, 0); |
324 CHECK_EQ(value_count, | 324 CHECK_EQ(value_count, control->op()->ControlInputCount()); |
325 OperatorProperties::GetControlInputCount(control->op())); | |
326 CHECK_EQ(input_count, 1 + value_count); | 325 CHECK_EQ(input_count, 1 + value_count); |
327 // Type must be subsumed by all input types. | 326 // Type must be subsumed by all input types. |
328 // TODO(rossberg): for now at least, narrowing does not really hold. | 327 // TODO(rossberg): for now at least, narrowing does not really hold. |
329 /* | 328 /* |
330 for (int i = 0; i < value_count; ++i) { | 329 for (int i = 0; i < value_count; ++i) { |
331 // TODO(rossberg, jarin): Figure out what to do about lower bounds. | 330 // TODO(rossberg, jarin): Figure out what to do about lower bounds. |
332 // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower)); | 331 // CHECK(bounds(node).lower->Is(bounds(ValueInput(node, i)).lower)); |
333 CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper)); | 332 CHECK(bounds(ValueInput(node, i)).upper->Is(bounds(node).upper)); |
334 } | 333 } |
335 */ | 334 */ |
336 break; | 335 break; |
337 } | 336 } |
338 case IrOpcode::kEffectPhi: { | 337 case IrOpcode::kEffectPhi: { |
339 // EffectPhi input count matches parent control node. | 338 // EffectPhi input count matches parent control node. |
340 CHECK_EQ(0, value_count); | 339 CHECK_EQ(0, value_count); |
341 CHECK_EQ(1, control_count); | 340 CHECK_EQ(1, control_count); |
342 Node* control = NodeProperties::GetControlInput(node, 0); | 341 Node* control = NodeProperties::GetControlInput(node, 0); |
343 CHECK_EQ(effect_count, | 342 CHECK_EQ(effect_count, control->op()->ControlInputCount()); |
344 OperatorProperties::GetControlInputCount(control->op())); | |
345 CHECK_EQ(input_count, 1 + effect_count); | 343 CHECK_EQ(input_count, 1 + effect_count); |
346 break; | 344 break; |
347 } | 345 } |
348 case IrOpcode::kValueEffect: | 346 case IrOpcode::kValueEffect: |
349 // TODO(rossberg): what are the constraints on these? | 347 // TODO(rossberg): what are the constraints on these? |
350 break; | 348 break; |
351 case IrOpcode::kFinish: { | 349 case IrOpcode::kFinish: { |
352 // TODO(rossberg): what are the constraints on these? | 350 // TODO(rossberg): what are the constraints on these? |
353 // Type must be subsumed by input type. | 351 // Type must be subsumed by input type. |
354 if (typing == TYPED) { | 352 if (typing == TYPED) { |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 return true; | 768 return true; |
771 } | 769 } |
772 sub = sub->dominator(); | 770 sub = sub->dominator(); |
773 } | 771 } |
774 return false; | 772 return false; |
775 } | 773 } |
776 | 774 |
777 | 775 |
778 static void CheckInputsDominate(Schedule* schedule, BasicBlock* block, | 776 static void CheckInputsDominate(Schedule* schedule, BasicBlock* block, |
779 Node* node, int use_pos) { | 777 Node* node, int use_pos) { |
780 for (int j = OperatorProperties::GetValueInputCount(node->op()) - 1; j >= 0; | 778 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) { |
781 j--) { | |
782 BasicBlock* use_block = block; | 779 BasicBlock* use_block = block; |
783 if (node->opcode() == IrOpcode::kPhi) { | 780 if (node->opcode() == IrOpcode::kPhi) { |
784 use_block = use_block->PredecessorAt(j); | 781 use_block = use_block->PredecessorAt(j); |
785 use_pos = static_cast<int>(use_block->NodeCount()) - 1; | 782 use_pos = static_cast<int>(use_block->NodeCount()) - 1; |
786 } | 783 } |
787 Node* input = node->InputAt(j); | 784 Node* input = node->InputAt(j); |
788 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block, | 785 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block, |
789 use_pos)) { | 786 use_pos)) { |
790 V8_Fatal(__FILE__, __LINE__, | 787 V8_Fatal(__FILE__, __LINE__, |
791 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s", | 788 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s", |
792 node->id(), node->op()->mnemonic(), block->id().ToInt(), j, | 789 node->id(), node->op()->mnemonic(), block->id().ToInt(), j, |
793 input->id(), input->op()->mnemonic()); | 790 input->id(), input->op()->mnemonic()); |
794 } | 791 } |
795 } | 792 } |
796 // Ensure that nodes are dominated by their control inputs; | 793 // Ensure that nodes are dominated by their control inputs; |
797 // kEnd is an exception, as unreachable blocks resulting from kMerge | 794 // kEnd is an exception, as unreachable blocks resulting from kMerge |
798 // are not in the RPO. | 795 // are not in the RPO. |
799 if (OperatorProperties::GetControlInputCount(node->op()) == 1 && | 796 if (node->op()->ControlInputCount() == 1 && |
800 node->opcode() != IrOpcode::kEnd) { | 797 node->opcode() != IrOpcode::kEnd) { |
801 Node* ctl = NodeProperties::GetControlInput(node); | 798 Node* ctl = NodeProperties::GetControlInput(node); |
802 if (!Dominates(schedule, ctl, node)) { | 799 if (!Dominates(schedule, ctl, node)) { |
803 V8_Fatal(__FILE__, __LINE__, | 800 V8_Fatal(__FILE__, __LINE__, |
804 "Node #%d:%s in B%d is not dominated by control input #%d:%s", | 801 "Node #%d:%s in B%d is not dominated by control input #%d:%s", |
805 node->id(), node->op()->mnemonic(), block->id(), ctl->id(), | 802 node->id(), node->op()->mnemonic(), block->id(), ctl->id(), |
806 ctl->op()->mnemonic()); | 803 ctl->op()->mnemonic()); |
807 } | 804 } |
808 } | 805 } |
809 } | 806 } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 } | 941 } |
945 | 942 |
946 // Verify phis are placed in the block of their control input. | 943 // Verify phis are placed in the block of their control input. |
947 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); | 944 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); |
948 ++b) { | 945 ++b) { |
949 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) { | 946 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) { |
950 Node* phi = *i; | 947 Node* phi = *i; |
951 if (phi->opcode() != IrOpcode::kPhi) continue; | 948 if (phi->opcode() != IrOpcode::kPhi) continue; |
952 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler | 949 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler |
953 // schedules don't have control inputs. | 950 // schedules don't have control inputs. |
954 if (phi->InputCount() > | 951 if (phi->InputCount() > phi->op()->ValueInputCount()) { |
955 OperatorProperties::GetValueInputCount(phi->op())) { | |
956 Node* control = NodeProperties::GetControlInput(phi); | 952 Node* control = NodeProperties::GetControlInput(phi); |
957 CHECK(control->opcode() == IrOpcode::kMerge || | 953 CHECK(control->opcode() == IrOpcode::kMerge || |
958 control->opcode() == IrOpcode::kLoop); | 954 control->opcode() == IrOpcode::kLoop); |
959 CHECK_EQ((*b), schedule->block(control)); | 955 CHECK_EQ((*b), schedule->block(control)); |
960 } | 956 } |
961 } | 957 } |
962 } | 958 } |
963 | 959 |
964 // Verify that all uses are dominated by their definitions. | 960 // Verify that all uses are dominated by their definitions. |
965 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); | 961 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end(); |
(...skipping 10 matching lines...) Expand all Loading... |
976 // Check inputs for all nodes in the block. | 972 // Check inputs for all nodes in the block. |
977 for (size_t i = 0; i < block->NodeCount(); i++) { | 973 for (size_t i = 0; i < block->NodeCount(); i++) { |
978 Node* node = block->NodeAt(i); | 974 Node* node = block->NodeAt(i); |
979 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); | 975 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1); |
980 } | 976 } |
981 } | 977 } |
982 } | 978 } |
983 } | 979 } |
984 } | 980 } |
985 } // namespace v8::internal::compiler | 981 } // namespace v8::internal::compiler |
OLD | NEW |