|
void | potion_vm_init (Potion *P) |
|
PN | potion_vm_proto (Potion *P, PN cl, PN self,...) |
| entrypoint for all bytecode methods from the C api. More...
|
|
PN | potion_vm_class (Potion *P, PN cl, PN self) |
| implements the class op creates a class (or type) from a closure and parent class with obj ivars More...
|
|
PN | potion_vm_eq (Potion *P, PN a, PN b) |
|
PN | potion_vm_neq (Potion *P, PN a, PN b) |
|
static PN | potion_sig_check (Potion *P, struct PNClosure *cl, int arity, int numargs) |
|
PN | potion_debug (Potion *P, struct PNProto *f, PN self, PN_OP op, PN *reg, PN *stack) |
|
PN | potion_vm (Potion *P, PN proto, PN self, PN vargs, PN_SIZE upc, PN *upargs) |
| the bytecode run-loop More...
|
|
the vm execution loop, the "bytecode interpreter".
correct but slower than the jit.
usage: -B, -Dt or automatically when no jit is available for your architecture.
Potion uses a two-address register-based bytecode VM that is nearly a word-for-word copy of Lua's. The code is all different, but the bytecode is nearly identical. See http://luaforge.net/docman/83/98/ANoFrillsIntroToLua51VMInstructions.pdf or http://www.lua.org/doc/jucs05.pdf
It is even more space-efficient than a simple stack-based VM, and of course faster. Each 32-bit op word contains the op and its two arguments. I.e. the first address R(A) is always modified, as in a stack vm. A full non-destructive three-address scheme R(D) = OP R(A), R(B) is not needed.
- MOVE (pos) copy value between registers R(A)=R(B)
- LOADK (pos, need) load a constant into a register R(A)=value[B]
- LOADPN (pos) load a PN value into a register R(A)=B
- SELF (pos, need) prepare an object method for calling R(A+1) := R(B); R(A) := R(B)[RK(C)]
- GETLOCAL (pos, regs) read a local into a register R(A)=local[B])
- SETLOCAL (pos, regs) write a register value into a local local[A]=R(B)
- GETUPVAL (pos, lregs) read an upvalue (upper scope) R(A)=upval[B]
- SETUPVAL (pos, lregs) write to an upvalue upval[A]=R(B)
- GLOBAL (pos, need) returns a global (for get or set) name R(A)= value R(B)
- NEWTUPLE (pos, need) create tuple R(A)=()
- GETTUPLE (pos, need) get tuple key R(A)=R(A)(B&1024?R(B):B)
- SETTUPLE (pos, need) write register into tuple key R(A)=push(R(A), R(B)
- GETTABLE (pos, need) get table entry R(A)=R(A){B}
- SETTABLE (pos, need) write register into a table entry R(A) = R(A){R(A+1)} = R(B)
- NEWLICK (pos, need) create lick. R(A) := {} (size = B,C)
- GETPATH (pos, need) read obj field obj_get(R(A), R(B))
- SETPATH (pos, need) write into obj field obj_set(R(A), R(A+1), R(B))
- ADD (pos, need) R(A) = R(A) + R(B)
- SUB (pos, need) R(A) = R(A) - R(B)
- MULT (pos, need) -"-
- DIV (pos, need)
- REM (pos, need)
- POW (pos, need)
- NOT (pos) R(A) = !R(A)
- CMP (pos) R(A) = int( R(B) - R(A) )
- NEQ (pos) R(A) = R(A) != R(B)
- EQ (pos) R(A) = R(A) == R(B)
- LT (pos) R(A) = R(A) < R(B)
- LTE (pos) R(A) = R(A) <= R(B)
- GT (pos) R(A) = R(A) > R(B)
- GTE (pos) R(A) = R(A) >= R(B)
- BITN (pos, need) R(A) = ~R(B)
- BITL (pos, need) R(A) = R(A) << R(B)
- BITR (pos, need) R(A) = R(A) >> R(B)
- DEF (pos, need) def_method(R(A), R(A+1), R(B)) define a method for an object
- BIND (pos, need) bind(R(A), R(B)) method lookup for receiver A and message B http://piumarta.com/software/cola/colas-whitepaper.pdf
- MSG (pos, need) message(R(A), R(B)) call a method of an object
- JMP (pos, jmps, offs, &jmpc) pos += R(A)
- TEST (pos) R(A) = bool R(A)
- TESTJMP (pos, jmps, offs, &jmpc) if R(A) pos += R(B)
- NOTJMP (pos, jmps, offs, &jmpc) if !R(A) pos += R(B)
- NAMED (pos, need) assign named args before a CALL
- CALL (pos, need) call a function. R(A),...:= R(A)(R(A+1),...,R(A+B-1)
- CALLSET (pos, need) get default writer for R(B) R(A)=get_callset(R(B))
- TAILCALL(pos, need) ? jumps back to the function entry (TODO)
- RETURN (pos) return R(A), ... ,R(A+B-2)
- PROTO (&pos, lregs, need, regs) define a method prototype
- CLASS (pos, need) R(A) = vm_class(R(B), R(A)) creates class from closure B and parent A
- DEBUG (pos) set ast to lineno
(c) 2008 why the lucky stiff, the freelance professor (c) 2013-2015 by perl11 org
Definition in file vm.c.
entrypoint for all bytecode methods from the C api.
- See also
- potion_test_eval()
- Parameters
-
cl | PNClosure to be called |
self | PN - sets self (ignored for most user defined functions). if self is a int < 10 it defines the number of args provided |
... | - arguments to the cl |
add = potion_eval(P, potion_str(P, "(x=N|y=N): x + y."));
addfn = PN_CLOSURE_F(add); // i.e. potion_vm_proto
num = addfn(P, add, 2, PN_NUM(3), PN_NUM(5));
num = addfn(P, add, 1, PN_NUM(3)); // 1 arg provided, 2nd arg=0
Note that methods with optional arguments ... are not very safe to call. potion_vm_proto() does not know the number of arguments on the stack. So it checks for all optional args the matching type. You can help by providing numargs as self argument if numargs < 10.
Definition at line 159 of file vm.c.