pytorch/torch/csrc/jit/frontend/source_range.cpp
Han Qi 0723639b60 Revert D34455360: Multisect successfully blamed D34455360 for test failures
Summary:
This diff is reverting D34455360 (61d6c43864)
D34455360 (61d6c43864) is making the following tests to fail and this revert diff is either the revert of the blame diff or the revert of the stack of diffs that need to be reverted to revert the blame diff

Tests affected:
- https://www.internalfb.com/intern/test/562950004334605/

Multisect link:
https://www.internalfb.com/intern/testinfra/multisect/756170

Test Plan: NA

Reviewed By: zhxchen17

Differential Revision: D34596156

fbshipit-source-id: a465bca0094db3caf6130c80f1ed49eea981359b
(cherry picked from commit ef5e5578c64ce9827570757fb016aafa9c782c6a)
2022-03-08 23:18:54 +00:00

208 lines
6.7 KiB
C++

#include <c10/util/irange.h>
#include <torch/csrc/jit/frontend/source_range.h>
#include <torch/csrc/jit/serialization/source_range_serialization.h>
namespace torch {
namespace jit {
size_t SourceRangeHasher::operator()(const torch::jit::SourceRange& key) const {
return (
std::hash<uintptr_t>()(reinterpret_cast<uintptr_t>(key.source().get())) ^
std::hash<size_t>()(key.start()) ^ std::hash<size_t>()(key.end()));
}
c10::optional<SourceRange> SourceView::findSourceRangeThatGenerated(
const SourceRange& range) {
if (!gen_ranges_) {
return c10::nullopt;
}
return gen_ranges_->findSourceRangeThatGenerated(range);
}
C10_EXPORT void SourceRange::highlight(std::ostream& out) const {
// Retrieve original SourceRange, if present.
if (auto orig_source_range = findSourceRangeThatGenerated()) {
orig_source_range->highlight(out);
out << "Serialized ";
}
print_with_context(out, CONTEXT, true, "");
}
C10_EXPORT void format_stack_trace(
std::ostream& out,
const std::vector<StackEntry>& entries) {
bool has_orig_ranges = false;
std::vector<SourceRange> orig_ranges;
// gather original ranges. if we have a situation where we do not have orig
// ranges for some frames, we still want to report them for the frames we do
// have,
// so substitute the current range for that frame
for (const StackEntry& entry : entries) {
if (auto orig_source_range = entry.range.findSourceRangeThatGenerated()) {
orig_ranges.emplace_back(std::move(orig_source_range.value()));
has_orig_ranges = true;
} else {
orig_ranges.emplace_back(entry.range);
}
}
out << "Traceback of TorchScript";
if (has_orig_ranges) {
out << ", serialized code";
}
out << " (most recent call last):\n";
for (const StackEntry& entry : entries) {
entry.range.print_with_context(
out, SourceRange::CONTEXT, true, entry.filename);
}
if (has_orig_ranges) {
out << "\nTraceback of TorchScript, original code (most recent call last):\n";
auto it = entries.begin();
for (const SourceRange& range : orig_ranges) {
range.print_with_context(
out, SourceRange::CONTEXT, true, (*it++).filename);
}
}
}
C10_EXPORT void SourceRange::print_with_context(
std::ostream& out,
size_t context,
bool highlight,
const std::string& funcname) const {
// This is an empty SourceRange, used as a sentinel value.
if (!source_view_) {
return;
}
c10::string_view str = source_view_->text();
if (size() == str.size()) {
// this is just the entire file, not a subset, so print it out.
// primarily used to print out python stack traces
out << str;
return;
}
size_t range_end =
(str.size() < end()
? str.size()
: end()); // use instead of 'end()' because some ranges extend past
// the length of the source
// determine CONTEXT line range
size_t begin_line = start(); // beginning of lines to highlight
size_t end_line = range_end;
while (begin_line > 0 && str[begin_line - 1] != '\n')
--begin_line;
while (end_line < str.size() && str[end_line] != '\n')
++end_line;
AT_ASSERT(begin_line == 0 || str[begin_line - 1] == '\n');
AT_ASSERT(end_line == str.size() || str[end_line] == '\n');
size_t begin_context = begin_line; // beginning of context, CONTEXT lines
// before the highlight lines
for (size_t i = 0; begin_context > 0; --begin_context) {
if (str[begin_context - 1] == '\n') {
++i;
}
if (i >= context) {
break;
}
}
AT_ASSERT(begin_context == 0 || str[begin_context - 1] == '\n');
size_t end_context =
end_line; // end of context, CONTEXT lines after the highlight lines
for (size_t i = 0; end_context < str.size(); ++end_context) {
if (str[end_context] == '\n') {
++i;
}
if (i >= context) {
break;
}
}
AT_ASSERT(end_context == str.size() || str[end_context] == '\n');
// print out location information
if (auto flc = file_line_col()) {
std::string filename;
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
size_t line, col;
std::tie(filename, line, col) = *flc;
out << " File \"" << filename << "\", line " << line;
if (funcname != "") {
out << ", in " << funcname;
}
out << "\n";
}
// print out inital context
out << str.substr(begin_context, start() - begin_context);
size_t line_start = start();
size_t line_end = range_end;
if (highlight) {
line_end = start();
while (line_start < range_end) {
// move line_end to end of line
while (str[line_end] != '\n' && line_end < str.size()) {
++line_end;
}
// print line of code
auto actual_line = str.substr(line_start, (line_end - line_start) + 1);
out << actual_line;
if (actual_line.back() != '\n') {
out << "\n";
}
size_t empty_space = 0;
size_t highlight_space = 0;
size_t hightlight_begin = line_start;
size_t highlight_end = line_start;
// determine length of line which is being highlighted
while (hightlight_begin > 0 && str[hightlight_begin - 1] != '\n') {
--hightlight_begin;
}
while (highlight_end < range_end && str[highlight_end] != '\n') {
++highlight_end;
}
AT_ASSERT(hightlight_begin == 0 || str[hightlight_begin - 1] == '\n');
AT_ASSERT(highlight_end == range_end || str[highlight_end] == '\n');
// determine amount of empty space vs highlighted space
for (const auto i : c10::irange(hightlight_begin, highlight_end)) {
if (str[i] == ' ' || i < start()) {
empty_space++;
} else {
break;
}
}
highlight_space = highlight_end - hightlight_begin - empty_space;
if (highlight_space > 0) {
// some ranges are off and include empty white space on new lines which
// don't need to be printed
bool more_lines = false;
for (size_t i = line_end; i <= range_end; i++) {
if (str[i] != '\n' && str[i] != ' ') {
more_lines = true;
}
}
out << std::string(empty_space, ' ');
out << std::string(highlight_space, '~');
out << (more_lines && line_end != range_end ? "\n" : " <--- HERE\n");
}
++line_end;
line_start = line_end;
}
} else {
// print out code with no highlight
out << str.substr(start(), range_end - start());
}
// print out ending context
if (line_end <= str.size()) {
auto line_substr = str.substr(line_end, end_context - line_end);
out << line_substr;
if (!line_substr.empty() && line_substr.back() != '\n') {
out << "\n";
}
}
}
} // namespace jit
} // namespace torch