[439] | 1 | # The new bytecode
|
---|
| 2 |
|
---|
| 3 | We will reimplement VM to use 8bit instruction code. By
|
---|
| 4 | bytecode, we mean real byte code. The whole purpose is
|
---|
| 5 | reducing the memory consumption of mruby VM.
|
---|
| 6 |
|
---|
| 7 | # Instructions
|
---|
| 8 |
|
---|
| 9 | Instructions are bytes. There can be 256 instructions. Currently we
|
---|
| 10 | have 94 instructions. Instructions can take 0 to 3 operands.
|
---|
| 11 |
|
---|
| 12 | ## operands
|
---|
| 13 |
|
---|
| 14 | The size of operands can be either 8bits, 16bits or 24bits.
|
---|
| 15 | In the table.1 below, the second field describes the size (and
|
---|
| 16 | sign) of operands.
|
---|
| 17 |
|
---|
| 18 | * B: 8bit
|
---|
| 19 | * sB: signed 8bit
|
---|
| 20 | * S: 16bit
|
---|
| 21 | * sS: signed 16bit
|
---|
| 22 | * W: 24bit
|
---|
| 23 |
|
---|
| 24 | First two byte operands may be extended to 16bit. When those byte
|
---|
| 25 | operands are bigger than 256, the instruction will be prefixed by
|
---|
| 26 | `OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
|
---|
| 27 | is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
|
---|
| 28 |
|
---|
| 29 | For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
|
---|
| 30 | with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
---|
| 31 |
|
---|
| 32 | ## table.1 Instruction Table
|
---|
| 33 |
|
---|
| 34 | | Instruction Name | Operand type | Semantics |
|
---|
| 35 | |:-----------------|--------------|---------------------|
|
---|
| 36 | | OP_NOP | - | |
|
---|
| 37 | | OP_MOVE" | BB | R(a) = R(b)
|
---|
| 38 | | OP_LOADL" | BB | R(a) = Pool(b)
|
---|
| 39 | | OP_LOADI" | BsB | R(a) = mrb_int(b)
|
---|
| 40 | | OP_LOADI_0' | B | R(a) = 0
|
---|
| 41 | | OP_LOADI_1' | B | R(a) = 1
|
---|
| 42 | | OP_LOADI_2' | B | R(a) = 2
|
---|
| 43 | | OP_LOADI_3' | B | R(a) = 3
|
---|
| 44 | | OP_LOADSYM" | BB | R(a) = Syms(b)
|
---|
| 45 | | OP_LOADNIL' | B | R(a) = nil
|
---|
| 46 | | OP_LOADSELF' | B | R(a) = self
|
---|
| 47 | | OP_LOADT' | B | R(a) = true
|
---|
| 48 | | OP_LOADF' | B | R(a) = false
|
---|
| 49 | | OP_GETGV" | BB | R(a) = getglobal(Syms(b))
|
---|
| 50 | | OP_SETGV" | BB | setglobal(Syms(b), R(a))
|
---|
| 51 | | OP_GETSV" | BB | R(a) = Special[b]
|
---|
| 52 | | OP_SETSV" | BB | Special[b] = R(a)
|
---|
| 53 | | OP_GETIV" | BB | R(a) = ivget(Syms(b))
|
---|
| 54 | | OP_SETIV" | BB | ivset(Syms(b),R(a))
|
---|
| 55 | | OP_GETCV" | BB | R(a) = cvget(Syms(b))
|
---|
| 56 | | OP_SETCV" | BB | cvset(Syms(b),R(a))
|
---|
| 57 | | OP_GETCONST" | BB | R(a) = constget(Syms(b))
|
---|
| 58 | | OP_SETCONST" | BB | constset(Syms(b),R(a))
|
---|
| 59 | | OP_GETMCNST" | BB | R(a) = R(a)::Syms(b)
|
---|
| 60 | | OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a)
|
---|
| 61 | | OP_GETUPVAR' | BBB | R(a) = uvget(b,c)
|
---|
| 62 | | OP_SETUPVAR' | BBB | uvset(b,c,R(a))
|
---|
| 63 | | OP_JMP | S | pc+=a
|
---|
| 64 | | OP_JMPIF' | SB | if R(b) pc+=a
|
---|
| 65 | | OP_JMPNOT' | SB | if !R(b) pc+=a
|
---|
| 66 | | OP_ONERR | sS | rescue_push(pc+a)
|
---|
| 67 | | OP_EXCEPT' | B | R(a) = exc
|
---|
| 68 | | OP_RESCUE" | BB | R(b) = R(a).isa?(R(b))
|
---|
| 69 | | OP_POPERR | B | a.times{rescue_pop()}
|
---|
| 70 | | OP_RAISE' | B | raise(R(a))
|
---|
| 71 | | OP_EPUSH' | B | ensure_push(SEQ[a])
|
---|
| 72 | | OP_EPOP | B | A.times{ensure_pop().call}
|
---|
| 73 | | OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1))
|
---|
| 74 | | OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
---|
| 75 | | OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
---|
| 76 | | OP_SENDB" | BBB | R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
---|
| 77 | | OP_CALL' | B | R(a) = self.call(frame.argc, frame.argv)
|
---|
| 78 | | OP_SUPER' | BB | R(a) = super(R(a+1),... ,R(a+b+1))
|
---|
| 79 | | OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4)
|
---|
| 80 | | OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1)
|
---|
| 81 | | OP_KARG" | BB | R(a) = kdict[Syms(Bx)] # todo
|
---|
| 82 | | OP_KARG2" | BB | R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
---|
| 83 | | OP_RETURN' | B | return R(a) (normal)
|
---|
| 84 | | OP_RETURN_BLK' | B | return R(a) (in-block return)
|
---|
| 85 | | OP_BREAK' | B | break R(a)
|
---|
| 86 | | OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4)
|
---|
| 87 | | OP_ADD" | BB | R(a) = R(a)+R(a+1)
|
---|
| 88 | | OP_ADDI" | BBB | R(a) = R(a)+mrb_int(c)
|
---|
| 89 | | OP_SUB" | BB | R(a) = R(a)-R(a+1)
|
---|
| 90 | | OP_SUBI" | BB | R(a) = R(a)-C
|
---|
| 91 | | OP_MUL" | BB | R(a) = R(a)*R(a+1)
|
---|
| 92 | | OP_DIV" | BB | R(a) = R(a)/R(a+1)
|
---|
| 93 | | OP_EQ" | BB | R(a) = R(a)==R(a+1)
|
---|
| 94 | | OP_LT" | BB | R(a) = R(a)<R(a+1)
|
---|
| 95 | | OP_LE" | BB | R(a) = R(a)<=R(a+1)
|
---|
| 96 | | OP_GT" | BB | R(a) = R(a)>R(a+1)
|
---|
| 97 | | OP_GE" | BB | R(a) = R(a)>=R(a+1)
|
---|
| 98 | | OP_ARRAY' | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
---|
| 99 | | OP_ARRAY2" | BB | R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
---|
| 100 | | OP_ARYCAT' | B | ary_cat(R(a),R(a+1))
|
---|
| 101 | | OP_ARYPUSH' | B | ary_push(R(a),R(a+1))
|
---|
| 102 | | OP_AREF' | BB | R(a) = R(a)[b]
|
---|
| 103 | | OP_ASET' | BB | R(a)[b] = R(a+1)
|
---|
| 104 | | OP_APOST' | BB | *R(a),R(A+1)..R(A+C) = R(a)[B..]
|
---|
| 105 | | OP_STRING" | BB | R(a) = str_dup(Lit(b))
|
---|
| 106 | | OP_STRCAT' | B | str_cat(R(a),R(a+1))
|
---|
| 107 | | OP_HASH' | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
---|
| 108 | | OP_HASHADD' | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
---|
| 109 | | OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
---|
| 110 | | OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
---|
| 111 | | OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD)
|
---|
| 112 | | OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE)
|
---|
| 113 | | OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE)
|
---|
| 114 | | OP_OCLASS' | B | R(a) = ::Object
|
---|
| 115 | | OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1))
|
---|
| 116 | | OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b))
|
---|
| 117 | | OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b])
|
---|
| 118 | | OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1))
|
---|
| 119 | | OP_ALIAS' | B | alias_method(R(a),R(a+1),R(a+2))
|
---|
| 120 | | OP_UNDEF" | BB | undef_method(R(a),Syms(b))
|
---|
| 121 | | OP_SCLASS' | B | R(a) = R(a).singleton_class
|
---|
| 122 | | OP_TCLASS' | B | R(a) = target_class
|
---|
| 123 | | OP_ERR' | B | raise(RuntimeError, Lit(Bx))
|
---|
| 124 | | OP_EXT1 | - | make 1st operand 16bit
|
---|
| 125 | | OP_EXT2 | - | make 2nd operand 16bit
|
---|
| 126 | | OP_EXT3 | - | make 1st and 2nd operands 16bit
|
---|
| 127 | | OP_STOP | - | stop VM
|
---|