214 lines
6.8 KiB
C
214 lines
6.8 KiB
C
// This defines the bytecode instructions used by the VM. It does so by invoking
|
|
// an OPCODE() macro which is expected to be defined at the point that this is
|
|
// included. (See: http://en.wikipedia.org/wiki/X_Macro for more.)
|
|
//
|
|
// The first argument is the name of the opcode. The second is its "stack
|
|
// effect" -- the amount that the op code changes the size of the stack. A
|
|
// stack effect of 1 means it pushes a value and the stack grows one larger.
|
|
// -2 means it pops two values, etc.
|
|
//
|
|
// Note that the order of instructions here affects the order of the dispatch
|
|
// table in the VM's interpreter loop. That in turn affects caching which
|
|
// affects overall performance. Take care to run benchmarks if you change the
|
|
// order here.
|
|
|
|
// Load the constant at index [arg].
|
|
OPCODE(CONSTANT, 1)
|
|
|
|
// Push null onto the stack.
|
|
OPCODE(NULL, 1)
|
|
|
|
// Push false onto the stack.
|
|
OPCODE(FALSE, 1)
|
|
|
|
// Push true onto the stack.
|
|
OPCODE(TRUE, 1)
|
|
|
|
// Pushes the value in the given local slot.
|
|
OPCODE(LOAD_LOCAL_0, 1)
|
|
OPCODE(LOAD_LOCAL_1, 1)
|
|
OPCODE(LOAD_LOCAL_2, 1)
|
|
OPCODE(LOAD_LOCAL_3, 1)
|
|
OPCODE(LOAD_LOCAL_4, 1)
|
|
OPCODE(LOAD_LOCAL_5, 1)
|
|
OPCODE(LOAD_LOCAL_6, 1)
|
|
OPCODE(LOAD_LOCAL_7, 1)
|
|
OPCODE(LOAD_LOCAL_8, 1)
|
|
|
|
// Note: The compiler assumes the following _STORE instructions always
|
|
// immediately follow their corresponding _LOAD ones.
|
|
|
|
// Pushes the value in local slot [arg].
|
|
OPCODE(LOAD_LOCAL, 1)
|
|
|
|
// Stores the top of stack in local slot [arg]. Does not pop it.
|
|
OPCODE(STORE_LOCAL, 0)
|
|
|
|
// Pushes the value in upvalue [arg].
|
|
OPCODE(LOAD_UPVALUE, 1)
|
|
|
|
// Stores the top of stack in upvalue [arg]. Does not pop it.
|
|
OPCODE(STORE_UPVALUE, 0)
|
|
|
|
// Pushes the value of the top-level variable in slot [arg].
|
|
OPCODE(LOAD_MODULE_VAR, 1)
|
|
|
|
// Stores the top of stack in top-level variable slot [arg]. Does not pop it.
|
|
OPCODE(STORE_MODULE_VAR, 0)
|
|
|
|
// Pushes the value of the field in slot [arg] of the receiver of the current
|
|
// function. This is used for regular field accesses on "this" directly in
|
|
// methods. This instruction is faster than the more general CODE_LOAD_FIELD
|
|
// instruction.
|
|
OPCODE(LOAD_FIELD_THIS, 1)
|
|
|
|
// Stores the top of the stack in field slot [arg] in the receiver of the
|
|
// current value. Does not pop the value. This instruction is faster than the
|
|
// more general CODE_LOAD_FIELD instruction.
|
|
OPCODE(STORE_FIELD_THIS, 0)
|
|
|
|
// Pops an instance and pushes the value of the field in slot [arg] of it.
|
|
OPCODE(LOAD_FIELD, 0)
|
|
|
|
// Pops an instance and stores the subsequent top of stack in field slot
|
|
// [arg] in it. Does not pop the value.
|
|
OPCODE(STORE_FIELD, -1)
|
|
|
|
// Pop and discard the top of stack.
|
|
OPCODE(POP, -1)
|
|
|
|
// Invoke the method with symbol [arg]. The number indicates the number of
|
|
// arguments (not including the receiver).
|
|
OPCODE(CALL_0, 0)
|
|
OPCODE(CALL_1, -1)
|
|
OPCODE(CALL_2, -2)
|
|
OPCODE(CALL_3, -3)
|
|
OPCODE(CALL_4, -4)
|
|
OPCODE(CALL_5, -5)
|
|
OPCODE(CALL_6, -6)
|
|
OPCODE(CALL_7, -7)
|
|
OPCODE(CALL_8, -8)
|
|
OPCODE(CALL_9, -9)
|
|
OPCODE(CALL_10, -10)
|
|
OPCODE(CALL_11, -11)
|
|
OPCODE(CALL_12, -12)
|
|
OPCODE(CALL_13, -13)
|
|
OPCODE(CALL_14, -14)
|
|
OPCODE(CALL_15, -15)
|
|
OPCODE(CALL_16, -16)
|
|
|
|
// Invoke a superclass method with symbol [arg]. The number indicates the
|
|
// number of arguments (not including the receiver).
|
|
OPCODE(SUPER_0, 0)
|
|
OPCODE(SUPER_1, -1)
|
|
OPCODE(SUPER_2, -2)
|
|
OPCODE(SUPER_3, -3)
|
|
OPCODE(SUPER_4, -4)
|
|
OPCODE(SUPER_5, -5)
|
|
OPCODE(SUPER_6, -6)
|
|
OPCODE(SUPER_7, -7)
|
|
OPCODE(SUPER_8, -8)
|
|
OPCODE(SUPER_9, -9)
|
|
OPCODE(SUPER_10, -10)
|
|
OPCODE(SUPER_11, -11)
|
|
OPCODE(SUPER_12, -12)
|
|
OPCODE(SUPER_13, -13)
|
|
OPCODE(SUPER_14, -14)
|
|
OPCODE(SUPER_15, -15)
|
|
OPCODE(SUPER_16, -16)
|
|
|
|
// Jump the instruction pointer [arg] forward.
|
|
OPCODE(JUMP, 0)
|
|
|
|
// Jump the instruction pointer [arg] backward.
|
|
OPCODE(LOOP, 0)
|
|
|
|
// Pop and if not truthy then jump the instruction pointer [arg] forward.
|
|
OPCODE(JUMP_IF, -1)
|
|
|
|
// If the top of the stack is false, jump [arg] forward. Otherwise, pop and
|
|
// continue.
|
|
OPCODE(AND, -1)
|
|
|
|
// If the top of the stack is non-false, jump [arg] forward. Otherwise, pop
|
|
// and continue.
|
|
OPCODE(OR, -1)
|
|
|
|
// Close the upvalue for the local on the top of the stack, then pop it.
|
|
OPCODE(CLOSE_UPVALUE, -1)
|
|
|
|
// Exit from the current function and return the value on the top of the
|
|
// stack.
|
|
OPCODE(RETURN, 0)
|
|
|
|
// Creates a closure for the function stored at [arg] in the constant table.
|
|
//
|
|
// Following the function argument is a number of arguments, two for each
|
|
// upvalue. The first is true if the variable being captured is a local (as
|
|
// opposed to an upvalue), and the second is the index of the local or
|
|
// upvalue being captured.
|
|
//
|
|
// Pushes the created closure.
|
|
OPCODE(CLOSURE, 1)
|
|
|
|
// Creates a new instance of a class.
|
|
//
|
|
// Assumes the class object is in slot zero, and replaces it with the new
|
|
// uninitialized instance of that class. This opcode is only emitted by the
|
|
// compiler-generated constructor metaclass methods.
|
|
OPCODE(CONSTRUCT, 0)
|
|
|
|
// Creates a new instance of a foreign class.
|
|
//
|
|
// Assumes the class object is in slot zero, and replaces it with the new
|
|
// uninitialized instance of that class. This opcode is only emitted by the
|
|
// compiler-generated constructor metaclass methods.
|
|
OPCODE(FOREIGN_CONSTRUCT, 0)
|
|
|
|
// Creates a class. Top of stack is the superclass. Below that is a string for
|
|
// the name of the class. Byte [arg] is the number of fields in the class.
|
|
OPCODE(CLASS, -1)
|
|
|
|
// Creates a foreign class. Top of stack is the superclass. Below that is a
|
|
// string for the name of the class.
|
|
OPCODE(FOREIGN_CLASS, -1)
|
|
|
|
// Define a method for symbol [arg]. The class receiving the method is popped
|
|
// off the stack, then the function defining the body is popped.
|
|
//
|
|
// If a foreign method is being defined, the "function" will be a string
|
|
// identifying the foreign method. Otherwise, it will be a function or
|
|
// closure.
|
|
OPCODE(METHOD_INSTANCE, -2)
|
|
|
|
// Define a method for symbol [arg]. The class whose metaclass will receive
|
|
// the method is popped off the stack, then the function defining the body is
|
|
// popped.
|
|
//
|
|
// If a foreign method is being defined, the "function" will be a string
|
|
// identifying the foreign method. Otherwise, it will be a function or
|
|
// closure.
|
|
OPCODE(METHOD_STATIC, -2)
|
|
|
|
// This is executed at the end of the module's body. Pushes NULL onto the stack
|
|
// as the "return value" of the import statement and stores the module as the
|
|
// most recently imported one.
|
|
OPCODE(END_MODULE, 1)
|
|
|
|
// Import a module whose name is the string stored at [arg] in the constant
|
|
// table.
|
|
//
|
|
// Pushes null onto the stack so that the fiber for the imported module can
|
|
// replace that with a dummy value when it returns. (Fibers always return a
|
|
// value when resuming a caller.)
|
|
OPCODE(IMPORT_MODULE, 1)
|
|
|
|
// Import a variable from the most recently imported module. The name of the
|
|
// variable to import is at [arg] in the constant table. Pushes the loaded
|
|
// variable's value.
|
|
OPCODE(IMPORT_VARIABLE, 1)
|
|
|
|
// This pseudo-instruction indicates the end of the bytecode. It should
|
|
// always be preceded by a `CODE_RETURN`, so is never actually executed.
|
|
OPCODE(END, 0)
|