summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-06-28 15:19:52 -0700
committerGitHub <noreply@github.com>2023-06-28 15:19:52 -0700
commit84316e8fc3448932c4d62d1e749047aaacf02ef2 (patch)
tree2aa17a37f0b51d8596cd29632ad093908a6a3b7d /src
parent1fb1a2e2970472e9e93f9de94c8a2c674d0a0581 (diff)
downloadbinaryen-84316e8fc3448932c4d62d1e749047aaacf02ef2.tar.gz
binaryen-84316e8fc3448932c4d62d1e749047aaacf02ef2.tar.bz2
binaryen-84316e8fc3448932c4d62d1e749047aaacf02ef2.zip
Limit printing of Literal[s] in a general way (#5792)
Previously we limited printing in a single Literals. But we can have infinitely recursive GC literals, or just huge graphs even without infinite recursion where no single Literals is that big (but we still get exponential blowup). This PR adds a general limit on how much we print once we start to print a Literal or Literals.
Diffstat (limited to 'src')
-rw-r--r--src/wasm/literal.cpp65
1 files changed, 49 insertions, 16 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index a0e3d2bf6..075028127 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -540,7 +540,36 @@ void Literal::printVec128(std::ostream& o, const std::array<uint8_t, 16>& v) {
o << std::dec;
}
+// Printing literals is mainly for debugging purposes, and they can be of
+// massive size or even infinitely recursive, so abbreviate past some point.
+// We do so by tracking how much we've printed so far, and whether we are the
+// "toplevel" call (the entry point from somewhere else), and we reset the
+// count when we leave the toplevel call.
+namespace {
+struct PrintLimiter {
+ static const size_t PRINT_LIMIT = 100;
+ static thread_local size_t printed;
+
+ bool isTopLevel;
+
+ PrintLimiter() : isTopLevel(printed == 0) { printed++; }
+
+ ~PrintLimiter() {
+ if (isTopLevel) {
+ printed = 0;
+ }
+ }
+
+ bool stop() { return printed >= PRINT_LIMIT; }
+};
+
+thread_local size_t PrintLimiter::printed = 0;
+
+} // namespace
+
std::ostream& operator<<(std::ostream& o, Literal literal) {
+ PrintLimiter limiter;
+
prepareMinorColor(o);
assert(literal.type.isSingle());
if (literal.type.isBasic()) {
@@ -618,7 +647,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
assert(literal.isData());
auto data = literal.getGCData();
assert(data);
- // TODO: infinite recursion is possible here, if the data is cyclic
o << "[ref " << data->type << ' ' << data->values << ']';
}
}
@@ -626,27 +654,32 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
return o;
}
-// Printing literals is mainly for debugging purposes, and they can be of
-// massive size, so abbreviate past some point.
-static size_t LITERALS_PRINT_LIMIT = 20;
-
std::ostream& operator<<(std::ostream& o, wasm::Literals literals) {
+ PrintLimiter limiter;
+
+ if (limiter.stop()) {
+ return o << "[..]";
+ }
+
if (literals.size() == 1) {
return o << literals[0];
- } else {
- o << '(';
- if (literals.size() > 0) {
- o << literals[0];
+ }
+
+ o << '(';
+ bool first = true;
+ for (auto& literal : literals) {
+ if (limiter.stop()) {
+ o << "[..]";
+ break;
}
- for (size_t i = 1; i < literals.size(); ++i) {
- o << ", " << literals[i];
- if (i == LITERALS_PRINT_LIMIT) {
- o << "[..]";
- break;
- }
+ if (first) {
+ first = false;
+ } else {
+ o << ", ";
}
- return o << ')';
+ o << literal;
}
+ return o << ')';
}
Literal Literal::countLeadingZeroes() const {