mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
vm.c
Go to the documentation of this file.
1
15
16/***** Feature test switches ************************************************/
17/***** System headers *******************************************************/
18//@cond
19#include "vm_config.h"
20#include <stddef.h>
21#include <string.h>
22#include <assert.h>
23//@endcond
24
25/***** Local headers ********************************************************/
26#include "opcode.h"
27#include "mrubyc.h"
28
29/***** Constat values *******************************************************/
30#define CALL_MAXARGS 15 // 15 is CALL_MAXARGS in mruby
31
32
33/***** Macros ***************************************************************/
34/***** Typedefs *************************************************************/
35/***** Function prototypes **************************************************/
36/***** Local variables ******************************************************/
38static uint16_t free_vm_bitmap[MAX_VM_COUNT / 16 + 1];
39
40
41/***** Global variables *****************************************************/
42/***** Signal catching functions ********************************************/
43/***** Local functions ******************************************************/
44//================================================================
52static void send_by_name( struct VM *vm, mrbc_sym sym_id, int a, int c )
53{
54 int narg = c & 0x0f;
55 int karg = (c >> 4) & 0x0f;
56 int have_block = (c >> 8);
57 mrbc_value *recv = vm->cur_regs + a;
58
59 // If it's packed in an array, expand it.
60 if( narg == CALL_MAXARGS ) {
61 mrbc_value argary = recv[1];
62 int n_move = (karg == CALL_MAXARGS) ? 2 : karg * 2 + 1;
63
64 narg = mrbc_array_size(&argary);
65 for( int i = 0; i < narg; i++ ) {
66 mrbc_incref( &argary.array->data[i] );
67 }
68
69 memmove( recv + narg + 1, recv + 2, sizeof(mrbc_value) * n_move );
70 memcpy( recv + 1, argary.array->data, sizeof(mrbc_value) * narg );
71 mrbc_decref(&argary);
72 }
73
74 mrbc_value *r1 = recv + narg;
75
76 // Convert keyword argument to hash.
77 if( karg && karg != CALL_MAXARGS ) {
78 mrbc_value hval = mrbc_hash_new( vm, karg );
79 if( !hval.hash ) return; // ENOMEM
80
81 memcpy( hval.hash->data, r1+1, sizeof(mrbc_value) * karg * 2 );
82 hval.hash->n_stored = karg * 2;
83
84 r1[1] = hval;
85 r1[2] = r1[karg * 2 + 1]; // Proc
86 memset( r1 + 3, 0, sizeof(mrbc_value) * (karg * 2 - 1) );
87 }
88
89 // is not have block
90 if( !have_block ) {
91 r1 += (!!karg + 1);
92 mrbc_decref( r1 );
93 mrbc_set_nil( r1 );
94 }
95
96 // find a method
98 mrbc_method method;
99 if( mrbc_find_method( &method, cls, sym_id ) != 0 ) goto CALL_METHOD;
100
101 // method missing?
102 if( mrbc_find_method( &method, cls, MRBC_SYM(method_missing) ) == 0 ) {
103 mrbc_raisef(vm, MRBC_CLASS(NoMethodError),
104 "undefined local variable or method '%s' for %s",
106 if( vm->callinfo_tail != 0 ) {
108 }
109 return;
110 }
111
112 // prepare to call 'method_missing' method.
113 for( int i = narg+1; i != 0; i-- ) { // shift arguments
114 recv[i+1] = recv[i];
115 }
116 recv[1] = mrbc_symbol_value(sym_id);
117 sym_id = MRBC_SYM(method_missing);
118 narg++;
119
120
121 CALL_METHOD:
122 if( !method.c_func ) goto CALL_RUBY_METHOD;
123
124 method.func(vm, recv, narg);
125
126 if( mrbc_israised(vm) && vm->exception.exception->method_id == 0 ) {
127 vm->exception.exception->method_id = sym_id;
128 }
129 if( sym_id == MRBC_SYM(call) ) return;
130 if( sym_id == MRBC_SYM(new) ) return;
131
132 for( int i = 1; i <= narg + !!karg + have_block; i++ ) {
133 mrbc_decref_empty( recv + i );
134 }
135 return;
136
137
138 CALL_RUBY_METHOD:;
139 mrbc_callinfo *callinfo = mrbc_push_callinfo(vm, sym_id, a, narg);
140 callinfo->own_class = method.cls;
141
142 vm->cur_irep = method.irep;
143 vm->inst = vm->cur_irep->inst;
144 vm->cur_regs = recv;
145}
146
147
148//================================================================
151static const mrbc_irep_catch_handler *find_catch_handler_ensure( const struct VM *vm )
152{
153 const mrbc_irep *irep = vm->cur_irep;
154 int cnt = irep->clen;
155 if( cnt == 0 ) return NULL;
156
157 const mrbc_irep_catch_handler *catch_table =
158 (const mrbc_irep_catch_handler *)(irep->inst + irep->ilen);
159 uint32_t inst = vm->inst - irep->inst;
160
161 for( cnt--; cnt >= 0 ; cnt-- ) {
162 const mrbc_irep_catch_handler *handler = catch_table + cnt;
163 // Catch type and range check
164 if( (handler->type == 1) && // 1=CATCH_FILTER_ENSURE
165 (bin_to_uint32(handler->begin) < inst) &&
166 (inst <= bin_to_uint32(handler->end)) ) {
167 return handler;
168 }
169 }
170
171 return NULL;
172}
173
174
175/***** Global functions *****************************************************/
176
177//================================================================
181{
182 memset(free_vm_bitmap, 0, sizeof(free_vm_bitmap));
183}
184
185
186//================================================================
193{
194 uint8_t rb = vm->inst[-2];
195 /* NOTE
196 -2 is not always better value.
197 This value is OP_SEND operator's B register.
198 */
199 return mrbc_irep_symbol_id(vm->cur_irep, rb);
200}
201
202
203//================================================================
209const char *mrbc_get_callee_name( struct VM *vm )
210{
211 uint8_t rb = vm->inst[-2];
212 return mrbc_irep_symbol_cstr(vm->cur_irep, rb);
213}
214
215
216//================================================================
219mrbc_callinfo * mrbc_push_callinfo( struct VM *vm, mrbc_sym method_id, int reg_offset, int n_args )
220{
221 mrbc_callinfo *callinfo = mrbc_alloc(vm, sizeof(mrbc_callinfo));
222 if( !callinfo ) return callinfo;
223
224 callinfo->cur_irep = vm->cur_irep;
225 callinfo->inst = vm->inst;
226 callinfo->cur_regs = vm->cur_regs;
227 callinfo->target_class = vm->target_class;
228
229 callinfo->own_class = 0;
230 callinfo->karg_keep = 0;
231 callinfo->method_id = method_id;
232 callinfo->reg_offset = reg_offset;
233 callinfo->n_args = n_args;
234 callinfo->is_called_super = 0;
235
236 callinfo->prev = vm->callinfo_tail;
237 vm->callinfo_tail = callinfo;
238
239 return callinfo;
240}
241
242
243//================================================================
246void mrbc_pop_callinfo( struct VM *vm )
247{
248 assert( vm->callinfo_tail );
249
250 // clear used register.
251 mrbc_callinfo *callinfo = vm->callinfo_tail;
252 mrbc_value *r0 = vm->cur_regs;
253
254 for( int i = 1; i < vm->cur_irep->nregs; i++ ) {
255 mrbc_decref_empty( r0+i );
256 }
257
258 if( callinfo->karg_keep ) {
259 mrbc_hash_delete( &(mrbc_value){.tt = MRBC_TT_HASH, .hash = callinfo->karg_keep} );
260 }
261
262 // copy callinfo to vm
263 vm->cur_irep = callinfo->cur_irep;
264 vm->inst = callinfo->inst;
265 vm->cur_regs = callinfo->cur_regs;
266 vm->target_class = callinfo->target_class;
267 vm->callinfo_tail = callinfo->prev;
268
269 mrbc_free(vm, callinfo);
270}
271
272
273//================================================================
292mrbc_vm * mrbc_vm_new( int regs_size )
293{
294 unsigned int vm_total_size = sizeof(mrbc_vm) + sizeof(mrbc_value) * regs_size;
295
296 mrbc_vm *vm = mrbc_raw_alloc(vm_total_size);
297 if( !vm ) return NULL;
298
299 memset(vm, 0, vm_total_size); // caution: assume NULL is zero.
300#if defined(MRBC_DEBUG)
301 memcpy(vm->obj_mark_, "VM", 2);
302#endif
303 vm->flag_need_memfree = 1;
304 vm->regs_size = regs_size;
305
306 return vm;
307}
308
309
310//================================================================
316mrbc_vm * mrbc_vm_open( struct VM *vm )
317{
318 if( !vm ) vm = mrbc_vm_new( MAX_REGS_SIZE );
319 if( !vm ) return NULL;
320
321 // allocate vm id.
322 int vm_id;
323 for( vm_id = 0; vm_id < MAX_VM_COUNT; vm_id++ ) {
324 int idx = vm_id >> 4;
325 int bit = 1 << (vm_id & 0x0f);
326 if( (free_vm_bitmap[idx] & bit) == 0 ) {
327 free_vm_bitmap[idx] |= bit; // found
328 break;
329 }
330 }
331
332 if( vm_id == MAX_VM_COUNT ) {
333 if( vm->flag_need_memfree ) mrbc_raw_free(vm);
334 return NULL;
335 }
336
337 vm->vm_id = ++vm_id;
338
339 return vm;
340}
341
342
343//================================================================
348void mrbc_vm_begin( struct VM *vm )
349{
350 vm->cur_irep = vm->top_irep;
351 vm->inst = vm->cur_irep->inst;
352 vm->cur_regs = vm->regs;
353 vm->target_class = MRBC_CLASS(Object);
354 vm->callinfo_tail = NULL;
355 vm->ret_blk = NULL;
357 vm->flag_preemption = 0;
358 vm->flag_stop = 0;
359
360 // set self to reg[0], others nil
361 mrbc_decref( &vm->regs[0] );
362 vm->regs[0] = mrbc_instance_new(vm, MRBC_CLASS(Object), 0);
363 if( vm->regs[0].instance == NULL ) return; // ENOMEM
364 for( int i = 1; i < vm->regs_size; i++ ) {
365 vm->regs[i] = mrbc_nil_value();
366 }
367}
368
369
370//================================================================
375void mrbc_vm_end( struct VM *vm )
376{
377 if( mrbc_israised(vm) ) {
378#if defined(MRBC_ABORT_BY_EXCEPTION)
379 MRBC_ABORT_BY_EXCEPTION(vm);
380#else
383#endif
384 }
385 assert( vm->ret_blk == 0 );
386
387 int n_used = 0;
388 for( int i = 1; i < vm->regs_size; i++ ) {
389 //mrbc_printf("vm->regs[%d].tt = %d\n", i, mrbc_type(vm->regs[i]));
390 if( mrbc_type(vm->regs[i]) != MRBC_TT_NIL ) n_used = i;
391 mrbc_decref_empty(&vm->regs[i]);
392 }
393 (void)n_used; // avoid warning.
394#if defined(MRBC_DEBUG_REGS)
395 mrbc_printf("Finally number of registers used was %d in VM %d.\n",
396 n_used, vm->vm_id );
397#endif
398
399#if defined(MRBC_ALLOC_VMID)
400 mrbc_global_clear_vm_id();
401 mrbc_free_all(vm);
402#endif
403}
404
405
406//================================================================
411void mrbc_vm_close( struct VM *vm )
412{
413 mrbc_decref( &vm->regs[0] );
414
415 // free vm id.
416 if( vm->vm_id != 0 ) {
417 int idx = (vm->vm_id-1) >> 4;
418 int bit = 1 << ((vm->vm_id-1) & 0x0f);
419 free_vm_bitmap[idx] &= ~bit;
420 }
421
422 // free irep and vm
423 if( vm->top_irep ) mrbc_irep_free( vm->top_irep );
424 if( vm->flag_need_memfree ) mrbc_raw_free(vm);
425}
426
427
428/***** opecode functions ****************************************************/
429#if defined(MRBC_SUPPORT_OP_EXT)
430#define EXT , int ext
431#else
432#define EXT
433#endif
434//================================================================
439static inline void op_nop( mrbc_vm *vm, mrbc_value *regs EXT )
440{
441 FETCH_Z();
442}
443
444
445//================================================================
450static inline void op_move( mrbc_vm *vm, mrbc_value *regs EXT )
451{
452 FETCH_BB();
453
454 mrbc_incref(&regs[b]);
455 mrbc_decref(&regs[a]);
456 regs[a] = regs[b];
457}
458
459
460//================================================================
465static inline void op_loadl( mrbc_vm *vm, mrbc_value *regs EXT )
466{
467 FETCH_BB();
468
469 mrbc_decref(&regs[a]);
470 regs[a] = mrbc_irep_pool_value(vm, b);
471}
472
473
474//================================================================
479static inline void op_loadi( mrbc_vm *vm, mrbc_value *regs EXT )
480{
481 FETCH_BB();
482
483 mrbc_decref(&regs[a]);
484 mrbc_set_integer(&regs[a], b);
485}
486
487
488//================================================================
493static inline void op_loadineg( mrbc_vm *vm, mrbc_value *regs EXT )
494{
495 FETCH_BB();
496
497 mrbc_decref(&regs[a]);
498 mrbc_set_integer(&regs[a], -(mrbc_int_t)b);
499}
500
501
502//================================================================
507static inline void op_loadi_n( mrbc_vm *vm, mrbc_value *regs EXT )
508{
509 // get n
510 int opcode = vm->inst[-1];
511 int n = opcode - OP_LOADI_0;
512
513 FETCH_B();
514
515 mrbc_decref(&regs[a]);
516 mrbc_set_integer(&regs[a], n);
517}
518
519
520//================================================================
525static inline void op_loadi16( mrbc_vm *vm, mrbc_value *regs EXT )
526{
527 FETCH_BS();
528
529 mrbc_decref(&regs[a]);
530 int16_t signed_b = (int16_t)b;
531 mrbc_set_integer(&regs[a], signed_b);
532}
533
534
535//================================================================
540static inline void op_loadi32( mrbc_vm *vm, mrbc_value *regs EXT )
541{
542 FETCH_BSS();
543
544 mrbc_decref(&regs[a]);
545 mrbc_set_integer(&regs[a], (((int32_t)b<<16)+(int32_t)c));
546}
547
548
549//================================================================
554static inline void op_loadsym( mrbc_vm *vm, mrbc_value *regs EXT )
555{
556 FETCH_BB();
557
558 mrbc_decref(&regs[a]);
560}
561
562
563//================================================================
568static inline void op_loadnil( mrbc_vm *vm, mrbc_value *regs EXT )
569{
570 FETCH_B();
571
572 mrbc_decref(&regs[a]);
573 mrbc_set_nil(&regs[a]);
574}
575
576
577//================================================================
582static inline void op_loadself( mrbc_vm *vm, mrbc_value *regs EXT )
583{
584 FETCH_B();
585
586 mrbc_decref(&regs[a]);
587 regs[a] = *mrbc_get_self( vm, regs );
588 mrbc_incref( &regs[a] );
589}
590
591
592//================================================================
597static inline void op_loadt( mrbc_vm *vm, mrbc_value *regs EXT )
598{
599 FETCH_B();
600
601 mrbc_decref(&regs[a]);
602 mrbc_set_true(&regs[a]);
603}
604
605
606//================================================================
611static inline void op_loadf( mrbc_vm *vm, mrbc_value *regs EXT )
612{
613 FETCH_B();
614
615 mrbc_decref(&regs[a]);
616 mrbc_set_false(&regs[a]);
617}
618
619
620//================================================================
625static inline void op_getgv( mrbc_vm *vm, mrbc_value *regs EXT )
626{
627 FETCH_BB();
628
629 mrbc_decref(&regs[a]);
631 if( v == NULL ) {
632 mrbc_set_nil(&regs[a]);
633 } else {
634 mrbc_incref(v);
635 regs[a] = *v;
636 }
637}
638
639
640//================================================================
645static inline void op_setgv( mrbc_vm *vm, mrbc_value *regs EXT )
646{
647 FETCH_BB();
648
649 mrbc_incref(&regs[a]);
650 mrbc_set_global( mrbc_irep_symbol_id(vm->cur_irep, b), &regs[a] );
651}
652
653
654//================================================================
659static inline void op_getiv( mrbc_vm *vm, mrbc_value *regs EXT )
660{
661 FETCH_BB();
662
663 const char *sym_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
664 mrbc_sym sym_id = mrbc_str_to_symid(sym_name+1); // skip '@'
665 if( sym_id < 0 ) {
666 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
667 return;
668 }
669 mrbc_value *self = mrbc_get_self( vm, regs );
670 if( self->tt != MRBC_TT_OBJECT ) {
671 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), 0);
672 return;
673 }
674
675 mrbc_decref(&regs[a]);
676 regs[a] = mrbc_instance_getiv(self, sym_id);
677}
678
679
680//================================================================
685static inline void op_setiv( mrbc_vm *vm, mrbc_value *regs EXT )
686{
687 FETCH_BB();
688
689 const char *sym_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
690 mrbc_sym sym_id = mrbc_str_to_symid(sym_name+1); // skip '@'
691 if( sym_id < 0 ) {
692 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
693 return;
694 }
695 mrbc_value *self = mrbc_get_self( vm, regs );
696 if( self->tt != MRBC_TT_OBJECT ) {
697 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), 0);
698 return;
699 }
700
701 mrbc_instance_setiv(self, sym_id, &regs[a]);
702}
703
704
705//================================================================
710static inline void op_getconst( mrbc_vm *vm, mrbc_value *regs EXT )
711{
712 FETCH_BB();
713
714 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
715 mrbc_class *crit_cls;
716 mrbc_value *ret;
717
718 if( vm->callinfo_tail && vm->callinfo_tail->own_class ) {
719 crit_cls = vm->callinfo_tail->own_class;
720 } else {
721 crit_cls = find_class_by_object( mrbc_get_self(vm, regs) );
722 }
723
724 // search in my class, then search nested outer class.
725 mrbc_class *cls = crit_cls;
726 while( 1 ) {
727 ret = mrbc_get_class_const(cls, sym_id);
728 if( ret ) goto DONE;
729 if( !mrbc_is_nested_symid(cls->sym_id) ) break;
730
731 mrbc_sym outer_id;
732 mrbc_separate_nested_symid( cls->sym_id, &outer_id, 0 );
733 cls = mrbc_get_const( outer_id )->cls;
734 }
735
736 // search in super class.
737 cls = crit_cls->super;
738 while( cls ) {
739 ret = mrbc_get_class_const(cls, sym_id);
740 if( ret ) goto DONE;
741 cls = cls->super;
742 }
743
744 // is top level constant definition?
745 ret = mrbc_get_const(sym_id);
746 if( ret == NULL ) {
747 mrbc_raisef( vm, MRBC_CLASS(NameError),
748 "uninitialized constant %s", mrbc_symid_to_str(sym_id));
749 return;
750 }
751
752 DONE:
753 mrbc_incref(ret);
754 mrbc_decref(&regs[a]);
755 regs[a] = *ret;
756}
757
758
759//================================================================
764static inline void op_setconst( mrbc_vm *vm, mrbc_value *regs EXT )
765{
766 FETCH_BB();
767
768 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
769
770 mrbc_incref(&regs[a]);
771 if( regs[0].tt == MRBC_TT_CLASS || regs[0].tt == MRBC_TT_MODULE ) {
772 mrbc_set_class_const(regs[0].cls, sym_id, &regs[a]);
773 } else {
774 mrbc_set_const(sym_id, &regs[a]);
775 }
776}
777
778
779//================================================================
784static inline void op_getmcnst( mrbc_vm *vm, mrbc_value *regs EXT )
785{
786 FETCH_BB();
787
788 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
789 mrbc_class *cls = regs[a].cls;
790 mrbc_value *ret;
791
792 // ::CONST case
793 if( cls->sym_id == MRBC_SYM(Object) ) {
794 ret = mrbc_get_const(sym_id);
795 if( ret == NULL ) {
796 mrbc_raisef( vm, MRBC_CLASS(NameError), "uninitialized constant %s::%s",
797 "", mrbc_symid_to_str( sym_id ));
798 return;
799 }
800 goto DONE;
801 }
802
803 while( !(ret = mrbc_get_class_const(cls, sym_id)) ) {
804 cls = cls->super;
805 if( !cls ) {
806 mrbc_raisef( vm, MRBC_CLASS(NameError), "uninitialized constant %s::%s",
807 mrbc_symid_to_str( regs[a].cls->sym_id ), mrbc_symid_to_str( sym_id ));
808 return;
809 }
810 }
811
812 DONE:
813 mrbc_incref(ret);
814 mrbc_decref(&regs[a]);
815 regs[a] = *ret;
816}
817
818
819//================================================================
827static inline void op_getupvar( mrbc_vm *vm, mrbc_value *regs EXT )
828{
829 FETCH_BBB();
830
831 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
832 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
833
834 for( int i = 0; i < c; i++ ) {
835 assert( callinfo );
836 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
837
838 if( mrbc_type(*reg0) != MRBC_TT_PROC ) break; // What to do?
839 callinfo = reg0->proc->callinfo;
840 }
841
842 mrbc_value *p_val;
843 if( callinfo == 0 ) {
844 p_val = vm->regs + b;
845 } else {
846 p_val = callinfo->cur_regs + callinfo->reg_offset + b;
847 }
848 mrbc_incref( p_val );
849
850 mrbc_decref( &regs[a] );
851 regs[a] = *p_val;
852}
853
854
855//================================================================
860static inline void op_setupvar( mrbc_vm *vm, mrbc_value *regs EXT )
861{
862 FETCH_BBB();
863
864 assert( regs[0].tt == MRBC_TT_PROC );
865 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
866
867 for( int i = 0; i < c; i++ ) {
868 assert( callinfo );
869 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
870 assert( reg0->tt == MRBC_TT_PROC );
871 callinfo = reg0->proc->callinfo;
872 }
873
874 mrbc_value *p_val;
875 if( callinfo == 0 ) {
876 p_val = vm->regs + b;
877 } else {
878 p_val = callinfo->cur_regs + callinfo->reg_offset + b;
879 }
880 mrbc_decref( p_val );
881
882 mrbc_incref( &regs[a] );
883 *p_val = regs[a];
884}
885
886
887//================================================================
892static inline void op_getidx( mrbc_vm *vm, mrbc_value *regs EXT )
893{
894 FETCH_B();
895
896 send_by_name( vm, MRBC_SYMID_BL_BR, a, 1 );
897}
898
899
900//================================================================
905static inline void op_setidx( mrbc_vm *vm, mrbc_value *regs EXT )
906{
907 FETCH_B();
908
909 send_by_name( vm, MRBC_SYMID_BL_BR_EQ, a, 2 );
910}
911
912
913//================================================================
918static inline void op_jmp( mrbc_vm *vm, mrbc_value *regs EXT )
919{
920 FETCH_S();
921
922 vm->inst += (int16_t)a;
923}
924
925
926//================================================================
931static inline void op_jmpif( mrbc_vm *vm, mrbc_value *regs EXT )
932{
933 FETCH_BS();
934
935 if( regs[a].tt > MRBC_TT_FALSE ) {
936 vm->inst += (int16_t)b;
937 }
938}
939
940
941//================================================================
946static inline void op_jmpnot( mrbc_vm *vm, mrbc_value *regs EXT )
947{
948 FETCH_BS();
949
950 if( regs[a].tt <= MRBC_TT_FALSE ) {
951 vm->inst += (int16_t)b;
952 }
953}
954
955
956//================================================================
961static inline void op_jmpnil( mrbc_vm *vm, mrbc_value *regs EXT )
962{
963 FETCH_BS();
964
965 if( regs[a].tt == MRBC_TT_NIL ) {
966 vm->inst += (int16_t)b;
967 }
968}
969
970
971//================================================================
976static inline void op_jmpuw( mrbc_vm *vm, mrbc_value *regs EXT )
977{
978 FETCH_S();
979
980 const uint8_t *jump_inst = vm->inst + (int16_t)a;
981
982 // check catch handler (ensure)
984 if( !handler ) {
985 vm->inst = jump_inst;
986 return;
987 }
988
989 // check whether the jump point is inside or outside the catch handler.
990 uint32_t jump_point = jump_inst - vm->cur_irep->inst;
991 if( (bin_to_uint32(handler->begin) < jump_point) &&
992 (jump_point <= bin_to_uint32(handler->end)) ) {
993 vm->inst = jump_inst;
994 return;
995 }
996
997 // jump point is outside, thus jump to ensure.
998 assert( vm->exception.tt == MRBC_TT_NIL );
1000 vm->exception.handle = (void*)jump_inst;
1001 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1002}
1003
1004
1005//================================================================
1010static inline void op_except( mrbc_vm *vm, mrbc_value *regs EXT )
1011{
1012 FETCH_B();
1013
1014 mrbc_decref( &regs[a] );
1015 regs[a] = vm->exception;
1016 mrbc_set_nil( &vm->exception );
1017}
1018
1019
1020//================================================================
1025static inline void op_rescue( mrbc_vm *vm, mrbc_value *regs EXT )
1026{
1027 FETCH_BB();
1028
1029 assert( regs[a].tt == MRBC_TT_EXCEPTION );
1030 assert( regs[b].tt == MRBC_TT_CLASS );
1031
1032 int res = mrbc_obj_is_kind_of( &regs[a], regs[b].cls );
1033 mrbc_set_bool( &regs[b], res );
1034}
1035
1036
1037//================================================================
1042static inline void op_raiseif( mrbc_vm *vm, mrbc_value *regs EXT )
1043{
1044 FETCH_B();
1045
1046 // save the parameter.
1047 mrbc_value ra = regs[a];
1048 regs[a].tt = MRBC_TT_EMPTY;
1049
1050 switch( mrbc_type(ra) ) {
1051 case MRBC_TT_RETURN: goto CASE_OP_RETURN;
1052 case MRBC_TT_RETURN_BLK: goto CASE_OP_RETURN_BLK;
1053 case MRBC_TT_BREAK: goto CASE_OP_BREAK;
1054 case MRBC_TT_JMPUW: goto CASE_OP_JMPUW;
1055 case MRBC_TT_EXCEPTION: goto CASE_OP_EXCEPTION;
1056 default: break;
1057 }
1058
1059 assert( mrbc_type(ra) == MRBC_TT_NIL );
1060 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1061 return;
1062
1063
1064CASE_OP_RETURN:
1065{
1066 // find ensure that still needs to be executed.
1068 if( handler ) {
1069 vm->exception = ra;
1070 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1071 return;
1072 }
1073
1074 // set the return value and return to caller.
1075 mrbc_decref(&regs[0]);
1076 regs[0] = regs[ vm->cur_irep->nregs ];
1077 regs[ vm->cur_irep->nregs ].tt = MRBC_TT_EMPTY;
1078
1080 return;
1081}
1082
1083
1084CASE_OP_RETURN_BLK:
1085{
1086 assert( vm->ret_blk );
1087
1088 // return to the proc generated level.
1089 while( 1 ) {
1090 // find ensure that still needs to be executed.
1092 if( handler ) {
1093 vm->exception = ra;
1094 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1095 return;
1096 }
1097
1098 // Is it the origin (generator) of proc?
1099 if( vm->callinfo_tail == vm->ret_blk->callinfo_self ) break;
1100
1102 }
1103
1104 // top level return ?
1105 if( vm->callinfo_tail == NULL ) {
1106 mrbc_decref(&(mrbc_value){.tt = MRBC_TT_PROC, .proc = vm->ret_blk});
1107 vm->ret_blk = 0;
1108
1109 vm->flag_preemption = 1;
1110 vm->flag_stop = 1;
1111 return;
1112 }
1113
1114 // set the return value and return to caller.
1116 mrbc_decref(reg0);
1117 *reg0 = vm->ret_blk->ret_val;
1118
1119 mrbc_decref(&(mrbc_value){.tt = MRBC_TT_PROC, .proc = vm->ret_blk});
1120 vm->ret_blk = 0;
1121
1123 return;
1124}
1125
1126
1127CASE_OP_BREAK: {
1128 assert( vm->ret_blk );
1129
1130 // return to the proc generated level.
1131 int reg_offset = 0;
1132 while( vm->callinfo_tail != vm->ret_blk->callinfo ) {
1133 // find ensure that still needs to be executed.
1135 if( handler ) {
1136 vm->exception = ra;
1137 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1138 return;
1139 }
1140
1141 reg_offset = vm->callinfo_tail->reg_offset;
1143 }
1144
1145 // set the return value.
1146 mrbc_value *reg0 = vm->cur_regs + reg_offset;
1147 mrbc_decref(reg0);
1148 *reg0 = vm->ret_blk->ret_val;
1149
1150 mrbc_decref(&(mrbc_value){.tt = MRBC_TT_PROC, .proc = vm->ret_blk});
1151 vm->ret_blk = 0;
1152 return;
1153}
1154
1155
1156CASE_OP_JMPUW:
1157{
1158 // find ensure that still needs to be executed.
1160 if( !handler ) {
1161 vm->inst = ra.handle;
1162 return;
1163 }
1164
1165 // check whether the jump point is inside or outside the catch handler.
1166 uint32_t jump_point = (uint8_t *)ra.handle - vm->cur_irep->inst;
1167 if( (bin_to_uint32(handler->begin) < jump_point) &&
1168 (jump_point <= bin_to_uint32(handler->end)) ) {
1169 vm->inst = ra.handle;
1170 return;
1171 }
1172
1173 // jump point is outside, thus jump to ensure.
1174 assert( vm->exception.tt == MRBC_TT_NIL );
1175 vm->exception = ra;
1176 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1177 return;
1178}
1179
1180
1181CASE_OP_EXCEPTION:
1182{
1183 vm->exception = ra;
1184 vm->flag_preemption = 2;
1185 return;
1186}
1187}
1188
1189
1190//================================================================
1195static inline void op_ssend( mrbc_vm *vm, mrbc_value *regs EXT )
1196{
1197 FETCH_BBB();
1198
1199 mrbc_decref( &regs[a] );
1200 regs[a] = *mrbc_get_self( vm, regs );
1201 mrbc_incref( &regs[a] );
1202
1203 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c );
1204}
1205
1206
1207
1208//================================================================
1213static inline void op_ssendb( mrbc_vm *vm, mrbc_value *regs EXT )
1214{
1215 FETCH_BBB();
1216
1217 mrbc_decref( &regs[a] );
1218 regs[a] = *mrbc_get_self( vm, regs );
1219 mrbc_incref( &regs[a] );
1220
1221 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c | 0x100 );
1222}
1223
1224
1225
1226//================================================================
1231static inline void op_send( mrbc_vm *vm, mrbc_value *regs EXT )
1232{
1233 FETCH_BBB();
1234
1235 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c );
1236}
1237
1238
1239//================================================================
1244static inline void op_sendb( mrbc_vm *vm, mrbc_value *regs EXT )
1245{
1246 FETCH_BBB();
1247
1248 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c | 0x100 );
1249}
1250
1251
1252//================================================================
1257static inline void op_super( mrbc_vm *vm, mrbc_value *regs EXT )
1258{
1259 FETCH_BB();
1260
1261 int narg = b & 0x0f;
1262 int karg = (b >> 4) & 0x0f;
1263 mrbc_value *recv = regs + a; // new regs[0]
1264
1265 // set self to new regs[0]
1266 mrbc_value *self = mrbc_get_self(vm, regs);
1267 assert( self->tt != MRBC_TT_PROC );
1268
1269 mrbc_incref( self );
1270 mrbc_decref( recv );
1271 *recv = *self;
1272
1273 // If it's packed in an array, expand it.
1274 if( narg == CALL_MAXARGS ) {
1275 /* (note)
1276 on mrbc ver 3.1
1277 b = 15 in initialize method.
1278 b = 255 in other method.
1279 */
1280
1281 mrbc_value argary = recv[1];
1282 int n_move = (karg == CALL_MAXARGS) ? 2 : karg * 2 + 1;
1283 narg = mrbc_array_size(&argary);
1284 for( int i = 0; i < narg; i++ ) {
1285 mrbc_incref( &argary.array->data[i] );
1286 }
1287
1288 memmove( recv + narg + 1, recv + 2, sizeof(mrbc_value) * n_move );
1289 memcpy( recv + 1, argary.array->data, sizeof(mrbc_value) * narg );
1290 mrbc_decref(&argary);
1291 }
1292
1293 mrbc_value *r1 = recv + narg;
1294
1295 // Convert keyword argument to hash.
1296 if( karg && karg != CALL_MAXARGS ) {
1297 mrbc_value hval = mrbc_hash_new( vm, karg );
1298 if( !hval.hash ) return; // ENOMEM
1299
1300 memcpy( hval.hash->data, r1+1, sizeof(mrbc_value) * karg * 2 );
1301 hval.hash->n_stored = karg * 2;
1302
1303 r1[1] = hval;
1304 r1[2] = r1[karg * 2 + 1]; // Proc
1305 memset( r1 + 3, 0, sizeof(mrbc_value) * (karg * 2 - 1) );
1306 }
1307
1308 // find super class
1309 mrbc_callinfo *callinfo = vm->callinfo_tail;
1310 mrbc_class *cls = callinfo->own_class;
1311 mrbc_method method;
1312
1313 assert( cls );
1314 cls = cls->super;
1315 assert( cls );
1316 if( mrbc_find_method( &method, cls, callinfo->method_id ) == 0 ) {
1317 mrbc_raisef( vm, MRBC_CLASS(NoMethodError),
1318 "no superclass method '%s' for %s",
1319 mrbc_symid_to_str(callinfo->method_id),
1320 mrbc_symid_to_str(callinfo->own_class->sym_id));
1321 return;
1322 }
1323
1324 // call C function and return.
1325 if( method.c_func ) {
1326 method.func(vm, recv, narg - !!karg);
1327 for( int i = 1; i <= narg+1; i++ ) {
1328 mrbc_decref_empty( recv + i );
1329 }
1330 return;
1331 }
1332
1333 // call Ruby method.
1334 callinfo = mrbc_push_callinfo(vm, callinfo->method_id, a, narg);
1335 callinfo->own_class = method.cls;
1336 callinfo->is_called_super = 1;
1337
1338 vm->cur_irep = method.irep;
1339 vm->inst = vm->cur_irep->inst;
1340 vm->cur_regs = recv;
1341}
1342
1343
1344//================================================================
1351static inline void op_argary( mrbc_vm *vm, mrbc_value *regs EXT )
1352{
1353 FETCH_BS();
1354
1355 int m1 = (b >> 11) & 0x3f;
1356 int d = (b >> 4) & 0x01;
1357 int lv = b & 0x0f;
1358
1359 if( b & 0x400 ) { // check REST parameter.
1360 // TODO: want to support.
1361 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "Not support rest parameter by super");
1362 return;
1363 }
1364 if( b & 0x3e0 ) { // check m2 parameter.
1365 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1366 return;
1367 }
1368
1369 mrbc_value *reg0 = regs;
1370 mrbc_callinfo *callinfo = 0;
1371
1372 // rewind proc nest
1373 if( lv ) {
1374 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1375 callinfo = reg0->proc->callinfo;
1376 assert( callinfo );
1377
1378 for( int i = 1; i < lv; i ++ ) {
1379 reg0 = callinfo->cur_regs + callinfo->reg_offset;
1380 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1381 callinfo = reg0->proc->callinfo;
1382 assert( callinfo );
1383 }
1384
1385 reg0 = callinfo->cur_regs + callinfo->reg_offset;
1386 }
1387
1388 // create argument array.
1389 int array_size = m1 + d;
1390 mrbc_value argary = mrbc_array_new( vm, array_size );
1391 if( !argary.array ) return; // ENOMEM
1392
1393 for( int i = 1; i <= m1; i++ ) {
1394 mrbc_incref( &reg0[i] );
1395 mrbc_array_push( &argary, &reg0[i] );
1396 }
1397
1398 if( d ) {
1399 if( !callinfo ) callinfo = vm->callinfo_tail;
1400 assert( callinfo->karg_keep );
1401 mrbc_value karg = (mrbc_value){.tt = MRBC_TT_HASH, .hash = callinfo->karg_keep};
1402 karg = mrbc_hash_dup(vm, &karg);
1403 mrbc_array_push( &argary, &karg );
1404 }
1405
1406 mrbc_decref( &regs[a] );
1407 regs[a] = argary;
1408
1409 // copy a block object
1410 mrbc_decref( &regs[a+1] );
1411 regs[a+1] = reg0[array_size+1];
1412 mrbc_incref( &regs[a+1] );
1413}
1414
1415
1416//================================================================
1423static inline void op_enter( mrbc_vm *vm, mrbc_value *regs EXT )
1424{
1425#define FLAG_REST 0x1000
1426#define FLAG_M2 0x0f80
1427#define FLAG_KW 0x007c
1428#define FLAG_DICT 0x0002
1429#define FLAG_BLOCK 0x0001
1430
1431 FETCH_W();
1432
1433 // Check the number of registers to use.
1434 int reg_use_max = regs - vm->regs + vm->cur_irep->nregs;
1435 if( reg_use_max >= vm->regs_size ) {
1436 mrbc_raise( vm, MRBC_CLASS(Exception), "MAX_REGS_SIZE overflow");
1437 return;
1438 }
1439
1440 // Check m2 parameter.
1441 if( a & FLAG_M2 ) {
1442 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1443 return;
1444 }
1445
1446 int m1 = (a >> 18) & 0x1f; // num of required parameters 1
1447 int o = (a >> 13) & 0x1f; // num of optional parameters
1448 int argc = vm->callinfo_tail->n_args;
1449 int flag_kwarg = regs[argc+1].tt == MRBC_TT_HASH;
1450
1451 argc += flag_kwarg;
1452
1453 if( argc < m1 && regs[0].tt != MRBC_TT_PROC ) {
1454 mrbc_raise( vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1455 return;
1456 }
1457
1458 // save proc (or nil) object.
1459 mrbc_value proc = regs[argc+1];
1460 regs[argc+1].tt = MRBC_TT_EMPTY;
1461
1462 // support yield [...] pattern, to expand array.
1463 if( regs[0].tt == MRBC_TT_PROC && regs[1].tt == MRBC_TT_ARRAY &&
1464 argc == 1 && m1 > 1 ) {
1465 mrbc_value argary = regs[1];
1466 int argary_size = mrbc_array_size(&argary);
1467
1468 argc = argary_size > m1 ? argary_size : m1;
1469
1470 for( int i = argc; i > 0; i-- ) {
1471 if( i != 1 ) mrbc_decref( &regs[i] );
1472 if( argary_size >= i ) {
1473 regs[i] = argary.array->data[i-1];
1474 mrbc_incref(&regs[i]);
1475 } else {
1476 mrbc_set_nil( &regs[i] );
1477 }
1478 }
1479
1480 mrbc_decref(&argary);
1481 }
1482
1483 // dictionary, keyword or rest parameter exists.
1484 if( a & (FLAG_DICT|FLAG_KW|FLAG_REST) ) {
1485 mrbc_value dict;
1486 if( a & (FLAG_DICT|FLAG_KW) ) {
1487 if( (argc - m1) > 0 && regs[argc].tt == MRBC_TT_HASH ) {
1488 dict = regs[argc];
1489 regs[argc--].tt = MRBC_TT_EMPTY;
1490 } else {
1491 dict = mrbc_hash_new( vm, 0 );
1492 }
1493 }
1494
1495 mrbc_value rest;
1496 if( a & FLAG_REST ) {
1497 int rest_size = argc - m1 - o;
1498 if( rest_size < 0 ) rest_size = 0;
1499 rest = mrbc_array_new(vm, rest_size);
1500 if( !rest.array ) return; // ENOMEM
1501
1502 int rest_reg = m1 + o + 1;
1503 for( int i = 0; i < rest_size; i++ ) {
1504 mrbc_array_push( &rest, &regs[rest_reg] );
1505 regs[rest_reg++].tt = MRBC_TT_EMPTY;
1506 }
1507 }
1508
1509 // reorder arguments.
1510 for( int i = argc; i < m1; ) {
1511 mrbc_decref( &regs[++i] );
1512 mrbc_set_nil( &regs[i] );
1513 }
1514 int i = m1 + o;
1515 if( a & FLAG_REST ) {
1516 mrbc_decref(&regs[++i]);
1517 regs[i] = rest;
1518 }
1519 if( a & (FLAG_DICT|FLAG_KW) ) {
1520 mrbc_decref(&regs[++i]);
1521 regs[i] = dict;
1522 vm->callinfo_tail->karg_keep = mrbc_hash_dup(vm, &dict).hash;
1523 }
1524 mrbc_decref(&regs[i+1]);
1525 regs[i+1] = proc;
1526 vm->callinfo_tail->n_args = i;
1527
1528 } else {
1529 // reorder arguments.
1530 for( int i = argc; i < m1; ) {
1531 mrbc_decref( &regs[++i] );
1532 mrbc_set_nil( &regs[i] );
1533 }
1534 int i = m1 + o;
1535 mrbc_decref(&regs[i+1]);
1536 regs[i+1] = proc;
1537 vm->callinfo_tail->n_args = i;
1538 }
1539
1540 // prepare for get default arguments.
1541 int jmp_ofs = argc - m1;
1542 if( jmp_ofs > 0 ) {
1543 if( jmp_ofs > o ) {
1544 jmp_ofs = o;
1545
1546 if( !(a & FLAG_REST) && regs[0].tt != MRBC_TT_PROC ) {
1547 mrbc_raise( vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1548 return;
1549 }
1550 }
1551 vm->inst += jmp_ofs * 3; // 3 = bytecode size of OP_JMP
1552 }
1553
1554#undef FLAG_REST
1555#undef FLAG_M2
1556#undef FLAG_KW
1557#undef FLAG_DICT
1558#undef FLAG_BLOCK
1559}
1560
1561
1562//================================================================
1567static inline void op_key_p( mrbc_vm *vm, mrbc_value *regs EXT )
1568{
1569 FETCH_BB();
1570
1571 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1572 mrbc_sym sym_id = mrbc_irep_symbol_id( vm->cur_irep, b );
1573 mrbc_value *v = mrbc_hash_search_by_id( kdict, sym_id );
1574
1575 mrbc_decref(&regs[a]);
1576 mrbc_set_bool(&regs[a], v);
1577}
1578
1579
1580//================================================================
1585static inline void op_keyend( mrbc_vm *vm, mrbc_value *regs EXT )
1586{
1587 FETCH_Z();
1588
1589 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1590
1591 if( mrbc_hash_size(kdict) != 0 ) {
1593 mrbc_value *kv = mrbc_hash_i_next(&ite);
1594
1595 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "unknown keyword: %s",
1597 }
1598}
1599
1600
1601//================================================================
1606static inline void op_karg( mrbc_vm *vm, mrbc_value *regs EXT )
1607{
1608 FETCH_BB();
1609
1610 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1611 mrbc_sym sym_id = mrbc_irep_symbol_id( vm->cur_irep, b );
1612 mrbc_value v = mrbc_hash_remove_by_id( kdict, sym_id );
1613
1614 if( v.tt == MRBC_TT_EMPTY ) {
1615 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "missing keywords: %s",
1616 mrbc_symid_to_str(sym_id));
1617 return;
1618 }
1619
1620 mrbc_decref(&regs[a]);
1621 regs[a] = v;
1622}
1623
1624
1625//================================================================
1628static inline void op_return__sub( mrbc_vm *vm, mrbc_value *regs, int a )
1629{
1630 // If have a ensure, jump to it.
1631 if( vm->cur_irep->clen ) {
1633 if( handler ) {
1634 assert( vm->exception.tt == MRBC_TT_NIL );
1635
1636 // Save the return value in the last+1 register.
1637 regs[ vm->cur_irep->nregs ] = regs[a];
1638 regs[a].tt = MRBC_TT_EMPTY;
1639
1641 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1642 return;
1643 }
1644 }
1645
1646 // return without anything if top level.
1647 if( vm->callinfo_tail == NULL ) {
1648 if (vm->flag_permanence == 1) {
1649 mrbc_incref(&regs[a]);
1650 } else {
1651 mrbc_decref(&regs[0]);
1652 regs[0] = regs[a];
1653 regs[a].tt = MRBC_TT_EMPTY;
1654 }
1655 vm->flag_preemption = 1;
1656 vm->flag_stop = 1;
1657 return;
1658 }
1659
1660 // not in initialize method, set return value.
1661 if( vm->callinfo_tail->method_id != MRBC_SYM(initialize) ) goto SET_RETURN;
1662
1663 // not called by op_super, ignore return value.
1664 if( !vm->callinfo_tail->is_called_super ) goto RETURN;
1665
1666 // set the return value
1667 SET_RETURN:
1668 mrbc_decref(&regs[0]);
1669 regs[0] = regs[a];
1670 regs[a].tt = MRBC_TT_EMPTY;
1671
1672 RETURN:
1674}
1675
1676
1677//================================================================
1682static inline void op_return( mrbc_vm *vm, mrbc_value *regs EXT )
1683{
1684 FETCH_B();
1685
1686 op_return__sub( vm, regs, a );
1687}
1688
1689
1690//================================================================
1695static inline void op_return_blk( mrbc_vm *vm, mrbc_value *regs EXT )
1696{
1697 FETCH_B();
1698
1699 if( mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1700 op_return__sub( vm, regs, a );
1701 return;
1702 }
1703
1704 // Save the return value in the proc object.
1705 mrbc_incref( &regs[0] );
1706 vm->ret_blk = regs[0].proc;
1707 vm->ret_blk->ret_val = regs[a];
1708 regs[a].tt = MRBC_TT_EMPTY;
1709
1710 // return to the proc generated level.
1711 while( 1 ) {
1712 // If have a ensure, jump to it.
1714 if( handler ) {
1715 assert( vm->exception.tt == MRBC_TT_NIL );
1717 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1718 return;
1719 }
1720
1721 // Is it the origin (generator) of proc?
1722 if( vm->callinfo_tail == vm->ret_blk->callinfo_self ) break;
1723
1725 }
1726
1727 // top level return ?
1728 if( vm->callinfo_tail == NULL ) {
1729 vm->flag_preemption = 1;
1730 vm->flag_stop = 1;
1731 } else {
1732 // set the return value.
1733 mrbc_decref(&vm->cur_regs[0]);
1734 vm->cur_regs[0] = vm->ret_blk->ret_val;
1735
1737 }
1738
1739 mrbc_decref(&(mrbc_value){.tt = MRBC_TT_PROC, .proc = vm->ret_blk});
1740 vm->ret_blk = 0;
1741}
1742
1743
1744//================================================================
1749static inline void op_break( mrbc_vm *vm, mrbc_value *regs EXT )
1750{
1751 FETCH_B();
1752
1753 assert( regs[0].tt == MRBC_TT_PROC );
1754
1755 // Save the return value in the proc object.
1756 mrbc_incref( &regs[0] );
1757 vm->ret_blk = regs[0].proc;
1758 vm->ret_blk->ret_val = regs[a];
1759 regs[a].tt = MRBC_TT_EMPTY;
1760
1761 // return to the proc generated level.
1762 int reg_offset = 0;
1763 while( 1 ) {
1764 // If have a ensure, jump to it.
1766 if( handler ) {
1767 assert( vm->exception.tt == MRBC_TT_NIL );
1769 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1770 return;
1771 }
1772
1773 // Is it the origin (generator) of proc?
1774 if( vm->callinfo_tail == vm->ret_blk->callinfo ) break;
1775
1776 reg_offset = vm->callinfo_tail->reg_offset;
1778 }
1779
1780 // set the return value.
1781 mrbc_value *reg0 = vm->cur_regs + reg_offset;
1782 mrbc_decref(reg0);
1783 *reg0 = vm->ret_blk->ret_val;
1784
1785 mrbc_decref(&(mrbc_value){.tt = MRBC_TT_PROC, .proc = vm->ret_blk});
1786 vm->ret_blk = 0;
1787}
1788
1789
1790//================================================================
1795static inline void op_blkpush( mrbc_vm *vm, mrbc_value *regs EXT )
1796{
1797 FETCH_BS();
1798
1799 int m1 = (b >> 11) & 0x3f;
1800 int r = (b >> 10) & 0x01;
1801 int m2 = (b >> 5) & 0x1f;
1802 int d = (b >> 4) & 0x01;
1803 int lv = (b ) & 0x0f;
1804
1805 if( m2 ) {
1806 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1807 return;
1808 }
1809
1810 int offset = m1 + r + d + 1;
1811 mrbc_value *blk;
1812
1813 if( lv == 0 ) {
1814 // current env
1815 blk = regs + offset;
1816
1817 } else {
1818 // upper env
1819 assert( regs[0].tt == MRBC_TT_PROC );
1820 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
1821
1822 for( int i = 0; i < lv-1; i++ ) {
1823 assert( callinfo );
1824 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
1825 assert( reg0->tt == MRBC_TT_PROC );
1826 callinfo = reg0->proc->callinfo;
1827 }
1828
1829 blk = callinfo->cur_regs + callinfo->reg_offset + offset;
1830 }
1831
1832 if( blk->tt != MRBC_TT_PROC ) {
1833 mrbc_raise( vm, MRBC_CLASS(Exception), "no block given (yield)");
1834 return;
1835 }
1836
1837 mrbc_incref(blk);
1838 mrbc_decref(&regs[a]);
1839 regs[a] = *blk;
1840}
1841
1842
1843//================================================================
1848static inline void op_add( mrbc_vm *vm, mrbc_value *regs EXT )
1849{
1850 FETCH_B();
1851
1852 // in case of Integer + Integer
1853 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_INTEGER ) {
1854 regs[a].i += regs[a+1].i;
1855 return;
1856 }
1857
1858#if MRBC_USE_FLOAT
1859 // in case of Integer + Float
1860 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_FLOAT ) {
1861 mrbc_set_float( &regs[a], regs[a].i + regs[a+1].d );
1862 return;
1863 }
1864
1865 // in case of Float + Integer
1866 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_INTEGER ) {
1867 regs[a].d += regs[a+1].i;
1868 return;
1869 }
1870
1871 // in case of Float + Float
1872 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_FLOAT ) {
1873 regs[a].d += regs[a+1].d;
1874 return;
1875 }
1876#endif
1877
1878 // other case
1879 send_by_name( vm, MRBC_SYM(PLUS), a, 1 );
1880}
1881
1882
1883//================================================================
1888static inline void op_addi( mrbc_vm *vm, mrbc_value *regs EXT )
1889{
1890 FETCH_BB();
1891
1892 if( regs[a].tt == MRBC_TT_INTEGER ) {
1893 regs[a].i += b;
1894 return;
1895 }
1896
1897#if MRBC_USE_FLOAT
1898 if( regs[a].tt == MRBC_TT_FLOAT ) {
1899 regs[a].d += b;
1900 return;
1901 }
1902#endif
1903
1904 mrbc_decref(&regs[a+1]);
1905 regs[a+1] = mrbc_integer_value(b);
1906 send_by_name(vm, MRBC_SYM(PLUS), a, 1);
1907}
1908
1909
1910//================================================================
1915static inline void op_sub( mrbc_vm *vm, mrbc_value *regs EXT )
1916{
1917 FETCH_B();
1918
1919 // in case of Integer - Integer
1920 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_INTEGER ) {
1921 regs[a].i -= regs[a+1].i;
1922 return;
1923 }
1924
1925#if MRBC_USE_FLOAT
1926 // in case of Integer - Float
1927 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_FLOAT ) {
1928 mrbc_set_float( &regs[a], regs[a].i - regs[a+1].d );
1929 return;
1930 }
1931
1932 // in case of Float - Integer
1933 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_INTEGER ) {
1934 regs[a].d -= regs[a+1].i;
1935 return;
1936 }
1937
1938 // in case of Float - Float
1939 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_FLOAT ) {
1940 regs[a].d -= regs[a+1].d;
1941 return;
1942 }
1943#endif
1944
1945 // other case
1946 send_by_name( vm, MRBC_SYM(MINUS), a, 1 );
1947}
1948
1949
1950//================================================================
1955static inline void op_subi( mrbc_vm *vm, mrbc_value *regs EXT )
1956{
1957 FETCH_BB();
1958
1959 if( regs[a].tt == MRBC_TT_INTEGER ) {
1960 regs[a].i -= b;
1961 return;
1962 }
1963
1964#if MRBC_USE_FLOAT
1965 if( regs[a].tt == MRBC_TT_FLOAT ) {
1966 regs[a].d -= b;
1967 return;
1968 }
1969#endif
1970
1971 mrbc_decref(&regs[a+1]);
1972 regs[a+1] = mrbc_integer_value(b);
1973 send_by_name(vm, MRBC_SYM(MINUS), a, 1);
1974}
1975
1976
1977//================================================================
1982static inline void op_mul( mrbc_vm *vm, mrbc_value *regs EXT )
1983{
1984 FETCH_B();
1985
1986 // in case of Integer * Integer
1987 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_INTEGER ) {
1988 regs[a].i *= regs[a+1].i;
1989 return;
1990 }
1991
1992#if MRBC_USE_FLOAT
1993 // in case of Integer * Float
1994 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_FLOAT ) {
1995 mrbc_set_float( &regs[a], regs[a].i * regs[a+1].d );
1996 return;
1997 }
1998
1999 // in case of Float * Integer
2000 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_INTEGER ) {
2001 regs[a].d *= regs[a+1].i;
2002 return;
2003 }
2004
2005 // in case of Float * Float
2006 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_FLOAT ) {
2007 regs[a].d *= regs[a+1].d;
2008 return;
2009 }
2010#endif
2011
2012 // other case
2013 send_by_name( vm, MRBC_SYM(MUL), a, 1 );
2014}
2015
2016
2017//================================================================
2022static inline void op_div( mrbc_vm *vm, mrbc_value *regs EXT )
2023{
2024 FETCH_B();
2025
2026 // in case of Integer / Integer
2027 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_INTEGER ) {
2028 mrbc_int_t v0 = regs[a].i;
2029 mrbc_int_t v1 = regs[a+1].i;
2030
2031 if( v1 == 0 ) {
2032 mrbc_raise(vm, MRBC_CLASS(ZeroDivisionError), 0 );
2033 return;
2034 }
2035
2036 mrbc_int_t ret = v0 / v1;
2037 mrbc_int_t mod = v0 % v1;
2038
2039 if( (mod != 0) && ((v0 ^ v1) < 0) ) ret -= 1;
2040
2041 regs[a].i = ret;
2042 return;
2043 }
2044
2045#if MRBC_USE_FLOAT
2046 // in case of Integer / Float
2047 if( regs[a].tt == MRBC_TT_INTEGER && regs[a+1].tt == MRBC_TT_FLOAT ) {
2048 mrbc_set_float( &regs[a], regs[a].i / regs[a+1].d );
2049 return;
2050 }
2051
2052 // in case of Float / Integer
2053 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_INTEGER ) {
2054 regs[a].d /= regs[a+1].i;
2055 return;
2056 }
2057
2058 // in case of Float / Float
2059 if( regs[a].tt == MRBC_TT_FLOAT && regs[a+1].tt == MRBC_TT_FLOAT ) {
2060 regs[a].d /= regs[a+1].d;
2061 return;
2062 }
2063#endif
2064
2065 // other case
2066 send_by_name( vm, MRBC_SYM(DIV), a, 1 );
2067}
2068
2069
2070//================================================================
2075static inline void op_eq( mrbc_vm *vm, mrbc_value *regs EXT )
2076{
2077 FETCH_B();
2078
2079 if (regs[a].tt == MRBC_TT_OBJECT) {
2080 send_by_name(vm, MRBC_SYM(EQ_EQ), a, 1);
2081 return;
2082 }
2083
2084 int result = mrbc_compare(&regs[a], &regs[a+1]);
2085
2086 mrbc_decref(&regs[a]);
2087 regs[a].tt = result ? MRBC_TT_FALSE : MRBC_TT_TRUE;
2088}
2089
2090
2091//================================================================
2096static inline void op_lt( mrbc_vm *vm, mrbc_value *regs EXT )
2097{
2098 FETCH_B();
2099
2100 if (regs[a].tt == MRBC_TT_OBJECT) {
2101 send_by_name(vm, MRBC_SYM(LT), a, 1);
2102 return;
2103 }
2104
2105 int result = mrbc_compare(&regs[a], &regs[a+1]);
2106
2107 mrbc_decref(&regs[a]);
2108 regs[a].tt = result < 0 ? MRBC_TT_TRUE : MRBC_TT_FALSE;
2109}
2110
2111
2112//================================================================
2117static inline void op_le( mrbc_vm *vm, mrbc_value *regs EXT )
2118{
2119 FETCH_B();
2120
2121 if (regs[a].tt == MRBC_TT_OBJECT) {
2122 send_by_name(vm, MRBC_SYM(LT_EQ), a, 1);
2123 return;
2124 }
2125
2126 int result = mrbc_compare(&regs[a], &regs[a+1]);
2127
2128 mrbc_decref(&regs[a]);
2129 regs[a].tt = result <= 0 ? MRBC_TT_TRUE : MRBC_TT_FALSE;
2130}
2131
2132
2133//================================================================
2138static inline void op_gt( mrbc_vm *vm, mrbc_value *regs EXT )
2139{
2140 FETCH_B();
2141
2142 if (regs[a].tt == MRBC_TT_OBJECT) {
2143 send_by_name(vm, MRBC_SYM(GT), a, 1);
2144 return;
2145 }
2146
2147 int result = mrbc_compare(&regs[a], &regs[a+1]);
2148
2149 mrbc_decref(&regs[a]);
2150 regs[a].tt = result > 0 ? MRBC_TT_TRUE : MRBC_TT_FALSE;
2151}
2152
2153
2154//================================================================
2159static inline void op_ge( mrbc_vm *vm, mrbc_value *regs EXT )
2160{
2161 FETCH_B();
2162
2163 if (regs[a].tt == MRBC_TT_OBJECT) {
2164 send_by_name(vm, MRBC_SYM(GT_EQ), a, 1);
2165 return;
2166 }
2167
2168 int result = mrbc_compare(&regs[a], &regs[a+1]);
2169
2170 mrbc_decref(&regs[a]);
2171 regs[a].tt = result >= 0 ? MRBC_TT_TRUE : MRBC_TT_FALSE;
2172}
2173
2174
2175//================================================================
2180static inline void op_array( mrbc_vm *vm, mrbc_value *regs EXT )
2181{
2182 FETCH_BB();
2183
2184 mrbc_value ret = mrbc_array_new(vm, b);
2185 if( ret.array == NULL ) return; // ENOMEM
2186
2187 memcpy( ret.array->data, &regs[a], sizeof(mrbc_value) * b );
2188 memset( &regs[a], 0, sizeof(mrbc_value) * b );
2189 ret.array->n_stored = b;
2190
2191 mrbc_decref(&regs[a]);
2192 regs[a] = ret;
2193}
2194
2195
2196//================================================================
2201static inline void op_array2( mrbc_vm *vm, mrbc_value *regs EXT )
2202{
2203 FETCH_BBB();
2204
2205 mrbc_value ret = mrbc_array_new(vm, c);
2206 if( ret.array == NULL ) return; // ENOMEM
2207
2208 memcpy( ret.array->data, &regs[b], sizeof(mrbc_value) * c );
2209 memset( &regs[b], 0, sizeof(mrbc_value) * c );
2210 ret.array->n_stored = c;
2211
2212 mrbc_decref(&regs[a]);
2213 regs[a] = ret;
2214}
2215
2216
2217//================================================================
2222static inline void op_arycat( mrbc_vm *vm, mrbc_value *regs EXT )
2223{
2224 FETCH_B();
2225
2226 if( regs[a].tt == MRBC_TT_NIL ) {
2227 // arycat(nil, [...]) #=> [...]
2228 assert( regs[a+1].tt == MRBC_TT_ARRAY );
2229 regs[a] = regs[a+1];
2230 regs[a+1].tt = MRBC_TT_NIL;
2231
2232 return;
2233 }
2234
2235 assert( regs[a ].tt == MRBC_TT_ARRAY );
2236 assert( regs[a+1].tt == MRBC_TT_ARRAY );
2237
2238 int size_1 = regs[a ].array->n_stored;
2239 int size_2 = regs[a+1].array->n_stored;
2240 int new_size = size_1 + regs[a+1].array->n_stored;
2241
2242 // need resize?
2243 if( regs[a].array->data_size < new_size ) {
2244 mrbc_array_resize(&regs[a], new_size);
2245 }
2246
2247 for( int i = 0; i < size_2; i++ ) {
2248 mrbc_incref( &regs[a+1].array->data[i] );
2249 regs[a].array->data[size_1+i] = regs[a+1].array->data[i];
2250 }
2251 regs[a].array->n_stored = new_size;
2252}
2253
2254
2255//================================================================
2260static inline void op_arypush( mrbc_vm *vm, mrbc_value *regs EXT )
2261{
2262 FETCH_BB();
2263
2264 int sz1 = mrbc_array_size(&regs[a]);
2265
2266 int ret = mrbc_array_resize(&regs[a], sz1 + b);
2267 if( ret != 0 ) return; // ENOMEM ?
2268
2269 // data copy.
2270 memcpy( regs[a].array->data + sz1, &regs[a+1], sizeof(mrbc_value) * b );
2271 memset( &regs[a+1], 0, sizeof(mrbc_value) * b );
2272 regs[a].array->n_stored = sz1 + b;
2273}
2274
2275
2276//================================================================
2281static inline void op_arydup( mrbc_vm *vm, mrbc_value *regs EXT )
2282{
2283 FETCH_B();
2284
2285 mrbc_value ret = mrbc_array_dup( vm, &regs[a] );
2286 mrbc_decref(&regs[a]);
2287 regs[a] = ret;
2288}
2289
2290
2291//================================================================
2296static inline void op_aref( mrbc_vm *vm, mrbc_value *regs EXT )
2297{
2298 FETCH_BBB();
2299
2300 mrbc_value *src = &regs[b];
2301 mrbc_value *dst = &regs[a];
2302
2303 mrbc_decref( dst );
2304
2305 if( mrbc_type(*src) == MRBC_TT_ARRAY ) {
2306 // src is Array
2307 *dst = mrbc_array_get(src, c);
2308 mrbc_incref(dst);
2309 } else {
2310 // src is not Array
2311 if( c == 0 ) {
2312 mrbc_incref(src);
2313 *dst = *src;
2314 } else {
2315 mrbc_set_nil( dst );
2316 }
2317 }
2318}
2319
2320
2321//================================================================
2326static inline void op_aset( mrbc_vm *vm, mrbc_value *regs EXT )
2327{
2328 FETCH_BBB();
2329
2330 assert( mrbc_type(regs[b]) == MRBC_TT_ARRAY );
2331
2332 mrbc_incref( &regs[b] );
2333 mrbc_array_set(&regs[a], c, &regs[b]);
2334}
2335
2336
2337//================================================================
2342static inline void op_apost( mrbc_vm *vm, mrbc_value *regs EXT )
2343{
2344 FETCH_BBB();
2345
2346 mrbc_value src = regs[a];
2347 if( mrbc_type(src) != MRBC_TT_ARRAY ) {
2348 src = mrbc_array_new(vm, 1);
2349 src.array->data[0] = regs[a];
2350 src.array->n_stored = 1;
2351 }
2352
2353 int pre = b;
2354 int post = c;
2355 int len = mrbc_array_size(&src);
2356
2357 if( len > pre + post ) {
2358 int ary_size = len - pre - post;
2359 regs[a] = mrbc_array_new(vm, ary_size);
2360
2361 // copy elements
2362 for( int i = 0; i < ary_size; i++ ) {
2363 regs[a].array->data[i] = src.array->data[pre+i];
2364 mrbc_incref( &regs[a].array->data[i] );
2365 }
2366 regs[a].array->n_stored = ary_size;
2367
2368 } else {
2369 assert(!"Not support this case in op_apost");
2370 // empty
2371 regs[a] = mrbc_array_new(vm, 0);
2372 }
2373
2374 mrbc_decref(&src);
2375}
2376
2377
2378//================================================================
2383static inline void op_intern( mrbc_vm *vm, mrbc_value *regs EXT )
2384{
2385 FETCH_B();
2386
2387 assert( regs[a].tt == MRBC_TT_STRING );
2388
2389 mrbc_value sym_val = mrbc_symbol_new(vm, (const char*)regs[a].string->data);
2390
2391 mrbc_decref( &regs[a] );
2392 regs[a] = sym_val;
2393}
2394
2395
2396//================================================================
2401static inline void op_symbol( mrbc_vm *vm, mrbc_value *regs EXT )
2402{
2403 FETCH_BB();
2404
2405 const char *p = (const char *)mrbc_irep_pool_ptr(vm->cur_irep, b);
2406 mrbc_sym sym_id = mrbc_str_to_symid( p+3 ); // 3 is TT and length
2407 if( sym_id < 0 ) {
2408 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
2409 return;
2410 }
2411
2412 mrbc_decref(&regs[a]);
2413 regs[a] = mrbc_symbol_value( sym_id );
2414}
2415
2416
2417//================================================================
2422static inline void op_string( mrbc_vm *vm, mrbc_value *regs EXT )
2423{
2424 FETCH_BB();
2425
2426 mrbc_decref(&regs[a]);
2427 regs[a] = mrbc_irep_pool_value(vm, b);
2428}
2429
2430
2431//================================================================
2436static inline void op_strcat( mrbc_vm *vm, mrbc_value *regs EXT )
2437{
2438 FETCH_B();
2439
2440#if MRBC_USE_STRING
2441 // call "to_s"
2442 mrbc_method method;
2443 if( mrbc_find_method( &method, find_class_by_object(&regs[a+1]),
2444 MRBC_SYM(to_s)) == 0 ) return;
2445 if( !method.c_func ) return; // TODO: Not support?
2446
2447 method.func( vm, regs + a + 1, 0 );
2448 mrbc_string_append( &regs[a], &regs[a+1] );
2449 mrbc_decref_empty( &regs[a+1] );
2450
2451#else
2452 mrbc_raise(vm, MRBC_CLASS(Exception), "Not support String");
2453#endif
2454}
2455
2456
2457//================================================================
2462static inline void op_hash( mrbc_vm *vm, mrbc_value *regs EXT )
2463{
2464 FETCH_BB();
2465
2466 mrbc_value value = mrbc_hash_new(vm, b);
2467 if( value.hash == NULL ) return; // ENOMEM
2468
2469 // note: Do not detect duplicate keys.
2470 b *= 2;
2471 memcpy( value.hash->data, &regs[a], sizeof(mrbc_value) * b );
2472 memset( &regs[a], 0, sizeof(mrbc_value) * b );
2473 value.hash->n_stored = b;
2474
2475 mrbc_decref(&regs[a]);
2476 regs[a] = value;
2477}
2478
2479
2480//================================================================
2485static inline void op_hashadd( mrbc_vm *vm, mrbc_value *regs EXT )
2486{
2487 FETCH_BB();
2488
2489 int sz1 = mrbc_array_size(&regs[a]);
2490 int sz2 = b * 2;
2491
2492 int ret = mrbc_array_resize(&regs[a], sz1 + sz2);
2493 if( ret != 0 ) return; // ENOMEM
2494
2495 // data copy.
2496 // note: Do not detect duplicate keys.
2497 memcpy( regs[a].hash->data + sz1, &regs[a+1], sizeof(mrbc_value) * sz2 );
2498 memset( &regs[a+1], 0, sizeof(mrbc_value) * sz2 );
2499 regs[a].hash->n_stored = sz1 + sz2;
2500}
2501
2502
2503//================================================================
2508static inline void op_hashcat( mrbc_vm *vm, mrbc_value *regs EXT )
2509{
2510 FETCH_B();
2511
2513
2514 while( mrbc_hash_i_has_next(&ite) ) {
2515 mrbc_value *kv = mrbc_hash_i_next(&ite);
2516 mrbc_hash_set( &regs[a], &kv[0], &kv[1] );
2517 mrbc_incref( &kv[0] );
2518 mrbc_incref( &kv[1] );
2519 }
2520}
2521
2522
2523//================================================================
2528static inline void op_block( mrbc_vm *vm, mrbc_value *regs EXT )
2529{
2530 FETCH_BB();
2531
2532 mrbc_value ret = mrbc_proc_new(vm, mrbc_irep_child_irep(vm->cur_irep, b), 'B');
2533 if( !ret.proc ) return; // ENOMEM
2534
2535 mrbc_decref(&regs[a]);
2536 regs[a] = ret;
2537}
2538
2539
2540//================================================================
2545static inline void op_method( mrbc_vm *vm, mrbc_value *regs EXT )
2546{
2547 FETCH_BB();
2548
2549 mrbc_value ret = mrbc_proc_new(vm, mrbc_irep_child_irep(vm->cur_irep, b), 'M');
2550 if( !ret.proc ) return; // ENOMEM
2551
2552 mrbc_decref(&regs[a]);
2553 regs[a] = ret;
2554}
2555
2556
2557//================================================================
2562static inline void op_range_inc( mrbc_vm *vm, mrbc_value *regs EXT )
2563{
2564 FETCH_B();
2565
2566 mrbc_value value = mrbc_range_new(vm, &regs[a], &regs[a+1], 0);
2567 regs[a] = value;
2568 regs[a+1].tt = MRBC_TT_EMPTY;
2569}
2570
2571
2572//================================================================
2577static inline void op_range_exc( mrbc_vm *vm, mrbc_value *regs EXT )
2578{
2579 FETCH_B();
2580
2581 mrbc_value value = mrbc_range_new(vm, &regs[a], &regs[a+1], 1);
2582 regs[a] = value;
2583 regs[a+1].tt = MRBC_TT_EMPTY;
2584}
2585
2586
2587//================================================================
2592static inline void op_oclass( mrbc_vm *vm, mrbc_value *regs EXT )
2593{
2594 FETCH_B();
2595
2596 mrbc_decref(&regs[a]);
2597 regs[a].tt = MRBC_TT_CLASS;
2598 regs[a].cls = MRBC_CLASS(Object);
2599}
2600
2601
2602//================================================================
2607static inline void op_class( mrbc_vm *vm, mrbc_value *regs EXT )
2608{
2609 FETCH_BB();
2610
2611 mrbc_class *super;
2612
2613 switch( regs[a+1].tt ) {
2614 case MRBC_TT_CLASS:
2615 super = regs[a+1].cls;
2616 break;
2617 case MRBC_TT_NIL:
2618 super = 0;
2619 break;
2620 default:
2621 mrbc_raise(vm, MRBC_CLASS(TypeError), "superclass must be a Class");
2622 return;
2623 }
2624
2625 // check unsupported pattern.
2626 if( super ) {
2627 for( int i = 1; i < MRBC_TT_MAXVAL; i++ ) {
2628 if( super == mrbc_class_tbl[i] ) {
2629 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Inherit the built-in class is not supported");
2630 return;
2631 }
2632 }
2633 }
2634
2635 mrbc_class *outer = 0;
2636
2637 if( regs[a].tt == MRBC_TT_CLASS || regs[a].tt == MRBC_TT_MODULE ) {
2638 outer = regs[a].cls;
2639 } else if( vm->cur_regs[0].tt == MRBC_TT_CLASS || vm->cur_regs[0].tt == MRBC_TT_MODULE ) {
2640 outer = vm->cur_regs[0].cls;
2641 }
2642
2643 const char *class_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
2644 mrbc_class *cls;
2645
2646 // define a new class (or get an already defined class)
2647 if( outer ) {
2648 cls = mrbc_define_class_under(vm, outer, class_name, super);
2649 } else {
2650 cls = mrbc_define_class(vm, class_name, super);
2651 }
2652
2653 // (note)
2654 // regs[a] was set to NIL or Class by compiler. So, no need to release.
2655 regs[a].tt = MRBC_TT_CLASS;
2656 regs[a].cls = cls;
2657}
2658
2659
2660//================================================================
2665static inline void op_module( mrbc_vm *vm, mrbc_value *regs EXT )
2666{
2667 FETCH_BB();
2668
2669 mrbc_class *outer = 0;
2670
2671 if( regs[a].tt == MRBC_TT_CLASS || regs[a].tt == MRBC_TT_MODULE ) {
2672 outer = regs[a].cls;
2673 } else if( vm->cur_regs[0].tt == MRBC_TT_CLASS || vm->cur_regs[0].tt == MRBC_TT_MODULE ) {
2674 outer = vm->cur_regs[0].cls;
2675 }
2676
2677 const char *module_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
2678 mrbc_class *cls;
2679
2680 // define a new module (or get an already defined class)
2681 if( outer ) {
2682 cls = mrbc_define_module_under(vm, outer, module_name);
2683 } else {
2684 cls = mrbc_define_module(vm, module_name);
2685 }
2686
2687 // (note)
2688 // regs[a] was set to Class, Module or NIL by compiler. So, no need to release.
2689 regs[a].tt = MRBC_TT_MODULE;
2690 regs[a].cls = cls;
2691}
2692
2693
2694//================================================================
2699static inline void op_exec( mrbc_vm *vm, mrbc_value *regs EXT )
2700{
2701 FETCH_BB();
2702 assert( regs[a].tt == MRBC_TT_CLASS || regs[a].tt == MRBC_TT_MODULE );
2703
2704 // prepare callinfo
2705 mrbc_push_callinfo(vm, regs[a].cls->sym_id, a, 0);
2706
2707 // target irep
2709 vm->inst = vm->cur_irep->inst;
2710 vm->cur_regs += a;
2711
2712 vm->target_class = regs[a].cls;
2713}
2714
2715
2716//----------------------------------------------------------------
2717static void sub_irep_incref( mrbc_irep *irep, int inc_dec )
2718{
2719 for( int i = 0; i < irep->rlen; i++ ) {
2720 sub_irep_incref( mrbc_irep_child_irep(irep, i), inc_dec );
2721 }
2722
2723 irep->ref_count += inc_dec;
2724}
2725
2726static void sub_def_alias( mrbc_class *cls, mrbc_method *method, mrbc_sym sym_id )
2727{
2728 method->next = cls->method_link;
2729 cls->method_link = method;
2730
2731 if( !method->c_func ) sub_irep_incref( method->irep, +1 );
2732
2733 // checking same method
2734 for( ;method->next != NULL; method = method->next ) {
2735 if( method->next->sym_id == sym_id ) {
2736 // Found it. Unchain it in linked list and remove.
2737 mrbc_method *del_method = method->next;
2738
2739 method->next = del_method->next;
2740 if( del_method->type == 'M' ) {
2741 if( !del_method->c_func ) sub_irep_incref( del_method->irep, -1 );
2742 mrbc_raw_free( del_method );
2743 }
2744
2745 break;
2746 }
2747 }
2748}
2749
2750//================================================================
2755static inline void op_def( mrbc_vm *vm, mrbc_value *regs EXT )
2756{
2757 FETCH_BB();
2758
2759 assert( regs[a].tt == MRBC_TT_CLASS || regs[a].tt == MRBC_TT_MODULE );
2760 assert( regs[a+1].tt == MRBC_TT_PROC );
2761
2762 mrbc_class *cls = regs[a].cls;
2763 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
2764 mrbc_proc *proc = regs[a+1].proc;
2765 mrbc_method *method = (vm->vm_id == 0) ?
2767 mrbc_raw_alloc( sizeof(mrbc_method) );
2768 if( !method ) return; // ENOMEM
2769
2770 method->type = (vm->vm_id == 0) ? 'm' : 'M';
2771 method->c_func = 0;
2772 method->sym_id = sym_id;
2773 method->irep = proc->irep;
2774
2775 sub_def_alias( cls, method, sym_id );
2776 mrbc_set_symbol(&regs[a], sym_id);
2777}
2778
2779
2780//================================================================
2785static inline void op_alias( mrbc_vm *vm, mrbc_value *regs EXT )
2786{
2787 FETCH_BB();
2788
2789 mrbc_sym sym_id_new = mrbc_irep_symbol_id(vm->cur_irep, a);
2790 mrbc_sym sym_id_org = mrbc_irep_symbol_id(vm->cur_irep, b);
2791 mrbc_class *cls = vm->target_class;
2792 mrbc_method *method = (vm->vm_id == 0) ?
2794 mrbc_raw_alloc( sizeof(mrbc_method) );
2795 if( !method ) return; // ENOMEM
2796
2797 if( mrbc_find_method( method, cls, sym_id_org ) == 0 ) {
2798 mrbc_raisef(vm, MRBC_CLASS(NameError), "undefined method '%s'",
2799 mrbc_symid_to_str(sym_id_org));
2800 if(vm->vm_id != 0) mrbc_raw_free( method );
2801 return;
2802 }
2803
2804 method->type = (vm->vm_id == 0) ? 'm' : 'M';
2805 method->sym_id = sym_id_new;
2806
2807 sub_def_alias( cls, method, sym_id_new );
2808}
2809
2810
2811//================================================================
2816static inline void op_sclass( mrbc_vm *vm, mrbc_value *regs EXT )
2817{
2818 // currently, not supported
2819 FETCH_B();
2820}
2821
2822
2823//================================================================
2828static inline void op_tclass( mrbc_vm *vm, mrbc_value *regs EXT )
2829{
2830 FETCH_B();
2831
2832 mrbc_decref(&regs[a]);
2833 regs[a].tt = MRBC_TT_CLASS;
2834 regs[a].cls = vm->target_class;
2835}
2836
2837
2838#if !defined(MRBC_SUPPORT_OP_EXT)
2839//================================================================
2846static inline void op_ext( mrbc_vm *vm, mrbc_value *regs EXT )
2847{
2848 FETCH_Z();
2849 mrbc_raise(vm, MRBC_CLASS(Exception),
2850 "Not support op_ext. Re-compile with MRBC_SUPPORT_OP_EXT");
2851}
2852#endif
2853
2854
2855//================================================================
2860static inline void op_stop( mrbc_vm *vm, mrbc_value *regs EXT )
2861{
2862 FETCH_Z();
2863
2864 vm->flag_preemption = 1;
2865 vm->flag_stop = 1;
2866 vm->inst--; // to not proceed beyond OP_STOP.
2867}
2868
2869
2870//================================================================
2871/* Unsupported opecodes
2872*/
2873static inline void op_unsupported( mrbc_vm *vm, mrbc_value *regs EXT )
2874{
2875 mrbc_raisef( vm, MRBC_CLASS(Exception),
2876 "Unimplemented opcode (0x%02x) found", *(vm->inst - 1));
2877}
2878#undef EXT
2879
2880
2881//================================================================
2889int mrbc_vm_run( struct VM *vm )
2890{
2891#if defined(MRBC_SUPPORT_OP_EXT)
2892 int ext = 0;
2893#define EXT , ext
2894#else
2895#define EXT
2896#endif
2897
2898 while( 1 ) {
2899 mrbc_value *regs = vm->cur_regs;
2900 uint8_t op = *vm->inst++; // Dispatch
2901
2902 switch( op ) {
2903 case OP_NOP: op_nop (vm, regs EXT); break;
2904 case OP_MOVE: op_move (vm, regs EXT); break;
2905 case OP_LOADL: op_loadl (vm, regs EXT); break;
2906 case OP_LOADI: op_loadi (vm, regs EXT); break;
2907 case OP_LOADINEG: op_loadineg (vm, regs EXT); break;
2908 case OP_LOADI__1: // fall through
2909 case OP_LOADI_0: // fall through
2910 case OP_LOADI_1: // fall through
2911 case OP_LOADI_2: // fall through
2912 case OP_LOADI_3: // fall through
2913 case OP_LOADI_4: // fall through
2914 case OP_LOADI_5: // fall through
2915 case OP_LOADI_6: // fall through
2916 case OP_LOADI_7: op_loadi_n (vm, regs EXT); break;
2917 case OP_LOADI16: op_loadi16 (vm, regs EXT); break;
2918 case OP_LOADI32: op_loadi32 (vm, regs EXT); break;
2919 case OP_LOADSYM: op_loadsym (vm, regs EXT); break;
2920 case OP_LOADNIL: op_loadnil (vm, regs EXT); break;
2921 case OP_LOADSELF: op_loadself (vm, regs EXT); break;
2922 case OP_LOADT: op_loadt (vm, regs EXT); break;
2923 case OP_LOADF: op_loadf (vm, regs EXT); break;
2924 case OP_GETGV: op_getgv (vm, regs EXT); break;
2925 case OP_SETGV: op_setgv (vm, regs EXT); break;
2926 case OP_GETSV: op_unsupported(vm, regs EXT); break; // not implemented.
2927 case OP_SETSV: op_unsupported(vm, regs EXT); break; // not implemented.
2928 case OP_GETIV: op_getiv (vm, regs EXT); break;
2929 case OP_SETIV: op_setiv (vm, regs EXT); break;
2930 case OP_GETCV: op_unsupported(vm, regs EXT); break; // not implemented.
2931 case OP_SETCV: op_unsupported(vm, regs EXT); break; // not implemented.
2932 case OP_GETCONST: op_getconst (vm, regs EXT); break;
2933 case OP_SETCONST: op_setconst (vm, regs EXT); break;
2934 case OP_GETMCNST: op_getmcnst (vm, regs EXT); break;
2935 case OP_SETMCNST: op_unsupported(vm, regs EXT); break; // not implemented.
2936 case OP_GETUPVAR: op_getupvar (vm, regs EXT); break;
2937 case OP_SETUPVAR: op_setupvar (vm, regs EXT); break;
2938 case OP_GETIDX: op_getidx (vm, regs EXT); break;
2939 case OP_SETIDX: op_setidx (vm, regs EXT); break;
2940 case OP_JMP: op_jmp (vm, regs EXT); break;
2941 case OP_JMPIF: op_jmpif (vm, regs EXT); break;
2942 case OP_JMPNOT: op_jmpnot (vm, regs EXT); break;
2943 case OP_JMPNIL: op_jmpnil (vm, regs EXT); break;
2944 case OP_JMPUW: op_jmpuw (vm, regs EXT); break;
2945 case OP_EXCEPT: op_except (vm, regs EXT); break;
2946 case OP_RESCUE: op_rescue (vm, regs EXT); break;
2947 case OP_RAISEIF: op_raiseif (vm, regs EXT); break;
2948 case OP_SSEND: op_ssend (vm, regs EXT); break;
2949 case OP_SSENDB: op_ssendb (vm, regs EXT); break;
2950 case OP_SEND: op_send (vm, regs EXT); break;
2951 case OP_SENDB: op_sendb (vm, regs EXT); break;
2952 case OP_CALL: op_unsupported(vm, regs EXT); break; // not implemented.
2953 case OP_SUPER: op_super (vm, regs EXT); break;
2954 case OP_ARGARY: op_argary (vm, regs EXT); break;
2955 case OP_ENTER: op_enter (vm, regs EXT); break;
2956 case OP_KEY_P: op_key_p (vm, regs EXT); break;
2957 case OP_KEYEND: op_keyend (vm, regs EXT); break;
2958 case OP_KARG: op_karg (vm, regs EXT); break;
2959 case OP_RETURN: op_return (vm, regs EXT); break;
2960 case OP_RETURN_BLK: op_return_blk (vm, regs EXT); break;
2961 case OP_BREAK: op_break (vm, regs EXT); break;
2962 case OP_BLKPUSH: op_blkpush (vm, regs EXT); break;
2963 case OP_ADD: op_add (vm, regs EXT); break;
2964 case OP_ADDI: op_addi (vm, regs EXT); break;
2965 case OP_SUB: op_sub (vm, regs EXT); break;
2966 case OP_SUBI: op_subi (vm, regs EXT); break;
2967 case OP_MUL: op_mul (vm, regs EXT); break;
2968 case OP_DIV: op_div (vm, regs EXT); break;
2969 case OP_EQ: op_eq (vm, regs EXT); break;
2970 case OP_LT: op_lt (vm, regs EXT); break;
2971 case OP_LE: op_le (vm, regs EXT); break;
2972 case OP_GT: op_gt (vm, regs EXT); break;
2973 case OP_GE: op_ge (vm, regs EXT); break;
2974 case OP_ARRAY: op_array (vm, regs EXT); break;
2975 case OP_ARRAY2: op_array2 (vm, regs EXT); break;
2976 case OP_ARYCAT: op_arycat (vm, regs EXT); break;
2977 case OP_ARYPUSH: op_arypush (vm, regs EXT); break;
2978 case OP_ARYDUP: op_arydup (vm, regs EXT); break;
2979 case OP_AREF: op_aref (vm, regs EXT); break;
2980 case OP_ASET: op_aset (vm, regs EXT); break;
2981 case OP_APOST: op_apost (vm, regs EXT); break;
2982 case OP_INTERN: op_intern (vm, regs EXT); break;
2983 case OP_SYMBOL: op_symbol (vm, regs EXT); break;
2984 case OP_STRING: op_string (vm, regs EXT); break;
2985 case OP_STRCAT: op_strcat (vm, regs EXT); break;
2986 case OP_HASH: op_hash (vm, regs EXT); break;
2987 case OP_HASHADD: op_hashadd (vm, regs EXT); break;
2988 case OP_HASHCAT: op_hashcat (vm, regs EXT); break;
2989 case OP_LAMBDA: op_unsupported(vm, regs EXT); break; // not implemented.
2990 case OP_BLOCK: op_block (vm, regs EXT); break;
2991 case OP_METHOD: op_method (vm, regs EXT); break;
2992 case OP_RANGE_INC: op_range_inc (vm, regs EXT); break;
2993 case OP_RANGE_EXC: op_range_exc (vm, regs EXT); break;
2994 case OP_OCLASS: op_oclass (vm, regs EXT); break;
2995 case OP_CLASS: op_class (vm, regs EXT); break;
2996 case OP_MODULE: op_module (vm, regs EXT); break;
2997 case OP_EXEC: op_exec (vm, regs EXT); break;
2998 case OP_DEF: op_def (vm, regs EXT); break;
2999 case OP_ALIAS: op_alias (vm, regs EXT); break;
3000 case OP_UNDEF: op_unsupported(vm, regs EXT); break; // not implemented.
3001 case OP_SCLASS: op_sclass (vm, regs EXT); break;
3002 case OP_TCLASS: op_tclass (vm, regs EXT); break;
3003 case OP_DEBUG: op_unsupported(vm, regs EXT); break; // not implemented.
3004 case OP_ERR: op_unsupported(vm, regs EXT); break; // not implemented.
3005#if defined(MRBC_SUPPORT_OP_EXT)
3006 case OP_EXT1: ext = 1; continue;
3007 case OP_EXT2: ext = 2; continue;
3008 case OP_EXT3: ext = 3; continue;
3009#else
3010 case OP_EXT1: // fall through
3011 case OP_EXT2: // fall through
3012 case OP_EXT3: op_ext (vm, regs EXT); break;
3013#endif
3014 case OP_STOP: op_stop (vm, regs EXT); break;
3015 default: op_unsupported(vm, regs EXT); break;
3016 } // end switch.
3017
3018#undef EXT
3019#if defined(MRBC_SUPPORT_OP_EXT)
3020 ext = 0;
3021#endif
3022 if( !vm->flag_preemption ) continue; // execute next ope code.
3023 if( !mrbc_israised(vm) ) return vm->flag_stop; // normal return.
3024
3025
3026 // Handle exception
3027 vm->flag_preemption = 0;
3028 const mrbc_irep_catch_handler *handler;
3029
3030 while( 1 ) {
3031 const mrbc_irep *irep = vm->cur_irep;
3032 const mrbc_irep_catch_handler *catch_table =
3033 (const mrbc_irep_catch_handler *)(irep->inst + irep->ilen);
3034 uint32_t inst = vm->inst - irep->inst;
3035 int cnt = irep->clen;
3036
3037 for( cnt--; cnt >= 0 ; cnt-- ) {
3038 handler = catch_table + cnt;
3039 if( (bin_to_uint32(handler->begin) < inst) &&
3040 (inst <= bin_to_uint32(handler->end)) ) goto JUMP_TO_HANDLER;
3041 }
3042
3043 if( !vm->callinfo_tail ) return 2; // return due to exception.
3044 mrbc_pop_callinfo( vm );
3045 }
3046
3047 JUMP_TO_HANDLER:
3048 // jump to handler (rescue or ensure).
3049 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
3050 }
3051}
void * mrbc_raw_alloc(unsigned int size)
Definition alloc.c:500
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:619
void mrbc_raw_free(void *ptr)
Definition alloc.c:695
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:252
int mrbc_array_set(mrbc_value *ary, int idx, mrbc_value *set_val)
Definition c_array.c:178
mrbc_value mrbc_array_get(const mrbc_value *ary, int idx)
Definition c_array.c:216
mrbc_value mrbc_array_new(struct VM *vm, int size)
Definition c_array.c:82
int mrbc_array_resize(mrbc_value *ary, int size)
Definition c_array.c:155
mrbc_value mrbc_array_dup(struct VM *vm, const mrbc_value *ary)
Definition c_array.c:497
static int mrbc_array_size(const mrbc_value *ary)
Definition c_array.h:81
mrbc_value mrbc_hash_remove_by_id(mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:253
void mrbc_hash_delete(mrbc_value *hash)
Definition c_hash.c:108
mrbc_value * mrbc_hash_search_by_id(const mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:145
mrbc_value mrbc_hash_dup(struct VM *vm, mrbc_value *src)
Definition c_hash.c:313
int mrbc_hash_set(mrbc_value *hash, mrbc_value *key, mrbc_value *val)
Definition c_hash.c:168
mrbc_value mrbc_hash_new(struct VM *vm, int size)
Definition c_hash.c:77
static mrbc_value * mrbc_hash_i_next(mrbc_hash_iterator *ite)
Definition c_hash.h:141
static int mrbc_hash_size(const mrbc_value *hash)
Definition c_hash.h:86
static int mrbc_hash_i_has_next(mrbc_hash_iterator *ite)
Definition c_hash.h:133
struct RHashIterator mrbc_hash_iterator
Define Hash iterator.
static mrbc_hash_iterator mrbc_hash_iterator_new(const mrbc_value *v)
Definition c_hash.h:120
mrbc_value mrbc_proc_new(struct VM *vm, void *irep, uint8_t b_or_m)
Definition c_proc.c:42
struct RProc mrbc_proc
Proc object.
mrbc_value mrbc_range_new(struct VM *vm, mrbc_value *first, mrbc_value *last, int flag_exclude)
Definition c_range.c:43
int mrbc_string_append(mrbc_value *s1, const mrbc_value *s2)
Definition c_string.c:210
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:331
mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
Definition class.c:255
int mrbc_obj_is_kind_of(const mrbc_value *obj, const mrbc_class *tcls)
Definition class.c:419
mrbc_value mrbc_instance_getiv(mrbc_value *obj, mrbc_sym sym_id)
Definition class.c:388
mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
Definition class.c:210
void mrbc_instance_setiv(mrbc_value *obj, mrbc_sym sym_id, mrbc_value *v)
Definition class.c:374
mrbc_method * mrbc_find_method(mrbc_method *r_method, mrbc_class *cls, mrbc_sym sym_id)
Definition class.c:442
mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
Definition class.c:163
mrbc_class *const mrbc_class_tbl[MRBC_TT_MAXVAL+1]
Definition class.c:37
mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
Definition class.c:118
struct RMethod mrbc_method
Method management structure.
#define MRBC_CLASS(cls)
Definition class.h:51
static mrbc_class * find_class_by_object(const mrbc_value *obj)
Definition class.h:235
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:180
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:236
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:173
#define mrbc_israised(vm)
Definition error.h:37
mrbc_value * mrbc_get_class_const(const struct RClass *cls, mrbc_sym sym_id)
Definition global.c:101
int mrbc_set_global(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:149
mrbc_value * mrbc_get_const(mrbc_sym sym_id)
Definition global.c:88
mrbc_value * mrbc_get_global(mrbc_sym sym_id)
Definition global.c:161
int mrbc_set_class_const(const struct RClass *cls, mrbc_sym sym_id, mrbc_value *v)
Definition global.c:71
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:53
mrbc_value mrbc_irep_pool_value(struct VM *vm, int n)
Definition load.c:360
void mrbc_irep_free(struct IREP *irep)
Definition load.c:340
Include at once the necessary header files.
Define operation codes and associated macros.
#define FETCH_BB()
Definition opcode.h:67
#define FETCH_W()
Definition opcode.h:100
#define FETCH_BBB()
Definition opcode.h:73
#define FETCH_BSS()
Definition opcode.h:86
#define FETCH_BS()
Definition opcode.h:80
#define FETCH_S()
Definition opcode.h:95
@ OP_KEY_P
BB R[a] = kdict.key?(Syms[b])
Definition opcode.h:177
@ OP_DEBUG
BBB print a,b,c.
Definition opcode.h:224
@ OP_CALL
Z R[0] = self.call(frame.argc, frame.argv)
Definition opcode.h:173
@ OP_EXT2
Z make 2nd operand (b) 16bit.
Definition opcode.h:227
@ OP_EXEC
BB R[a] = blockexec(R[a],Irep[b])
Definition opcode.h:218
@ OP_SSENDB
BBB R[a] = self.send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..,&R[a+n+2k+1])
Definition opcode.h:170
@ OP_EQ
B R[a] = R[a]==R[a+1].
Definition opcode.h:190
@ OP_SETIDX
B R[a][R[a+1]] = R[a+2].
Definition opcode.h:160
@ OP_LOADI__1
B R[a] = mrb_int(-1)
Definition opcode.h:129
@ OP_MODULE
BB R[a] = newmodule(R[a],Syms[b])
Definition opcode.h:217
@ OP_RANGE_INC
B R[a] = range_new(R[a],R[a+1],FALSE)
Definition opcode.h:213
@ OP_EXT1
Z make 1st operand (a) 16bit.
Definition opcode.h:226
@ OP_CLASS
BB R[a] = newclass(R[a],Syms[b],R[a+1])
Definition opcode.h:216
@ OP_LOADSELF
B R[a] = self.
Definition opcode.h:142
@ OP_BLKPUSH
BS R[a] = block (16=m5:r1:m5:d1:lv4)
Definition opcode.h:183
@ OP_LOADI_3
B R[a] = mrb_int(3)
Definition opcode.h:133
@ OP_GE
B R[a] = R[a]>=R[a+1].
Definition opcode.h:194
@ OP_LOADI_4
B R[a] = mrb_int(4)
Definition opcode.h:134
@ OP_EXT3
Z make 1st and 2nd operands 16bit.
Definition opcode.h:228
@ OP_SETIV
BB ivset(Syms[b],R[a])
Definition opcode.h:150
@ OP_SUBI
BB R[a] = R[a]-mrb_int(b)
Definition opcode.h:187
@ OP_TCLASS
B R[a] = target_class.
Definition opcode.h:223
@ OP_STOP
Z stop VM.
Definition opcode.h:229
@ OP_AREF
BBB R[a] = R[b][c].
Definition opcode.h:200
@ OP_APOST
BBB *R[a],R[a+1]..R[a+c] = R[a][b..].
Definition opcode.h:202
@ OP_RETURN_BLK
B return R[a] (in-block return)
Definition opcode.h:181
@ OP_LOADI_6
B R[a] = mrb_int(6)
Definition opcode.h:136
@ OP_ALIAS
BB alias_method(target_class,Syms[a],Syms[b])
Definition opcode.h:220
@ OP_SSEND
BBB R[a] = self.send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n|k<<4)
Definition opcode.h:169
@ OP_NOP
Z no operation.
Definition opcode.h:124
@ OP_SETCONST
BB constset(Syms[b],R[a])
Definition opcode.h:154
@ OP_LOADSYM
BB R[a] = Syms[b].
Definition opcode.h:140
@ OP_ARYCAT
B ary_cat(R[a],R[a+1])
Definition opcode.h:197
@ OP_LAMBDA
BB R[a] = lambda(Irep[b],L_LAMBDA)
Definition opcode.h:210
@ OP_RANGE_EXC
B R[a] = range_new(R[a],R[a+1],TRUE)
Definition opcode.h:214
@ OP_LOADI_5
B R[a] = mrb_int(5)
Definition opcode.h:135
@ OP_LOADI_7
B R[a] = mrb_int(7)
Definition opcode.h:137
@ OP_LOADNIL
B R[a] = nil.
Definition opcode.h:141
@ OP_SETGV
BB setglobal(Syms[b], R[a])
Definition opcode.h:146
@ OP_STRCAT
B str_cat(R[a],R[a+1])
Definition opcode.h:206
@ OP_LOADI
BB R[a] = mrb_int(b)
Definition opcode.h:127
@ OP_SEND
BBB R[a] = R[a].send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n|k<<4)
Definition opcode.h:171
@ OP_BREAK
B break R[a].
Definition opcode.h:182
@ OP_GETIDX
B R[a] = R[a][R[a+1]].
Definition opcode.h:159
@ OP_SUB
B R[a] = R[a]-R[a+1].
Definition opcode.h:186
@ OP_GETSV
BB R[a] = Special[Syms[b]].
Definition opcode.h:147
@ OP_DIV
B R[a] = R[a]/R[a+1].
Definition opcode.h:189
@ OP_ASET
BBB R[b][c] = R[a].
Definition opcode.h:201
@ OP_RAISEIF
B raise(R[a]) if R[a].
Definition opcode.h:168
@ OP_GETUPVAR
BBB R[a] = uvget(b,c)
Definition opcode.h:157
@ OP_ARRAY2
BBB R[a] = ary_new(R[b],R[b+1]..R[b+c])
Definition opcode.h:196
@ OP_ARYDUP
B R[a] = ary_dup(R[a])
Definition opcode.h:199
@ OP_LOADI_1
B R[a] = mrb_int(1)
Definition opcode.h:131
@ OP_JMPNIL
BS if R[a]==nil pc+=b.
Definition opcode.h:164
@ OP_LT
B R[a] = R[a]<R[a+1].
Definition opcode.h:191
@ OP_JMPUW
S unwind_and_jump_to(a)
Definition opcode.h:165
@ OP_INTERN
B R[a] = intern(R[a])
Definition opcode.h:203
@ OP_SETUPVAR
BBB uvset(b,c,R[a])
Definition opcode.h:158
@ OP_ENTER
W arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1)
Definition opcode.h:176
@ OP_LOADF
B R[a] = false.
Definition opcode.h:144
@ OP_UNDEF
B undef_method(target_class,Syms[a])
Definition opcode.h:221
@ OP_KARG
BB R[a] = kdict[Syms[b]]; kdict.delete(Syms[b])
Definition opcode.h:179
@ OP_GETCV
BB R[a] = cvget(Syms[b])
Definition opcode.h:151
@ OP_HASHADD
BB hash_push(R[a],R[a+1]..R[a+b*2])
Definition opcode.h:208
@ OP_ARGARY
BS R[a] = argument array (16=m5:r1:m5:d1:lv4)
Definition opcode.h:175
@ OP_METHOD
BB R[a] = lambda(Irep[b],L_METHOD)
Definition opcode.h:212
@ OP_ARYPUSH
BB ary_push(R[a],R[a+1]..R[a+b])
Definition opcode.h:198
@ OP_ADD
B R[a] = R[a]+R[a+1].
Definition opcode.h:184
@ OP_LOADT
B R[a] = true.
Definition opcode.h:143
@ OP_OCLASS
B R[a] = Object.
Definition opcode.h:215
@ OP_SYMBOL
BB R[a] = intern(Pool[b])
Definition opcode.h:204
@ OP_MUL
B R[a] = R[a]*R[a+1].
Definition opcode.h:188
@ OP_STRING
BB R[a] = str_dup(Pool[b])
Definition opcode.h:205
@ OP_ERR
B raise(LocalJumpError, Pool[a])
Definition opcode.h:225
@ OP_RESCUE
BB R[b] = R[a].isa?(R[b])
Definition opcode.h:167
@ OP_GETIV
BB R[a] = ivget(Syms[b])
Definition opcode.h:149
@ OP_LOADI32
BSS R[a] = mrb_int((b<<16)+c)
Definition opcode.h:139
@ OP_LOADINEG
BB R[a] = mrb_int(-b)
Definition opcode.h:128
@ OP_JMPNOT
BS if !R[a] pc+=b.
Definition opcode.h:163
@ OP_HASHCAT
B R[a] = hash_cat(R[a],R[a+1])
Definition opcode.h:209
@ OP_DEF
BB R[a].newmethod(Syms[b],R[a+1]); R[a] = Syms[b].
Definition opcode.h:219
@ OP_LOADI_2
B R[a] = mrb_int(2)
Definition opcode.h:132
@ OP_SETCV
BB cvset(Syms[b],R[a])
Definition opcode.h:152
@ OP_GT
B R[a] = R[a]>R[a+1].
Definition opcode.h:193
@ OP_KEYEND
Z raise unless kdict.empty?
Definition opcode.h:178
@ OP_LOADI_0
B R[a] = mrb_int(0)
Definition opcode.h:130
@ OP_LE
B R[a] = R[a]<=R[a+1].
Definition opcode.h:192
@ OP_GETGV
BB R[a] = getglobal(Syms[b])
Definition opcode.h:145
@ OP_RETURN
B return R[a] (normal)
Definition opcode.h:180
@ OP_EXCEPT
B R[a] = exc.
Definition opcode.h:166
@ OP_MOVE
BB R[a] = R[b].
Definition opcode.h:125
@ OP_SETSV
BB Special[Syms[b]] = R[a].
Definition opcode.h:148
@ OP_ARRAY
BB R[a] = ary_new(R[a],R[a+1]..R[a+b])
Definition opcode.h:195
@ OP_ADDI
BB R[a] = R[a]+mrb_int(b)
Definition opcode.h:185
@ OP_SCLASS
B R[a] = R[a].singleton_class.
Definition opcode.h:222
@ OP_SUPER
BB R[a] = super(R[a+1],... ,R[a+b+1])
Definition opcode.h:174
@ OP_LOADL
BB R[a] = Pool[b].
Definition opcode.h:126
@ OP_GETCONST
BB R[a] = constget(Syms[b])
Definition opcode.h:153
@ OP_SETMCNST
BB R[a+1]Syms[b] = R[a].
Definition opcode.h:156
@ OP_SENDB
BBB R[a] = R[a].send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..,&R[a+n+2k+1])
Definition opcode.h:172
@ OP_BLOCK
BB R[a] = lambda(Irep[b],L_BLOCK)
Definition opcode.h:211
@ OP_GETMCNST
BB R[a] = R[a]Syms[b].
Definition opcode.h:155
@ OP_LOADI16
BS R[a] = mrb_int(b)
Definition opcode.h:138
@ OP_JMPIF
BS if R[a] pc+=b.
Definition opcode.h:162
@ OP_JMP
S pc+=a.
Definition opcode.h:161
@ OP_HASH
BB R[a] = hash_new(R[a],R[a+1]..R[a+b*2-1])
Definition opcode.h:207
#define FETCH_Z()
Definition opcode.h:27
#define FETCH_B()
Definition opcode.h:62
uint8_t is_called_super
this is called by op_super.
Definition vm.h:130
const mrbc_irep * cur_irep
copy from mrbc_vm.
Definition vm.h:120
mrbc_sym method_id
called method ID.
Definition vm.h:127
struct RHash * karg_keep
keyword argument backup for OP_ARGARY.
Definition vm.h:126
uint8_t n_args
num of arguments.
Definition vm.h:129
mrbc_class * target_class
copy from mrbc_vm.
Definition vm.h:123
struct CALLINFO * prev
previous linked list.
Definition vm.h:119
mrbc_class * own_class
class that owns method.
Definition vm.h:125
const uint8_t * inst
copy from mrbc_vm.
Definition vm.h:121
mrbc_value * cur_regs
copy from mrbc_vm.
Definition vm.h:122
uint8_t reg_offset
register offset after call.
Definition vm.h:128
uint8_t target[4]
The address to jump to if a match is made.
Definition vm.h:110
uint8_t begin[4]
The starting address to match the handler. Includes this.
Definition vm.h:108
uint8_t type
enum mrb_catch_type, 1 byte. 0=rescue, 1=ensure
Definition vm.h:107
uint8_t end[4]
The endpoint address that matches the handler. Not Includes this.
Definition vm.h:109
const uint8_t * inst
pointer to instruction in RITE binary
Definition vm.h:62
uint16_t ilen
num of bytes in OpCode
Definition vm.h:54
uint16_t ref_count
reference counter
Definition vm.h:47
uint16_t rlen
num of child IREP blocks
Definition vm.h:52
uint16_t clen
num of catch handlers
Definition vm.h:53
uint16_t nregs
num of register variables
Definition vm.h:51
uint16_t n_stored
num of stored.
Definition c_array.h:44
mrbc_value * data
pointer to allocated memory.
Definition c_array.h:45
struct RMethod * method_link
pointer to method link.
Definition class.h:91
struct RClass * super
pointer to super class.
Definition class.h:89
mrbc_sym sym_id
class name's symbol ID
Definition class.h:84
mrbc_sym method_id
raised method, if it is known.
Definition error.h:51
uint16_t n_stored
num of stored.
Definition c_hash.h:46
mrbc_value * data
pointer to allocated memory.
Definition c_hash.h:47
struct RClass * cls
return value for mrbc_find_method.
Definition class.h:180
mrbc_sym sym_id
function names symbol ID
Definition class.h:173
uint8_t type
M:OP_DEF or OP_ALIAS, m:mrblib or define_method()
Definition class.h:171
struct IREP * irep
to IREP for ruby proc.
Definition class.h:175
struct RMethod * next
link to next method.
Definition class.h:179
uint8_t c_func
0:IREP, 1:C Func, 2:C Func (built-in)
Definition class.h:172
mrbc_func_t func
to C function.
Definition class.h:176
struct RProc * proc
Definition value.h:162
struct RException * exception
Definition value.h:167
struct RInstance * instance
Definition value.h:161
mrbc_sym sym_id
Definition value.h:158
struct RHash * hash
Definition value.h:166
void * handle
Definition value.h:168
mrbc_vtype tt
Definition value.h:152
struct RClass * cls
Definition value.h:160
struct RArray * array
Definition value.h:163
struct IREP * irep
Definition c_proc.h:46
mrbc_value ret_val
Definition c_proc.h:48
struct CALLINFO * callinfo
Definition c_proc.h:44
struct CALLINFO * callinfo_self
Definition c_proc.h:45
Virtual Machine.
Definition vm.h:140
mrbc_class * target_class
Target class.
Definition vm.h:156
unsigned int flag_need_memfree
Definition vm.h:146
uint16_t regs_size
size of regs[]
Definition vm.h:150
const mrbc_irep * cur_irep
IREP currently running.
Definition vm.h:153
unsigned int flag_stop
Definition vm.h:147
mrbc_callinfo * callinfo_tail
Last point of CALLINFO link.
Definition vm.h:157
uint8_t vm_id
vm_id : 1..MAX_VM_COUNT
Definition vm.h:144
volatile int8_t flag_preemption
Definition vm.h:145
mrbc_value exception
Raised exception or nil.
Definition vm.h:160
unsigned int flag_permanence
Definition vm.h:148
const uint8_t * inst
Instruction pointer.
Definition vm.h:154
mrbc_value regs[]
Definition vm.h:161
mrbc_value * cur_regs
Current register top.
Definition vm.h:155
mrbc_proc * ret_blk
Return block.
Definition vm.h:158
mrbc_irep * top_irep
IREP tree top.
Definition vm.h:152
mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
Definition symbol.c:334
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:217
void mrbc_separate_nested_symid(mrbc_sym sym_id, mrbc_sym *id1, mrbc_sym *id2)
Definition symbol.c:305
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:238
static int mrbc_is_nested_symid(mrbc_sym sym_id)
Definition symbol.h:68
#define MRBC_SYM(sym)
Definition symbol.h:30
int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition value.c:66
int32_t mrbc_int_t
Definition value.h:45
static void mrbc_decref(mrbc_value *v)
Definition value.h:604
#define mrbc_set_nil(p)
Definition value.h:201
#define mrbc_nil_value()
Definition value.h:210
static void mrbc_decref_empty(mrbc_value *v)
Definition value.h:622
static uint32_t bin_to_uint32(const void *s)
Definition value.h:678
#define mrbc_set_false(p)
Definition value.h:203
#define mrbc_symbol_value(n)
Definition value.h:214
#define MRBC_TT_MAXVAL
Definition value.h:101
#define mrbc_set_true(p)
Definition value.h:202
static void mrbc_incref(mrbc_value *v)
Definition value.h:589
#define mrbc_set_bool(p, n)
Definition value.h:204
#define mrbc_set_integer(p, n)
Definition value.h:199
#define mrbc_type(o)
Definition value.h:193
#define mrbc_set_float(p, n)
Definition value.h:200
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:59
@ MRBC_TT_FALSE
FalseClass.
Definition value.h:79
@ MRBC_TT_STRING
String.
Definition value.h:95
@ MRBC_TT_FLOAT
Float.
Definition value.h:85
@ MRBC_TT_INTEGER
Integer.
Definition value.h:83
@ MRBC_TT_RETURN
Definition value.h:73
@ MRBC_TT_EXCEPTION
Exception.
Definition value.h:98
@ MRBC_TT_EMPTY
Definition value.h:77
@ MRBC_TT_PROC
Proc.
Definition value.h:93
@ MRBC_TT_JMPUW
Definition value.h:70
@ MRBC_TT_OBJECT
General instance.
Definition value.h:92
@ MRBC_TT_BREAK
Definition value.h:71
@ MRBC_TT_ARRAY
Array.
Definition value.h:94
@ MRBC_TT_MODULE
Module.
Definition value.h:88
@ MRBC_TT_TRUE
TrueClass.
Definition value.h:82
@ MRBC_TT_NIL
NilClass.
Definition value.h:78
@ MRBC_TT_RETURN_BLK
Definition value.h:72
@ MRBC_TT_HASH
Hash.
Definition value.h:97
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
#define SET_RETURN(n)
Definition value.h:261
#define mrbc_set_symbol(p, n)
Definition value.h:205
#define mrbc_integer_value(n)
Definition value.h:208
static void op_send(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1231
static void op_loadsym(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:554
mrbc_callinfo * mrbc_push_callinfo(struct VM *vm, mrbc_sym method_id, int reg_offset, int n_args)
Definition vm.c:219
#define EXT
Definition vm.c:432
static void op_loadt(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:597
static void op_lt(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2096
static void op_getgv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:625
static void op_mul(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1982
static void op_array(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2180
static void op_move(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:450
static void op_strcat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2436
static void op_jmpif(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:931
static void op_return__sub(mrbc_vm *vm, mrbc_value *regs, int a)
Definition vm.c:1628
static void op_def(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2755
static void op_stop(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2860
static void sub_irep_incref(mrbc_irep *irep, int inc_dec)
Definition vm.c:2717
static void op_alias(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2785
static void op_setupvar(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:860
static void op_sendb(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1244
static void op_setidx(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:905
mrbc_vm * mrbc_vm_new(int regs_size)
Definition vm.c:292
static void op_symbol(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2401
static void op_ssendb(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1213
static const mrbc_irep_catch_handler * find_catch_handler_ensure(const struct VM *vm)
Definition vm.c:151
static void op_getconst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:710
static void op_hash(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2462
static void op_jmpnot(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:946
static void op_loadi_n(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:507
static void op_add(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1848
void mrbc_vm_end(struct VM *vm)
Definition vm.c:375
static void op_except(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1010
void mrbc_pop_callinfo(struct VM *vm)
Definition vm.c:246
static void op_addi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1888
static void op_ge(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2159
static void op_tclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2828
static void op_class(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2607
static void op_unsupported(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2873
static void op_sclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2816
static void op_gt(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2138
static void op_div(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2022
static void op_arydup(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2281
static void op_aref(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2296
static void op_module(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2665
mrbc_vm * mrbc_vm_open(struct VM *vm)
Definition vm.c:316
static void op_keyend(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1585
static void op_getiv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:659
static void sub_def_alias(mrbc_class *cls, mrbc_method *method, mrbc_sym sym_id)
Definition vm.c:2726
#define FLAG_DICT
static void op_argary(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1351
static void op_super(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1257
static void op_ssend(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1195
static void op_setiv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:685
static void op_getidx(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:892
static void op_apost(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2342
static void op_arypush(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2260
static void op_aset(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2326
#define CALL_MAXARGS
Definition vm.c:30
static void op_nop(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:439
static void op_ext(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2846
static void op_setgv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:645
mrbc_sym mrbc_get_callee_symid(struct VM *vm)
Definition vm.c:192
static void op_return(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1682
static void op_hashcat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2508
static void op_loadi16(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:525
static void op_jmpuw(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:976
static void op_getupvar(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:827
static void op_return_blk(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1695
static void op_karg(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1606
static void op_eq(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2075
static void op_key_p(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1567
static void op_intern(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2383
static void op_rescue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1025
static void op_loadineg(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:493
static void op_block(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2528
static void op_loadl(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:465
static void op_le(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2117
static void op_range_exc(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2577
static void op_subi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1955
void mrbc_vm_begin(struct VM *vm)
Definition vm.c:348
static void op_method(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2545
static void op_setconst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:764
static void op_array2(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2201
static void op_arycat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2222
static void op_blkpush(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1795
static void op_enter(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1423
#define FLAG_KW
static void op_loadself(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:582
#define FLAG_REST
void mrbc_cleanup_vm(void)
Definition vm.c:180
static void op_jmp(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:918
static void op_sub(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1915
static void send_by_name(struct VM *vm, mrbc_sym sym_id, int a, int c)
Definition vm.c:52
static void op_range_inc(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2562
static void op_jmpnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:961
static void op_loadi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:479
int mrbc_vm_run(struct VM *vm)
Definition vm.c:2889
static void op_loadi32(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:540
static void op_hashadd(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2485
static void op_loadnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:568
static void op_exec(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2699
static void op_getmcnst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:784
static void op_raiseif(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1042
const char * mrbc_get_callee_name(struct VM *vm)
Definition vm.c:209
static void op_loadf(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:611
static void op_break(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1749
static void op_string(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2422
void mrbc_vm_close(struct VM *vm)
Definition vm.c:411
static uint16_t free_vm_bitmap[MAX_VM_COUNT/16+1]
for getting the VM ID
Definition vm.c:38
#define FLAG_M2
static void op_oclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2592
#define mrbc_irep_pool_ptr(irep, n)
get a pointer to n'th pool data.
Definition vm.h:88
static mrbc_value * mrbc_get_self(struct VM *vm, mrbc_value *regs)
Definition vm.h:191
struct CALLINFO mrbc_callinfo
Call information.
#define mrbc_irep_symbol_id(irep, n)
get a n'th symbol id in irep
Definition vm.h:77
#define mrbc_irep_child_irep(irep, n)
get a n'th child irep
Definition vm.h:97
struct IREP_CATCH_HANDLER mrbc_irep_catch_handler
IREP Catch Handler.
#define mrbc_irep_symbol_cstr(irep, n)
get a n'th symbol string in irep
Definition vm.h:80
struct IREP mrbc_irep
IREP Internal REPresentation.
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.
#define MAX_VM_COUNT
Definition vm_config.h:18
#define MAX_REGS_SIZE
Definition vm_config.h:23