Skip to content

Virtual Machine

TJS2 VM

TJS2 first compiles scripts into binary code for a virtual machine (the TJS2 VM) and then executes it.

Disassembled TJS2 VM code is shown when an exception occurs or when a dump is performed, so this page briefly describes the virtual machine.

Instruction code

The TJS2 VM is independent for each execution unit, such as a function or property; a function never shares its instruction code space, register space, flag, or constant area with another function.

The instruction pointer (ip) always starts at 0 at the beginning of a function or other unit.

A short, human-readable name for an instruction code is called a mnemonic.

Registers

TJS2 VM registers are written as %(number) in mnemonics. The number can be negative. There is no limit on the number of registers. Local variables, temporary values during computation, and so on are all stored in registers. There is no main memory or stack.

A register holds the same kinds of values as a TJS2 variable: integers, real numbers, objects, strings, octet strings, and void.

In the current version, register %0 is always void. Register %-1 is this. Register %-2 is a special object called the this proxy: a member lookup on it first checks this, and if the member is not there, checks global. The this proxy does not exist in global-level execution units. Function arguments and the like are stored in registers %-3, %-4, and so on before execution starts.

Apart from such registers, whose purpose is predetermined or which hold values before execution, register values are undefined when execution starts.

Flag

The TJS2 VM has a single flag, which stores the result of comparisons. The flag is either true or false.

Constant area

The TJS2 VM constant area stores constants and is written as *(number) in mnemonics. The constant area is read-only; the const instruction moves a value from it into a register. The "names" used to access object members by name, such as function and property names, are also stored in the constant area.

VM mnemonics

Some instructions have operands of the form %obj.*name or %obj.%name; these involve object member access.

An operand of the form %obj.*name is a direct reference: it refers to the member named by *name in the object given by register %obj.

An operand of the form %obj.%name is an indirect reference: it refers to the member named by %name in the object given by register %obj.

The mnemonics of such instructions have the suffix d or pd (direct / property direct), or i or pi (indirect / property indirect).

Those with p in the suffix invoke the property handler of the target register (the behavior of the unary '*' operator).

  • nop
    (no operation)

    Does nothing.
  • const
    (copy constant value)

    Syntax: const %dest, *src

Copies the value at *src in the constant area to register %dest. - cp
(copy register)

Syntax: cp %dest, %src

Copies the value of register %src to register %dest. - cl
(clear register)

Syntax: cl %dest

Sets register %dest to void. - ccl
(clear register)

Syntax: ccl %low-%high

Sets all registers from %low through %high to void. - tt
(test true)

Syntax: tt %reg

Sets the flag to true if register %reg represents true, and to false if it represents false. - tf
(test false)

Syntax: tf %reg

The opposite of tt: sets the flag to false if register %reg represents true, and to true if it represents false. - ceq
(compare equal)

Syntax: ceq %reg1, %reg2

Sets the flag to true if %reg1 and %reg2 are equal by ordinary comparison (the behavior of the == operator), and to false otherwise. - cdeq
(compare distinct equal)

Syntax: cdeq %reg1, %reg2

Sets the flag to true if %reg1 and %reg2 are equal by identity comparison (the behavior of the === operator), and to false otherwise. - clt
(compare littler than)

Syntax: clt %reg1, %reg2

Sets the flag to true if %reg1 < %reg2, and to false otherwise. - cgt
(compare greater than)

Syntax: cgt %reg1, %reg2

Sets the flag to true if %reg1 > %reg2, and to false otherwise. - setf
(set flag)

Syntax: setf %dest

Sets %dest to true (a nonzero integer) if the flag is true, and to false (integer 0) if it is false. - setnf
(set not flag)

Syntax: setnf %dest

The opposite of setf: sets %dest to true (a nonzero integer) if the flag is false, and to false (integer 0) if it is true. - lnot
(logical not)

Syntax: lnot %reg

Inverts the truth value of %reg. - nf
(not flag)

Syntax: nf

Inverts the flag. - jf
(jump if flag)

Syntax: jf ip

Jumps to ip if the flag is true. - jnf
(jump if not flag)

Syntax: jnf ip

Jumps to ip if the flag is false. - inc, incpd, incpi, incp
(increment)

Syntax: inc %reg

Syntax: incpd %res, %obj.*name

Syntax: incpi %res, %obj.%name

Syntax: incp %res, %propobj

Increments %reg, %obj.*name, %obj.%name, or %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - dec, decpd, decpi, decp
(decrement)

