  A key strength of managed runtimes over hardware is the ability to gain
detailed insight into the dynamic execution of programs with instrumentation.
Analyses such as code coverage, execution frequency, tracing, and debugging,
are all made easier in a virtual setting. As a portable, low-level bytecode,
WebAssembly offers inexpensive in-process sandboxing with high performance. Yet
to date, Wasm engines have not offered much insight into executing programs,
supporting at best bytecode-level stepping and basic source maps, but no
instrumentation capabilities. In this paper, we show the first non-intrusive
dynamic instrumentation system for WebAssembly in the open-source Wizard
Research Engine. Our innovative design offers a flexible, complete hierarchy of
instrumentation primitives that support building high-level, complex analyses
in terms of low-level, programmable probes. In contrast to emulation or machine
code instrumentation, injecting probes at the bytecode level increases
expressiveness and vastly simplifies the implementation by reusing the engine's
JIT compiler, interpreter, and deoptimization mechanism rather than building
new ones. Wizard supports both dynamic instrumentation insertion and removal
while providing consistency guarantees, which is key to composing multiple
analyses without interference. We detail a fully-featured implementation in a
high-performance multi-tier Wasm engine, show novel optimizations specifically
designed to minimize instrumentation overhead, and evaluate performance
characteristics under load from various analyses. This design is well-suited
for production engine adoption as probes can be implemented to have no impact
on production performance when not in use.
