Skip to content

Latest commit

 

History

History
40 lines (35 loc) · 4.14 KB

Design.md

File metadata and controls

40 lines (35 loc) · 4.14 KB

Wizard Engine Design

Simplicity and Functionality First

Unlike other engines that have either grown out of Web Engines (V8, Spidermonkey, Chakra, and JSC) or emerged from compiler designs (Cranelift, Wasmtime), Wizard has the benefit of both hindsight and foresight. It is designed to be simple and yet also takes all in-flight Wasm proposals as requirements. Rather than optimize for performance for a specific set of Wasm features now, it is designed to first sum today's and tomorrow's requirements first.

Architecture

  • Module - The centerpiece of any Wasm engine, this is the decoded, in-memory representation of a Wasm module. It contains the declared module members, i.e. signatures, types, functions, memories, tables, etc. To support relaxed section order, a module keeps the members in the ordered declared in the binary and contains an index of members segregated by their kind.

  • Instance - Represents the entire state of an instantiated module, including its memories, tables, and bound imports. An instance is the primary data structure needed to execute code, e.g. in the interpreter. The Instantiator class contains the logic to bind imports (by consulting import processors) and to properly construct an instance in order of its original declarations.

  • Function - Represents a function bound to a instance, or a host function, supplied by the surrounding environment.

  • Bytecode - The copied raw bytes of an individual function from a module. It contains a small side data structure (the control transfer information) that helps the interpreter run without linear overhead, due to Wasm's structured control constructs.

  • Opcodes - The central place for describing the opcode, name, immediates, and simple signature of each bytecode. This makes it easy to see at a glance what each bytecode does. Immediate kinds separate the logic of decoding an opcode from its immediate. We make nice use of Virgil's enhanced enum language mechanism here.

  • BinParser - Contains the logic of parsing Wasm module bytes into the internal memory representation. Internally it utilizes a simple state machine to be push-based, i.e. it is possible to create a BinParser and then feed parts of a module incrementally as they become available, for example over a network.

  • ValueType - The one place where types are represented in the engine. This makes it easy to see what kinds of types are needed, and the logic for all type relations (e.g. assignability, subtyping, least-upper-bound) are expressed here.

  • CodeValidator - Contains all logic for validating function bodies. The code validator uses the standard single-pass abstract interpretation approach for checking code. In addition to validating all types and control flow, it produces the control transfer information needed for the fast interpreter.

  • Value - Contains all the Wasm values, including primitives, references, etc.

  • Interpreter - The low-overhead interpreter that executes Wasm binary code directly. It contains a straightforward value stack and call stack and makes heavy use of Virgil's first-class primitive operators in order to be concise. It uses the control transfer information to execute branches and if's with low overhead.

  • Host - Contains the base declarations for all host-provided functionality, e.g. for an embedding.

  • Errors - Contains all the logic for the many kinds of errors that can be produced by an engine when decoding, validating, or instantiating a Wasm module. This separation allows the mainline code of decoding, validation, and instantiation to be kept tidy.

  • Extensions - Contains an enumeration of all the extensions that can be individually enabled for the engine.

  • SpecTest - Contains a parser for the .bin.wast format in which specification tests are expressed, along with an interpreter capable of running them.