Commit 7ba4789d authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[csa] Add debug file position on BasicBlock and CSA-variables

Change-Id: I525e29f278c76dbd02cb727d9c70c2d67a47e4c9
Reviewed-on: https://chromium-review.googlesource.com/449676
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44431}
parent 92f435c0
......@@ -29,7 +29,7 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
Int32Constant(kSeqStringTag)),
&if_sequential, &if_external);
Bind(&if_sequential);
BIND(&if_sequential);
{
var_data.Bind(IntPtrAdd(
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
......@@ -37,7 +37,7 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
Goto(&if_join);
}
Bind(&if_external);
BIND(&if_external);
{
// This is only valid for ExternalStrings where the resource data
// pointer is cached (i.e. no short external strings).
......
......@@ -46,6 +46,7 @@ class CodeAssemblerState;
}; \
void Builtins::Generate_##Name(compiler::CodeAssemblerState* state) { \
Name##Assembler assembler(state); \
state->SetInitialDebugInformation(#Name, __FILE__, __LINE__); \
assembler.Generate##Name##Impl(); \
} \
void Name##Assembler::Generate##Name##Impl()
......
......@@ -1474,10 +1474,16 @@ class ToDirectStringAssembler : public CodeStubAssembler {
#define CSA_ASSERT_JS_ARGC_EQ(csa, expected) \
CSA_ASSERT_JS_ARGC_OP(csa, Word32Equal, ==, expected)
#else
#define BIND(label) Bind(label, {#label, __FILE__, __LINE__})
#define VARIABLE(name, ...) \
Variable name(this, #name, {__FILE__, __LINE__, __VA_ARGS__});
#else // DEBUG
#define CSA_ASSERT(csa, x) ((void)0)
#define CSA_ASSERT_JS_ARGC_EQ(csa, expected) ((void)0)
#endif
#define BIND(label) Bind(label);
#define VARIABLE(name, ...) Variable name(this, __VA_ARGS__);
#endif // DEBUG
#ifdef ENABLE_SLOW_DCHECKS
#define CSA_SLOW_ASSERT(csa, x) \
......
......@@ -84,6 +84,21 @@ int CodeAssemblerState::parameter_count() const {
CodeAssembler::~CodeAssembler() {}
#if DEBUG
void CodeAssemblerState::PrintCurrentBlock(std::ostream& os) {
raw_assembler_->PrintCurrentBlock(os);
}
#endif
void CodeAssemblerState::SetInitialDebugInformation(const char* msg,
const char* file,
int line) {
#if DEBUG
AssemblerDebugInfo debug_info = {msg, file, line};
raw_assembler_->SetInitialDebugInformation(debug_info);
#endif // DEBUG
}
class BreakOnNodeDecorator final : public GraphDecorator {
public:
explicit BreakOnNodeDecorator(NodeId node_id) : node_id_(node_id) {}
......@@ -332,6 +347,12 @@ void CodeAssembler::Comment(const char* format, ...) {
void CodeAssembler::Bind(Label* label) { return label->Bind(); }
#if DEBUG
void CodeAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) {
return label->Bind(debug_info);
}
#endif // DEBUG
Node* CodeAssembler::LoadFramePointer() {
return raw_assembler()->LoadFramePointer();
}
......@@ -754,7 +775,23 @@ RawMachineAssembler* CodeAssembler::raw_assembler() const {
// properly be verified.
class CodeAssemblerVariable::Impl : public ZoneObject {
public:
explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
explicit Impl(MachineRepresentation rep)
:
#if DEBUG
debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
#endif
value_(nullptr),
rep_(rep) {
}
#if DEBUG
AssemblerDebugInfo debug_info() const { return debug_info_; }
void set_debug_info(AssemblerDebugInfo debug_info) {
debug_info_ = debug_info;
}
AssemblerDebugInfo debug_info_;
#endif // DEBUG
Node* value_;
MachineRepresentation rep_;
};
......@@ -772,6 +809,25 @@ CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
Bind(initial_value);
}
#if DEBUG
CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
AssemblerDebugInfo debug_info,
MachineRepresentation rep)
: impl_(new (assembler->zone()) Impl(rep)), state_(assembler->state()) {
impl_->set_debug_info(debug_info);
state_->variables_.insert(impl_);
}
CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
AssemblerDebugInfo debug_info,
MachineRepresentation rep,
Node* initial_value)
: CodeAssemblerVariable(assembler, debug_info, rep) {
impl_->set_debug_info(debug_info);
Bind(initial_value);
}
#endif // DEBUG
CodeAssemblerVariable::~CodeAssemblerVariable() {
state_->variables_.erase(impl_);
}
......@@ -779,7 +835,18 @@ CodeAssemblerVariable::~CodeAssemblerVariable() {
void CodeAssemblerVariable::Bind(Node* value) { impl_->value_ = value; }
Node* CodeAssemblerVariable::value() const {
DCHECK_NOT_NULL(impl_->value_);
#if DEBUG
if (!IsBound()) {
std::stringstream str;
str << "#Use of unbound variable:"
<< "#\n Variable: " << *this;
if (state_) {
str << "#\n Current Block: ";
state_->PrintCurrentBlock(str);
}
FATAL(str.str().c_str());
}
#endif // DEBUG
return impl_->value_;
}
......@@ -787,6 +854,21 @@ MachineRepresentation CodeAssemblerVariable::rep() const { return impl_->rep_; }
bool CodeAssemblerVariable::IsBound() const { return impl_->value_ != nullptr; }
std::ostream& operator<<(std::ostream& os,
const CodeAssemblerVariable::Impl& impl) {
#if DEBUG
AssemblerDebugInfo info = impl.debug_info();
if (info.name) os << "V" << info;
#endif // DEBUG
return os;
}
std::ostream& operator<<(std::ostream& os,
const CodeAssemblerVariable& variable) {
os << *variable.impl_;
return os;
}
CodeAssemblerLabel::CodeAssemblerLabel(CodeAssembler* assembler,
size_t vars_count,
CodeAssemblerVariable* const* vars,
......@@ -808,7 +890,7 @@ CodeAssemblerLabel::~CodeAssemblerLabel() { label_->~RawMachineLabel(); }
void CodeAssemblerLabel::MergeVariables() {
++merge_count_;
for (auto var : state_->variables_) {
for (CodeAssemblerVariable::Impl* var : state_->variables_) {
size_t count = 0;
Node* node = var->value_;
if (node != nullptr) {
......@@ -843,19 +925,42 @@ void CodeAssemblerLabel::MergeVariables() {
// the variable after the label bind (it's not possible to add phis to
// the bound label after the fact, just make sure to list the variable
// in the label's constructor's list of merged variables).
DCHECK(find_if(i->second.begin(), i->second.end(),
[node](Node* e) -> bool { return node != e; }) ==
i->second.end());
#if DEBUG
if (find_if(i->second.begin(), i->second.end(),
[node](Node* e) -> bool { return node != e; }) !=
i->second.end()) {
std::stringstream str;
str << "Unmerged variable found when jumping to block. \n"
<< "# Variable: " << *var;
if (bound_) {
str << "\n# Target block: " << *label_->block();
}
str << "\n# Current Block: ";
state_->PrintCurrentBlock(str);
FATAL(str.str().c_str());
}
#endif // DEBUG
}
}
}
}
}
#if DEBUG
void CodeAssemblerLabel::Bind(AssemblerDebugInfo debug_info) {
DCHECK(!bound_);
state_->raw_assembler_->Bind(label_, debug_info);
UpdateVariablesAfterBind();
}
#endif // DEBUG
void CodeAssemblerLabel::Bind() {
DCHECK(!bound_);
state_->raw_assembler_->Bind(label_);
UpdateVariablesAfterBind();
}
void CodeAssemblerLabel::UpdateVariablesAfterBind() {
// Make sure that all variables that have changed along any path up to this
// point are marked as merge variables.
for (auto var : state_->variables_) {
......
......@@ -250,6 +250,9 @@ class V8_EXPORT_PRIVATE CodeAssembler {
void Comment(const char* format, ...);
void Bind(Label* label);
#if DEBUG
void Bind(Label* label, AssemblerDebugInfo debug_info);
#endif // DEBUG
void Goto(Label* label);
void GotoIf(Node* condition, Label* true_label);
void GotoIfNot(Node* condition, Label* false_label);
......@@ -441,6 +444,13 @@ class CodeAssemblerVariable {
MachineRepresentation rep);
CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
Node* initial_value);
#if DEBUG
CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
MachineRepresentation rep);
CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
MachineRepresentation rep, Node* initial_value);
#endif // DEBUG
~CodeAssemblerVariable();
void Bind(Node* value);
Node* value() const;
......@@ -448,13 +458,18 @@ class CodeAssemblerVariable {
bool IsBound() const;
private:
class Impl;
friend class CodeAssemblerLabel;
friend class CodeAssemblerState;
class Impl;
friend std::ostream& operator<<(std::ostream&, const Impl&);
friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
Impl* impl_;
CodeAssemblerState* state_;
};
std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
class CodeAssemblerLabel {
public:
enum Type { kDeferred, kNonDeferred };
......@@ -490,6 +505,10 @@ class CodeAssemblerLabel {
friend class CodeAssembler;
void Bind();
#if DEBUG
void Bind(AssemblerDebugInfo debug_info);
#endif // DEBUG
void UpdateVariablesAfterBind();
void MergeVariables();
bool bound_;
......@@ -523,6 +542,11 @@ class V8_EXPORT_PRIVATE CodeAssemblerState {
const char* name() const { return name_; }
int parameter_count() const;
#if DEBUG
void PrintCurrentBlock(std::ostream& os);
#endif // DEBUG
void SetInitialDebugInformation(const char* msg, const char* file, int line);
private:
friend class CodeAssembler;
friend class CodeAssemblerLabel;
......
......@@ -84,6 +84,7 @@ class MachineRepresentationInferrer {
void Run() {
auto blocks = schedule_->all_blocks();
for (BasicBlock* block : *blocks) {
current_block_ = block;
for (size_t i = 0; i <= block->NodeCount(); ++i) {
Node const* node =
i < block->NodeCount() ? block->NodeAt(i) : block->control_input();
......@@ -280,6 +281,7 @@ class MachineRepresentationInferrer {
Schedule const* const schedule_;
Linkage const* const linkage_;
ZoneVector<MachineRepresentation> representation_vector_;
BasicBlock* current_block_;
};
class MachineRepresentationChecker {
......@@ -291,11 +293,13 @@ class MachineRepresentationChecker {
: schedule_(schedule),
inferrer_(inferrer),
is_stub_(is_stub),
name_(name) {}
name_(name),
current_block_(nullptr) {}
void Run() {
BasicBlockVector const* blocks = schedule_->all_blocks();
for (BasicBlock* block : *blocks) {
current_block_ = block;
for (size_t i = 0; i <= block->NodeCount(); ++i) {
Node const* node =
i < block->NodeCount() ? block->NodeAt(i) : block->control_input();
......@@ -806,7 +810,8 @@ class MachineRepresentationChecker {
void PrintDebugHelp(std::ostream& out, Node const* node) {
if (DEBUG_BOOL) {
out << "\n#\n# Specify option --csa-trap-on-node=" << name_ << ","
out << "\n# Current block: " << *current_block_;
out << "\n#\n# Specify option --csa-trap-on-node=" << name_ << ","
<< node->id() << " for debugging.";
}
}
......@@ -815,6 +820,7 @@ class MachineRepresentationChecker {
MachineRepresentationInferrer const* const inferrer_;
bool is_stub_;
const char* name_;
BasicBlock* current_block_;
};
} // namespace
......
......@@ -278,7 +278,17 @@ Node* RawMachineAssembler::CallCFunction8(
Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
return AddNode(common()->Call(descriptor), arraysize(args), args);
}
BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
label->used_ = true;
return EnsureBlock(label);
}
BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
if (label->block_ == nullptr) {
label->block_ = schedule()->NewBasicBlock();
}
return label->block_;
}
void RawMachineAssembler::Bind(RawMachineLabel* label) {
DCHECK(current_block_ == nullptr);
......@@ -288,18 +298,29 @@ void RawMachineAssembler::Bind(RawMachineLabel* label) {
current_block_->set_deferred(label->deferred_);
}
BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
label->used_ = true;
return EnsureBlock(label);
#if DEBUG
void RawMachineAssembler::Bind(RawMachineLabel* label,
AssemblerDebugInfo info) {
if (current_block_ != nullptr) {
std::stringstream str;
str << "Binding label without closing previous block:"
<< "\n# label: " << info
<< "\n# previous block: " << *current_block_;
FATAL(str.str().c_str());
}
Bind(label);
current_block_->set_debug_info(info);
}
BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
if (label->block_ == nullptr) label->block_ = schedule()->NewBasicBlock();
return label->block_;
void RawMachineAssembler::PrintCurrentBlock(std::ostream& os) {
os << CurrentBlock();
}
void RawMachineAssembler::SetInitialDebugInformation(
AssemblerDebugInfo debug_info) {
CurrentBlock()->set_debug_info(debug_info);
}
#endif // DEBUG
BasicBlock* RawMachineAssembler::CurrentBlock() {
DCHECK(current_block_);
......
......@@ -798,6 +798,12 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
void Unreachable();
void Comment(const char* msg);
#if DEBUG
void Bind(RawMachineLabel* label, AssemblerDebugInfo info);
void SetInitialDebugInformation(AssemblerDebugInfo info);
void PrintCurrentBlock(std::ostream& os);
#endif // DEBUG
// Add success / exception successor blocks and ends the current block ending
// in a potentially throwing call node.
void Continuations(Node* call, RawMachineLabel* if_success,
......@@ -862,6 +868,8 @@ class V8_EXPORT_PRIVATE RawMachineLabel final {
: deferred_(type == kDeferred) {}
~RawMachineLabel();
BasicBlock* block() const { return block_; }
private:
BasicBlock* block_ = nullptr;
bool used_ = false;
......
......@@ -27,8 +27,11 @@ BasicBlock::BasicBlock(Zone* zone, Id id)
nodes_(zone),
successors_(zone),
predecessors_(zone),
id_(id) {}
#if DEBUG
debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
#endif
id_(id) {
}
bool BasicBlock::LoopContains(BasicBlock* block) const {
// RPO numbers must be initialized.
......@@ -93,6 +96,24 @@ BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
return b1;
}
std::ostream& operator<<(std::ostream& os, const BasicBlock& block) {
os << "B" << block.id();
#if DEBUG
AssemblerDebugInfo info = block.debug_info();
if (info.name) os << info;
// Print predecessor blocks for better debugging.
const int kMaxDisplayedBlocks = 4;
int i = 0;
const BasicBlock* current_block = &block;
while (current_block->PredecessorCount() > 0 && i++ < kMaxDisplayedBlocks) {
current_block = current_block->predecessors().front();
os << " <= B" << current_block->id();
info = current_block->debug_info();
if (info.name) os << info;
}
#endif
return os;
}
std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
switch (c) {
......
......@@ -20,11 +20,9 @@ class BasicBlock;
class BasicBlockInstrumentor;
class Node;
typedef ZoneVector<BasicBlock*> BasicBlockVector;
typedef ZoneVector<Node*> NodeVector;
// A basic block contains an ordered list of nodes and ends with a control
// node. Note that if a basic block has phis, then all phis must appear as the
// first nodes in the block.
......@@ -60,6 +58,12 @@ class V8_EXPORT_PRIVATE BasicBlock final
BasicBlock(Zone* zone, Id id);
Id id() const { return id_; }
#if DEBUG
void set_debug_info(AssemblerDebugInfo debug_info) {
debug_info_ = debug_info;
}
AssemblerDebugInfo debug_info() const { return debug_info_; }
#endif // DEBUG
// Predecessors.
BasicBlockVector& predecessors() { return predecessors_; }
......@@ -167,11 +171,15 @@ class V8_EXPORT_PRIVATE BasicBlock final
BasicBlockVector successors_;
BasicBlockVector predecessors_;
#if DEBUG
AssemblerDebugInfo debug_info_;
#endif
Id id_;
DISALLOW_COPY_AND_ASSIGN(BasicBlock);
};
std::ostream& operator<<(std::ostream&, const BasicBlock&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
......
......@@ -1403,6 +1403,20 @@ inline const char* SuspendTypeFor(SuspendFlags flags) {
return "";
}
struct AssemblerDebugInfo {
AssemblerDebugInfo(const char* name, const char* file, int line)
: name(name), file(file), line(line) {}
const char* name;
const char* file;
int line;
};
inline std::ostream& operator<<(std::ostream& os,
const AssemblerDebugInfo& info) {
os << "(" << info.name << ":" << info.file << ":" << info.line << ")";
return os;
}
} // namespace internal
} // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment