Skip to content

Commit

Permalink
[monitors] Add ConstMonitor which tracks constant arguments to functions
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Sep 23, 2024
1 parent 518f8a6 commit 6e141a5
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 5 deletions.
16 changes: 13 additions & 3 deletions issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,21 @@ Prio Component Issue

Monitors + trace
--------------------------------
All --trace-interpreter, memory, calls, etc output events in code in nested call trace format
> func1
> func2A
call event
> func3
instr event
memory access event
> func2B
--trace-interpreter accepts a function filter
build general-purpose "what is this program doing" monitor
CallsMonitor should report source-names of callees
TablesMonitor should report read/write/calls through tables
--trace-tables should report read/write/calls through tables
TrapsMonitor shows state of program at trap points (default?)
VirgilMonitor hooks into sections of Virgil-generated Wasm
ExceptionMonitor tracks try/throw/catch
--trace-exception tracks try/throw/catch
MallocMonitor tracks malloc/free behavior
- tries to find memory leaks
- perf metrics: total usage, average usage, distribution of alloc sizes, free distance
Expand Down Expand Up @@ -91,10 +100,10 @@ Monitors + trace
- wasm: traps, throw/catch, memory access, suspend/resume, host calls, frame unwind
- engine: gc, compile, load, verify
LoopMonitor track and display loop count distribution, improve display
ConstArgs track runtime function argument uniqueness to detect specialization/inlining opportunities
Interactive - show an interactive, terminal-animated view of execution, e.g. which function
func | xxx xx | <- color indicates how recent / hot
mem | ====== |
ConstMonitor - track const load/store, global get/set



Expand Down Expand Up @@ -228,6 +237,7 @@ Inline WasmObject.values array

Done
--------------------------------
monitor Track runtime function argument consts to detect specialization/inlining opportunities
ext extended constants
fast-int non-final subtyping check for call_indirect
interpreter implement atomics
Expand Down
105 changes: 105 additions & 0 deletions src/monitors/ConstMonitor.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2024 Wizard Authors. All rights reserved.
// See LICENSE for details of Apache 2.0 license.

// Implements a simple monitor that counts the number of iterations of each loop.
def monitor_ = MonitorRegistry.add(
"const", "Tracks constants in various places in the program.",
FuncArgsMonitor.new());
def filter = monitor_.options.addAlias(
monitor_.options.newDeclFilterOption("filter", "apply constant tracking to selected functions"),
"f");
var funcArgs = true;
// XXX: trace loads/stores to memory, get/set of globals
var entries: List<FuncArgsEntry>;

class FuncArgsMonitor extends Monitor {
def onParse(m: Module) {
ModuleInstrumenter.new(m).forEachFuncFiltered(filter.val, instrument);
}

def onFinish(i: Instance, r: Result) {
if (MonitorOptions.CSV.val) reportCsv(out);
else report(out);
}

private def instrument(mm: ModuleInstrumenter, func: FuncDecl) {
if (funcArgs) {
var probe = FuncArgsEntry.new(mm.module, func);
entries = List.new(probe, entries);
Instrumentation.insertLocalProbe(mm.module, func.func_index, 0, probe);
}

}
}

def report(out: TraceBuilder) {
for (l = Lists.reverse(entries); l != null; l = l.tail) {
var entry = l.head;
if (entry.count == 0) continue;
out.beginColor(Color.FUNC)
.put1("func %q:", entry.func.render(entry.module.names, _))
.beginColor(Color.COUNT)
.put1(" %d", entry.count)
.endColors()
.puts(": (");
for (i < entry.consts.length) {
var v = entry.consts[i];
if (i > 0) out.csp();
if (v == NON_CONST_VALUE) out.puts("?");
else out.beginColor(Color.VALUE).putv(v).endColors();
}
out.puts(")").ln();
}
}
def reportCsv(out: TraceBuilder) {
out.puts("func,count,args").ln();
for (l = Lists.reverse(entries); l != null; l = l.tail) {
var entry = l.head;
if (entry.count == 0) continue;
out.put1("%q", entry.func.render(entry.module.names, _))
.put1(",%d,", entry.count)
.puts("(");
for (i < entry.consts.length) {
var v = entry.consts[i];
if (i > 0) out.sp();
if (v == NON_CONST_VALUE) out.puts("?");
else out.putv(v);
}
out.puts(")").ln();
}
}

var NON_CONST_VALUE = Value.Ref(Object.new()); // nothing will compare equal to this value.

// Records constants for function arguments.
private class FuncArgsEntry(module: Module, func: FuncDecl) extends Probe {
var count = 0uL;
def consts = Array<Value>.new(func.sig.params.length);
def fire(loc: DynamicLoc) -> Resumption {
var accessor = loc.frame.getFrameAccessor();
if (count++ != 0) {
// n'th invocation; check if any argument is different.
for (i < consts.length) {
var prev = consts[i];
var got = accessor.getLocal(i);
if (prev != got) consts[i] = NON_CONST_VALUE;
}
} else {
// first invocation.
for (i < consts.length) consts[i] = accessor.getLocal(i);
}
return Resumption.Continue;
}
}

private class ConstEntry {
var count = 0uL;
var const: Value;

def add(v: Value) {
if (count++ != 0 && const != v) const = NON_CONST_VALUE;
else return void(const = v);

}
}

4 changes: 2 additions & 2 deletions src/util/OptionsRegistry.v3
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// See LICENSE for details of Apache 2.0 license.

// Centralizes management of help for options and sections for various utilities,
// which is used to print out
// which is used to print out help for all command-line options.
component OptionsRegistry {
def ALL = BasicOptions.new(null);
var groups: List<(OptionGroup, TraceBuilder -> void)>;
Expand Down Expand Up @@ -125,4 +125,4 @@ def setFlag(str: string, onParse: string -> void) -> bool {
return str == null || Strings.equal(str, "true");
}

class OptionGroupEntry(opt: Opt, var display_name: string, type_name: string, help: string) {}
class OptionGroupEntry(opt: Opt, var display_name: string, type_name: string, help: string) {}
Binary file added test/monitors/const_arg0.wasm
Binary file not shown.
11 changes: 11 additions & 0 deletions test/monitors/const_arg0.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(module
(func $main (export "main")
(call $start)
)
(func $start (export "_start")
(call $foo (i32.const 0) (i32.const 1))
(call $foo (i32.const 0) (i32.const 2))
)
(func $foo (param i32 i32)
)
)

0 comments on commit 6e141a5

Please sign in to comment.