Syntax: dec %reg

Syntax: decpd %res, %obj.*name

Syntax: decpi %res, %obj.%name

Syntax: decp %res, %propobj

Decrements %reg, %obj.*name, %obj.%name, or %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - lor, lorpd, lorpi, lorp
(logical or)

Syntax: lor %dest, %src

Computes the logical OR of %dest and %src and stores the result in %dest.

Syntax: lorpd %res, %obj.*name, %src

Computes the logical OR of %obj.name and %src and stores the result in %obj.name.

Syntax: lorpi %res, %obj.%name, %src

Computes the logical OR of %obj.%name and %src and stores the result in %obj.%name.

Syntax: lorp %res, %propobj, %src

Computes the logical OR of %propobj and %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - land, landpd, landpi, landp
(logical and)

Syntax: land %dest, %src

Computes the logical AND of %dest and %src and stores the result in %dest.

Syntax: landpd %res, %obj.*name, %src

Computes the logical AND of %obj.name and %src and stores the result in %obj.name.

Syntax: landpi %res, %obj.%name, %src

Computes the logical AND of %obj.%name and %src and stores the result in %obj.%name.

Syntax: landp %res, %propobj, %src

Computes the logical AND of %propobj and %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - bor, borpd, borpi, borp
(bitwise or)

Syntax: bor %dest, %src

Computes the bitwise OR of %dest and %src and stores the result in %dest.

Syntax: borpd %res, %obj.*name, %src

Computes the bitwise OR of %obj.name and %src and stores the result in %obj.name.

Syntax: borpi %res, %obj.%name, %src

Computes the bitwise OR of %obj.%name and %src and stores the result in %obj.%name.

Syntax: borp %res, %propobj, %src

Computes the bitwise OR of %propobj and %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - bxor, bxorpd, bxorpi, bxorp
(bitwise xor)

Syntax: bxor %dest, %src

Computes the bitwise XOR of %dest and %src and stores the result in %dest.

Syntax: bxorpd %res, %obj.*name, %src

Computes the bitwise XOR of %obj.name and %src and stores the result in %obj.name.

Syntax: bxorpi %res, %obj.%name, %src

Computes the bitwise XOR of %obj.%name and %src and stores the result in %obj.%name.

Syntax: bxorp %res, %propobj, %src

Computes the bitwise XOR of %propobj and %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - band, bandpd, bandpi, bandp
(bitwise and)

Syntax: band %dest, %src

Computes the bitwise AND of %dest and %src and stores the result in %dest.

Syntax: bandpd %res, %obj.*name, %src

Computes the bitwise AND of %obj.name and %src and stores the result in %obj.name.

Syntax: bandpi %res, %obj.%name, %src

Computes the bitwise AND of %obj.%name and %src and stores the result in %obj.%name.

Syntax: bandp %res, %propobj, %src

Computes the bitwise AND of %propobj and %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - sar, sarpd, sarpi, sarp
(shift arithmetic right)

Syntax: sar %dest, %src

Shifts %dest arithmetically right by the number of bits given by %src and stores the result in %dest.

Syntax: sarpd %res, %obj.*name, %src

Shifts %obj.name arithmetically right by the number of bits given by %src and stores the result in %obj.name.

Syntax: sarpi %res, %obj.%name, %src

Shifts %obj.%name arithmetically right by the number of bits given by %src and stores the result in %obj.%name.

Syntax: sarp %res, %propobj, %src

Shifts %propobj arithmetically right by the number of bits given by %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - sal, salpd, salpi, salp
(shift arithmetic left)

Syntax: sal %dest, %src

Shifts %dest arithmetically left by the number of bits given by %src and stores the result in %dest.

Syntax: salpd %res, %obj.*name, %src

Shifts %obj.name arithmetically left by the number of bits given by %src and stores the result in %obj.name.

Syntax: salpi %res, %obj.%name, %src

Shifts %obj.%name arithmetically left by the number of bits given by %src and stores the result in %obj.%name.

Syntax: salp %res, %propobj, %src

Shifts %propobj arithmetically left by the number of bits given by %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - sr, srpd, srpi, srp
(shift bitwise right)

Syntax: sr %dest, %src

Shifts %dest logically (bitwise) right by the number of bits given by %src and stores the result in %dest.

Syntax: srpd %res, %obj.*name, %src

Shifts %obj.name logically (bitwise) right by the number of bits given by %src and stores the result in %obj.name.

Syntax: srpi %res, %obj.%name, %src

Shifts %obj.%name logically (bitwise) right by the number of bits given by %src and stores the result in %obj.%name.

Syntax: srp %res, %propobj, %src

Shifts %propobj logically (bitwise) right by the number of bits given by %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - add, addpd, addpi, addp
(add)

Syntax: add %dest, %src

Adds %src to %dest and stores the result in %dest.

Syntax: addpd %res, %obj.*name, %src

Adds %src to %obj.name and stores the result in %obj.name.

Syntax: addpi %res, %obj.%name, %src

Adds %src to %obj.%name and stores the result in %obj.%name.

Syntax: addp %res, %propobj, %src

Adds %src to %propobj and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - sub, subpd, subpi, subp
(subtract)

Syntax: sub %dest, %src

Subtracts %src from %dest and stores the result in %dest.

Syntax: subpd %res, %obj.*name, %src

Subtracts %src from %obj.name and stores the result in %obj.name.

Syntax: subpi %res, %obj.%name, %src

Subtracts %src from %obj.%name and stores the result in %obj.%name.

Syntax: subp %res, %propobj, %src

Subtracts %src from %propobj and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - mod, modpd, modpi, modp
(modulo)

Syntax: mod %dest, %src

Stores in %dest the remainder of dividing %dest by %src.

Syntax: modpd %res, %obj.*name, %src

Stores in %obj.name the remainder of dividing %obj.name by %src.

Syntax: modpi %res, %obj.%name, %src

Stores in %obj.%name the remainder of dividing %obj.%name by %src.

Syntax: modp %res, %propobj, %src

Stores in %propobj the remainder of dividing %propobj by %src.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - div, divpd, divpi, divp
(real divide)

Syntax: div %dest, %src

Divides %dest by %src (real division) and stores the result in %dest.

Syntax: divpd %res, %obj.*name, %src

Divides %obj.name by %src (real division) and stores the result in %obj.name.

Syntax: divpi %res, %obj.%name, %src

Divides %obj.%name by %src (real division) and stores the result in %obj.%name.

Syntax: divp %res, %propobj, %src

Divides %propobj by %src (real division) and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - idiv, idivpd, idivpi, idivp
(integer divide)

Syntax: idiv %dest, %src

Divides %dest by %src (integer division) and stores the result in %dest.

Syntax: idivpd %res, %obj.*name, %src

Divides %obj.name by %src (integer division) and stores the result in %obj.name.

Syntax: idivpi %res, %obj.%name, %src

Divides %obj.%name by %src (integer division) and stores the result in %obj.%name.

Syntax: divp %res, %propobj, %src

Divides %propobj by %src (integer division) and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - mul, mulpd, mulpi, mulp
(multiply)

Syntax: mul %dest, %src

Multiplies %dest by %src and stores the result in %dest.

Syntax: mulpd %res, %obj.*name, %src

Multiplies %obj.name by %src and stores the result in %obj.name.

Syntax: mulpi %res, %obj.%name, %src

Multiplies %obj.%name by %src and stores the result in %obj.%name.

Syntax: mulp %res, %propobj, %src

Multiplies %propobj by %src and stores the result in %propobj.

Of the instructions above, those that take %res also store the result in %res if res is not 0. - bnot
(bitwise not)

Syntax: bnot %reg

Inverts each bit of %reg and stores the result back in %reg. - asc
(ascii code)

Syntax: asc %reg

