blob: 0e3428522147f3ce187ca756aabad95f0ba92125 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#include "src/compiler/verifier.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <algorithm>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include <deque>
9#include <queue>
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010#include <sstream>
11#include <string>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/bit-vector.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/compiler/all-nodes.h"
15#include "src/compiler/common-operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/compiler/graph.h"
17#include "src/compiler/node.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/compiler/node-properties.h"
19#include "src/compiler/opcodes.h"
20#include "src/compiler/operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#include "src/compiler/schedule.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023#include "src/compiler/simplified-operator.h"
24#include "src/ostreams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025
26namespace v8 {
27namespace internal {
28namespace compiler {
29
30
31static bool IsDefUseChainLinkPresent(Node* def, Node* use) {
Ben Murdochda12d292016-06-02 14:46:10 +010032 const Node::Uses uses = def->uses();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 return std::find(uses.begin(), uses.end(), use) != uses.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034}
35
36
37static bool IsUseDefChainLinkPresent(Node* def, Node* use) {
Ben Murdochda12d292016-06-02 14:46:10 +010038 const Node::Inputs inputs = use->inputs();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 return std::find(inputs.begin(), inputs.end(), def) != inputs.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040}
41
42
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043class Verifier::Visitor {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 public:
Ben Murdochc5610432016-08-08 18:44:38 +010045 Visitor(Zone* z, Typing typed, CheckInputs check_inputs)
46 : zone(z), typing(typed), check_inputs(check_inputs) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 void Check(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 Zone* zone;
51 Typing typing;
Ben Murdochc5610432016-08-08 18:44:38 +010052 CheckInputs check_inputs;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053
54 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 void CheckNotTyped(Node* node) {
56 if (NodeProperties::IsTyped(node)) {
57 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 str << "TypeError: node #" << node->id() << ":" << *node->op()
59 << " should never have a type";
60 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061 }
62 }
63 void CheckUpperIs(Node* node, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 if (typing == TYPED && !NodeProperties::GetType(node)->Is(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 str << "TypeError: node #" << node->id() << ":" << *node->op()
67 << " type ";
68 NodeProperties::GetType(node)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069 str << " is not ";
70 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 }
73 }
74 void CheckUpperMaybe(Node* node, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 if (typing == TYPED && !NodeProperties::GetType(node)->Maybe(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 str << "TypeError: node #" << node->id() << ":" << *node->op()
78 << " type ";
79 NodeProperties::GetType(node)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 str << " must intersect ";
81 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083 }
84 }
85 void CheckValueInputIs(Node* node, int i, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 Node* input = NodeProperties::GetValueInput(node, i);
87 if (typing == TYPED && !NodeProperties::GetType(input)->Is(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 str << "TypeError: node #" << node->id() << ":" << *node->op()
90 << "(input @" << i << " = " << input->opcode() << ":"
91 << input->op()->mnemonic() << ") type ";
92 NodeProperties::GetType(input)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093 str << " is not ";
94 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 FATAL(str.str().c_str());
96 }
97 }
98 void CheckOutput(Node* node, Node* use, int count, const char* kind) {
99 if (count <= 0) {
100 std::ostringstream str;
101 str << "GraphError: node #" << node->id() << ":" << *node->op()
102 << " does not produce " << kind << " output used by node #"
103 << use->id() << ":" << *use->op();
104 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400105 }
106 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107};
108
109
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110void Verifier::Visitor::Check(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400111 int value_count = node->op()->ValueInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 int context_count = OperatorProperties::GetContextInputCount(node->op());
113 int frame_state_count =
114 OperatorProperties::GetFrameStateInputCount(node->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115 int effect_count = node->op()->EffectInputCount();
116 int control_count = node->op()->ControlInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117
118 // Verify number of inputs matches up.
Ben Murdochc5610432016-08-08 18:44:38 +0100119 int input_count = value_count + context_count + frame_state_count;
120 if (check_inputs == kAll) {
121 input_count += effect_count + control_count;
122 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 CHECK_EQ(input_count, node->InputCount());
124
125 // Verify that frame state has been inserted for the nodes that need it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 for (int i = 0; i < frame_state_count; i++) {
127 Node* frame_state = NodeProperties::GetFrameStateInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 CHECK(frame_state->opcode() == IrOpcode::kFrameState ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 // kFrameState uses Start as a sentinel.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 (node->opcode() == IrOpcode::kFrameState &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 frame_state->opcode() == IrOpcode::kStart));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132 CHECK(IsDefUseChainLinkPresent(frame_state, node));
133 CHECK(IsUseDefChainLinkPresent(frame_state, node));
134 }
135
136 // Verify all value inputs actually produce a value.
137 for (int i = 0; i < value_count; ++i) {
138 Node* value = NodeProperties::GetValueInput(node, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 CheckOutput(value, node, value->op()->ValueOutputCount(), "value");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 CHECK(IsDefUseChainLinkPresent(value, node));
141 CHECK(IsUseDefChainLinkPresent(value, node));
Ben Murdochda12d292016-06-02 14:46:10 +0100142 // Verify that only parameters and projections can have input nodes with
143 // multiple outputs.
144 CHECK(node->opcode() == IrOpcode::kParameter ||
145 node->opcode() == IrOpcode::kProjection ||
146 value->op()->ValueOutputCount() <= 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 }
148
149 // Verify all context inputs are value nodes.
150 for (int i = 0; i < context_count; ++i) {
151 Node* context = NodeProperties::GetContextInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 CheckOutput(context, node, context->op()->ValueOutputCount(), "context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 CHECK(IsDefUseChainLinkPresent(context, node));
154 CHECK(IsUseDefChainLinkPresent(context, node));
155 }
156
Ben Murdochc5610432016-08-08 18:44:38 +0100157 if (check_inputs == kAll) {
158 // Verify all effect inputs actually have an effect.
159 for (int i = 0; i < effect_count; ++i) {
160 Node* effect = NodeProperties::GetEffectInput(node);
161 CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect");
162 CHECK(IsDefUseChainLinkPresent(effect, node));
163 CHECK(IsUseDefChainLinkPresent(effect, node));
164 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165
Ben Murdochc5610432016-08-08 18:44:38 +0100166 // Verify all control inputs are control nodes.
167 for (int i = 0; i < control_count; ++i) {
168 Node* control = NodeProperties::GetControlInput(node, i);
169 CheckOutput(control, node, control->op()->ControlOutputCount(),
170 "control");
171 CHECK(IsDefUseChainLinkPresent(control, node));
172 CHECK(IsUseDefChainLinkPresent(control, node));
173 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 }
175
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 switch (node->opcode()) {
177 case IrOpcode::kStart:
178 // Start has no inputs.
179 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400180 // Type is a tuple.
181 // TODO(rossberg): Multiple outputs are currently typed as Internal.
182 CheckUpperIs(node, Type::Internal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 break;
184 case IrOpcode::kEnd:
185 // End has no outputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186 CHECK(node->op()->ValueOutputCount() == 0);
187 CHECK(node->op()->EffectOutputCount() == 0);
188 CHECK(node->op()->ControlOutputCount() == 0);
189 // Type is empty.
190 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 break;
192 case IrOpcode::kDead:
193 // Dead is never connected to the graph.
194 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 case IrOpcode::kBranch: {
197 // Branch uses are IfTrue and IfFalse.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400198 int count_true = 0, count_false = 0;
Ben Murdochda12d292016-06-02 14:46:10 +0100199 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 CHECK(use->opcode() == IrOpcode::kIfTrue ||
201 use->opcode() == IrOpcode::kIfFalse);
202 if (use->opcode() == IrOpcode::kIfTrue) ++count_true;
203 if (use->opcode() == IrOpcode::kIfFalse) ++count_false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 CHECK_EQ(1, count_true);
206 CHECK_EQ(1, count_false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207 // Type is empty.
208 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 break;
210 }
211 case IrOpcode::kIfTrue:
212 case IrOpcode::kIfFalse:
213 CHECK_EQ(IrOpcode::kBranch,
214 NodeProperties::GetControlInput(node, 0)->opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 // Type is empty.
216 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 case IrOpcode::kIfSuccess: {
219 // IfSuccess and IfException continuation only on throwing nodes.
220 Node* input = NodeProperties::GetControlInput(node, 0);
221 CHECK(!input->op()->HasProperty(Operator::kNoThrow));
222 // Type is empty.
223 CheckNotTyped(node);
224 break;
225 }
226 case IrOpcode::kIfException: {
227 // IfSuccess and IfException continuation only on throwing nodes.
228 Node* input = NodeProperties::GetControlInput(node, 0);
229 CHECK(!input->op()->HasProperty(Operator::kNoThrow));
230 // Type can be anything.
231 CheckUpperIs(node, Type::Any());
232 break;
233 }
234 case IrOpcode::kSwitch: {
235 // Switch uses are Case and Default.
236 int count_case = 0, count_default = 0;
Ben Murdochda12d292016-06-02 14:46:10 +0100237 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 switch (use->opcode()) {
239 case IrOpcode::kIfValue: {
Ben Murdochda12d292016-06-02 14:46:10 +0100240 for (const Node* user : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 if (user != use && user->opcode() == IrOpcode::kIfValue) {
242 CHECK_NE(OpParameter<int32_t>(use->op()),
243 OpParameter<int32_t>(user->op()));
244 }
245 }
246 ++count_case;
247 break;
248 }
249 case IrOpcode::kIfDefault: {
250 ++count_default;
251 break;
252 }
253 default: {
254 V8_Fatal(__FILE__, __LINE__, "Switch #%d illegally used by #%d:%s",
255 node->id(), use->id(), use->op()->mnemonic());
256 break;
257 }
258 }
259 }
260 CHECK_EQ(1, count_default);
261 CHECK_EQ(node->op()->ControlOutputCount(), count_case + count_default);
262 // Type is empty.
263 CheckNotTyped(node);
264 break;
265 }
266 case IrOpcode::kIfValue:
267 case IrOpcode::kIfDefault:
268 CHECK_EQ(IrOpcode::kSwitch,
269 NodeProperties::GetControlInput(node)->opcode());
270 // Type is empty.
271 CheckNotTyped(node);
272 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 case IrOpcode::kLoop:
274 case IrOpcode::kMerge:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 CHECK_EQ(control_count, input_count);
276 // Type is empty.
277 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100279 case IrOpcode::kDeoptimizeIf:
280 case IrOpcode::kDeoptimizeUnless:
281 // Type is empty.
282 CheckNotTyped(node);
283 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 case IrOpcode::kDeoptimize:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 case IrOpcode::kReturn:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 case IrOpcode::kThrow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 // Deoptimize, Return and Throw uses are End.
Ben Murdochda12d292016-06-02 14:46:10 +0100288 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 CHECK_EQ(IrOpcode::kEnd, use->opcode());
290 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291 // Type is empty.
292 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294 case IrOpcode::kTerminate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 // Terminates take one loop and effect.
296 CHECK_EQ(1, control_count);
297 CHECK_EQ(1, effect_count);
298 CHECK_EQ(2, input_count);
299 CHECK_EQ(IrOpcode::kLoop,
300 NodeProperties::GetControlInput(node)->opcode());
301 // Terminate uses are End.
Ben Murdochda12d292016-06-02 14:46:10 +0100302 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 CHECK_EQ(IrOpcode::kEnd, use->opcode());
304 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400305 // Type is empty.
306 CheckNotTyped(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 break;
308 case IrOpcode::kOsrNormalEntry:
309 case IrOpcode::kOsrLoopEntry:
310 // Osr entries take one control and effect.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311 CHECK_EQ(1, control_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 CHECK_EQ(1, effect_count);
313 CHECK_EQ(2, input_count);
314 // Type is empty.
315 CheckNotTyped(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 break;
317
318 // Common operators
319 // ----------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 case IrOpcode::kParameter: {
321 // Parameters have the start node as inputs.
322 CHECK_EQ(1, input_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 // Parameter has an input that produces enough values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 int const index = ParameterIndexOf(node->op());
325 Node* const start = NodeProperties::GetValueInput(node, 0);
326 CHECK_EQ(IrOpcode::kStart, start->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 // Currently, parameter indices start at -1 instead of 0.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 CHECK_LE(-1, index);
329 CHECK_LT(index + 1, start->op()->ValueOutputCount());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400330 // Type can be anything.
331 CheckUpperIs(node, Type::Any());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 break;
333 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400334 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
335 // Constants have no inputs.
336 CHECK_EQ(0, input_count);
337 // Type is a 32 bit integer, signed or unsigned.
338 CheckUpperIs(node, Type::Integral32());
339 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 case IrOpcode::kInt64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 // Constants have no inputs.
342 CHECK_EQ(0, input_count);
343 // Type is internal.
344 // TODO(rossberg): Introduce proper Int64 type.
345 CheckUpperIs(node, Type::Internal());
346 break;
347 case IrOpcode::kFloat32Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 case IrOpcode::kFloat64Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349 case IrOpcode::kNumberConstant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400350 // Constants have no inputs.
351 CHECK_EQ(0, input_count);
352 // Type is a number.
353 CheckUpperIs(node, Type::Number());
354 break;
Ben Murdochc5610432016-08-08 18:44:38 +0100355 case IrOpcode::kRelocatableInt32Constant:
356 case IrOpcode::kRelocatableInt64Constant:
357 CHECK_EQ(0, input_count);
358 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 case IrOpcode::kHeapConstant:
360 // Constants have no inputs.
361 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400362 // Type can be anything represented as a heap pointer.
363 CheckUpperIs(node, Type::TaggedPointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400365 case IrOpcode::kExternalConstant:
366 // Constants have no inputs.
367 CHECK_EQ(0, input_count);
368 // Type is considered internal.
369 CheckUpperIs(node, Type::Internal());
370 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 case IrOpcode::kOsrValue:
372 // OSR values have a value and a control input.
373 CHECK_EQ(1, control_count);
374 CHECK_EQ(1, input_count);
375 // Type is merged from other values in the graph and could be any.
376 CheckUpperIs(node, Type::Any());
377 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 case IrOpcode::kProjection: {
379 // Projection has an input that produces enough values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 int index = static_cast<int>(ProjectionIndexOf(node->op()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400381 Node* input = NodeProperties::GetValueInput(node, 0);
382 CHECK_GT(input->op()->ValueOutputCount(), index);
383 // Type can be anything.
384 // TODO(rossberg): Introduce tuple types for this.
385 // TODO(titzer): Convince rossberg not to.
386 CheckUpperIs(node, Type::Any());
387 break;
388 }
389 case IrOpcode::kSelect: {
390 CHECK_EQ(0, effect_count);
391 CHECK_EQ(0, control_count);
392 CHECK_EQ(3, value_count);
393 break;
394 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 case IrOpcode::kPhi: {
396 // Phi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400397 CHECK_EQ(0, effect_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 CHECK_EQ(1, control_count);
399 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400 CHECK_EQ(value_count, control->op()->ControlInputCount());
401 CHECK_EQ(input_count, 1 + value_count);
402 // Type must be subsumed by all input types.
403 // TODO(rossberg): for now at least, narrowing does not really hold.
404 /*
405 for (int i = 0; i < value_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 CHECK(type_of(ValueInput(node, i))->Is(type_of(node)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400407 }
408 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 break;
410 }
411 case IrOpcode::kEffectPhi: {
412 // EffectPhi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400413 CHECK_EQ(0, value_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 CHECK_EQ(1, control_count);
415 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400416 CHECK_EQ(effect_count, control->op()->ControlInputCount());
417 CHECK_EQ(input_count, 1 + effect_count);
418 break;
419 }
Ben Murdochc5610432016-08-08 18:44:38 +0100420 case IrOpcode::kTypeGuard:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 // TODO(bmeurer): what are the constraints on these?
422 break;
Ben Murdochc5610432016-08-08 18:44:38 +0100423 case IrOpcode::kCheckPoint:
424 // Type is empty.
425 CheckNotTyped(node);
426 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 case IrOpcode::kBeginRegion:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400428 // TODO(rossberg): what are the constraints on these?
429 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 case IrOpcode::kFinishRegion: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400431 // TODO(rossberg): what are the constraints on these?
432 // Type must be subsumed by input type.
433 if (typing == TYPED) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 Node* val = NodeProperties::GetValueInput(node, 0);
435 CHECK(NodeProperties::GetType(val)->Is(NodeProperties::GetType(node)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400436 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 break;
438 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100439 case IrOpcode::kFrameState: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 // TODO(jarin): what are the constraints on these?
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 CHECK_EQ(5, value_count);
442 CHECK_EQ(0, control_count);
443 CHECK_EQ(0, effect_count);
444 CHECK_EQ(6, input_count);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100445 for (int i = 0; i < 3; ++i) {
446 CHECK(NodeProperties::GetValueInput(node, i)->opcode() ==
447 IrOpcode::kStateValues ||
448 NodeProperties::GetValueInput(node, i)->opcode() ==
449 IrOpcode::kTypedStateValues);
450 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100452 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 case IrOpcode::kObjectState:
455 case IrOpcode::kTypedStateValues:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400456 // TODO(jarin): what are the constraints on these?
457 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 case IrOpcode::kCall:
459 // TODO(rossberg): what are the constraints on these?
460 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 case IrOpcode::kTailCall:
462 // TODO(bmeurer): what are the constraints on these?
463 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464
465 // JavaScript operators
466 // --------------------
467 case IrOpcode::kJSEqual:
468 case IrOpcode::kJSNotEqual:
469 case IrOpcode::kJSStrictEqual:
470 case IrOpcode::kJSStrictNotEqual:
471 case IrOpcode::kJSLessThan:
472 case IrOpcode::kJSGreaterThan:
473 case IrOpcode::kJSLessThanOrEqual:
474 case IrOpcode::kJSGreaterThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 // Type is Boolean.
476 CheckUpperIs(node, Type::Boolean());
477 break;
478
479 case IrOpcode::kJSBitwiseOr:
480 case IrOpcode::kJSBitwiseXor:
481 case IrOpcode::kJSBitwiseAnd:
482 case IrOpcode::kJSShiftLeft:
483 case IrOpcode::kJSShiftRight:
484 case IrOpcode::kJSShiftRightLogical:
485 // Type is 32 bit integral.
486 CheckUpperIs(node, Type::Integral32());
487 break;
488 case IrOpcode::kJSAdd:
489 // Type is Number or String.
490 CheckUpperIs(node, Type::NumberOrString());
491 break;
492 case IrOpcode::kJSSubtract:
493 case IrOpcode::kJSMultiply:
494 case IrOpcode::kJSDivide:
495 case IrOpcode::kJSModulus:
496 // Type is Number.
497 CheckUpperIs(node, Type::Number());
498 break;
499
500 case IrOpcode::kJSToBoolean:
501 // Type is Boolean.
502 CheckUpperIs(node, Type::Boolean());
503 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100504 case IrOpcode::kJSToInteger:
505 // Type is OrderedNumber.
506 CheckUpperIs(node, Type::OrderedNumber());
507 break;
508 case IrOpcode::kJSToLength:
509 // Type is OrderedNumber.
510 CheckUpperIs(node, Type::OrderedNumber());
511 break;
512 case IrOpcode::kJSToName:
513 // Type is Name.
514 CheckUpperIs(node, Type::Name());
515 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400516 case IrOpcode::kJSToNumber:
517 // Type is Number.
518 CheckUpperIs(node, Type::Number());
519 break;
520 case IrOpcode::kJSToString:
521 // Type is String.
522 CheckUpperIs(node, Type::String());
523 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400524 case IrOpcode::kJSToObject:
525 // Type is Receiver.
526 CheckUpperIs(node, Type::Receiver());
527 break;
528
529 case IrOpcode::kJSCreate:
530 // Type is Object.
531 CheckUpperIs(node, Type::Object());
532 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 case IrOpcode::kJSCreateArguments:
534 // Type is OtherObject.
535 CheckUpperIs(node, Type::OtherObject());
536 break;
537 case IrOpcode::kJSCreateArray:
538 // Type is OtherObject.
539 CheckUpperIs(node, Type::OtherObject());
540 break;
541 case IrOpcode::kJSCreateClosure:
542 // Type is Function.
543 CheckUpperIs(node, Type::Function());
544 break;
545 case IrOpcode::kJSCreateIterResultObject:
546 // Type is OtherObject.
547 CheckUpperIs(node, Type::OtherObject());
548 break;
549 case IrOpcode::kJSCreateLiteralArray:
550 case IrOpcode::kJSCreateLiteralObject:
551 case IrOpcode::kJSCreateLiteralRegExp:
552 // Type is OtherObject.
553 CheckUpperIs(node, Type::OtherObject());
554 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400555 case IrOpcode::kJSLoadProperty:
556 case IrOpcode::kJSLoadNamed:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 case IrOpcode::kJSLoadGlobal:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400558 // Type can be anything.
559 CheckUpperIs(node, Type::Any());
560 break;
561 case IrOpcode::kJSStoreProperty:
562 case IrOpcode::kJSStoreNamed:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 case IrOpcode::kJSStoreGlobal:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400564 // Type is empty.
565 CheckNotTyped(node);
566 break;
567 case IrOpcode::kJSDeleteProperty:
568 case IrOpcode::kJSHasProperty:
569 case IrOpcode::kJSInstanceOf:
570 // Type is Boolean.
571 CheckUpperIs(node, Type::Boolean());
572 break;
573 case IrOpcode::kJSTypeOf:
574 // Type is String.
575 CheckUpperIs(node, Type::String());
576 break;
577
578 case IrOpcode::kJSLoadContext:
579 // Type can be anything.
580 CheckUpperIs(node, Type::Any());
581 break;
582 case IrOpcode::kJSStoreContext:
583 // Type is empty.
584 CheckNotTyped(node);
585 break;
586 case IrOpcode::kJSCreateFunctionContext:
587 case IrOpcode::kJSCreateCatchContext:
588 case IrOpcode::kJSCreateWithContext:
589 case IrOpcode::kJSCreateBlockContext:
590 case IrOpcode::kJSCreateModuleContext:
591 case IrOpcode::kJSCreateScriptContext: {
592 // Type is Context, and operand is Internal.
593 Node* context = NodeProperties::GetContextInput(node);
594 // TODO(rossberg): This should really be Is(Internal), but the typer
595 // currently can't do backwards propagation.
596 CheckUpperMaybe(context, Type::Internal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 if (typing == TYPED) CHECK(NodeProperties::GetType(node)->IsContext());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 break;
599 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400600
601 case IrOpcode::kJSCallConstruct:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 case IrOpcode::kJSConvertReceiver:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 // Type is Receiver.
604 CheckUpperIs(node, Type::Receiver());
605 break;
606 case IrOpcode::kJSCallFunction:
607 case IrOpcode::kJSCallRuntime:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 // Type can be anything.
609 CheckUpperIs(node, Type::Any());
610 break;
611
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 case IrOpcode::kJSForInPrepare: {
613 // TODO(bmeurer): What are the constraints on thse?
614 CheckUpperIs(node, Type::Any());
615 break;
616 }
617 case IrOpcode::kJSForInDone: {
618 // TODO(bmeurer): OSR breaks this invariant, although the node is not user
619 // visible, so we know it is safe (fullcodegen has an unsigned smi there).
620 // CheckValueInputIs(node, 0, Type::UnsignedSmall());
621 break;
622 }
623 case IrOpcode::kJSForInNext: {
624 CheckUpperIs(node, Type::Union(Type::Name(), Type::Undefined(), zone));
625 break;
626 }
627 case IrOpcode::kJSForInStep: {
628 // TODO(bmeurer): OSR breaks this invariant, although the node is not user
629 // visible, so we know it is safe (fullcodegen has an unsigned smi there).
630 // CheckValueInputIs(node, 0, Type::UnsignedSmall());
631 CheckUpperIs(node, Type::UnsignedSmall());
632 break;
633 }
634
635 case IrOpcode::kJSLoadMessage:
636 case IrOpcode::kJSStoreMessage:
637 break;
638
639 case IrOpcode::kJSStackCheck:
640 // Type is empty.
641 CheckNotTyped(node);
642 break;
643
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400644 // Simplified operators
645 // -------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400646 case IrOpcode::kBooleanNot:
647 // Boolean -> Boolean
648 CheckValueInputIs(node, 0, Type::Boolean());
649 CheckUpperIs(node, Type::Boolean());
650 break;
651 case IrOpcode::kBooleanToNumber:
652 // Boolean -> Number
653 CheckValueInputIs(node, 0, Type::Boolean());
654 CheckUpperIs(node, Type::Number());
655 break;
656 case IrOpcode::kNumberEqual:
Ben Murdochc5610432016-08-08 18:44:38 +0100657 // (NumberOrUndefined, NumberOrUndefined) -> Boolean
658 CheckValueInputIs(node, 0, Type::NumberOrUndefined());
659 CheckValueInputIs(node, 1, Type::NumberOrUndefined());
660 CheckUpperIs(node, Type::Boolean());
661 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400662 case IrOpcode::kNumberLessThan:
663 case IrOpcode::kNumberLessThanOrEqual:
664 // (Number, Number) -> Boolean
Ben Murdochc5610432016-08-08 18:44:38 +0100665 CheckValueInputIs(node, 0, Type::NumberOrUndefined());
666 CheckValueInputIs(node, 1, Type::NumberOrUndefined());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400667 CheckUpperIs(node, Type::Boolean());
668 break;
669 case IrOpcode::kNumberAdd:
670 case IrOpcode::kNumberSubtract:
671 case IrOpcode::kNumberMultiply:
672 case IrOpcode::kNumberDivide:
Ben Murdochc5610432016-08-08 18:44:38 +0100673 // (Number, Number) -> Number
674 CheckValueInputIs(node, 0, Type::NumberOrUndefined());
675 CheckValueInputIs(node, 1, Type::NumberOrUndefined());
676 // CheckUpperIs(node, Type::Number());
677 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400678 case IrOpcode::kNumberModulus:
679 // (Number, Number) -> Number
680 CheckValueInputIs(node, 0, Type::Number());
681 CheckValueInputIs(node, 1, Type::Number());
682 // TODO(rossberg): activate once we retype after opcode changes.
683 // CheckUpperIs(node, Type::Number());
684 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000685 case IrOpcode::kNumberBitwiseOr:
686 case IrOpcode::kNumberBitwiseXor:
687 case IrOpcode::kNumberBitwiseAnd:
688 // (Signed32, Signed32) -> Signed32
689 CheckValueInputIs(node, 0, Type::Signed32());
690 CheckValueInputIs(node, 1, Type::Signed32());
691 CheckUpperIs(node, Type::Signed32());
692 break;
693 case IrOpcode::kNumberShiftLeft:
694 case IrOpcode::kNumberShiftRight:
695 // (Signed32, Unsigned32) -> Signed32
696 CheckValueInputIs(node, 0, Type::Signed32());
697 CheckValueInputIs(node, 1, Type::Unsigned32());
698 CheckUpperIs(node, Type::Signed32());
699 break;
700 case IrOpcode::kNumberShiftRightLogical:
701 // (Unsigned32, Unsigned32) -> Unsigned32
702 CheckValueInputIs(node, 0, Type::Unsigned32());
703 CheckValueInputIs(node, 1, Type::Unsigned32());
704 CheckUpperIs(node, Type::Unsigned32());
705 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100706 case IrOpcode::kNumberImul:
707 // (Unsigned32, Unsigned32) -> Signed32
708 CheckValueInputIs(node, 0, Type::Unsigned32());
709 CheckValueInputIs(node, 1, Type::Unsigned32());
710 CheckUpperIs(node, Type::Signed32());
711 break;
712 case IrOpcode::kNumberClz32:
713 // Unsigned32 -> Unsigned32
714 CheckValueInputIs(node, 0, Type::Unsigned32());
715 CheckUpperIs(node, Type::Unsigned32());
716 break;
717 case IrOpcode::kNumberCeil:
718 case IrOpcode::kNumberFloor:
719 case IrOpcode::kNumberRound:
720 case IrOpcode::kNumberTrunc:
721 // Number -> Number
722 CheckValueInputIs(node, 0, Type::Number());
723 CheckUpperIs(node, Type::Number());
724 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400725 case IrOpcode::kNumberToInt32:
726 // Number -> Signed32
Ben Murdochc5610432016-08-08 18:44:38 +0100727 CheckValueInputIs(node, 0, Type::NumberOrUndefined());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400728 CheckUpperIs(node, Type::Signed32());
729 break;
730 case IrOpcode::kNumberToUint32:
731 // Number -> Unsigned32
Ben Murdochc5610432016-08-08 18:44:38 +0100732 CheckValueInputIs(node, 0, Type::NumberOrUndefined());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400733 CheckUpperIs(node, Type::Unsigned32());
734 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 case IrOpcode::kNumberIsHoleNaN:
736 // Number -> Boolean
737 CheckValueInputIs(node, 0, Type::Number());
738 CheckUpperIs(node, Type::Boolean());
739 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400740 case IrOpcode::kStringEqual:
741 case IrOpcode::kStringLessThan:
742 case IrOpcode::kStringLessThanOrEqual:
743 // (String, String) -> Boolean
744 CheckValueInputIs(node, 0, Type::String());
745 CheckValueInputIs(node, 1, Type::String());
746 CheckUpperIs(node, Type::Boolean());
747 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100748 case IrOpcode::kStringToNumber:
749 // String -> Number
750 CheckValueInputIs(node, 0, Type::String());
751 CheckUpperIs(node, Type::Number());
752 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400753 case IrOpcode::kReferenceEqual: {
754 // (Unique, Any) -> Boolean and
755 // (Any, Unique) -> Boolean
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400756 CheckUpperIs(node, Type::Boolean());
757 break;
758 }
Ben Murdochc5610432016-08-08 18:44:38 +0100759 case IrOpcode::kObjectIsCallable:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760 case IrOpcode::kObjectIsNumber:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100761 case IrOpcode::kObjectIsReceiver:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400762 case IrOpcode::kObjectIsSmi:
Ben Murdochc5610432016-08-08 18:44:38 +0100763 case IrOpcode::kObjectIsString:
Ben Murdochda12d292016-06-02 14:46:10 +0100764 case IrOpcode::kObjectIsUndetectable:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400765 CheckValueInputIs(node, 0, Type::Any());
766 CheckUpperIs(node, Type::Boolean());
767 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 case IrOpcode::kAllocate:
769 CheckValueInputIs(node, 0, Type::PlainNumber());
770 CheckUpperIs(node, Type::TaggedPointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400771 break;
772
Ben Murdochc5610432016-08-08 18:44:38 +0100773 case IrOpcode::kChangeTaggedSignedToInt32: {
774 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
775 // TODO(neis): Activate once ChangeRepresentation works in typer.
776 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
777 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
778 // CheckValueInputIs(node, 0, from));
779 // CheckUpperIs(node, to));
780 break;
781 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400782 case IrOpcode::kChangeTaggedToInt32: {
783 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
784 // TODO(neis): Activate once ChangeRepresentation works in typer.
785 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
786 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
787 // CheckValueInputIs(node, 0, from));
788 // CheckUpperIs(node, to));
789 break;
790 }
791 case IrOpcode::kChangeTaggedToUint32: {
792 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
793 // TODO(neis): Activate once ChangeRepresentation works in typer.
794 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
795 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
796 // CheckValueInputIs(node, 0, from));
797 // CheckUpperIs(node, to));
798 break;
799 }
800 case IrOpcode::kChangeTaggedToFloat64: {
801 // Number /\ Tagged -> Number /\ UntaggedFloat64
802 // TODO(neis): Activate once ChangeRepresentation works in typer.
803 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
804 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
805 // CheckValueInputIs(node, 0, from));
806 // CheckUpperIs(node, to));
807 break;
808 }
Ben Murdochc5610432016-08-08 18:44:38 +0100809 case IrOpcode::kChangeInt31ToTaggedSigned: {
810 // Signed31 /\ UntaggedInt32 -> Signed31 /\ Tagged
811 // TODO(neis): Activate once ChangeRepresentation works in typer.
812 // Type* from =Type::Intersect(Type::Signed31(), Type::UntaggedInt32());
813 // Type* to = Type::Intersect(Type::Signed31(), Type::Tagged());
814 // CheckValueInputIs(node, 0, from));
815 // CheckUpperIs(node, to));
816 break;
817 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400818 case IrOpcode::kChangeInt32ToTagged: {
819 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
820 // TODO(neis): Activate once ChangeRepresentation works in typer.
821 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
822 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
823 // CheckValueInputIs(node, 0, from));
824 // CheckUpperIs(node, to));
825 break;
826 }
827 case IrOpcode::kChangeUint32ToTagged: {
828 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
829 // TODO(neis): Activate once ChangeRepresentation works in typer.
830 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
831 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
832 // CheckValueInputIs(node, 0, from));
833 // CheckUpperIs(node, to));
834 break;
835 }
836 case IrOpcode::kChangeFloat64ToTagged: {
837 // Number /\ UntaggedFloat64 -> Number /\ Tagged
838 // TODO(neis): Activate once ChangeRepresentation works in typer.
839 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
840 // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
841 // CheckValueInputIs(node, 0, from));
842 // CheckUpperIs(node, to));
843 break;
844 }
Ben Murdochc5610432016-08-08 18:44:38 +0100845 case IrOpcode::kChangeTaggedToBit: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400846 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
847 // TODO(neis): Activate once ChangeRepresentation works in typer.
848 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
849 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
850 // CheckValueInputIs(node, 0, from));
851 // CheckUpperIs(node, to));
852 break;
853 }
Ben Murdochc5610432016-08-08 18:44:38 +0100854 case IrOpcode::kChangeBitToTagged: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400855 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
856 // TODO(neis): Activate once ChangeRepresentation works in typer.
857 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
858 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
859 // CheckValueInputIs(node, 0, from));
860 // CheckUpperIs(node, to));
861 break;
862 }
Ben Murdochc5610432016-08-08 18:44:38 +0100863 case IrOpcode::kTruncateTaggedToWord32: {
864 // Number /\ Tagged -> Signed32 /\ UntaggedInt32
865 // TODO(neis): Activate once ChangeRepresentation works in typer.
866 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
867 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedInt32());
868 // CheckValueInputIs(node, 0, from));
869 // CheckUpperIs(node, to));
870 break;
871 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400872
873 case IrOpcode::kLoadField:
874 // Object -> fieldtype
875 // TODO(rossberg): activate once machine ops are typed.
876 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 // CheckUpperIs(node, FieldAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400878 break;
879 case IrOpcode::kLoadBuffer:
880 break;
881 case IrOpcode::kLoadElement:
882 // Object -> elementtype
883 // TODO(rossberg): activate once machine ops are typed.
884 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 // CheckUpperIs(node, ElementAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400886 break;
887 case IrOpcode::kStoreField:
888 // (Object, fieldtype) -> _|_
889 // TODO(rossberg): activate once machine ops are typed.
890 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000891 // CheckValueInputIs(node, 1, FieldAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892 CheckNotTyped(node);
893 break;
894 case IrOpcode::kStoreBuffer:
895 break;
896 case IrOpcode::kStoreElement:
897 // (Object, elementtype) -> _|_
898 // TODO(rossberg): activate once machine ops are typed.
899 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000900 // CheckValueInputIs(node, 1, ElementAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400901 CheckNotTyped(node);
902 break;
903
904 // Machine operators
905 // -----------------------
906 case IrOpcode::kLoad:
907 case IrOpcode::kStore:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100908 case IrOpcode::kStackSlot:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400909 case IrOpcode::kWord32And:
910 case IrOpcode::kWord32Or:
911 case IrOpcode::kWord32Xor:
912 case IrOpcode::kWord32Shl:
913 case IrOpcode::kWord32Shr:
914 case IrOpcode::kWord32Sar:
915 case IrOpcode::kWord32Ror:
916 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000917 case IrOpcode::kWord32Clz:
918 case IrOpcode::kWord32Ctz:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100919 case IrOpcode::kWord32ReverseBits:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 case IrOpcode::kWord32Popcnt:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 case IrOpcode::kWord64And:
922 case IrOpcode::kWord64Or:
923 case IrOpcode::kWord64Xor:
924 case IrOpcode::kWord64Shl:
925 case IrOpcode::kWord64Shr:
926 case IrOpcode::kWord64Sar:
927 case IrOpcode::kWord64Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 case IrOpcode::kWord64Clz:
929 case IrOpcode::kWord64Popcnt:
930 case IrOpcode::kWord64Ctz:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100931 case IrOpcode::kWord64ReverseBits:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400932 case IrOpcode::kWord64Equal:
933 case IrOpcode::kInt32Add:
934 case IrOpcode::kInt32AddWithOverflow:
935 case IrOpcode::kInt32Sub:
936 case IrOpcode::kInt32SubWithOverflow:
937 case IrOpcode::kInt32Mul:
938 case IrOpcode::kInt32MulHigh:
939 case IrOpcode::kInt32Div:
940 case IrOpcode::kInt32Mod:
941 case IrOpcode::kInt32LessThan:
942 case IrOpcode::kInt32LessThanOrEqual:
943 case IrOpcode::kUint32Div:
944 case IrOpcode::kUint32Mod:
945 case IrOpcode::kUint32MulHigh:
946 case IrOpcode::kUint32LessThan:
947 case IrOpcode::kUint32LessThanOrEqual:
948 case IrOpcode::kInt64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 case IrOpcode::kInt64AddWithOverflow:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400950 case IrOpcode::kInt64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 case IrOpcode::kInt64SubWithOverflow:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400952 case IrOpcode::kInt64Mul:
953 case IrOpcode::kInt64Div:
954 case IrOpcode::kInt64Mod:
955 case IrOpcode::kInt64LessThan:
956 case IrOpcode::kInt64LessThanOrEqual:
957 case IrOpcode::kUint64Div:
958 case IrOpcode::kUint64Mod:
959 case IrOpcode::kUint64LessThan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 case IrOpcode::kUint64LessThanOrEqual:
961 case IrOpcode::kFloat32Add:
962 case IrOpcode::kFloat32Sub:
Ben Murdochc5610432016-08-08 18:44:38 +0100963 case IrOpcode::kFloat32SubPreserveNan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 case IrOpcode::kFloat32Mul:
965 case IrOpcode::kFloat32Div:
966 case IrOpcode::kFloat32Max:
967 case IrOpcode::kFloat32Min:
968 case IrOpcode::kFloat32Abs:
969 case IrOpcode::kFloat32Sqrt:
970 case IrOpcode::kFloat32Equal:
971 case IrOpcode::kFloat32LessThan:
972 case IrOpcode::kFloat32LessThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400973 case IrOpcode::kFloat64Add:
974 case IrOpcode::kFloat64Sub:
Ben Murdochc5610432016-08-08 18:44:38 +0100975 case IrOpcode::kFloat64SubPreserveNan:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400976 case IrOpcode::kFloat64Mul:
977 case IrOpcode::kFloat64Div:
978 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979 case IrOpcode::kFloat64Max:
980 case IrOpcode::kFloat64Min:
981 case IrOpcode::kFloat64Abs:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400982 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 case IrOpcode::kFloat32RoundDown:
984 case IrOpcode::kFloat64RoundDown:
985 case IrOpcode::kFloat32RoundUp:
986 case IrOpcode::kFloat64RoundUp:
987 case IrOpcode::kFloat32RoundTruncate:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400988 case IrOpcode::kFloat64RoundTruncate:
989 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 case IrOpcode::kFloat32RoundTiesEven:
991 case IrOpcode::kFloat64RoundTiesEven:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400992 case IrOpcode::kFloat64Equal:
993 case IrOpcode::kFloat64LessThan:
994 case IrOpcode::kFloat64LessThanOrEqual:
995 case IrOpcode::kTruncateInt64ToInt32:
Ben Murdochc5610432016-08-08 18:44:38 +0100996 case IrOpcode::kRoundFloat64ToInt32:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100997 case IrOpcode::kRoundInt32ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000998 case IrOpcode::kRoundInt64ToFloat32:
999 case IrOpcode::kRoundInt64ToFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001000 case IrOpcode::kRoundUint32ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 case IrOpcode::kRoundUint64ToFloat64:
1002 case IrOpcode::kRoundUint64ToFloat32:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001003 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdochc5610432016-08-08 18:44:38 +01001004 case IrOpcode::kTruncateFloat64ToWord32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 case IrOpcode::kBitcastFloat32ToInt32:
1006 case IrOpcode::kBitcastFloat64ToInt64:
1007 case IrOpcode::kBitcastInt32ToFloat32:
1008 case IrOpcode::kBitcastInt64ToFloat64:
Ben Murdochc5610432016-08-08 18:44:38 +01001009 case IrOpcode::kBitcastWordToTagged:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001010 case IrOpcode::kChangeInt32ToInt64:
1011 case IrOpcode::kChangeUint32ToUint64:
1012 case IrOpcode::kChangeInt32ToFloat64:
1013 case IrOpcode::kChangeUint32ToFloat64:
1014 case IrOpcode::kChangeFloat32ToFloat64:
1015 case IrOpcode::kChangeFloat64ToInt32:
1016 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdochda12d292016-06-02 14:46:10 +01001017 case IrOpcode::kTruncateFloat64ToUint32:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001018 case IrOpcode::kTruncateFloat32ToInt32:
1019 case IrOpcode::kTruncateFloat32ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 case IrOpcode::kTryTruncateFloat32ToInt64:
1021 case IrOpcode::kTryTruncateFloat64ToInt64:
1022 case IrOpcode::kTryTruncateFloat32ToUint64:
1023 case IrOpcode::kTryTruncateFloat64ToUint64:
1024 case IrOpcode::kFloat64ExtractLowWord32:
1025 case IrOpcode::kFloat64ExtractHighWord32:
1026 case IrOpcode::kFloat64InsertLowWord32:
1027 case IrOpcode::kFloat64InsertHighWord32:
Ben Murdochda12d292016-06-02 14:46:10 +01001028 case IrOpcode::kInt32PairAdd:
1029 case IrOpcode::kInt32PairSub:
1030 case IrOpcode::kInt32PairMul:
1031 case IrOpcode::kWord32PairShl:
1032 case IrOpcode::kWord32PairShr:
1033 case IrOpcode::kWord32PairSar:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001034 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001036 case IrOpcode::kLoadParentFramePointer:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001037 case IrOpcode::kCheckedLoad:
1038 case IrOpcode::kCheckedStore:
Ben Murdochc5610432016-08-08 18:44:38 +01001039 case IrOpcode::kAtomicLoad:
1040 case IrOpcode::kAtomicStore:
1041
1042#define SIMD_MACHINE_OP_CASE(Name) case IrOpcode::k##Name:
1043 MACHINE_SIMD_OP_LIST(SIMD_MACHINE_OP_CASE)
1044#undef SIMD_MACHINE_OP_CASE
1045
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001046 // TODO(rossberg): Check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047 break;
1048 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049} // NOLINT(readability/fn_size)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001050
Ben Murdochc5610432016-08-08 18:44:38 +01001051void Verifier::Run(Graph* graph, Typing typing, CheckInputs check_inputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 CHECK_NOT_NULL(graph->start());
1053 CHECK_NOT_NULL(graph->end());
Ben Murdochda12d292016-06-02 14:46:10 +01001054 Zone zone(graph->zone()->allocator());
Ben Murdochc5610432016-08-08 18:44:38 +01001055 Visitor visitor(&zone, typing, check_inputs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 AllNodes all(&zone, graph);
1057 for (Node* node : all.live) visitor.Check(node);
1058
1059 // Check the uniqueness of projections.
1060 for (Node* proj : all.live) {
1061 if (proj->opcode() != IrOpcode::kProjection) continue;
1062 Node* node = proj->InputAt(0);
1063 for (Node* other : node->uses()) {
1064 if (all.IsLive(other) && other != proj &&
1065 other->opcode() == IrOpcode::kProjection &&
1066 ProjectionIndexOf(other->op()) == ProjectionIndexOf(proj->op())) {
1067 V8_Fatal(__FILE__, __LINE__,
1068 "Node #%d:%s has duplicate projections #%d and #%d",
1069 node->id(), node->op()->mnemonic(), proj->id(), other->id());
1070 }
1071 }
1072 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073}
1074
1075
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001076// -----------------------------------------------------------------------------
1077
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001078static bool HasDominatingDef(Schedule* schedule, Node* node,
1079 BasicBlock* container, BasicBlock* use_block,
1080 int use_pos) {
1081 BasicBlock* block = use_block;
1082 while (true) {
1083 while (use_pos >= 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001084 if (block->NodeAt(use_pos) == node) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 use_pos--;
1086 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001087 block = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 if (block == nullptr) break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001089 use_pos = static_cast<int>(block->NodeCount()) - 1;
1090 if (node == block->control_input()) return true;
1091 }
1092 return false;
1093}
1094
1095
1096static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) {
1097 BasicBlock* dom = schedule->block(dominator);
1098 BasicBlock* sub = schedule->block(dominatee);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 while (sub != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001100 if (sub == dom) {
1101 return true;
1102 }
1103 sub = sub->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 }
1105 return false;
1106}
1107
1108
1109static void CheckInputsDominate(Schedule* schedule, BasicBlock* block,
1110 Node* node, int use_pos) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001111 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 BasicBlock* use_block = block;
1113 if (node->opcode() == IrOpcode::kPhi) {
1114 use_block = use_block->PredecessorAt(j);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001115 use_pos = static_cast<int>(use_block->NodeCount()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001116 }
1117 Node* input = node->InputAt(j);
1118 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block,
1119 use_pos)) {
1120 V8_Fatal(__FILE__, __LINE__,
1121 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 node->id(), node->op()->mnemonic(), block->rpo_number(), j,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001123 input->id(), input->op()->mnemonic());
1124 }
1125 }
1126 // Ensure that nodes are dominated by their control inputs;
1127 // kEnd is an exception, as unreachable blocks resulting from kMerge
1128 // are not in the RPO.
1129 if (node->op()->ControlInputCount() == 1 &&
1130 node->opcode() != IrOpcode::kEnd) {
1131 Node* ctl = NodeProperties::GetControlInput(node);
1132 if (!Dominates(schedule, ctl, node)) {
1133 V8_Fatal(__FILE__, __LINE__,
1134 "Node #%d:%s in B%d is not dominated by control input #%d:%s",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001135 node->id(), node->op()->mnemonic(), block->rpo_number(),
1136 ctl->id(), ctl->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 }
1138 }
1139}
1140
1141
1142void ScheduleVerifier::Run(Schedule* schedule) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001143 const size_t count = schedule->BasicBlockCount();
Ben Murdochda12d292016-06-02 14:46:10 +01001144 Zone tmp_zone(schedule->zone()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145 Zone* zone = &tmp_zone;
1146 BasicBlock* start = schedule->start();
1147 BasicBlockVector* rpo_order = schedule->rpo_order();
1148
1149 // Verify the RPO order contains only blocks from this schedule.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001150 CHECK_GE(count, rpo_order->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1152 ++b) {
1153 CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001154 // All predecessors and successors should be in rpo and in this schedule.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155 for (BasicBlock const* predecessor : (*b)->predecessors()) {
1156 CHECK_GE(predecessor->rpo_number(), 0);
1157 CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001158 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159 for (BasicBlock const* successor : (*b)->successors()) {
1160 CHECK_GE(successor->rpo_number(), 0);
1161 CHECK_EQ(successor, schedule->GetBlockById(successor->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001162 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163 }
1164
1165 // Verify RPO numbers of blocks.
1166 CHECK_EQ(start, rpo_order->at(0)); // Start should be first.
1167 for (size_t b = 0; b < rpo_order->size(); b++) {
1168 BasicBlock* block = rpo_order->at(b);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001169 CHECK_EQ(static_cast<int>(b), block->rpo_number());
1170 BasicBlock* dom = block->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001171 if (b == 0) {
1172 // All blocks except start should have a dominator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 CHECK_NULL(dom);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 } else {
1175 // Check that the immediate dominator appears somewhere before the block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 CHECK_NOT_NULL(dom);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001177 CHECK_LT(dom->rpo_number(), block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001178 }
1179 }
1180
1181 // Verify that all blocks reachable from start are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001182 BoolVector marked(static_cast<int>(count), false, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001183 {
1184 ZoneQueue<BasicBlock*> queue(zone);
1185 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001186 marked[start->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187 while (!queue.empty()) {
1188 BasicBlock* block = queue.front();
1189 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001190 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001192 if (!marked[succ->id().ToSize()]) {
1193 marked[succ->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194 queue.push(succ);
1195 }
1196 }
1197 }
1198 }
1199 // Verify marked blocks are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001200 for (size_t i = 0; i < count; i++) {
1201 BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 if (marked[i]) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001203 CHECK_GE(block->rpo_number(), 0);
1204 CHECK_EQ(block, rpo_order->at(block->rpo_number()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205 }
1206 }
1207 // Verify RPO blocks are marked.
1208 for (size_t b = 0; b < rpo_order->size(); b++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001209 CHECK(marked[rpo_order->at(b)->id().ToSize()]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 }
1211
1212 {
1213 // Verify the dominance relation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001214 ZoneVector<BitVector*> dominators(zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 dominators.resize(count, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216
1217 // Compute a set of all the nodes that dominate a given node by using
1218 // a forward fixpoint. O(n^2).
1219 ZoneQueue<BasicBlock*> queue(zone);
1220 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 dominators[start->id().ToSize()] =
1222 new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001223 while (!queue.empty()) {
1224 BasicBlock* block = queue.front();
1225 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001226 BitVector* block_doms = dominators[block->id().ToSize()];
1227 BasicBlock* idom = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 if (idom != nullptr && !block_doms->Contains(idom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 block->rpo_number(), idom->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001231 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001232 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001234 BitVector* succ_doms = dominators[succ->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236 if (succ_doms == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 // First time visiting the node. S.doms = B U B.doms
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001238 succ_doms = new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001239 succ_doms->CopyFrom(*block_doms);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001240 succ_doms->Add(block->id().ToInt());
1241 dominators[succ->id().ToSize()] = succ_doms;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001242 queue.push(succ);
1243 } else {
1244 // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001245 bool had = succ_doms->Contains(block->id().ToInt());
1246 if (had) succ_doms->Remove(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247 if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001248 if (had) succ_doms->Add(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249 }
1250 }
1251 }
1252
1253 // Verify the immediateness of dominators.
1254 for (BasicBlockVector::iterator b = rpo_order->begin();
1255 b != rpo_order->end(); ++b) {
1256 BasicBlock* block = *b;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001257 BasicBlock* idom = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 if (idom == nullptr) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001259 BitVector* block_doms = dominators[block->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001260
1261 for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001262 BasicBlock* dom =
1263 schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current()));
1264 if (dom != idom &&
1265 !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 V8_Fatal(__FILE__, __LINE__,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001267 "Block B%d is not immediately dominated by B%d",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001268 block->rpo_number(), idom->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269 }
1270 }
1271 }
1272 }
1273
1274 // Verify phis are placed in the block of their control input.
1275 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1276 ++b) {
1277 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) {
1278 Node* phi = *i;
1279 if (phi->opcode() != IrOpcode::kPhi) continue;
1280 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler
1281 // schedules don't have control inputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001282 if (phi->InputCount() > phi->op()->ValueInputCount()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 Node* control = NodeProperties::GetControlInput(phi);
1284 CHECK(control->opcode() == IrOpcode::kMerge ||
1285 control->opcode() == IrOpcode::kLoop);
1286 CHECK_EQ((*b), schedule->block(control));
1287 }
1288 }
1289 }
1290
1291 // Verify that all uses are dominated by their definitions.
1292 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1293 ++b) {
1294 BasicBlock* block = *b;
1295
1296 // Check inputs to control for this block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001297 Node* control = block->control_input();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298 if (control != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 CHECK_EQ(block, schedule->block(control));
1300 CheckInputsDominate(schedule, block, control,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001301 static_cast<int>(block->NodeCount()) - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 }
1303 // Check inputs for all nodes in the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001304 for (size_t i = 0; i < block->NodeCount(); i++) {
1305 Node* node = block->NodeAt(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
1307 }
1308 }
1309}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310
1311
1312#ifdef DEBUG
1313
1314// static
1315void Verifier::VerifyNode(Node* node) {
1316 CHECK_EQ(OperatorProperties::GetTotalInputCount(node->op()),
1317 node->InputCount());
1318 // If this node has no effect or no control outputs,
1319 // we check that no its uses are effect or control inputs.
1320 bool check_no_control = node->op()->ControlOutputCount() == 0;
1321 bool check_no_effect = node->op()->EffectOutputCount() == 0;
1322 bool check_no_frame_state = node->opcode() != IrOpcode::kFrameState;
1323 if (check_no_effect || check_no_control) {
1324 for (Edge edge : node->use_edges()) {
1325 Node* const user = edge.from();
1326 CHECK(!user->IsDead());
1327 if (NodeProperties::IsControlEdge(edge)) {
1328 CHECK(!check_no_control);
1329 } else if (NodeProperties::IsEffectEdge(edge)) {
1330 CHECK(!check_no_effect);
1331 } else if (NodeProperties::IsFrameStateEdge(edge)) {
1332 CHECK(!check_no_frame_state);
1333 }
1334 }
1335 }
1336 // Frame state inputs should be frame states (or sentinels).
1337 for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op());
1338 i++) {
1339 Node* input = NodeProperties::GetFrameStateInput(node, i);
1340 CHECK(input->opcode() == IrOpcode::kFrameState ||
1341 input->opcode() == IrOpcode::kStart ||
1342 input->opcode() == IrOpcode::kDead);
1343 }
1344 // Effect inputs should be effect-producing nodes (or sentinels).
1345 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
1346 Node* input = NodeProperties::GetEffectInput(node, i);
1347 CHECK(input->op()->EffectOutputCount() > 0 ||
1348 input->opcode() == IrOpcode::kDead);
1349 }
1350 // Control inputs should be control-producing nodes (or sentinels).
1351 for (int i = 0; i < node->op()->ControlInputCount(); i++) {
1352 Node* input = NodeProperties::GetControlInput(node, i);
1353 CHECK(input->op()->ControlOutputCount() > 0 ||
1354 input->opcode() == IrOpcode::kDead);
1355 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001357
1358
1359void Verifier::VerifyEdgeInputReplacement(const Edge& edge,
1360 const Node* replacement) {
1361 // Check that the user does not misuse the replacement.
1362 DCHECK(!NodeProperties::IsControlEdge(edge) ||
1363 replacement->op()->ControlOutputCount() > 0);
1364 DCHECK(!NodeProperties::IsEffectEdge(edge) ||
1365 replacement->op()->EffectOutputCount() > 0);
1366 DCHECK(!NodeProperties::IsFrameStateEdge(edge) ||
1367 replacement->opcode() == IrOpcode::kFrameState);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369
1370#endif // DEBUG
1371
1372} // namespace compiler
1373} // namespace internal
1374} // namespace v8