[turbofan] Added --csa-trap-on-node option that helps debugging graph verification issues.

The error reported by the graph verifier looks like:

#
# Fatal error in ../src/compiler/machine-graph-verifier.cc, line 638
# TypeError: node #54:ChangeInt32ToInt64 uses node #53:ChangeUint32ToUint64 which doesn't have an int32-compatible representation.
#
# Specify option --csa-trap-on-node=test,54 for debugging.
#

BUG=

Review-Url: https://codereview.chromium.org/2574353002
Cr-Commit-Position: refs/heads/master@{#41721}
This commit is contained in:
ishell 2016-12-15 05:32:27 -08:00 committed by Commit bot
parent 7bd61b601c
commit 1805315470
8 changed files with 106 additions and 17 deletions

View File

@ -11,6 +11,38 @@ namespace internal {
using compiler::Node;
CodeStubAssembler::CodeStubAssembler(compiler::CodeAssemblerState* state)
: compiler::CodeAssembler(state) {
if (DEBUG_BOOL && FLAG_csa_trap_on_node != nullptr) {
HandleBreakOnNode();
}
}
void CodeStubAssembler::HandleBreakOnNode() {
// FLAG_csa_trap_on_node should be in a form "STUB,NODE" where STUB is a
// string specifying the name of a stub and NODE is number specifying node id.
const char* name = state()->name();
size_t name_length = strlen(name);
if (strncmp(FLAG_csa_trap_on_node, name, name_length) != 0) {
// Different name.
return;
}
size_t option_length = strlen(FLAG_csa_trap_on_node);
if (option_length < name_length + 2 ||
FLAG_csa_trap_on_node[name_length] != ',') {
// Option is too short.
return;
}
const char* start = &FLAG_csa_trap_on_node[name_length + 1];
char* end;
int node_id = static_cast<int>(strtol(start, &end, 10));
if (start == end) {
// Bad node id.
return;
}
BreakOnNode(node_id);
}
void CodeStubAssembler::Assert(const NodeGenerator& codition_body,
const char* message, const char* file,
int line) {

View File

@ -53,8 +53,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
public:
typedef compiler::Node Node;
CodeStubAssembler(compiler::CodeAssemblerState* state)
: compiler::CodeAssembler(state) {}
CodeStubAssembler(compiler::CodeAssemblerState* state);
enum AllocationFlag : uint8_t {
kNone = 0,
@ -1124,6 +1123,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
private:
friend class CodeStubArguments;
void HandleBreakOnNode();
Node* AllocateRawAligned(Node* size_in_bytes, AllocationFlags flags,
Node* top_address, Node* limit_address);
Node* AllocateRawUnaligned(Node* size_in_bytes, AllocationFlags flags,

View File

@ -65,6 +65,28 @@ CodeAssemblerState::~CodeAssemblerState() {}
CodeAssembler::~CodeAssembler() {}
class BreakOnNodeDecorator final : public GraphDecorator {
public:
explicit BreakOnNodeDecorator(NodeId node_id) : node_id_(node_id) {}
void Decorate(Node* node) final {
if (node->id() == node_id_) {
base::OS::DebugBreak();
}
}
private:
NodeId node_id_;
};
void CodeAssembler::BreakOnNode(int node_id) {
Graph* graph = raw_assembler()->graph();
Zone* zone = graph->zone();
GraphDecorator* decorator =
new (zone) BreakOnNodeDecorator(static_cast<NodeId>(node_id));
graph->AddDecorator(decorator);
}
void CodeAssembler::CallPrologue() {}
void CodeAssembler::CallEpilogue() {}

View File

@ -454,6 +454,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
CodeAssemblerState* state() { return state_; }
void BreakOnNode(int node_id);
protected:
// Enables subclasses to perform operations before and after a call.
virtual void CallPrologue();
@ -463,6 +465,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
void InstallBreakOnNodeDecorator();
RawMachineAssembler* raw_assembler() const;
CodeAssemblerState* state_;
@ -545,6 +549,8 @@ class V8_EXPORT_PRIVATE CodeAssemblerState {
~CodeAssemblerState();
const char* name() const { return name_; }
private:
friend class CodeAssembler;
friend class CodeAssemblerLabel;

View File

@ -275,8 +275,12 @@ class MachineRepresentationChecker {
public:
MachineRepresentationChecker(
Schedule const* const schedule,
MachineRepresentationInferrer const* const inferrer, bool is_stub)
: schedule_(schedule), inferrer_(inferrer), is_stub_(is_stub) {}
MachineRepresentationInferrer const* const inferrer, bool is_stub,
const char* name)
: schedule_(schedule),
inferrer_(inferrer),
is_stub_(is_stub),
name_(name) {}
void Run() {
BasicBlockVector const* blocks = schedule_->all_blocks();
@ -520,6 +524,7 @@ class MachineRepresentationChecker {
std::stringstream str;
str << "Node #" << node->id() << ":" << *node->op()
<< " in the machine graph is not being checked.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
break;
@ -549,6 +554,7 @@ class MachineRepresentationChecker {
<< " uses node #" << input->id() << ":" << *input->op() << ":"
<< input_representation << " which doesn't have a " << representation
<< " representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
}
@ -567,6 +573,7 @@ class MachineRepresentationChecker {
str << "TypeError: node #" << node->id() << ":" << *node->op()
<< " uses node #" << input->id() << ":" << *input->op()
<< " which doesn't have a tagged representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
@ -599,6 +606,7 @@ class MachineRepresentationChecker {
str << "TypeError: node #" << node->id() << ":" << *node->op()
<< " uses node #" << input->id() << ":" << *input->op()
<< " which doesn't have a tagged or pointer representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
}
@ -615,6 +623,7 @@ class MachineRepresentationChecker {
std::ostringstream str;
str << "TypeError: node #" << input->id() << ":" << *input->op()
<< " is untyped.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
break;
}
@ -625,6 +634,7 @@ class MachineRepresentationChecker {
str << "TypeError: node #" << node->id() << ":" << *node->op()
<< " uses node #" << input->id() << ":" << *input->op()
<< " which doesn't have an int32-compatible representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
@ -639,6 +649,7 @@ class MachineRepresentationChecker {
std::ostringstream str;
str << "TypeError: node #" << input->id() << ":" << *input->op()
<< " is untyped.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
break;
}
@ -651,6 +662,7 @@ class MachineRepresentationChecker {
<< " uses node #" << input->id() << ":" << *input->op() << ":"
<< input_representation
<< " which doesn't have a kWord64 representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
@ -664,6 +676,7 @@ class MachineRepresentationChecker {
str << "TypeError: node #" << node->id() << ":" << *node->op()
<< " uses node #" << input->id() << ":" << *input->op()
<< " which doesn't have a kFloat32 representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
@ -677,6 +690,7 @@ class MachineRepresentationChecker {
str << "TypeError: node #" << node->id() << ":" << *node->op()
<< " uses node #" << input->id() << ":" << *input->op()
<< " which doesn't have a kFloat64 representation.";
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
@ -703,6 +717,7 @@ class MachineRepresentationChecker {
}
}
if (should_log_error) {
PrintDebugHelp(str, node);
FATAL(str.str().c_str());
}
}
@ -765,20 +780,28 @@ class MachineRepresentationChecker {
return false;
}
void PrintDebugHelp(std::ostream& out, Node const* node) {
if (DEBUG_BOOL) {
out << "\n#\n# Specify option --csa-trap-on-node=" << name_ << ","
<< node->id() << " for debugging.";
}
}
Schedule const* const schedule_;
MachineRepresentationInferrer const* const inferrer_;
bool is_stub_;
const char* name_;
};
} // namespace
void MachineGraphVerifier::Run(Graph* graph, Schedule const* const schedule,
Linkage* linkage, bool is_stub,
Linkage* linkage, bool is_stub, const char* name,
Zone* temp_zone) {
MachineRepresentationInferrer representation_inferrer(schedule, graph,
linkage, temp_zone);
MachineRepresentationChecker checker(schedule, &representation_inferrer,
is_stub);
is_stub, name);
checker.Run();
}

View File

@ -21,7 +21,8 @@ class Schedule;
class MachineGraphVerifier {
public:
static void Run(Graph* graph, Schedule const* const schedule,
Linkage* linkage, bool is_stub, Zone* temp_zone);
Linkage* linkage, bool is_stub, const char* name,
Zone* temp_zone);
};
} // namespace compiler

View File

@ -302,7 +302,7 @@ class PipelineData {
DCHECK(register_allocation_data_ == nullptr);
register_allocation_data_ = new (register_allocation_zone())
RegisterAllocationData(config, register_allocation_zone(), frame(),
sequence(), debug_name_.get());
sequence(), debug_name());
}
void BeginPhaseKind(const char* phase_kind_name) {
@ -317,6 +317,8 @@ class PipelineData {
}
}
const char* debug_name() const { return debug_name_.get(); }
private:
Isolate* const isolate_;
CompilationInfo* const info_;
@ -1757,28 +1759,27 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage,
}
bool verify_stub_graph = data->verify_graph();
if (verify_stub_graph || (FLAG_turbo_verify_machine_graph != nullptr &&
if (verify_stub_graph ||
(FLAG_turbo_verify_machine_graph != nullptr &&
(!strcmp(FLAG_turbo_verify_machine_graph, "*") ||
!strcmp(FLAG_turbo_verify_machine_graph,
data->info()->GetDebugName().get())))) {
!strcmp(FLAG_turbo_verify_machine_graph, data->debug_name())))) {
if (FLAG_trace_csa_verify) {
AllowHandleDereference allow_deref;
CompilationInfo* info = data->info();
CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
os << "--------------------------------------------------\n"
<< "--- Verifying " << info->GetDebugName().get()
<< " generated by TurboFan\n"
<< "--- Verifying " << data->debug_name() << " generated by TurboFan\n"
<< "--------------------------------------------------\n"
<< *data->schedule()
<< "--------------------------------------------------\n"
<< "--- End of " << info->GetDebugName().get()
<< " generated by TurboFan\n"
<< "--- End of " << data->debug_name() << " generated by TurboFan\n"
<< "--------------------------------------------------\n";
}
Zone temp_zone(data->isolate()->allocator(), ZONE_NAME);
MachineGraphVerifier::Run(data->graph(), data->schedule(), linkage,
data->info()->IsStub(), &temp_zone);
data->info()->IsStub(), data->debug_name(),
&temp_zone);
}
data->InitializeInstructionSequence(call_descriptor);

View File

@ -444,6 +444,9 @@ DEFINE_STRING(turbo_verify_machine_graph, nullptr,
DEFINE_BOOL(csa_verify, DEBUG_BOOL,
"verify TurboFan machine graph of code stubs")
DEFINE_BOOL(trace_csa_verify, false, "trace code stubs verification")
DEFINE_STRING(csa_trap_on_node, nullptr,
"trigger break point when a node with given id is created in "
"given stub. The format is: StubName,NodeId")
DEFINE_BOOL(turbo_stats, false, "print TurboFan statistics")
DEFINE_BOOL(turbo_stats_nvp, false,
"print TurboFan statistics in machine-readable format")