Stores in %reg the character code of the first character of the string in %reg (the # operator). - chr
(make character)

Syntax: chr %reg

Creates the single character corresponding to the number in %reg and stores it back in %reg (the $ operator). - num
(number)

Syntax: num %reg

Converts register %reg to a number. - chs
(change sign)

Syntax: chs %reg

Negates the number in register %reg. - inv
(invalidate)

Syntax: inv %reg

Invalidates the object in %reg. - chkinv
(invalidate)

Syntax: chkinv %reg

Sets %reg to true if the object in %reg has not been invalidated, and to false otherwise. - int
(convert to integer)

Syntax: int %reg

Converts register %reg to an integer. - real
(convert to real)

Syntax: real %reg

Converts register %reg to a real number. - string
(convert to string)

Syntax: string %reg

Converts register %reg to a string. - octet
(convert to octet)

Syntax: octet %reg

Converts register %reg to an octet string. - typeof, typeofd, typeofi
(check type)

Syntax: typeof %reg

Syntax: typeofd %obj.*name

Syntax: typeofi %obj.%name

Determines the type of %reg, %obj.name, or %obj.%name, and stores a string representing that type back in %reg, %obj.name, or %obj.%name. - eval
(evaluate expression)

Syntax: eval %reg

Evaluates the string in %reg as an expression and stores the result back in %reg. - eexp
(execute expression)

Syntax: eexp %reg

Evaluates the string in %reg as an expression and discards the result. - chkins
(check instance)

Syntax: chkins %reg, %classname

Stores true in %reg if the object in %reg is an instance of the class whose name is given by %classname, and false otherwise. - call, calld, calli
(function call)

Syntax: call %dest, %func(%arg1, %arg2, %arg3, ...)

Syntax: calld %dest, %obj.*name(%arg1, %arg2, %arg3, ...)

Syntax: calli %dest, %obj.%name(%arg1, %arg2, %arg3, ...)

Calls the function object given by %func, %obj.*name, or %obj.%name with the arguments %arg1, %arg2, %arg3, ..., and stores the result in %dest. If %dest is %0, the result is discarded (not stored in %0). - new
(create new)

Syntax: new %dest, %func(%arg1, %arg2, %arg3, ...)

Constructs an instance of the class object given by %func with the arguments %arg1, %arg2, %arg3, ..., and stores the result in %dest. - gpd, gpds
(get property direct)

Syntax: gpd %dest, %obj.*name

Syntax: gpds %dest, %obj.*name

Looks up the member named by *name in the object given by %obj and copies its value to %dest.

gpd invokes the property handler; gpds does not, and gets the property object itself. - gpi, gpis
(get property indirect)

Syntax: gpi %dest, %obj.%name

Syntax: gpis %dest, %obj.%name

Looks up the member named by %name in the object given by %obj and copies its value to %dest.

gpi invokes the property handler; gpis does not, and gets the property object itself. - spd, spde, spdeh, spds
(set property direct)

Syntax: spd %obj.*name

Syntax: spde %obj.*name

Syntax: spdeh %obj.*name

Syntax: spds %obj.*name

Assigns the value of %src to the member named by *name in the object given by %obj.

spd performs an ordinary access; an exception is thrown if the member does not exist.

spde creates the member if it does not exist.

spdeh sets the member as a hidden member. This has no effect in the current version.

spds does not invoke the property handler and replaces the property object itself. - spi, spie, spis
(set property indirect)

Syntax: spi %obj.%name

Syntax: spie %obj.%name

Syntax: spis %obj.%name

Assigns the value of %src to the member named by %name in the object given by %obj.

spi performs an ordinary access; an exception is thrown if the member does not exist.

spie creates the member if it does not exist.

spis does not invoke the property handler and replaces the property object itself. - getp
Syntax: getp %reg, %propobj

Invokes the getter of the property object given by %propobj and assigns the property's value to %reg. This is the behavior of the unary '*' operator. - setp
Syntax: setp %propobj, %reg

Invokes the setter of the property object given by %propobj to set the value of %reg. This is the behavior of the unary '*' operator. - deld, deli
(delete member)

Syntax: deld %reg, %obj.*name

Syntax: deli %reg, %obj.%name

Deletes the member named by *name or %name from the object given by %obj.

Stores in %reg whether the deletion succeeded; if %reg is %0, the result is discarded. - srv
(set result value)

Syntax: srv %reg

Sets the value of %reg as the function's return value (the function returns the value in %reg). - ret
(return)

Syntax: ret

Returns to the caller. - entry
(enter try block)

Syntax: entry ip, %reg

Enters an exception-protected block. If an exception occurs, jumps to ip and sets the exception object in %reg. - extry
(exit from try block)

Syntax: extry

Leaves an exception-protected block. - throw
(throw exception object)

Syntax: throw %reg

Throws the object in %reg as an exception object. - chgthis
(change this)

Syntax: chgthis %dest, %src

Changes the closure part (context) of the object in %dest to the object given by %src. - global
(get global object)

Syntax: global %dest

Stores the global object in %dest. - addci
(add class instance information)

Syntax: addci %dest, %info

Adds %info to the class instance information of the object in %dest. - regmember
(register members)

Syntax: regmember

Registers the class members in the "this" object. Used internally. - debugger
(call debugger)

Syntax: debugger

Breaks execution and invokes the debugger. In the current implementation, this invokes the native debugger rather than a TJS2 debugger.