Reference

std/machine/lib

std/machine/src/lib.trb

The kernel the bytecode VM of torb run --vm runs on: raw 64-bit words, and the C runtime behind them (docs/design/VM.md section 6).

The VM keeps its registers in one ArrayList<Int64>, and a value there is the runtime's own bytes - a String is the two words of a torb_text, a list the two of a torb_list, a counted block its pointer. Machine is what does the part TorbScript cannot do on such words: call a function of the runtime with them, read and write a word of a counted block, and place a text or a float constant into them.

This package is not for programs. Its operations trust their operands the way machine code does - a wrong register or address is a wrong write, not a panic - and a sandboxed script never gets it, because a sandbox's capabilities are its imports.

type Machine

native type Machine

The six natives of the VM's kernel. Every one of them is runtime/machine.c.

fn operate

native static fn operate(var words: ArrayList<Int64>, base: Int64, code: ArrayList<Int64>, at: Int64): Int64

Runs one operation of the kernel on the registers, and answers one word. code[at] is the operation's number - an operation of the kernel's own table below 1024, a function of the runtime from 1024 on - and the words after it are its operands: register offsets from base, location indices, sizes.

It is native because it is the runtime: every function of runtime/ is reached through it, with the words of the registers as its arguments, so the VM and a native binary share one implementation of every native.

Pitfalls

Nothing is checked. A register outside of words is memory that belongs to somebody else.

fn load

native static fn load(address: Int64): Int64

The word at address: a field of a counted block of the VM. It is native because an address is raw storage.

Pitfalls

An address that is no field of a live block is undefined behaviour, exactly as it is in C.

fn store

native static fn store(address: Int64, value: Int64)

Writes the word at address. Native for the reason Machine.load is.

Pitfalls

The block has to be unique before a write goes through it; the VM makes it so first, as the IR says.

fn placeText

native static fn placeText(var words: ArrayList<Int64>, at: Int64, text: String)

An immortal copy of text as the two words of a torb_text, at the register at of words (an absolute index). It is how the constant pool gets its strings, and it is native because the storage of a text is the runtime's.

fn placeFloat

native static fn placeFloat(var words: ArrayList<Int64>, at: Int64, value: Float64)

The bits of value as one word at the register at. It is how the constant pool gets its floats, and it is native because the language has no way to see the bits of a float.

fn install

native static fn install(interpreter: (Int64) => Int64)

Hands the kernel the one function it calls back into the interpreter with: a test body runtime/test.c runs behind its recovery point, an equals or a hash of the program's own a map asks for, a task the scheduler resumes. The kernel calls interpreter with the address of a request it describes, and the answer is the request's one word.

It is native because the runtime is what calls it: a closure handed to C is the one way C reaches TorbScript. The kernel keeps interpreter until the next install replaces it.

Pitfalls

A request is only valid while the call that made it runs, and the interpreter has to answer it before anything else of the kernel runs on the same registers.