Operations
Here are virtual machine instructions described on assembler (phantasm) language level. (Phantasm is not used anymore for system development, but is good to describe bytecode structure.)
Strange stuff
| nop |
No operation. This operation does completely nothing.
debug
debug; // just print stacks |
Prints string argument (if any), and top values of integer and object stack. Integer argument (mode) is one byte and upper bit is used internally, so don’t pass anything > 0x7F or < 0 – will be stripped.
Bit 0 (& 0x01) of mode byte turns on debug instruction printing.
Bit 1 (& 0x02) turns it off.
Flow control
jmp
jmp label;label: |
Unconditional jump.
djnz
const 10;loop: // do something 10 times |
Decrement top of int stack. If top of int stack is not zero — jump to label.
NB! This operation does not pop integer stack!
|
jz repeat: // calculate while conditiondone: |
While-style loop operator. Jump if top of int stack is zero.
NB! This operation does pop integer stack!
switch shift divisor label…// calculate expression on int stackcase1: // if expression was 0 we’ll come herecase2: // if expression was 1 we’ll come herecase3: // if expression was 2 we’ll come here out: |
Top of int stack (popped) is diminished by shift (signed), divided by divisor (unsigned) and is used as offset into the jump address table. If result is out of bounds, operator falls through, else jumps to selected address.
ret
ret; |
Top of object stack is popped and pushed on caller’s stack. If stack is empty null object is pushed to caller. All the exception catchers pushed in this call are discarded.
call methodIndex numberOfArgs
call 0 2; |
Pops numberOfArgs arguments from object stack, than pops object to call method for. Calls selected method passing given number of args. Top of integer stack of called method will have number of arguments passed. After the return exactly one object (possibly null) will be on the object stack.
sys syscall_number
sys 0; |
Executes this (and only this!) object’s embedded method. NB – it is not possible to execute sys for other object than this because it will render its specialness visible from outside.
This operation is valid for a very limited number of classes.
Nothing can be guaranteed about sys. As for now all of them return something, but it is not enforced by interpreter. Though, for normal operation sys must return some object.
It is possible to pass parameters to sys on int stack and receive some return there as well, which is differs from call, which passes data on object stack only. That is so because sys does not create a call frame and thus all the current stack data is available to its code.
Generally, sys is used as the only content of internal class methods.
Stack manipulations
|
os dup is dup os dup; // now we have one more whatever it was |
Duplicate stack top – either object or int.
|
os drop is drop call 0 0; |
Delete stack top.
os pull displacement
os pull 2; |
Copy object displacement steps down from top of object stack on top of it. Pull 0 is equal to dup. NB! Deprecated!
load slot_num
load 3; |
Load object reference from this object slot (field), push to top of stack.
save slot_num
save 3; |
Pop object reference, store to selected slot (field) of this object.
get absolute_stack_position
get 0; |
Load object from given position of object stack, push to top of stack.
set absolute_stack_position
set 0; |
Pop object, store to selected position of object stack. These two are for local variables access.
compose n_objects
// code object on stack |
Top of stack is class object, initializers follow. New object of that class will be constructed, new object slots will be filled with n_objects objects from stack.
NB!! This operation must be available to objects of classes that permit it explicitly. Corresponding checks must be added.
NB!! It is better to kill it at all.
decompose
decompose; |
Will store on stack all of the fields of top stack object. Number of objects will be pushed to integer stack.
NB!! This operation must be available to objects of classes that permit it explicitly. Corresponding checks must be added.
NB!! It is better to kill it at all.
new
new; |
Create a new object of given (stack top) class. It does not call any constructor.
copy
copy; |
Create a copy of top stack object. Same class, same slot values.
os eq
os eq; |
Pop and compare two objects on object stack. If they are the same, push non-zero on integer stack, else push zero.
os neq
os neq; |
Pop and compare two objects on object stack. If they are the same, push zero on integer stack, else push non-zero.
os isnull
os isnull; |
Pop object. If it is a null, push non-zero on integer stack, else push zero.
Exceptions
push catcher labelsummon “internal.class.string”;string_thrown: // on exception of string type we’ll get here |
Top of stack contains class object. Exceptions of that class will be catched here and control will be passed to a label if such exception is thrown. Thrown object will be on stack top in this case. In general no other assumptions about stack state can be done.
pop catcher
pop catcher; |
Last pushed catcher will be deleted.
throw
const “we have a problem here”; |
Object on top of stack is thrown down. If stack is empty - will throw special system-wide object (null?), if already on top of call stack - will kill current thread in a bad way.
Constants
const
const “hi there”; |
Push constant on stack top. Special shortcuts for 0 and 1 exist. Strings are Unicode UTF-8. MUST BE PLAIN 2-BYTE UNICODE?
Summoning
summon this
summon this |
Puts this object reference on stack.
summon thread
summon thread |
Puts current thread object reference on stack.
summon null
summon null |
Put null object on stack.
summon class_name
summon “internal.class.class”; |
Push corresponding class object on stack.
NB!! Define implementation! Must go through some thread specific class loader?
Integer stack operations
|
i2o o2i const 10; |
These operations can be used to move data between integer and object stacks.
NB! What exception is thrown if it is not int?
iload slot_num
iload 3; |
(Not implemented!) Load object from this object slot, push to top of integer stack.
isave slot_num
isave 3; |
(Not implemented!) Pop value from integer stack, store to selected slot of this object.
|
isum imul const 10; |
Addition and multiplication.
|
isubul isublu idivul idivlu const 10; |
Integer subtraction and division.
|
ior iand ixor inot |
Bit wise operations on integer stack top.
|
|| && ! |
logical operations on integer stack top.
Not yet described codes
None at the moment.
Stuff to implement
int 64 bit
int variable length
It is possible that all integers and pointers will be 64 bit in phantom in a near future because persistent memory has to be as large as common hard disks are, and gigabytes are not of interest now, we need terabytes to be addressable.
float 32 bit (24+8)
float variable length (for now – up to 80 bit, future ext)



