Back to Mruby

mruby Bytecode

doc/internal/opcode.md

4.0.015.5 KB
Original Source
<!-- summary: About mruby Virtual Machine Instructions -->

mruby Bytecode

mruby uses 8-bit instruction opcodes. Each instruction is a single byte, allowing up to 256 opcodes. Instructions can take 0 to 3 operands.

Operands

The size of operands can be either 8 bits, 16 bits, or 24 bits. In the instruction table below, the operand type field describes the size of each operand.

  • Z: no operand
  • B: 8 bits
  • S: 16 bits
  • W: 24 bits

If the first and second operands are of type B (8 bits), they may be extended to 16 bits by the operand extension instruction immediately preceding them. See also OP_EXT1, OP_EXT2 and OP_EXT3.

Instruction Table

No.Instruction NameOperand typeSemantics
0OP_NOPZno operation
1OP_MOVEBBR[a] = R[b]
2OP_LOADLBBR[a] = Pool[b]
3OP_LOADI8BBR[a] = mrb_int(b)
4OP_LOADINEGBBR[a] = mrb_int(-b)
5OP_LOADI__1BR[a] = mrb_int(-1)
6OP_LOADI_0BR[a] = mrb_int(0)
7OP_LOADI_1BR[a] = mrb_int(1)
8OP_LOADI_2BR[a] = mrb_int(2)
9OP_LOADI_3BR[a] = mrb_int(3)
10OP_LOADI_4BR[a] = mrb_int(4)
11OP_LOADI_5BR[a] = mrb_int(5)
12OP_LOADI_6BR[a] = mrb_int(6)
13OP_LOADI_7BR[a] = mrb_int(7)
14OP_LOADI16BSR[a] = mrb_int(b)
15OP_LOADI32BSSR[a] = mrb_int((b<<16)+c)
16OP_LOADSYMBBR[a] = Syms[b]
17OP_LOADNILBR[a] = nil
18OP_LOADSELFBR[a] = self
19OP_LOADTRUEBR[a] = true
20OP_LOADFALSEBR[a] = false
21OP_GETGVBBR[a] = getglobal(Syms[b])
22OP_SETGVBBsetglobal(Syms[b], R[a])
23OP_GETSVBBR[a] = Special[Syms[b]]
24OP_SETSVBBSpecial[Syms[b]] = R[a]
25OP_GETIVBBR[a] = ivget(Syms[b])
26OP_SETIVBBivset(Syms[b],R[a])
27OP_GETCVBBR[a] = cvget(Syms[b])
28OP_SETCVBBcvset(Syms[b],R[a])
29OP_GETCONSTBBR[a] = constget(Syms[b])
30OP_SETCONSTBBconstset(Syms[b],R[a])
31OP_GETMCNSTBBR[a] = R[a]::Syms[b]
32OP_SETMCNSTBBR[a+1]::Syms[b] = R[a]
33OP_GETUPVARBBBR[a] = uvget(b,c)
34OP_SETUPVARBBBuvset(b,c,R[a])
35OP_GETIDXBR[a] = R[a][R[a+1]]
36OP_GETIDX0BBR[a] = R[b][0]
37OP_SETIDXBR[a][R[a+1]] = R[a+2]
38OP_JMPSpc += a
39OP_JMPIFBSif R[a] pc += b
40OP_JMPNOTBSif !R[a] pc += b
41OP_JMPNILBSif R[a]==nil pc += b
42OP_JMPUWSunwind_and_jump_to(a)
43OP_EXCEPTBR[a] = exc
44OP_RESCUEBBR[b] = R[a].isa?(R[b])
45OP_RAISEIFBraise(R[a]) if R[a]
46OP_MATCHERRBraise NoMatchingPatternError unless R[a]
47OP_SSENDBBB`R[a] = self.send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n\
48OP_SSEND0BBR[a] = self.send(Syms[b]) (no args)
49OP_SSENDBBBBR[a] = self.send(Syms[b],R[a+1]..,&R[a+n+2k+1])
50OP_SENDBBB`R[a] = R[a].send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n\
51OP_SEND0BBR[a] = R[a].send(Syms[b]) (no args)
52OP_SENDBBBBR[a] = R[a].send(Syms[b],R[a+1]..,&R[a+n+2k+1])
53OP_CALLZself.call(*, **, &) (tailcall)
54OP_BLKCALLBBR[a] = R[a].call(R[a+1],...,R[a+b]) (direct block call)
55OP_SUPERBBR[a] = super(R[a+1],...,R[a+b+1])
56OP_ARGARYBSR[a] = argument array (16=m5:r1:m5:d1:lv4)
57OP_ENTERWarg setup according to flags (24=n1:m5:o5:r1:m5:k5:d1:b1)
58OP_KEY_PBBR[a] = kdict.key?(Syms[b])
59OP_KEYENDZraise unless kdict.empty?
60OP_KARGBBR[a] = kdict[Syms[b]]; kdict.delete(Syms[b])
61OP_RETURNBreturn R[a] (normal)
62OP_RETURN_BLKBreturn R[a] (in-block return)
63OP_RETSELFZreturn self
64OP_RETNILZreturn nil
65OP_RETTRUEZreturn true
66OP_RETFALSEZreturn false
67OP_BREAKBbreak R[a]
68OP_BLKPUSHBSR[a] = block (16=m5:r1:m5:d1:lv4)
69OP_ADDBR[a] = R[a] + R[a+1]
70OP_ADDIBBR[a] = R[a] + mrb_int(b)
71OP_SUBBR[a] = R[a] - R[a+1]
72OP_SUBIBBR[a] = R[a] - mrb_int(b)
73OP_ADDILVBBBR[a] = R[a] + mrb_int(c) (with local variable fallback)
74OP_SUBILVBBBR[a] = R[a] - mrb_int(c) (with local variable fallback)
75OP_MULBR[a] = R[a] * R[a+1]
76OP_DIVBR[a] = R[a] / R[a+1]
77OP_EQBR[a] = R[a] == R[a+1]
78OP_LTBR[a] = R[a] < R[a+1]
79OP_LEBR[a] = R[a] <= R[a+1]
80OP_GTBR[a] = R[a] > R[a+1]
81OP_GEBR[a] = R[a] >= R[a+1]
82OP_ARRAYBBR[a] = ary_new(R[a],R[a+1]..R[a+b])
83OP_ARRAY2BBBR[a] = ary_new(R[b],R[b+1]..R[b+c])
84OP_ARYCATBary_cat(R[a],R[a+1])
85OP_ARYPUSHBBary_push(R[a],R[a+1]..R[a+b])
86OP_ARYSPLATBR[a] = ary_splat(R[a])
87OP_AREFBBBR[a] = R[b][c]
88OP_ASETBBBR[b][c] = R[a]
89OP_APOSTBBB*R[a],R[a+1]..R[a+c] = R[a][b..]
90OP_INTERNBR[a] = intern(R[a])
91OP_SYMBOLBBR[a] = intern(Pool[b])
92OP_STRINGBBR[a] = str_dup(Pool[b])
93OP_STRCATBstr_cat(R[a],R[a+1])
94OP_HASHBBR[a] = hash_new(R[a],R[a+1]..R[a+b*2-1])
95OP_HASHADDBBhash_push(R[a],R[a+1]..R[a+b*2])
96OP_HASHCATBR[a] = hash_cat(R[a],R[a+1])
97OP_LAMBDABBR[a] = lambda(Irep[b],L_LAMBDA)
98OP_BLOCKBBR[a] = lambda(Irep[b],L_BLOCK)
99OP_METHODBBR[a] = lambda(Irep[b],L_METHOD)
100OP_RANGE_INCBR[a] = range_new(R[a],R[a+1],FALSE)
101OP_RANGE_EXCBR[a] = range_new(R[a],R[a+1],TRUE)
102OP_OCLASSBR[a] = ::Object
103OP_CLASSBBR[a] = newclass(R[a],Syms[b],R[a+1])
104OP_MODULEBBR[a] = newmodule(R[a],Syms[b])
105OP_EXECBBR[a] = blockexec(R[a],Irep[b])
106OP_DEFBBR[a].newmethod(Syms[b],R[a+1]); R[a] = Syms[b]
107OP_TDEFBBBtarget_class.newmethod(Syms[b],Irep[c]); R[a] = Syms[b]
108OP_SDEFBBBR[a].singleton_class.newmethod(Syms[b],Irep[c]); R[a] = Syms[b]
109OP_ALIASBBalias_method(target_class,Syms[a],Syms[b])
110OP_UNDEFBundef_method(target_class,Syms[a])
111OP_SCLASSBR[a] = R[a].singleton_class
112OP_TCLASSBR[a] = target_class
113OP_DEBUGBBBprint a,b,c
114OP_ERRBraise(LocalJumpError, Pool[a])
115OP_EXT1Zmake 1st operand (a) 16 bit
116OP_EXT2Zmake 2nd operand (b) 16 bit
117OP_EXT3Zmake 1st and 2nd operands 16 bit
118OP_STOPZstop VM

