| 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 |