[maglev] Simple Graph verifier
It currently only checks if the node inputs are expected to be tagged or untagged. Bug: v8:7700 Change-Id: Ibf068098dfb08c28b2744cb321fa857572998948 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3578804 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Victor Gomes <victorgomes@chromium.org> Auto-Submit: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/main@{#79945}
This commit is contained in:
parent
74178a4304
commit
1b456ebbe8
1
BUILD.gn
1
BUILD.gn
@ -3484,6 +3484,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/maglev/maglev-graph-labeller.h",
|
||||
"src/maglev/maglev-graph-printer.h",
|
||||
"src/maglev/maglev-graph-processor.h",
|
||||
"src/maglev/maglev-graph-verifier.h",
|
||||
"src/maglev/maglev-graph.h",
|
||||
"src/maglev/maglev-interpreter-frame-state.h",
|
||||
"src/maglev/maglev-ir.h",
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "src/maglev/maglev-graph-labeller.h"
|
||||
#include "src/maglev/maglev-graph-printer.h"
|
||||
#include "src/maglev/maglev-graph-processor.h"
|
||||
#include "src/maglev/maglev-graph-verifier.h"
|
||||
#include "src/maglev/maglev-graph.h"
|
||||
#include "src/maglev/maglev-interpreter-frame-state.h"
|
||||
#include "src/maglev/maglev-ir.h"
|
||||
@ -174,6 +175,13 @@ void MaglevCompiler::Compile() {
|
||||
PrintGraph(std::cout, toplevel_compilation_unit_, graph_builder.graph());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
GraphProcessor<MaglevGraphVerifier> verifier(toplevel_compilation_unit_);
|
||||
verifier.ProcessGraph(graph_builder.graph());
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
GraphMultiProcessor<NumberingProcessor, UseMarkingProcessor,
|
||||
MaglevVregAllocator>
|
||||
|
143
src/maglev/maglev-graph-verifier.h
Normal file
143
src/maglev/maglev-graph-verifier.h
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_MAGLEV_MAGLEV_GRAPH_VERIFIER_H_
|
||||
#define V8_MAGLEV_MAGLEV_GRAPH_VERIFIER_H_
|
||||
|
||||
#include "src/maglev/maglev-graph-labeller.h"
|
||||
#include "src/maglev/maglev-ir.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace maglev {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ValueRepresentation& repr) {
|
||||
switch (repr) {
|
||||
case ValueRepresentation::kTagged:
|
||||
os << "TaggedValue";
|
||||
break;
|
||||
case ValueRepresentation::kUntagged:
|
||||
os << "UntaggedValue";
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
class Graph;
|
||||
|
||||
// TODO(victorgomes): Currently it only verifies the inputs for all ValueNodes
|
||||
// are expected to be tagged/untagged. Add more verification later.
|
||||
class MaglevGraphVerifier {
|
||||
public:
|
||||
void PreProcessGraph(MaglevCompilationUnit* compilation_unit, Graph* graph) {
|
||||
if (compilation_unit->has_graph_labeller()) {
|
||||
graph_labeller_ = compilation_unit->graph_labeller();
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessGraph(MaglevCompilationUnit*, Graph* graph) {}
|
||||
void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block) {}
|
||||
|
||||
void CheckValueInputIs(NodeBase* node, int i, ValueRepresentation repr) {
|
||||
ValueNode* input = node->input(i).node();
|
||||
if (input->value_representation() != repr) {
|
||||
std::ostringstream str;
|
||||
str << "Type representation error: node ";
|
||||
if (graph_labeller_) {
|
||||
str << "#" << graph_labeller_->NodeId(node) << " : ";
|
||||
}
|
||||
str << node->opcode() << " (input @" << i << " = " << input->opcode()
|
||||
<< ") type " << input->value_representation() << " is not " << repr;
|
||||
FATAL("%s", str.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Process(NodeBase* node, const ProcessingState& state) {
|
||||
switch (node->opcode()) {
|
||||
case Opcode::kConstant:
|
||||
case Opcode::kSmiConstant:
|
||||
case Opcode::kInt32Constant:
|
||||
case Opcode::kRootConstant:
|
||||
case Opcode::kInitialValue:
|
||||
case Opcode::kRegisterInput:
|
||||
case Opcode::kGapMove:
|
||||
case Opcode::kEagerDeopt:
|
||||
case Opcode::kJump:
|
||||
case Opcode::kJumpLoop:
|
||||
// No input.
|
||||
DCHECK_EQ(node->input_count(), 0);
|
||||
break;
|
||||
case Opcode::kGenericNegate:
|
||||
case Opcode::kGenericIncrement:
|
||||
case Opcode::kGenericDecrement:
|
||||
case Opcode::kCheckedSmiUntag:
|
||||
case Opcode::kLoadField:
|
||||
case Opcode::kLoadGlobal:
|
||||
// TODO(victorgomes): Can we check that the input is actually a map?
|
||||
case Opcode::kCheckMaps:
|
||||
// TODO(victorgomes): Can we check that the input is Boolean?
|
||||
case Opcode::kBranchIfTrue:
|
||||
case Opcode::kBranchIfToBooleanTrue:
|
||||
case Opcode::kReturn:
|
||||
// Generic tagged unary operations.
|
||||
DCHECK_EQ(node->input_count(), 1);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||
break;
|
||||
case Opcode::kCheckedSmiTag:
|
||||
// Untagged unary operations.
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kUntagged);
|
||||
break;
|
||||
case Opcode::kGenericAdd:
|
||||
case Opcode::kGenericSubtract:
|
||||
case Opcode::kGenericMultiply:
|
||||
case Opcode::kGenericDivide:
|
||||
case Opcode::kGenericModulus:
|
||||
case Opcode::kGenericExponentiate:
|
||||
case Opcode::kGenericBitwiseAnd:
|
||||
case Opcode::kGenericBitwiseOr:
|
||||
case Opcode::kGenericBitwiseXor:
|
||||
case Opcode::kGenericShiftLeft:
|
||||
case Opcode::kGenericShiftRight:
|
||||
case Opcode::kGenericShiftRightLogical:
|
||||
case Opcode::kGenericBitwiseNot:
|
||||
// TODO(victorgomes): Can we use the fact that these nodes return a
|
||||
// Boolean?
|
||||
case Opcode::kGenericEqual:
|
||||
case Opcode::kGenericStrictEqual:
|
||||
case Opcode::kGenericLessThan:
|
||||
case Opcode::kGenericLessThanOrEqual:
|
||||
case Opcode::kGenericGreaterThan:
|
||||
case Opcode::kGenericGreaterThanOrEqual:
|
||||
// TODO(victorgomes): Can we check that first input is an Object?
|
||||
case Opcode::kStoreField:
|
||||
case Opcode::kLoadNamedGeneric:
|
||||
// Generic tagged binary operations.
|
||||
DCHECK_EQ(node->input_count(), 2);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||
CheckValueInputIs(node, 1, ValueRepresentation::kTagged);
|
||||
break;
|
||||
case Opcode::kInt32AddWithOverflow:
|
||||
// Untagged binary operations.
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kUntagged);
|
||||
CheckValueInputIs(node, 1, ValueRepresentation::kUntagged);
|
||||
break;
|
||||
case Opcode::kCall:
|
||||
case Opcode::kPhi:
|
||||
// All inputs should be tagged.
|
||||
for (int i = 0; i < node->input_count(); i++) {
|
||||
CheckValueInputIs(node, i, ValueRepresentation::kTagged);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MaglevGraphLabeller* graph_labeller_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace maglev
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_MAGLEV_MAGLEV_GRAPH_VERIFIER_H_
|
Loading…
Reference in New Issue
Block a user