Notes

OP_SEND0 / OP_SSEND0

These are optimized versions of OP_SEND / OP_SSEND for zero-argument method calls (no operand c needed).

OP_RETSELF / OP_RETNIL / OP_RETTRUE / OP_RETFALSE

These are optimized return instructions that avoid loading a value into a register before returning. Common patterns like attr_reader methods (return self.@x) and predicate methods (return true/return false) benefit from these specialized opcodes.

OP_BLKCALL

Direct block invocation that bypasses method dispatch. Used when calling a block argument directly (e.g., yield or block.call).

OP_ADDILV / OP_SUBILV

Optimized integer increment/decrement that keeps operands for method call fallback when the receiver is not a Fixnum.

OP_TDEF / OP_SDEF

Optimized method definition. OP_TDEF defines a method on the target_class directly from an irep without creating an intermediate RProc. OP_SDEF does the same for singleton methods.

OP_MATCHERR

Raises NoMatchingPatternError when a pattern match fails. Used by the case/in pattern matching syntax.

OP_GETIDX / OP_GETIDX0 / OP_SETIDX Optimization

These instructions optimize [] and []= access for Array, Hash, and String.

OP_GETIDX uses direct function calls:

  • Array: mrb_ary_entry() (integer index only)
  • Hash: mrb_hash_get()
  • String: mrb_str_aref() (integer/string/range index)

OP_GETIDX0 is a specialized variant for index 0 (e.g., ary[0]).

OP_SETIDX uses direct function calls:

  • Array: mrb_ary_set() (integer index only)
  • Hash: mrb_hash_set()

Fallback to method dispatch occurs when:

  • Object is a subclass (e.g., MyArray < Array)
  • Object has a singleton class (singleton methods defined)
  • Index type is not supported (e.g., non-integer for Array)

This allows subclasses to override []/[]= while base classes remain optimized.