mruby/c VM Source Code master (2026/08/06)
Loading...
Searching...
No Matches
vm.c
Go to the documentation of this file.
1
16
17/***** Feature test switches ************************************************/
18/***** System headers *******************************************************/
19//@cond
20#include "vm_config.h"
21#include <stddef.h>
22#include <string.h>
23#include <assert.h>
24//@endcond
25
26/***** Local headers ********************************************************/
27#include "opcode.h"
28#include "mrubyc.h"
29
30/***** Constat values *******************************************************/
31#define CALL_MAXARGS 15 // 15 is CALL_MAXARGS in mruby
32
33
34/***** Macros ***************************************************************/
35#define IS_CLASS_OR_MODULE(v) \
36 (mrbc_type(v) == MRBC_TT_CLASS || mrbc_type(v) == MRBC_TT_MODULE)
37
38
39/***** Typedefs *************************************************************/
40/***** Function prototypes **************************************************/
41/***** Local variables ******************************************************/
43static uint16_t free_vm_bitmap[MAX_VM_COUNT / 16 + 1];
44
45
46/***** Global variables *****************************************************/
47/***** Signal catching functions ********************************************/
48/***** Local functions ******************************************************/
49//================================================================
57static void send_by_name( mrbc_vm *vm, mrbc_sym sym_id, int a, int c )
58{
59 int narg = c & 0x0f;
60 int karg = (c >> 4) & 0x0f;
61 int have_block = (c >> 8);
62 mrbc_value *recv = vm->cur_regs + a;
63
64 // If it's packed in an array, expand it.
65 if( narg == CALL_MAXARGS ) {
66 mrbc_value argary = recv[1];
67 int n_move = (karg == CALL_MAXARGS) ? 2 : karg * 2 + 1;
68
69 narg = mrbc_array_size(&argary);
70 for( int i = 0; i < narg; i++ ) {
71 mrbc_incref( &argary.array->data[i] );
72 }
73
74 memmove( recv + narg + 1, recv + 2, sizeof(mrbc_value) * n_move );
75 if( narg == 0 ) {
76 mrbc_set_tt( recv + n_move + 1, MRBC_TT_EMPTY );
77 } else {
78 memcpy( recv + 1, argary.array->data, sizeof(mrbc_value) * narg );
79 }
80 mrbc_decref(&argary);
81 }
82
83 mrbc_value *r1 = recv + narg + 1;
84
85 // Process keyword arguments
86 if( karg ) {
87 if( karg == CALL_MAXARGS ) {
88 assert( mrbc_type(r1[0]) == MRBC_TT_HASH );
89 if( mrbc_hash_size(&r1[0]) == 0 ) {
90 // delete zero size keyword hash.
91 mrbc_decref(&r1[0]);
92 r1[0] = r1[1]; // move block Proc
94 r1--;
95 }
96 } else {
97 // Convert keyword argument to hash.
98 mrbc_value hval = mrbc_hash_new( vm, karg );
99
100 memcpy( hval.hash->data, r1, sizeof(mrbc_value) * karg * 2 );
101 hval.hash->n_stored = karg * 2;
102
103 r1[0] = hval;
104 r1[1] = r1[karg * 2]; // move block Proc
105 memset( r1 + 2, 0, sizeof(mrbc_value) * (karg * 2 - 1) );
106 }
107 r1++;
108 }
109
110 // is not have block
111 if( !have_block ) {
112 mrbc_decref( r1 );
113 mrbc_set_nil( r1 );
114 }
115
116 // find a method
117 mrbc_class *cls = find_class_by_object(recv);
118 mrbc_method method;
119 if( mrbc_find_method( &method, cls, sym_id ) != 0 ) goto CALL_METHOD;
120
121 // method missing?
122 if( mrbc_find_method( &method, cls, MRBC_SYM(method_missing) ) == 0 ) {
123 mrbc_raisef(vm, MRBC_CLASS(NoMethodError),
124 "undefined local variable or method '%s' for %s",
126 if( vm->callinfo_tail != 0 ) {
128 }
129 return;
130 }
131
132 // prepare to call 'method_missing' method.
133 for( int i = narg+1; i != 0; i-- ) { // shift arguments
134 recv[i+1] = recv[i];
135 }
136 mrbc_set_symbol( &recv[1], sym_id );
137 sym_id = MRBC_SYM(method_missing);
138 narg++;
139
140
141 CALL_METHOD:
142 if( !method.c_func ) goto CALL_RUBY_METHOD;
143
144 vm->callee_sym_id = sym_id;
145 method.func(vm, recv, narg);
146
147 if( mrbc_israised(vm) && vm->exception.exception->method_id == 0 ) {
148 vm->exception.exception->method_id = sym_id;
149 }
150 if( sym_id == MRBC_SYM(call) ) return;
151 if( sym_id == MRBC_SYM(new) ) return;
152
153 for( int i = 1; i <= narg + !!karg + have_block; i++ ) {
154 mrbc_decref_empty( recv + i );
155 }
156 return;
157
158
159 CALL_RUBY_METHOD:;
160 mrbc_callinfo *callinfo = mrbc_push_callinfo(vm, sym_id, a, narg);
161 callinfo->own_class = method.cls;
162
163 vm->cur_irep = method.irep;
164 vm->inst = vm->cur_irep->inst;
165 vm->cur_regs = recv;
166}
167
168
169//================================================================
173{
174 const mrbc_irep *irep = vm->cur_irep;
175 int cnt = irep->clen;
176 if( cnt == 0 ) return NULL;
177
178 const mrbc_irep_catch_handler *catch_table =
179 (const mrbc_irep_catch_handler *)(irep->inst + irep->ilen);
180 uint32_t inst = vm->inst - irep->inst;
181
182 for( cnt--; cnt >= 0 ; cnt-- ) {
183 const mrbc_irep_catch_handler *handler = catch_table + cnt;
184 // Catch type and range check
185 if( (handler->type == 1) && // 1=CATCH_FILTER_ENSURE
186 (bin_to_uint32(handler->begin) < inst) &&
187 (inst <= bin_to_uint32(handler->end)) ) {
188 return handler;
189 }
190 }
191
192 return NULL;
193}
194
195
196/***** Global functions *****************************************************/
197
198//================================================================
202{
203 memset(free_vm_bitmap, 0, sizeof(free_vm_bitmap));
204}
205
206
207//================================================================
210mrbc_callinfo * mrbc_push_callinfo( mrbc_vm *vm, mrbc_sym method_id, int reg_offset, int n_args )
211{
212 mrbc_callinfo *callinfo = mrbc_alloc(vm, sizeof(mrbc_callinfo));
213
214 *callinfo = (mrbc_callinfo){
215#if defined(MRBC_DEBUG)
216 .obj_mark_ = "CI",
217#endif
218 .cur_irep = vm->cur_irep,
219 .inst = vm->inst,
220 .cur_regs = vm->cur_regs,
221 .target_class = vm->target_class,
222 .prev = vm->callinfo_tail,
223 .own_class = 0,
224 .karg_keep = 0,
225 .method_id = method_id,
226 .reg_offset = reg_offset,
227 .n_args = n_args,
228 .is_called_super = 0,
229 .is_called_block = 0,
230 };
231
232 vm->callinfo_tail = callinfo;
233
234 return callinfo;
235}
236
237
238//================================================================
242{
243 assert( vm->callinfo_tail );
244
245 // clear used register.
246 mrbc_callinfo *callinfo = vm->callinfo_tail;
247 mrbc_value *r0 = vm->cur_regs;
248
249 for( int i = 1; i < vm->cur_irep->nregs; i++ ) {
250 mrbc_decref_empty( r0+i );
251 }
252
253 if( callinfo->karg_keep ) {
255 }
256
257 // copy callinfo to vm
258 vm->cur_irep = callinfo->cur_irep;
259 vm->inst = callinfo->inst;
260 vm->cur_regs = callinfo->cur_regs;
261 vm->target_class = callinfo->target_class;
262 vm->callinfo_tail = callinfo->prev;
263
264 mrbc_free(vm, callinfo);
265}
266
267
268//================================================================
287mrbc_vm * mrbc_vm_new( int regs_size )
288{
289 unsigned int vm_total_size = sizeof(mrbc_vm) + sizeof(mrbc_value) * regs_size;
290 mrbc_vm *vm = mrbc_raw_alloc(vm_total_size);
291
292 memset(vm, 0, vm_total_size); // caution: assume NULL is zero.
293#if defined(MRBC_DEBUG)
294 memcpy(vm->obj_mark_, "VM", 2);
295#endif
296 vm->flag_need_memfree = 1;
297 vm->regs_size = regs_size;
298
299 return vm;
300}
301
302
303//================================================================
310{
311 if( !vm ) vm = mrbc_vm_new( MAX_REGS_SIZE );
312
313 // allocate vm id.
314 int vm_id;
315 for( vm_id = 0; vm_id < MAX_VM_COUNT; vm_id++ ) {
316 int idx = vm_id >> 4;
317 uint16_t bit = (uint16_t)1 << (vm_id & 0x0f);
318 if( (free_vm_bitmap[idx] & bit) == 0 ) {
319 free_vm_bitmap[idx] |= bit; // found
320 break;
321 }
322 }
323
324 if( vm_id == MAX_VM_COUNT ) {
325 if( vm->flag_need_memfree ) mrbc_raw_free(vm);
326 return NULL;
327 }
328
329 vm->vm_id = ++vm_id;
330
331 return vm;
332}
333
334
335//================================================================
341{
342 vm->cur_irep = vm->top_irep;
343 vm->inst = vm->cur_irep->inst;
344 vm->cur_regs = vm->regs;
345 vm->target_class = MRBC_CLASS(Object);
346 vm->callinfo_tail = NULL;
347 vm->ret_blk = NULL;
349 vm->flag_preemption = 0;
350 vm->flag_stop = 0;
351
352 // set self to reg[0], others nil
353 mrbc_decref( &vm->regs[0] );
354 vm->regs[0] = mrbc_instance_new(vm, MRBC_CLASS(Object), 0);
355 for( int i = 1; i < vm->regs_size; i++ ) {
356 mrbc_set_nil( &vm->regs[i] );
357 }
358}
359
360
361//================================================================
367{
368 if( mrbc_israised(vm) ) {
369#if defined(MRBC_ABORT_BY_EXCEPTION)
370 MRBC_ABORT_BY_EXCEPTION(vm);
371#else
374#endif
375 }
376 assert( vm->ret_blk == 0 );
377
378 int n_used = 0;
379 for( int i = 1; i < vm->regs_size; i++ ) {
380 //mrbc_printf("vm->regs[%d].tt = %d\n", i, mrbc_type(vm->regs[i]));
381 if( mrbc_type(vm->regs[i]) != MRBC_TT_NIL ) n_used = i;
382 mrbc_decref_empty(&vm->regs[i]);
383 }
384 (void)n_used; // avoid warning.
385#if defined(MRBC_DEBUG_REGS)
386 mrbc_printf("Finally number of registers used was %d in VM %d.\n",
387 n_used, vm->vm_id );
388#endif
389
390#if defined(MRBC_ALLOC_VMID)
391 mrbc_global_clear_vm_id();
392 mrbc_free_all(vm);
393#endif
394}
395
396
397//================================================================
403{
404 mrbc_decref( &vm->regs[0] );
405
406 // free vm id.
407 if( vm->vm_id != 0 ) {
408 int idx = (vm->vm_id-1) >> 4;
409 uint16_t bit = (uint16_t)1 << ((vm->vm_id-1) & 0x0f);
410 free_vm_bitmap[idx] &= ~bit;
411 }
412
413 // free irep and vm
414 if( vm->top_irep ) mrbc_irep_free( vm->top_irep );
415 if( vm->flag_need_memfree ) mrbc_raw_free(vm);
416}
417
418
419/***** opecode functions ****************************************************/
420#if defined(MRBC_SUPPORT_OP_EXT)
421#define EXT , int ext
422#else
423#define EXT
424#endif
425//================================================================
430static inline void op_nop( mrbc_vm *vm, mrbc_value *regs EXT )
431{
432 FETCH_Z();
433}
434
435
436//================================================================
441static inline void op_move( mrbc_vm *vm, mrbc_value *regs EXT )
442{
443 FETCH_BB();
444
445 mrbc_incref(&regs[b]);
446 mrbc_decref(&regs[a]);
447 regs[a] = regs[b];
448}
449
450
451//================================================================
456static inline void op_loadl( mrbc_vm *vm, mrbc_value *regs EXT )
457{
458 FETCH_BB();
459
460 mrbc_decref(&regs[a]);
461 regs[a] = mrbc_irep_pool_value(vm, b);
462}
463
464
465//================================================================
470static inline void op_loadi8( mrbc_vm *vm, mrbc_value *regs EXT )
471{
472 FETCH_BB();
473
474 mrbc_decref(&regs[a]);
475 mrbc_set_integer(&regs[a], b);
476}
477
478
479//================================================================
484static inline void op_loadineg( mrbc_vm *vm, mrbc_value *regs EXT )
485{
486 FETCH_BB();
487
488 mrbc_decref(&regs[a]);
489 mrbc_set_integer(&regs[a], -(mrbc_int_t)b);
490}
491
492
493//================================================================
498static inline void op_loadi_n( mrbc_vm *vm, mrbc_value *regs EXT )
499{
500 // get n
501 int opcode = vm->inst[-1];
502 int n = opcode - OP_LOADI_0;
503
504 FETCH_B();
505
506 mrbc_decref(&regs[a]);
507 mrbc_set_integer(&regs[a], n);
508}
509
510
511//================================================================
516static inline void op_loadi16( mrbc_vm *vm, mrbc_value *regs EXT )
517{
518 FETCH_BS();
519
520 mrbc_decref(&regs[a]);
521 int16_t signed_b = (int16_t)b;
522 mrbc_set_integer(&regs[a], signed_b);
523}
524
525
526//================================================================
531static inline void op_loadi32( mrbc_vm *vm, mrbc_value *regs EXT )
532{
533 FETCH_BSS();
534
535 mrbc_decref(&regs[a]);
536 mrbc_set_integer(&regs[a], (((int32_t)b<<16)+(int32_t)c));
537}
538
539
540//================================================================
545static inline void op_loadsym( mrbc_vm *vm, mrbc_value *regs EXT )
546{
547 FETCH_BB();
548
549 mrbc_decref(&regs[a]);
551}
552
553
554//================================================================
559static inline void op_loadnil( mrbc_vm *vm, mrbc_value *regs EXT )
560{
561 FETCH_B();
562
563 mrbc_decref(&regs[a]);
564 mrbc_set_nil(&regs[a]);
565}
566
567
568//================================================================
573static inline void op_loadself( mrbc_vm *vm, mrbc_value *regs EXT )
574{
575 FETCH_B();
576
577 mrbc_decref(&regs[a]);
578 regs[a] = *mrbc_get_self( vm, regs );
579 mrbc_incref( &regs[a] );
580}
581
582
583//================================================================
588static inline void op_loadtrue( mrbc_vm *vm, mrbc_value *regs EXT )
589{
590 FETCH_B();
591
592 mrbc_decref(&regs[a]);
593 mrbc_set_true(&regs[a]);
594}
595
596
597//================================================================
602static inline void op_loadfalse( mrbc_vm *vm, mrbc_value *regs EXT )
603{
604 FETCH_B();
605
606 mrbc_decref(&regs[a]);
607 mrbc_set_false(&regs[a]);
608}
609
610
611//================================================================
616static inline void op_getgv( mrbc_vm *vm, mrbc_value *regs EXT )
617{
618 FETCH_BB();
619
620 mrbc_decref(&regs[a]);
622 if( v == NULL ) {
623 mrbc_set_nil(&regs[a]);
624 } else {
625 mrbc_incref(v);
626 regs[a] = *v;
627 }
628}
629
630
631//================================================================
636static inline void op_setgv( mrbc_vm *vm, mrbc_value *regs EXT )
637{
638 FETCH_BB();
639
640 mrbc_incref(&regs[a]);
641 mrbc_set_global( mrbc_irep_symbol_id(vm->cur_irep, b), &regs[a] );
642}
643
644
645//================================================================
650static inline void op_getiv( mrbc_vm *vm, mrbc_value *regs EXT )
651{
652 FETCH_BB();
653
654 const char *sym_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
655 mrbc_sym sym_id = mrbc_str_to_symid(sym_name+1); // skip '@'
656 if( sym_id < 0 ) {
657 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
658 return;
659 }
660
661 mrbc_value *self = mrbc_get_self( vm, regs );
662 mrbc_decref(&regs[a]);
663 regs[a] = mrbc_instance_getiv(self, sym_id);
664}
665
666
667//================================================================
672static inline void op_setiv( mrbc_vm *vm, mrbc_value *regs EXT )
673{
674 FETCH_BB();
675
676 const char *sym_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
677 mrbc_sym sym_id = mrbc_str_to_symid(sym_name+1); // skip '@'
678 if( sym_id < 0 ) {
679 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
680 return;
681 }
682
683 mrbc_value *self = mrbc_get_self( vm, regs );
684 if( mrbc_instance_setiv(self, sym_id, &regs[a]) == E_NOTIMP_ERROR ) {
685 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), 0);
686 }
687}
688
689
690//================================================================
695static inline void op_getconst( mrbc_vm *vm, mrbc_value *regs EXT )
696{
697 FETCH_BB();
698
699 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
700 mrbc_class *crit_cls;
701 mrbc_value *ret;
702
703 if( vm->callinfo_tail && vm->callinfo_tail->own_class ) {
704 crit_cls = vm->callinfo_tail->own_class;
705 if( crit_cls->flag_alias ) crit_cls = crit_cls->aliased;
706 } else {
707 crit_cls = find_class_by_object( mrbc_get_self(vm, regs) );
708 }
709
710 // search in my class, then search nested outer class.
711 mrbc_class *cls = crit_cls;
712 while( 1 ) {
713 ret = mrbc_get_class_const(cls, sym_id);
714 if( ret ) goto DONE;
715 if( !mrbc_is_nested_symid(cls->sym_id) ) break;
716
717 mrbc_sym outer_id, inner_id;
718 mrbc_separate_nested_symid( cls->sym_id, &outer_id, &inner_id );
719 cls = mrbc_get_const( outer_id )->cls;
720 }
721
722 // search in super class.
724 int nest_idx = 0;
725
726 cls = crit_cls;
727 while( (cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx )) ) {
728 if( cls->flag_alias ) cls = cls->aliased;
729 ret = mrbc_get_class_const(cls, sym_id);
730 if( ret ) goto DONE;
731 }
732
733 // is top level constant definition?
734 ret = mrbc_get_const(sym_id);
735 if( ret == NULL ) {
736 mrbc_raisef( vm, MRBC_CLASS(NameError),
737 "uninitialized constant %s", mrbc_symid_to_str(sym_id));
738 return;
739 }
740
741 DONE:
742 mrbc_incref(ret);
743 mrbc_decref(&regs[a]);
744 regs[a] = *ret;
745}
746
747
748//================================================================
753static inline void op_setconst( mrbc_vm *vm, mrbc_value *regs EXT )
754{
755 FETCH_BB();
756
757 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
758
759 mrbc_incref(&regs[a]);
760 if( IS_CLASS_OR_MODULE(regs[0]) ) {
761 mrbc_set_class_const(regs[0].cls, sym_id, &regs[a]);
762 } else {
763 mrbc_set_const(sym_id, &regs[a]);
764 }
765}
766
767
768//================================================================
773static inline void op_getmcnst( mrbc_vm *vm, mrbc_value *regs EXT )
774{
775 FETCH_BB();
776
777 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
778 mrbc_class *cls = regs[a].cls;
779 mrbc_value *ret;
780
781 // ::CONST case
782 if( cls->sym_id == MRBC_SYM(Object) ) {
783 ret = mrbc_get_const(sym_id);
784 if( ret == NULL ) {
785 mrbc_raisef( vm, MRBC_CLASS(NameError), "uninitialized constant %s::%s",
786 "", mrbc_symid_to_str( sym_id ));
787 return;
788 }
789 goto DONE;
790 }
791
793 int nest_idx = 0;
794
795 while( !(ret = mrbc_get_class_const(cls, sym_id)) ) {
796 cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx );
797 if( !cls ) {
798 mrbc_raisef( vm, MRBC_CLASS(NameError), "uninitialized constant %s::%s",
799 mrbc_symid_to_str( regs[a].cls->sym_id ), mrbc_symid_to_str( sym_id ));
800 return;
801 }
802 if( cls->flag_alias ) cls = cls->aliased;
803 }
804
805 DONE:
806 mrbc_incref(ret);
807 mrbc_decref(&regs[a]);
808 regs[a] = *ret;
809}
810
811
812//================================================================
820static inline void op_getupvar( mrbc_vm *vm, mrbc_value *regs EXT )
821{
822 FETCH_BBB();
823
824 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
825 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
826
827 for( int i = 0; i < c; i++ ) {
828 assert( callinfo );
829 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
830
831 if( mrbc_type(*reg0) != MRBC_TT_PROC ) break; // What to do?
832 callinfo = reg0->proc->callinfo;
833 }
834
835 mrbc_value *p_val;
836 if( callinfo == 0 ) {
837 p_val = vm->regs + b;
838 } else {
839 p_val = callinfo->cur_regs + callinfo->reg_offset + b;
840 }
841 mrbc_incref( p_val );
842
843 mrbc_decref( &regs[a] );
844 regs[a] = *p_val;
845}
846
847
848//================================================================
853static inline void op_setupvar( mrbc_vm *vm, mrbc_value *regs EXT )
854{
855 FETCH_BBB();
856
857 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
858 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
859
860 for( int i = 0; i < c; i++ ) {
861 assert( callinfo );
862 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
863 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
864 callinfo = reg0->proc->callinfo;
865 }
866
867 mrbc_value *p_val;
868 if( callinfo == 0 ) {
869 p_val = vm->regs + b;
870 } else {
871 p_val = callinfo->cur_regs + callinfo->reg_offset + b;
872 }
873 mrbc_decref( p_val );
874
875 mrbc_incref( &regs[a] );
876 *p_val = regs[a];
877}
878
879
880//================================================================
885static inline void op_getidx( mrbc_vm *vm, mrbc_value *regs EXT )
886{
887 FETCH_B();
888
889 send_by_name( vm, MRBC_SYMID_BL_BR, a, 1 );
890}
891
892
893//================================================================
898static inline void op_getidx0( mrbc_vm *vm, mrbc_value *regs EXT )
899{
900 FETCH_BB();
901
902 if( a != b ) {
903 mrbc_decref( &regs[a] );
904 regs[a] = regs[b];
905 mrbc_incref( &regs[a] );
906 }
907 mrbc_decref( &regs[a+1] );
908 mrbc_set_integer( &regs[a+1], 0 );
909 send_by_name( vm, MRBC_SYMID_BL_BR, a, 1 );
910}
911
912
913//================================================================
918static inline void op_setidx( mrbc_vm *vm, mrbc_value *regs EXT )
919{
920 FETCH_B();
921
922 send_by_name( vm, MRBC_SYMID_BL_BR_EQ, a, 2 );
923}
924
925
926//================================================================
931static inline void op_jmp( mrbc_vm *vm, mrbc_value *regs EXT )
932{
933 FETCH_S();
934
935 vm->inst += (int16_t)a;
936}
937
938
939//================================================================
944static inline void op_jmpif( mrbc_vm *vm, mrbc_value *regs EXT )
945{
946 FETCH_BS();
947
948 if( mrbc_type(regs[a]) > MRBC_TT_FALSE ) {
949 vm->inst += (int16_t)b;
950 }
951}
952
953
954//================================================================
959static inline void op_jmpnot( mrbc_vm *vm, mrbc_value *regs EXT )
960{
961 FETCH_BS();
962
963 if( mrbc_type(regs[a]) <= MRBC_TT_FALSE ) {
964 vm->inst += (int16_t)b;
965 }
966}
967
968
969//================================================================
974static inline void op_jmpnil( mrbc_vm *vm, mrbc_value *regs EXT )
975{
976 FETCH_BS();
977
978 if( mrbc_type(regs[a]) == MRBC_TT_NIL ) {
979 vm->inst += (int16_t)b;
980 }
981}
982
983
984//================================================================
989static inline void op_jmpuw( mrbc_vm *vm, mrbc_value *regs EXT )
990{
991 FETCH_S();
992
993 const uint8_t *jump_inst = vm->inst + (int16_t)a;
994
995 // check catch handler (ensure)
997 if( !handler ) {
998 vm->inst = jump_inst;
999 return;
1000 }
1001
1002 // check whether the jump point is inside or outside the catch handler.
1003 uint32_t jump_point = jump_inst - vm->cur_irep->inst;
1004 if( (bin_to_uint32(handler->begin) < jump_point) &&
1005 (jump_point <= bin_to_uint32(handler->end)) ) {
1006 vm->inst = jump_inst;
1007 return;
1008 }
1009
1010 // jump point is outside, thus jump to ensure.
1011 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1013 vm->exception.handle = (void*)jump_inst;
1014 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1015}
1016
1017
1018//================================================================
1023static inline void op_except( mrbc_vm *vm, mrbc_value *regs EXT )
1024{
1025 FETCH_B();
1026
1027 mrbc_decref( &regs[a] );
1028 regs[a] = vm->exception;
1029 mrbc_set_nil( &vm->exception );
1030}
1031
1032
1033//================================================================
1038static inline void op_rescue( mrbc_vm *vm, mrbc_value *regs EXT )
1039{
1040 FETCH_BB();
1041
1042 assert( mrbc_type(regs[a]) == MRBC_TT_EXCEPTION );
1043 assert( mrbc_type(regs[b]) == MRBC_TT_CLASS );
1044
1045 int res = mrbc_obj_is_kind_of( &regs[a], regs[b].cls );
1046 mrbc_set_bool( &regs[b], res );
1047}
1048
1049
1050//================================================================
1055static inline void op_raiseif( mrbc_vm *vm, mrbc_value *regs EXT )
1056{
1057 FETCH_B();
1058
1059 // save the parameter.
1060 mrbc_value ra = regs[a];
1061 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1062
1063 switch( mrbc_type(ra) ) {
1064 case MRBC_TT_RETURN: goto CASE_OP_RETURN;
1065 case MRBC_TT_RETURN_BLK: goto CASE_OP_RETURN_BLK;
1066 case MRBC_TT_BREAK: goto CASE_OP_BREAK;
1067 case MRBC_TT_JMPUW: goto CASE_OP_JMPUW;
1068 case MRBC_TT_EXCEPTION: goto CASE_OP_EXCEPTION;
1069 default: break;
1070 }
1071
1072 assert( mrbc_type(ra) == MRBC_TT_NIL );
1073 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1074 return;
1075
1076
1077CASE_OP_RETURN:
1078 {
1079 // find ensure that still needs to be executed.
1081 if( handler ) {
1082 vm->exception = ra;
1083 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1084 return;
1085 }
1086
1087 // set the return value and return to caller.
1088 mrbc_decref(&regs[0]);
1089 regs[0] = regs[ vm->cur_irep->nregs ];
1090 mrbc_set_tt( &regs[ vm->cur_irep->nregs ], MRBC_TT_EMPTY );
1091
1093 return;
1094 }
1095
1096
1097CASE_OP_RETURN_BLK:
1098 {
1099 assert( vm->ret_blk );
1100
1101 // return to the proc generated level.
1102 while( 1 ) {
1103 // find ensure that still needs to be executed.
1105 if( handler ) {
1106 vm->exception = ra;
1107 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1108 return;
1109 }
1110
1111 // Is it the origin (generator) of proc?
1112 if( vm->callinfo_tail == vm->ret_blk->callinfo_self ) break;
1113
1115 }
1116
1117 // top level return ?
1118 if( vm->callinfo_tail == NULL ) {
1120 vm->ret_blk = 0;
1121
1122 vm->flag_preemption = 1;
1123 vm->flag_stop = 1;
1124 return;
1125 }
1126
1127 // set the return value and return to caller.
1129 mrbc_decref(reg0);
1130 *reg0 = vm->ret_blk->ret_val;
1131
1133 vm->ret_blk = 0;
1134
1136 return;
1137 }
1138
1139
1140CASE_OP_BREAK:
1141 {
1142 assert( vm->ret_blk );
1143
1144 // return to the proc generated level.
1145 int reg_offset = 0;
1146 while( vm->callinfo_tail != vm->ret_blk->callinfo ) {
1147 // find ensure that still needs to be executed.
1149 if( handler ) {
1150 vm->exception = ra;
1151 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1152 return;
1153 }
1154
1155 reg_offset = vm->callinfo_tail->reg_offset;
1157 }
1158
1159 // set the return value.
1160 mrbc_value *reg0 = vm->cur_regs + reg_offset;
1161 mrbc_decref(reg0);
1162 *reg0 = vm->ret_blk->ret_val;
1163
1165 vm->ret_blk = 0;
1166 return;
1167 }
1168
1169
1170CASE_OP_JMPUW:
1171 {
1172 // find ensure that still needs to be executed.
1174 if( !handler ) {
1175 vm->inst = ra.handle;
1176 return;
1177 }
1178
1179 // check whether the jump point is inside or outside the catch handler.
1180 uint32_t jump_point = (uint8_t *)ra.handle - vm->cur_irep->inst;
1181 if( (bin_to_uint32(handler->begin) < jump_point) &&
1182 (jump_point <= bin_to_uint32(handler->end)) ) {
1183 vm->inst = ra.handle;
1184 return;
1185 }
1186
1187 // jump point is outside, thus jump to ensure.
1188 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1189 vm->exception = ra;
1190 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1191 return;
1192 }
1193
1194
1195CASE_OP_EXCEPTION:
1196 {
1197 vm->exception = ra;
1198 vm->flag_preemption = 2;
1199 return;
1200 }
1201}
1202
1203
1204//================================================================
1209static inline void op_matcherr( mrbc_vm *vm, mrbc_value *regs EXT )
1210{
1211 FETCH_B();
1212
1213 if( mrbc_type(regs[a]) <= MRBC_TT_FALSE ) {
1214 mrbc_raise( vm, MRBC_CLASS(NoMatchingPatternError), 0);
1215 }
1216}
1217
1218
1219//================================================================
1224static inline void op_ssend( mrbc_vm *vm, mrbc_value *regs EXT )
1225{
1226 FETCH_BBB();
1227
1228 mrbc_decref( &regs[a] );
1229 regs[a] = *mrbc_get_self( vm, regs );
1230 mrbc_incref( &regs[a] );
1231
1232 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c );
1233}
1234
1235
1236
1237//================================================================
1242static inline void op_ssend0( mrbc_vm *vm, mrbc_value *regs EXT )
1243{
1244 FETCH_BB();
1245
1246 mrbc_decref( &regs[a] );
1247 regs[a] = *mrbc_get_self( vm, regs );
1248 mrbc_incref( &regs[a] );
1249
1250 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, 0 );
1251}
1252
1253
1254
1255//================================================================
1260static inline void op_ssendb( mrbc_vm *vm, mrbc_value *regs EXT )
1261{
1262 FETCH_BBB();
1263
1264 mrbc_decref( &regs[a] );
1265 regs[a] = *mrbc_get_self( vm, regs );
1266 mrbc_incref( &regs[a] );
1267
1268 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c | 0x100 );
1269}
1270
1271
1272
1273//================================================================
1278static inline void op_send( mrbc_vm *vm, mrbc_value *regs EXT )
1279{
1280 FETCH_BBB();
1281
1282 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c );
1283}
1284
1285
1286//================================================================
1291static inline void op_send0( mrbc_vm *vm, mrbc_value *regs EXT )
1292{
1293 FETCH_BB();
1294
1295 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, 0 );
1296}
1297
1298
1299//================================================================
1304static inline void op_sendb( mrbc_vm *vm, mrbc_value *regs EXT )
1305{
1306 FETCH_BBB();
1307
1308 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c | 0x100 );
1309}
1310
1311
1312//================================================================
1317static inline void op_blkcall( mrbc_vm *vm, mrbc_value *regs EXT )
1318{
1319 FETCH_BB();
1320
1321 send_by_name( vm, MRBC_SYM(call), a, b | 0x100 );
1322}
1323
1324
1325//================================================================
1330static inline void op_super( mrbc_vm *vm, mrbc_value *regs EXT )
1331{
1332 FETCH_BB();
1333
1334 int narg = b & 0x0f;
1335 int karg = (b >> 4) & 0x0f;
1336 mrbc_value *recv = regs + a; // new regs[0]
1337
1338 // set self to new regs[0]
1339 mrbc_value *self = mrbc_get_self(vm, regs);
1340 assert( mrbc_type(*self) != MRBC_TT_PROC );
1341
1342 mrbc_incref( self );
1343 mrbc_decref( recv );
1344 *recv = *self;
1345
1346 // If it's packed in an array, expand it.
1347 if( narg == CALL_MAXARGS ) {
1348 mrbc_value argary = recv[1];
1349 int n_move = (karg == CALL_MAXARGS) ? 2 : karg * 2 + 1;
1350
1351 narg = mrbc_array_size(&argary);
1352 for( int i = 0; i < narg; i++ ) {
1353 mrbc_incref( &argary.array->data[i] );
1354 }
1355
1356 memmove( recv + narg + 1, recv + 2, sizeof(mrbc_value) * n_move );
1357 if( narg == 0 ) {
1358 mrbc_set_tt( recv + 2, MRBC_TT_EMPTY );
1359 } else {
1360 memcpy( recv + 1, argary.array->data, sizeof(mrbc_value) * narg );
1361 }
1362 mrbc_decref(&argary);
1363 }
1364
1365 mrbc_value *r1 = recv + narg + 1;
1366
1367 // Convert keyword argument to hash.
1368 if( karg && karg != CALL_MAXARGS ) {
1369 mrbc_value hval = mrbc_hash_new( vm, karg );
1370
1371 memcpy( hval.hash->data, r1, sizeof(mrbc_value) * karg * 2 );
1372 hval.hash->n_stored = karg * 2;
1373
1374 r1[0] = hval;
1375 r1[1] = r1[karg * 2]; // move block Proc
1376 memset( r1 + 2, 0, sizeof(mrbc_value) * (karg * 2 - 1) );
1377 }
1378
1379 // find super class
1380 mrbc_callinfo *callinfo = vm->callinfo_tail;
1381 if( callinfo == NULL ) {
1382 mrbc_raise(vm, MRBC_CLASS(NoMethodError), "super called outside of method");
1383 return;
1384 }
1385 mrbc_class *cls = callinfo->own_class;
1386 mrbc_method method;
1387
1388 assert( cls );
1389 cls = cls->super;
1390 assert( cls );
1391 if( mrbc_find_method( &method, cls, callinfo->method_id ) == 0 ) {
1392 mrbc_raisef( vm, MRBC_CLASS(NoMethodError),
1393 "no superclass method '%s' for %s",
1394 mrbc_symid_to_str(callinfo->method_id),
1395 mrbc_symid_to_str(callinfo->own_class->sym_id));
1396 return;
1397 }
1398
1399 // call C function and return.
1400 if( method.c_func ) {
1401 method.func(vm, recv, narg - !!karg);
1402 for( int i = 1; i <= narg+1; i++ ) {
1403 mrbc_decref_empty( recv + i );
1404 }
1405 return;
1406 }
1407
1408 // call Ruby method.
1409 callinfo = mrbc_push_callinfo(vm, callinfo->method_id, a, narg);
1410 callinfo->own_class = method.cls;
1411 callinfo->is_called_super = 1;
1412
1413 vm->cur_irep = method.irep;
1414 vm->inst = vm->cur_irep->inst;
1415 vm->cur_regs = recv;
1416}
1417
1418
1419//================================================================
1426static inline void op_argary( mrbc_vm *vm, mrbc_value *regs EXT )
1427{
1428 FETCH_BS();
1429
1430 int m1 = (b >> 11) & 0x1f;
1431 int r = (b >> 10) & 0x01;
1432 int m2 = (b >> 5) & 0x1f;
1433 int d = (b >> 4) & 0x01;
1434 int lv = (b ) & 0x0f;
1435
1436 if( m2 ) {
1437 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1438 return;
1439 }
1440
1441 mrbc_value *reg0 = regs;
1442 mrbc_callinfo *callinfo = 0;
1443
1444 // rewind proc nest
1445 if( lv ) {
1446 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1447 callinfo = reg0->proc->callinfo;
1448 assert( callinfo );
1449
1450 for( int i = 1; i < lv; i ++ ) {
1451 reg0 = callinfo->cur_regs + callinfo->reg_offset;
1452 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1453 callinfo = reg0->proc->callinfo;
1454 assert( callinfo );
1455 }
1456
1457 reg0 = callinfo->cur_regs + callinfo->reg_offset;
1458 }
1459
1460 // create argument array.
1461 int rest_len = 0;
1462 mrbc_value *rest_data = NULL;
1463 if( r && mrbc_type(reg0[m1+1]) == MRBC_TT_ARRAY ) {
1464 rest_len = mrbc_array_size(&reg0[m1+1]);
1465 rest_data = reg0[m1+1].array->data;
1466 }
1467
1468 mrbc_value argary = mrbc_array_new( vm, m1 + rest_len + m2 );
1469
1470 for( int i = 1; i <= m1; i++ ) {
1471 mrbc_incref( &reg0[i] );
1472 mrbc_array_push( &argary, &reg0[i] );
1473 }
1474
1475 for( int i = 0; i < rest_len; i++ ) {
1476 mrbc_incref( &rest_data[i] );
1477 mrbc_array_push( &argary, &rest_data[i] );
1478 }
1479
1480 int block_reg = m1 + r + m2;
1481
1482 if( d ) {
1483 if( !callinfo ) callinfo = vm->callinfo_tail;
1484 assert( callinfo->karg_keep );
1485 mrbc_value karg = mrbc_immediate_value(MRBC_TT_HASH, .hash = callinfo->karg_keep);
1486 karg = mrbc_hash_dup(vm, &karg);
1487 mrbc_array_push( &argary, &karg );
1488 block_reg++;
1489 }
1490
1491 mrbc_decref( &regs[a] );
1492 regs[a] = argary;
1493
1494 // copy a block object
1495 mrbc_decref( &regs[a+1] );
1496 regs[a+1] = reg0[block_reg+1];
1497 mrbc_incref( &regs[a+1] );
1498}
1499
1500
1501//================================================================
1508static inline void op_enter( mrbc_vm *vm, mrbc_value *regs EXT )
1509{
1510#define FLAG_REST 0x1000
1511#define FLAG_M2 0x0f80
1512#define FLAG_KW 0x007c
1513#define FLAG_DICT 0x0002
1514#define FLAG_BLOCK 0x0001
1515
1516 FETCH_W();
1517
1518 // Check the number of registers to use.
1519 int reg_use_max = regs - vm->regs + vm->cur_irep->nregs;
1520 if( reg_use_max >= vm->regs_size ) {
1521 mrbc_raise( vm, MRBC_CLASS(Exception), "MAX_REGS_SIZE overflow");
1522 return;
1523 }
1524
1525 // Check m2 parameter.
1526 if( a & FLAG_M2 ) {
1527 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1528 return;
1529 }
1530
1531 int m1 = (a >> 18) & 0x1f; // num of required parameters 1
1532 int o = (a >> 13) & 0x1f; // num of optional parameters
1533 int argc = vm->callinfo_tail->n_args;
1534 int flag_kwarg = mrbc_type(regs[argc+1]) == MRBC_TT_HASH;
1535
1536 argc += flag_kwarg;
1537
1538 if( argc < m1 && mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1539 mrbc_raise( vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1540 return;
1541 }
1542
1543 // save proc (or nil) object.
1544 mrbc_value proc = regs[argc+1];
1545 mrbc_set_tt( &regs[argc+1], MRBC_TT_EMPTY );
1546
1547 // support yield [...] pattern, to expand array.
1548 if( mrbc_type(regs[0]) == MRBC_TT_PROC &&
1549 mrbc_type(regs[1]) == MRBC_TT_ARRAY &&
1550 argc == 1 && m1 > 1 ) {
1551 mrbc_value argary = regs[1];
1552 int argary_size = mrbc_array_size(&argary);
1553
1554 argc = argary_size > m1 ? argary_size : m1;
1555
1556 for( int i = argc; i > 0; i-- ) {
1557 if( i != 1 ) mrbc_decref( &regs[i] );
1558 if( argary_size >= i ) {
1559 regs[i] = argary.array->data[i-1];
1560 mrbc_incref(&regs[i]);
1561 } else {
1562 mrbc_set_nil( &regs[i] );
1563 }
1564 }
1565
1566 mrbc_decref(&argary);
1567 }
1568
1569 // dictionary, keyword or rest parameter exists.
1570 if( a & (FLAG_DICT|FLAG_KW|FLAG_REST) ) {
1571 mrbc_value dict;
1572 if( a & (FLAG_DICT|FLAG_KW) ) {
1573 if( (argc - m1) > 0 && mrbc_type(regs[argc]) == MRBC_TT_HASH ) {
1574 dict = regs[argc];
1575 mrbc_set_tt( &regs[argc--], MRBC_TT_EMPTY );
1576 } else {
1577 dict = mrbc_hash_new( vm, 0 );
1578 }
1579 }
1580
1581 mrbc_value rest;
1582 if( a & FLAG_REST ) {
1583 int rest_size = argc - m1 - o;
1584 if( rest_size < 0 ) rest_size = 0;
1585 rest = mrbc_array_new(vm, rest_size);
1586
1587 int rest_reg = m1 + o + 1;
1588 for( int i = 0; i < rest_size; i++ ) {
1589 mrbc_array_push( &rest, &regs[rest_reg] );
1590 mrbc_set_tt( &regs[rest_reg++], MRBC_TT_EMPTY );
1591 }
1592 }
1593
1594 // reorder arguments.
1595 for( int i = argc; i < m1; ) {
1596 mrbc_decref( &regs[++i] );
1597 mrbc_set_nil( &regs[i] );
1598 }
1599 int i = m1 + o;
1600 if( a & FLAG_REST ) {
1601 mrbc_decref(&regs[++i]);
1602 regs[i] = rest;
1603 }
1604 if( a & (FLAG_DICT|FLAG_KW) ) {
1605 mrbc_decref(&regs[++i]);
1606 regs[i] = dict;
1607 vm->callinfo_tail->karg_keep = mrbc_hash_dup(vm, &dict).hash;
1608 }
1609 mrbc_decref(&regs[i+1]);
1610 regs[i+1] = proc;
1611 vm->callinfo_tail->n_args = i;
1612
1613 } else {
1614 // reorder arguments.
1615 for( int i = argc; i < m1; ) {
1616 mrbc_decref( &regs[++i] );
1617 mrbc_set_nil( &regs[i] );
1618 }
1619 int i = m1 + o;
1620 mrbc_decref(&regs[i+1]);
1621 regs[i+1] = proc;
1622 vm->callinfo_tail->n_args = i;
1623 }
1624
1625 // prepare for get default arguments.
1626 int jmp_ofs = argc - m1;
1627 if( jmp_ofs > 0 ) {
1628 if( jmp_ofs > o ) {
1629 jmp_ofs = o;
1630
1631 if( !(a & FLAG_REST) && mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1632 mrbc_raise( vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1633 return;
1634 }
1635 }
1636 vm->inst += jmp_ofs * 3; // 3 = bytecode size of OP_JMP
1637 }
1638
1639#undef FLAG_REST
1640#undef FLAG_M2
1641#undef FLAG_KW
1642#undef FLAG_DICT
1643#undef FLAG_BLOCK
1644}
1645
1646
1647//================================================================
1652static inline void op_key_p( mrbc_vm *vm, mrbc_value *regs EXT )
1653{
1654 FETCH_BB();
1655
1656 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1657 mrbc_sym sym_id = mrbc_irep_symbol_id( vm->cur_irep, b );
1658 mrbc_value *v = mrbc_hash_search_by_id( kdict, sym_id );
1659
1660 mrbc_decref(&regs[a]);
1661 mrbc_set_bool(&regs[a], v != NULL);
1662}
1663
1664
1665//================================================================
1670static inline void op_keyend( mrbc_vm *vm, mrbc_value *regs EXT )
1671{
1672 FETCH_Z();
1673
1674 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1675
1676 if( mrbc_hash_size(kdict) != 0 ) {
1678 mrbc_value *kv = mrbc_hash_i_next(&ite);
1679
1680 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "unknown keyword: %s",
1682 }
1683}
1684
1685
1686//================================================================
1691static inline void op_karg( mrbc_vm *vm, mrbc_value *regs EXT )
1692{
1693 FETCH_BB();
1694
1695 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1696 mrbc_sym sym_id = mrbc_irep_symbol_id( vm->cur_irep, b );
1697 mrbc_value v = mrbc_hash_remove_by_id( kdict, sym_id );
1698
1699 if( mrbc_type(v) == MRBC_TT_EMPTY ) {
1700 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "missing keywords: %s",
1701 mrbc_symid_to_str(sym_id));
1702 return;
1703 }
1704
1705 mrbc_decref(&regs[a]);
1706 regs[a] = v;
1707}
1708
1709
1710//================================================================
1713static inline void sub_op_return( mrbc_vm *vm, mrbc_value *regs, int a )
1714{
1715 // If have a ensure, jump to it.
1716 if( vm->cur_irep->clen ) {
1718 if( handler ) {
1719 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1720
1721 // Save the return value in the last+1 register.
1722 regs[ vm->cur_irep->nregs ] = regs[a];
1723 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1724
1726 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1727 return;
1728 }
1729 }
1730
1731 // return without anything if top level.
1732 if( vm->callinfo_tail == NULL ) {
1733 if (vm->flag_permanence == 1) {
1734 mrbc_incref(&regs[a]);
1735 } else {
1736 mrbc_decref(&regs[0]);
1737 regs[0] = regs[a];
1738 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1739 }
1740 vm->flag_preemption = 1;
1741 vm->flag_stop = 1;
1742 return;
1743 }
1744
1745 /* set the return value
1746 (conditions)
1747 iniialize super block then
1748 0 0 0 Set
1749 0 0 1 Set
1750 0 1 0 Set
1751 0 1 1 N/A
1752 1 0 0 Skip
1753 1 0 1 Set
1754 1 1 0 Set
1755 1 1 1 N/A
1756 */
1757 if( vm->callinfo_tail->method_id != MRBC_SYM(initialize) ||
1760 mrbc_decref(&regs[0]);
1761 regs[0] = regs[a];
1762 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1763 }
1764
1766}
1767
1768
1769//================================================================
1774static inline void op_return( mrbc_vm *vm, mrbc_value *regs EXT )
1775{
1776 FETCH_B();
1777
1778 sub_op_return( vm, regs, a );
1779}
1780
1781
1782//================================================================
1787static inline void op_return_blk( mrbc_vm *vm, mrbc_value *regs EXT )
1788{
1789 FETCH_B();
1790
1791 if( mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1792 sub_op_return( vm, regs, a );
1793 return;
1794 }
1795
1796 // Save the return value in the proc object.
1797 mrbc_incref( &regs[0] );
1798 vm->ret_blk = regs[0].proc;
1799 vm->ret_blk->ret_val = regs[a];
1800 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1801
1802 // return to the proc generated level.
1803 while( 1 ) {
1804 // If have a ensure, jump to it.
1806 if( handler ) {
1807 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1809 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1810 return;
1811 }
1812
1813 // Is it the origin (generator) of proc?
1814 if( vm->callinfo_tail == vm->ret_blk->callinfo_self ) break;
1815
1817 }
1818
1819 // top level return ?
1820 if( vm->callinfo_tail == NULL ) {
1821 vm->flag_preemption = 1;
1822 vm->flag_stop = 1;
1823 } else {
1824 // set the return value.
1825 mrbc_decref(&vm->cur_regs[0]);
1826 vm->cur_regs[0] = vm->ret_blk->ret_val;
1827
1829 }
1830
1832 vm->ret_blk = 0;
1833}
1834
1835
1836//================================================================
1841static inline void op_retself( mrbc_vm *vm, mrbc_value *regs EXT )
1842{
1843 FETCH_Z();
1844
1845 mrbc_decref(&regs[1]);
1846 regs[1] = *mrbc_get_self( vm, regs );
1847 mrbc_incref( &regs[1] );
1848
1849 sub_op_return( vm, regs, 1 );
1850}
1851
1852
1853//================================================================
1858static inline void op_retnil( mrbc_vm *vm, mrbc_value *regs EXT )
1859{
1860 FETCH_Z();
1861
1862 mrbc_decref(&regs[1]);
1863 mrbc_set_nil( &regs[1] );
1864
1865 sub_op_return( vm, regs, 1 );
1866}
1867
1868
1869//================================================================
1874static inline void op_rettrue( mrbc_vm *vm, mrbc_value *regs EXT )
1875{
1876 FETCH_Z();
1877
1878 mrbc_decref(&regs[1]);
1879 mrbc_set_true( &regs[1] );
1880
1881 sub_op_return( vm, regs, 1 );
1882}
1883
1884
1885//================================================================
1890static inline void op_retfalse( mrbc_vm *vm, mrbc_value *regs EXT )
1891{
1892 FETCH_Z();
1893
1894 mrbc_decref(&regs[1]);
1895 mrbc_set_false( &regs[1] );
1896
1897 sub_op_return( vm, regs, 1 );
1898}
1899
1900
1901//================================================================
1906static inline void op_break( mrbc_vm *vm, mrbc_value *regs EXT )
1907{
1908 FETCH_B();
1909
1910 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
1911
1912 // Save the return value in the proc object.
1913 mrbc_incref( &regs[0] );
1914 vm->ret_blk = regs[0].proc;
1915 vm->ret_blk->ret_val = regs[a];
1916 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1917
1918 // return to the proc generated level.
1919 // Check the origin (generator) of proc before the ensure handler: once we
1920 // reach the generator, break lands there and its body keeps running, so its
1921 // ensure must fire on the later normal return, not here. Running it now would
1922 // skip the rest of the generator body and corrupt the return value.
1923 int reg_offset = 0;
1924 while( vm->callinfo_tail != vm->ret_blk->callinfo ) {
1925 // If have a ensure, jump to it.
1927 if( handler ) {
1928 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1930 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1931 return;
1932 }
1933
1934 reg_offset = vm->callinfo_tail->reg_offset;
1936 }
1937
1938 // set the return value.
1939 mrbc_value *reg0 = vm->cur_regs + reg_offset;
1940 mrbc_decref(reg0);
1941 *reg0 = vm->ret_blk->ret_val;
1942
1944 vm->ret_blk = 0;
1945}
1946
1947
1948//================================================================
1953static inline void op_blkpush( mrbc_vm *vm, mrbc_value *regs EXT )
1954{
1955 FETCH_BS();
1956
1957 int m1 = (b >> 11) & 0x1f;
1958 int r = (b >> 10) & 0x01;
1959 int m2 = (b >> 5) & 0x1f;
1960 int d = (b >> 4) & 0x01;
1961 int lv = (b ) & 0x0f;
1962
1963 if( m2 ) {
1964 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1965 return;
1966 }
1967
1968 int offset = m1 + r + d + 1;
1969 mrbc_value *blk;
1970
1971 if( lv == 0 ) {
1972 // current env
1973 blk = regs + offset;
1974
1975 } else {
1976 // upper env
1977 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
1978 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
1979
1980 for( int i = 0; i < lv-1; i++ ) {
1981 assert( callinfo );
1982 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
1983 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1984 callinfo = reg0->proc->callinfo;
1985 }
1986
1987 blk = callinfo->cur_regs + callinfo->reg_offset + offset;
1988 }
1989
1990 if( mrbc_type(*blk) != MRBC_TT_PROC ) {
1991 mrbc_raise( vm, MRBC_CLASS(Exception), "no block given (yield)");
1992 return;
1993 }
1994
1995 mrbc_incref(blk);
1996 mrbc_decref(&regs[a]);
1997 regs[a] = *blk;
1998}
1999
2000
2001//================================================================
2006static inline void op_add( mrbc_vm *vm, mrbc_value *regs EXT )
2007{
2008 FETCH_B();
2009
2010 // in case of Integer + Integer
2011 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2012 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2013 regs[a].i += regs[a+1].i;
2014 return;
2015 }
2016
2017#if MRBC_USE_FLOAT
2018 // in case of Integer + Float
2019 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2020 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2021 mrbc_set_float( &regs[a], regs[a].i + regs[a+1].d );
2022 return;
2023 }
2024
2025 // in case of Float + Integer
2026 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2027 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2028 regs[a].d += regs[a+1].i;
2029 return;
2030 }
2031
2032 // in case of Float + Float
2033 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2034 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2035 regs[a].d += regs[a+1].d;
2036 return;
2037 }
2038#endif
2039
2040 // other case
2041 send_by_name( vm, MRBC_SYM(PLUS), a, 1 );
2042}
2043
2044
2045//================================================================
2050static inline void op_addi( mrbc_vm *vm, mrbc_value *regs EXT )
2051{
2052 FETCH_BB();
2053
2054 if( mrbc_type(regs[a]) == MRBC_TT_INTEGER ) {
2055 regs[a].i += b;
2056 return;
2057 }
2058
2059#if MRBC_USE_FLOAT
2060 if( mrbc_type(regs[a]) == MRBC_TT_FLOAT ) {
2061 regs[a].d += b;
2062 return;
2063 }
2064#endif
2065
2066 mrbc_decref(&regs[a+1]);
2067 mrbc_set_integer( &regs[a+1], b);
2068 send_by_name(vm, MRBC_SYM(PLUS), a, 1);
2069}
2070
2071
2072//================================================================
2077static inline void op_sub( mrbc_vm *vm, mrbc_value *regs EXT )
2078{
2079 FETCH_B();
2080
2081 // in case of Integer - Integer
2082 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2083 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2084 regs[a].i -= regs[a+1].i;
2085 return;
2086 }
2087
2088#if MRBC_USE_FLOAT
2089 // in case of Integer - Float
2090 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2091 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2092 mrbc_set_float( &regs[a], regs[a].i - regs[a+1].d );
2093 return;
2094 }
2095
2096 // in case of Float - Integer
2097 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2098 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2099 regs[a].d -= regs[a+1].i;
2100 return;
2101 }
2102
2103 // in case of Float - Float
2104 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2105 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2106 regs[a].d -= regs[a+1].d;
2107 return;
2108 }
2109#endif
2110
2111 // other case
2112 send_by_name( vm, MRBC_SYM(MINUS), a, 1 );
2113}
2114
2115
2116//================================================================
2121static inline void op_subi( mrbc_vm *vm, mrbc_value *regs EXT )
2122{
2123 FETCH_BB();
2124
2125 if( mrbc_type(regs[a]) == MRBC_TT_INTEGER ) {
2126 regs[a].i -= b;
2127 return;
2128 }
2129
2130#if MRBC_USE_FLOAT
2131 if( mrbc_type(regs[a]) == MRBC_TT_FLOAT ) {
2132 regs[a].d -= b;
2133 return;
2134 }
2135#endif
2136
2137 mrbc_decref(&regs[a+1]);
2138 mrbc_set_integer( &regs[a+1], b);
2139 send_by_name(vm, MRBC_SYM(MINUS), a, 1);
2140}
2141
2142
2143//================================================================
2148static inline void op_addilv( mrbc_vm *vm, mrbc_value *regs EXT )
2149{
2150 FETCH_BBB();
2151
2152 switch( mrbc_type(regs[a]) ) {
2153 case MRBC_TT_INTEGER:
2154 regs[a].i += c;
2155 break;
2156
2157#if MRBC_USE_FLOAT
2158 case MRBC_TT_FLOAT:
2159 regs[a].d += c;
2160 break;
2161#endif
2162
2163 default:
2164 mrbc_decref(&regs[a+1]);
2165 mrbc_set_integer( &regs[a+1], c);
2166 send_by_name(vm, MRBC_SYM(PLUS), a, 1);
2167 }
2168}
2169
2170
2171//================================================================
2176static inline void op_subilv( mrbc_vm *vm, mrbc_value *regs EXT )
2177{
2178 FETCH_BBB();
2179
2180 switch( mrbc_type(regs[a]) ) {
2181 case MRBC_TT_INTEGER:
2182 regs[a].i -= c;
2183 break;
2184
2185#if MRBC_USE_FLOAT
2186 case MRBC_TT_FLOAT:
2187 regs[a].d -= c;
2188 break;
2189#endif
2190
2191 default:
2192 mrbc_decref(&regs[a+1]);
2193 mrbc_set_integer( &regs[a+1], c);
2194 send_by_name(vm, MRBC_SYM(MINUS), a, 1);
2195 }
2196}
2197
2198
2199//================================================================
2204static inline void op_mul( mrbc_vm *vm, mrbc_value *regs EXT )
2205{
2206 FETCH_B();
2207
2208 // in case of Integer * Integer
2209 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2210 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2211 regs[a].i *= regs[a+1].i;
2212 return;
2213 }
2214
2215#if MRBC_USE_FLOAT
2216 // in case of Integer * Float
2217 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2218 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2219 mrbc_set_float( &regs[a], regs[a].i * regs[a+1].d );
2220 return;
2221 }
2222
2223 // in case of Float * Integer
2224 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2225 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2226 regs[a].d *= regs[a+1].i;
2227 return;
2228 }
2229
2230 // in case of Float * Float
2231 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2232 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2233 regs[a].d *= regs[a+1].d;
2234 return;
2235 }
2236#endif
2237
2238 // other case
2239 send_by_name( vm, MRBC_SYM(MUL), a, 1 );
2240}
2241
2242
2243//================================================================
2248static inline void op_div( mrbc_vm *vm, mrbc_value *regs EXT )
2249{
2250 FETCH_B();
2251
2252 // in case of Integer / Integer
2253 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2254 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2255 mrbc_int_t v0 = regs[a].i;
2256 mrbc_int_t v1 = regs[a+1].i;
2257
2258 if( v1 == 0 ) {
2259 mrbc_raise(vm, MRBC_CLASS(ZeroDivisionError), 0 );
2260 return;
2261 }
2262
2263 mrbc_int_t ret = v0 / v1;
2264 mrbc_int_t mod = v0 % v1;
2265
2266 if( (mod != 0) && ((v0 ^ v1) < 0) ) ret -= 1;
2267
2268 regs[a].i = ret;
2269 return;
2270 }
2271
2272#if MRBC_USE_FLOAT
2273 // in case of Integer / Float
2274 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2275 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2276 mrbc_set_float( &regs[a], regs[a].i / regs[a+1].d );
2277 return;
2278 }
2279
2280 // in case of Float / Integer
2281 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2282 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2283 regs[a].d /= regs[a+1].i;
2284 return;
2285 }
2286
2287 // in case of Float / Float
2288 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2289 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2290 regs[a].d /= regs[a+1].d;
2291 return;
2292 }
2293#endif
2294
2295 // other case
2296 send_by_name( vm, MRBC_SYM(DIV), a, 1 );
2297}
2298
2299
2300//================================================================
2305static inline void op_eq( mrbc_vm *vm, mrbc_value *regs EXT )
2306{
2307 FETCH_B();
2308
2309 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2310 send_by_name(vm, MRBC_SYM(EQ_EQ), a, 1);
2311 return;
2312 }
2313
2314 int result = mrbc_compare(&regs[a], &regs[a+1]);
2315
2316 mrbc_decref(&regs[a]);
2317 mrbc_set_bool( &regs[a], result == 0 );
2318}
2319
2320
2321//================================================================
2326static inline void op_lt( mrbc_vm *vm, mrbc_value *regs EXT )
2327{
2328 FETCH_B();
2329
2330 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2331 send_by_name(vm, MRBC_SYM(LT), a, 1);
2332 return;
2333 }
2334
2335 int result = mrbc_compare(&regs[a], &regs[a+1]);
2336
2337 mrbc_decref(&regs[a]);
2338 mrbc_set_bool( &regs[a], result < 0 );
2339}
2340
2341
2342//================================================================
2347static inline void op_le( mrbc_vm *vm, mrbc_value *regs EXT )
2348{
2349 FETCH_B();
2350
2351 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2352 send_by_name(vm, MRBC_SYM(LT_EQ), a, 1);
2353 return;
2354 }
2355
2356 int result = mrbc_compare(&regs[a], &regs[a+1]);
2357
2358 mrbc_decref(&regs[a]);
2359 mrbc_set_bool( &regs[a], result <= 0 );
2360}
2361
2362
2363//================================================================
2368static inline void op_gt( mrbc_vm *vm, mrbc_value *regs EXT )
2369{
2370 FETCH_B();
2371
2372 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2373 send_by_name(vm, MRBC_SYM(GT), a, 1);
2374 return;
2375 }
2376
2377 int result = mrbc_compare(&regs[a], &regs[a+1]);
2378
2379 mrbc_decref(&regs[a]);
2380 mrbc_set_bool( &regs[a], result > 0 );
2381}
2382
2383
2384//================================================================
2389static inline void op_ge( mrbc_vm *vm, mrbc_value *regs EXT )
2390{
2391 FETCH_B();
2392
2393 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2394 send_by_name(vm, MRBC_SYM(GT_EQ), a, 1);
2395 return;
2396 }
2397
2398 int result = mrbc_compare(&regs[a], &regs[a+1]);
2399
2400 mrbc_decref(&regs[a]);
2401 mrbc_set_bool( &regs[a], result >= 0 );
2402}
2403
2404
2405//================================================================
2410static inline void op_array( mrbc_vm *vm, mrbc_value *regs EXT )
2411{
2412 FETCH_BB();
2413
2414 mrbc_value ret = mrbc_array_new(vm, b);
2415
2416 memcpy( ret.array->data, &regs[a], sizeof(mrbc_value) * b );
2417 memset( &regs[a], 0, sizeof(mrbc_value) * b );
2418 ret.array->n_stored = b;
2419
2420 mrbc_decref(&regs[a]);
2421 regs[a] = ret;
2422}
2423
2424
2425//================================================================
2430static inline void op_array2( mrbc_vm *vm, mrbc_value *regs EXT )
2431{
2432 FETCH_BBB();
2433
2434 mrbc_value ret = mrbc_array_new(vm, c);
2435
2436 memcpy( ret.array->data, &regs[b], sizeof(mrbc_value) * c );
2437 memset( &regs[b], 0, sizeof(mrbc_value) * c );
2438 ret.array->n_stored = c;
2439
2440 mrbc_decref(&regs[a]);
2441 regs[a] = ret;
2442}
2443
2444
2445//================================================================
2450static inline void op_arycat( mrbc_vm *vm, mrbc_value *regs EXT )
2451{
2452 FETCH_B();
2453
2454 if( mrbc_type(regs[a]) == MRBC_TT_NIL ) {
2455 // arycat(nil, [...]) #=> [...]
2456 assert( mrbc_type(regs[a+1]) == MRBC_TT_ARRAY );
2457 regs[a] = regs[a+1];
2458 mrbc_set_nil( &regs[a+1] );
2459
2460 return;
2461 }
2462
2463 assert( mrbc_type(regs[a ]) == MRBC_TT_ARRAY );
2464 assert( mrbc_type(regs[a+1]) == MRBC_TT_ARRAY );
2465
2466 int size_1 = regs[a ].array->n_stored;
2467 int size_2 = regs[a+1].array->n_stored;
2468 int new_size = size_1 + regs[a+1].array->n_stored;
2469
2470 // need resize?
2471 if( regs[a].array->data_size < new_size ) {
2472 mrbc_array_resize(&regs[a], new_size);
2473 }
2474
2475 for( int i = 0; i < size_2; i++ ) {
2476 mrbc_incref( &regs[a+1].array->data[i] );
2477 regs[a].array->data[size_1+i] = regs[a+1].array->data[i];
2478 }
2479 regs[a].array->n_stored = new_size;
2480}
2481
2482
2483//================================================================
2488static inline void op_arypush( mrbc_vm *vm, mrbc_value *regs EXT )
2489{
2490 FETCH_BB();
2491
2492 int sz1 = mrbc_array_size(&regs[a]);
2493
2494 mrbc_array_resize(&regs[a], sz1 + b);
2495
2496 // data copy.
2497 memcpy( regs[a].array->data + sz1, &regs[a+1], sizeof(mrbc_value) * b );
2498 memset( &regs[a+1], 0, sizeof(mrbc_value) * b );
2499 regs[a].array->n_stored = sz1 + b;
2500}
2501
2502
2503//================================================================
2508static inline void op_arysplat( mrbc_vm *vm, mrbc_value *regs EXT )
2509{
2510 FETCH_B();
2511
2512 mrbc_value ret = mrbc_array_dup( vm, &regs[a] );
2513 mrbc_decref(&regs[a]);
2514 regs[a] = ret;
2515}
2516
2517
2518//================================================================
2523static inline void op_aref( mrbc_vm *vm, mrbc_value *regs EXT )
2524{
2525 FETCH_BBB();
2526
2527 mrbc_value *src = &regs[b];
2528 mrbc_value *dst = &regs[a];
2529
2530 mrbc_decref( dst );
2531
2532 if( mrbc_type(*src) == MRBC_TT_ARRAY ) {
2533 // src is Array
2534 *dst = mrbc_array_get(src, c);
2535 mrbc_incref(dst);
2536 } else {
2537 // src is not Array
2538 if( c == 0 ) {
2539 mrbc_incref(src);
2540 *dst = *src;
2541 } else {
2542 mrbc_set_nil( dst );
2543 }
2544 }
2545}
2546
2547
2548//================================================================
2553static inline void op_aset( mrbc_vm *vm, mrbc_value *regs EXT )
2554{
2555 FETCH_BBB();
2556
2557 assert( mrbc_type(regs[b]) == MRBC_TT_ARRAY );
2558
2559 mrbc_incref( &regs[b] );
2560 mrbc_array_set(&regs[a], c, &regs[b]);
2561}
2562
2563
2564//================================================================
2569static inline void op_apost( mrbc_vm *vm, mrbc_value *regs EXT )
2570{
2571 FETCH_BBB();
2572
2573 mrbc_value src = regs[a];
2574 if( mrbc_type(src) != MRBC_TT_ARRAY ) {
2575 src = mrbc_array_new(vm, 1);
2576 src.array->data[0] = regs[a];
2577 src.array->n_stored = 1;
2578 }
2579
2580 int pre = b;
2581 int post = c;
2582 int len = mrbc_array_size(&src);
2583
2584 if( len > pre + post ) {
2585 int ary_size = len - pre - post;
2586 regs[a] = mrbc_array_new(vm, ary_size);
2587
2588 // copy elements
2589 for( int i = 0; i < ary_size; i++ ) {
2590 regs[a].array->data[i] = src.array->data[pre+i];
2591 mrbc_incref( &regs[a].array->data[i] );
2592 }
2593 regs[a].array->n_stored = ary_size;
2594
2595 } else {
2596 assert(!"Not support this case in op_apost");
2597 // empty
2598 regs[a] = mrbc_array_new(vm, 0);
2599 }
2600
2601 mrbc_decref(&src);
2602}
2603
2604
2605//================================================================
2610static inline void op_intern( mrbc_vm *vm, mrbc_value *regs EXT )
2611{
2612 FETCH_B();
2613
2614 assert( mrbc_type(regs[a]) == MRBC_TT_STRING );
2615
2616 mrbc_value sym_val = mrbc_symbol_new(vm, (const char*)regs[a].string->data);
2617
2618 mrbc_decref( &regs[a] );
2619 regs[a] = sym_val;
2620}
2621
2622
2623//================================================================
2628static inline void op_symbol( mrbc_vm *vm, mrbc_value *regs EXT )
2629{
2630 FETCH_BB();
2631
2632 const char *p = (const char *)mrbc_irep_pool_ptr(vm->cur_irep, b);
2633 mrbc_sym sym_id = mrbc_str_to_symid( p+3 ); // 3 is TT and length
2634 if( sym_id < 0 ) {
2635 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
2636 return;
2637 }
2638
2639 mrbc_decref(&regs[a]);
2640 mrbc_set_symbol( &regs[a], sym_id );
2641}
2642
2643
2644//================================================================
2649static inline void op_string( mrbc_vm *vm, mrbc_value *regs EXT )
2650{
2651 FETCH_BB();
2652
2653 mrbc_decref(&regs[a]);
2654 regs[a] = mrbc_irep_pool_value(vm, b);
2655}
2656
2657
2658//================================================================
2663static inline void op_strcat( mrbc_vm *vm, mrbc_value *regs EXT )
2664{
2665 FETCH_B();
2666
2667#if MRBC_USE_STRING
2668 // call "to_s"
2669 mrbc_method method;
2670 if( mrbc_find_method( &method, find_class_by_object(&regs[a+1]),
2671 MRBC_SYM(to_s)) == 0 ) return;
2672 if( !method.c_func ) return; // TODO: Not support?
2673
2674 method.func( vm, regs + a + 1, 0 );
2675 mrbc_string_append( &regs[a], &regs[a+1] );
2676 mrbc_decref_empty( &regs[a+1] );
2677
2678#else
2679 mrbc_raise(vm, MRBC_CLASS(Exception), "Not support String");
2680#endif
2681}
2682
2683
2684//================================================================
2689static inline void op_hash( mrbc_vm *vm, mrbc_value *regs EXT )
2690{
2691 FETCH_BB();
2692
2693 mrbc_value value = mrbc_hash_new(vm, b);
2694
2695 // note: Do not detect duplicate keys.
2696 b *= 2;
2697 memcpy( value.hash->data, &regs[a], sizeof(mrbc_value) * b );
2698 memset( &regs[a], 0, sizeof(mrbc_value) * b );
2699 value.hash->n_stored = b;
2700
2701 mrbc_decref(&regs[a]);
2702 regs[a] = value;
2703}
2704
2705
2706//================================================================
2711static inline void op_hashadd( mrbc_vm *vm, mrbc_value *regs EXT )
2712{
2713 FETCH_BB();
2714
2715 int sz1 = mrbc_array_size(&regs[a]);
2716 int sz2 = b * 2;
2717
2718 mrbc_array_resize(&regs[a], sz1 + sz2);
2719
2720 // data copy.
2721 // note: Do not detect duplicate keys.
2722 memcpy( regs[a].hash->data + sz1, &regs[a+1], sizeof(mrbc_value) * sz2 );
2723 memset( &regs[a+1], 0, sizeof(mrbc_value) * sz2 );
2724 regs[a].hash->n_stored = sz1 + sz2;
2725}
2726
2727
2728//================================================================
2733static inline void op_hashcat( mrbc_vm *vm, mrbc_value *regs EXT )
2734{
2735 FETCH_B();
2736
2738
2739 while( mrbc_hash_i_has_next(&ite) ) {
2740 mrbc_value *kv = mrbc_hash_i_next(&ite);
2741 mrbc_hash_set( &regs[a], &kv[0], &kv[1] );
2742 mrbc_incref( &kv[0] );
2743 mrbc_incref( &kv[1] );
2744 }
2745}
2746
2747
2748//================================================================
2753static inline void op_block( mrbc_vm *vm, mrbc_value *regs EXT )
2754{
2755 FETCH_BB();
2756
2757 mrbc_value ret = mrbc_proc_new(vm, mrbc_irep_child_irep(vm->cur_irep, b), 'B');
2758
2759 mrbc_decref(&regs[a]);
2760 regs[a] = ret;
2761}
2762
2763
2764//================================================================
2769static inline void op_method( mrbc_vm *vm, mrbc_value *regs EXT )
2770{
2771 FETCH_BB();
2772
2773 mrbc_value ret = mrbc_proc_new(vm, mrbc_irep_child_irep(vm->cur_irep, b), 'M');
2774
2775 mrbc_decref(&regs[a]);
2776 regs[a] = ret;
2777}
2778
2779
2780//================================================================
2785static inline void op_range_inc( mrbc_vm *vm, mrbc_value *regs EXT )
2786{
2787 FETCH_B();
2788
2789 mrbc_value value = mrbc_range_new(vm, &regs[a], &regs[a+1], 0);
2790 regs[a] = value;
2791 mrbc_set_tt( &regs[a+1], MRBC_TT_EMPTY );
2792}
2793
2794
2795//================================================================
2800static inline void op_range_exc( mrbc_vm *vm, mrbc_value *regs EXT )
2801{
2802 FETCH_B();
2803
2804 mrbc_value value = mrbc_range_new(vm, &regs[a], &regs[a+1], 1);
2805 regs[a] = value;
2806 mrbc_set_tt( &regs[a+1], MRBC_TT_EMPTY );
2807}
2808
2809
2810//================================================================
2815static inline void op_oclass( mrbc_vm *vm, mrbc_value *regs EXT )
2816{
2817 FETCH_B();
2818
2819 mrbc_decref(&regs[a]);
2820 mrbc_set_tt(&regs[a], MRBC_TT_CLASS);
2821 regs[a].cls = MRBC_CLASS(Object);
2822}
2823
2824
2825//================================================================
2830static inline void op_class( mrbc_vm *vm, mrbc_value *regs EXT )
2831{
2832 FETCH_BB();
2833
2834 // get the super class.
2835 mrbc_class *super;
2836
2837 switch( mrbc_type(regs[a+1]) ) {
2838 case MRBC_TT_CLASS:
2839 super = regs[a+1].cls;
2840 break;
2841 case MRBC_TT_NIL:
2842 super = 0;
2843 break;
2844 default:
2845 mrbc_raise(vm, MRBC_CLASS(TypeError), "superclass must be a Class");
2846 return;
2847 }
2848
2849 // check unsupported pattern.
2850 if( super ) {
2851 for( int i = 1; i < MRBC_TT_MAXVAL; i++ ) {
2852 if( super == mrbc_class_tbl[i] ) {
2853 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Inherit the built-in class is not supported");
2854 return;
2855 }
2856 }
2857 }
2858
2859 // get the nested outer class or module.
2860 mrbc_class *outer = 0;
2861
2862 if( IS_CLASS_OR_MODULE(regs[a])) {
2863 outer = regs[a].cls;
2864 } else if( IS_CLASS_OR_MODULE(vm->cur_regs[0])) {
2865 outer = vm->cur_regs[0].cls;
2866 }
2867
2868 const char *class_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
2869 mrbc_class *cls;
2870
2871 // define a new class (or get an already defined class)
2872 if( outer ) {
2873 cls = mrbc_define_class_under(vm, outer, class_name, super);
2874 } else {
2875 cls = mrbc_define_class(vm, class_name, super);
2876 }
2877
2878 // (note)
2879 // regs[a] was set to NIL or Class by compiler. So, no need to release.
2880 mrbc_set_tt(&regs[a], MRBC_TT_CLASS);
2881 regs[a].cls = cls;
2882}
2883
2884
2885//================================================================
2890static inline void op_module( mrbc_vm *vm, mrbc_value *regs EXT )
2891{
2892 FETCH_BB();
2893
2894 // get the nested outer class or module.
2895 mrbc_class *outer = 0;
2896
2897 if( IS_CLASS_OR_MODULE(regs[a])) {
2898 outer = regs[a].cls;
2899 } else if( IS_CLASS_OR_MODULE(vm->cur_regs[0])) {
2900 outer = vm->cur_regs[0].cls;
2901 }
2902
2903 const char *module_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
2904 mrbc_class *cls;
2905
2906 // define a new module (or get an already defined class)
2907 if( outer ) {
2908 cls = mrbc_define_module_under(vm, outer, module_name);
2909 } else {
2910 cls = mrbc_define_module(vm, module_name);
2911 }
2912
2913 // (note)
2914 // regs[a] was set to Class, Module or NIL by compiler. So, no need to release.
2915 mrbc_set_tt(&regs[a], MRBC_TT_MODULE);
2916 regs[a].cls = cls;
2917}
2918
2919
2920//================================================================
2925static inline void op_exec( mrbc_vm *vm, mrbc_value *regs EXT )
2926{
2927 FETCH_BB();
2928
2929 // prepare callinfo
2930 mrbc_push_callinfo(vm, regs[a].cls->sym_id, a, 0);
2931
2932 // target irep
2934 vm->inst = vm->cur_irep->inst;
2935 vm->cur_regs += a;
2936
2937 vm->target_class = regs[a].cls;
2938}
2939
2940
2941//----------------------------------------------------------------
2942static void sub_irep_inc_dec_ref( mrbc_irep *irep, int inc_dec )
2943{
2944 for( int i = 0; i < irep->rlen; i++ ) {
2945 sub_irep_inc_dec_ref( mrbc_irep_child_irep(irep, i), inc_dec );
2946 }
2947
2948 irep->ref_count += inc_dec;
2949}
2950
2951static void sub_newmethod( mrbc_class *cls, mrbc_method *method, mrbc_sym sym_id )
2952{
2953 method->next = cls->method_link;
2954 cls->method_link = method;
2955
2956 if( !method->c_func ) sub_irep_inc_dec_ref( method->irep, +1 );
2957
2958 // checking same method
2959 for( ;method->next != NULL; method = method->next ) {
2960 if( method->next->sym_id == sym_id ) {
2961 // Found it. Unchain it in linked list and remove.
2962 mrbc_method *del_method = method->next;
2963
2964 method->next = del_method->next;
2965 if( del_method->type == 'M' ) {
2966 if( !del_method->c_func ) sub_irep_inc_dec_ref( del_method->irep, -1 );
2967 mrbc_raw_free( del_method );
2968 }
2969
2970 break;
2971 }
2972 }
2973}
2974
2975static void sub_op_def( mrbc_vm *vm, mrbc_class *cls, mrbc_irep *irep, mrbc_sym sym_id )
2976{
2977 if( cls->flag_nomethod ) {
2978 mrbc_raisef(vm, MRBC_CLASS(NotImplementedError),
2979 "Adding methods to the %s class is not supported",
2981 return;
2982 }
2983
2984 mrbc_method *method = (vm->vm_id == 0) ?
2986 mrbc_raw_alloc( sizeof(mrbc_method) );
2987
2988 *method = (mrbc_method){
2989 .type = (vm->vm_id == 0) ? 'm' : 'M',
2990 .c_func = 0,
2991 .sym_id = sym_id,
2992 .irep = irep,
2993 };
2994
2995 sub_newmethod( cls, method, sym_id );
2996}
2997
2998//================================================================
3003static inline void op_def( mrbc_vm *vm, mrbc_value *regs EXT )
3004{
3005 FETCH_BB();
3006
3007 mrbc_class *cls = regs[a].cls;
3008 mrbc_irep *irep = regs[a+1].proc->irep;
3009 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
3010
3011 sub_op_def( vm, cls, irep, sym_id );
3012 mrbc_set_symbol(&regs[a], sym_id);
3013}
3014
3015
3016//================================================================
3021static inline void op_tdef( mrbc_vm *vm, mrbc_value *regs EXT )
3022{
3023 FETCH_BBB();
3024
3025 mrbc_class *cls = vm->target_class;
3026 mrbc_irep *irep = mrbc_irep_child_irep(vm->cur_irep, c);
3027 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
3028
3029 sub_op_def( vm, cls, irep, sym_id );
3030 mrbc_set_symbol(&regs[a], sym_id);
3031}
3032
3033
3034//================================================================
3039static inline void op_sdef( mrbc_vm *vm, mrbc_value *regs EXT )
3040{
3041 FETCH_BBB();
3042
3043 mrbc_class *cls = regs[a].cls;
3044 mrbc_irep *irep = mrbc_irep_child_irep(vm->cur_irep, c);
3045 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
3046
3047 sub_op_def( vm, cls, irep, sym_id );
3048 mrbc_set_symbol(&regs[a], sym_id);
3049}
3050
3051
3052//================================================================
3057static inline void op_alias( mrbc_vm *vm, mrbc_value *regs EXT )
3058{
3059 FETCH_BB();
3060
3061 mrbc_sym sym_id_new = mrbc_irep_symbol_id(vm->cur_irep, a);
3062 mrbc_sym sym_id_org = mrbc_irep_symbol_id(vm->cur_irep, b);
3063 mrbc_class *cls = vm->target_class;
3064 mrbc_method *method = (vm->vm_id == 0) ?
3066 mrbc_raw_alloc( sizeof(mrbc_method) );
3067
3068 if( mrbc_find_method( method, cls, sym_id_org ) == 0 ) {
3069 mrbc_raisef(vm, MRBC_CLASS(NameError), "undefined method '%s'",
3070 mrbc_symid_to_str(sym_id_org));
3071 if(vm->vm_id != 0) mrbc_raw_free( method );
3072 return;
3073 }
3074
3075 method->type = (vm->vm_id == 0) ? 'm' : 'M';
3076 method->sym_id = sym_id_new;
3077
3078 sub_newmethod( cls, method, sym_id_new );
3079}
3080
3081
3082//================================================================
3087static inline void op_sclass( mrbc_vm *vm, mrbc_value *regs EXT )
3088{
3089 // currently, not supported
3090 FETCH_B();
3091}
3092
3093
3094//================================================================
3099static inline void op_tclass( mrbc_vm *vm, mrbc_value *regs EXT )
3100{
3101 FETCH_B();
3102
3103 mrbc_decref(&regs[a]);
3104 mrbc_set_tt(&regs[a], MRBC_TT_CLASS);
3105 regs[a].cls = vm->target_class;
3106}
3107
3108
3109#if !defined(MRBC_SUPPORT_OP_EXT)
3110//================================================================
3117static inline void op_ext( mrbc_vm *vm, mrbc_value *regs EXT )
3118{
3119 FETCH_Z();
3120 mrbc_raise(vm, MRBC_CLASS(Exception),
3121 "Not support op_ext. Re-compile with MRBC_SUPPORT_OP_EXT");
3122}
3123#endif
3124
3125
3126//================================================================
3131static inline void op_stop( mrbc_vm *vm, mrbc_value *regs EXT )
3132{
3133 FETCH_Z();
3134
3135 vm->flag_preemption = 1;
3136 vm->flag_stop = 1;
3137 vm->inst--; // to not proceed beyond OP_STOP.
3138}
3139
3140
3141//================================================================
3142/* Unsupported opecodes
3143*/
3144static inline void op_unsupported( mrbc_vm *vm, mrbc_value *regs EXT )
3145{
3146 mrbc_raisef( vm, MRBC_CLASS(Exception),
3147 "Unimplemented opcode (0x%02x) found", *(vm->inst - 1));
3148}
3149#undef EXT
3150
3151
3152//================================================================
3161{
3162#if defined(MRBC_SUPPORT_OP_EXT)
3163 int ext = 0;
3164#define EXT , ext
3165#else
3166#define EXT
3167#endif
3168
3169 while( 1 ) {
3170 mrbc_value *regs = vm->cur_regs;
3171 uint8_t op = *vm->inst++; // Dispatch
3172
3173 switch( op ) {
3174 case OP_NOP: op_nop (vm, regs EXT); break;
3175 case OP_MOVE: op_move (vm, regs EXT); break;
3176 case OP_LOADL: op_loadl (vm, regs EXT); break;
3177 case OP_LOADI8: op_loadi8 (vm, regs EXT); break;
3178 case OP_LOADINEG: op_loadineg (vm, regs EXT); break;
3179 case OP_LOADI__1: // fall through
3180 case OP_LOADI_0: // fall through
3181 case OP_LOADI_1: // fall through
3182 case OP_LOADI_2: // fall through
3183 case OP_LOADI_3: // fall through
3184 case OP_LOADI_4: // fall through
3185 case OP_LOADI_5: // fall through
3186 case OP_LOADI_6: // fall through
3187 case OP_LOADI_7: op_loadi_n (vm, regs EXT); break;
3188 case OP_LOADI16: op_loadi16 (vm, regs EXT); break;
3189 case OP_LOADI32: op_loadi32 (vm, regs EXT); break;
3190 case OP_LOADSYM: op_loadsym (vm, regs EXT); break;
3191 case OP_LOADNIL: op_loadnil (vm, regs EXT); break;
3192 case OP_LOADSELF: op_loadself (vm, regs EXT); break;
3193 case OP_LOADTRUE: op_loadtrue (vm, regs EXT); break;
3194 case OP_LOADFALSE: op_loadfalse (vm, regs EXT); break;
3195 case OP_GETGV: op_getgv (vm, regs EXT); break;
3196 case OP_SETGV: op_setgv (vm, regs EXT); break;
3197 case OP_GETSV: op_unsupported(vm, regs EXT); break; // not implemented.
3198 case OP_SETSV: op_unsupported(vm, regs EXT); break; // not implemented.
3199 case OP_GETIV: op_getiv (vm, regs EXT); break;
3200 case OP_SETIV: op_setiv (vm, regs EXT); break;
3201 case OP_GETCV: op_unsupported(vm, regs EXT); break; // not implemented.
3202 case OP_SETCV: op_unsupported(vm, regs EXT); break; // not implemented.
3203 case OP_GETCONST: op_getconst (vm, regs EXT); break;
3204 case OP_SETCONST: op_setconst (vm, regs EXT); break;
3205 case OP_GETMCNST: op_getmcnst (vm, regs EXT); break;
3206 case OP_SETMCNST: op_unsupported(vm, regs EXT); break; // not implemented.
3207 case OP_GETUPVAR: op_getupvar (vm, regs EXT); break;
3208 case OP_SETUPVAR: op_setupvar (vm, regs EXT); break;
3209 case OP_GETIDX: op_getidx (vm, regs EXT); break;
3210 case OP_GETIDX0: op_getidx0 (vm, regs EXT); break;
3211 case OP_SETIDX: op_setidx (vm, regs EXT); break;
3212 case OP_JMP: op_jmp (vm, regs EXT); break;
3213 case OP_JMPIF: op_jmpif (vm, regs EXT); break;
3214 case OP_JMPNOT: op_jmpnot (vm, regs EXT); break;
3215 case OP_JMPNIL: op_jmpnil (vm, regs EXT); break;
3216 case OP_JMPUW: op_jmpuw (vm, regs EXT); break;
3217 case OP_EXCEPT: op_except (vm, regs EXT); break;
3218 case OP_RESCUE: op_rescue (vm, regs EXT); break;
3219 case OP_RAISEIF: op_raiseif (vm, regs EXT); break;
3220 case OP_MATCHERR: op_matcherr (vm, regs EXT); break;
3221 case OP_SSEND: op_ssend (vm, regs EXT); break;
3222 case OP_SSEND0: op_ssend0 (vm, regs EXT); break;
3223 case OP_SSENDB: op_ssendb (vm, regs EXT); break;
3224 case OP_SEND: op_send (vm, regs EXT); break;
3225 case OP_SEND0: op_send0 (vm, regs EXT); break;
3226 case OP_SENDB: op_sendb (vm, regs EXT); break;
3227 case OP_CALL: op_unsupported(vm, regs EXT); break; // not implemented.
3228 case OP_BLKCALL: op_blkcall (vm, regs EXT); break;
3229 case OP_SUPER: op_super (vm, regs EXT); break;
3230 case OP_ARGARY: op_argary (vm, regs EXT); break;
3231 case OP_ENTER: op_enter (vm, regs EXT); break;
3232 case OP_KEY_P: op_key_p (vm, regs EXT); break;
3233 case OP_KEYEND: op_keyend (vm, regs EXT); break;
3234 case OP_KARG: op_karg (vm, regs EXT); break;
3235 case OP_RETURN: op_return (vm, regs EXT); break;
3236 case OP_RETURN_BLK: op_return_blk (vm, regs EXT); break;
3237 case OP_RETSELF: op_retself (vm, regs EXT); break;
3238 case OP_RETNIL: op_retnil (vm, regs EXT); break;
3239 case OP_RETTRUE: op_rettrue (vm, regs EXT); break;
3240 case OP_RETFALSE: op_retfalse (vm, regs EXT); break;
3241 case OP_BREAK: op_break (vm, regs EXT); break;
3242 case OP_BLKPUSH: op_blkpush (vm, regs EXT); break;
3243 case OP_ADD: op_add (vm, regs EXT); break;
3244 case OP_ADDI: op_addi (vm, regs EXT); break;
3245 case OP_SUB: op_sub (vm, regs EXT); break;
3246 case OP_SUBI: op_subi (vm, regs EXT); break;
3247 case OP_ADDILV: op_addilv (vm, regs EXT); break;
3248 case OP_SUBILV: op_subilv (vm, regs EXT); break;
3249 case OP_MUL: op_mul (vm, regs EXT); break;
3250 case OP_DIV: op_div (vm, regs EXT); break;
3251 case OP_EQ: op_eq (vm, regs EXT); break;
3252 case OP_LT: op_lt (vm, regs EXT); break;
3253 case OP_LE: op_le (vm, regs EXT); break;
3254 case OP_GT: op_gt (vm, regs EXT); break;
3255 case OP_GE: op_ge (vm, regs EXT); break;
3256 case OP_ARRAY: op_array (vm, regs EXT); break;
3257 case OP_ARRAY2: op_array2 (vm, regs EXT); break;
3258 case OP_ARYCAT: op_arycat (vm, regs EXT); break;
3259 case OP_ARYPUSH: op_arypush (vm, regs EXT); break;
3260 case OP_ARYSPLAT: op_arysplat (vm, regs EXT); break;
3261 case OP_AREF: op_aref (vm, regs EXT); break;
3262 case OP_ASET: op_aset (vm, regs EXT); break;
3263 case OP_APOST: op_apost (vm, regs EXT); break;
3264 case OP_INTERN: op_intern (vm, regs EXT); break;
3265 case OP_SYMBOL: op_symbol (vm, regs EXT); break;
3266 case OP_STRING: op_string (vm, regs EXT); break;
3267 case OP_STRCAT: op_strcat (vm, regs EXT); break;
3268 case OP_HASH: op_hash (vm, regs EXT); break;
3269 case OP_HASHADD: op_hashadd (vm, regs EXT); break;
3270 case OP_HASHCAT: op_hashcat (vm, regs EXT); break;
3271 case OP_LAMBDA: op_unsupported(vm, regs EXT); break; // not implemented.
3272 case OP_BLOCK: op_block (vm, regs EXT); break;
3273 case OP_METHOD: op_method (vm, regs EXT); break;
3274 case OP_RANGE_INC: op_range_inc (vm, regs EXT); break;
3275 case OP_RANGE_EXC: op_range_exc (vm, regs EXT); break;
3276 case OP_OCLASS: op_oclass (vm, regs EXT); break;
3277 case OP_CLASS: op_class (vm, regs EXT); break;
3278 case OP_MODULE: op_module (vm, regs EXT); break;
3279 case OP_EXEC: op_exec (vm, regs EXT); break;
3280 case OP_DEF: op_def (vm, regs EXT); break;
3281 case OP_TDEF: op_tdef (vm, regs EXT); break;
3282 case OP_SDEF: op_sdef (vm, regs EXT); break;
3283 case OP_ALIAS: op_alias (vm, regs EXT); break;
3284 case OP_UNDEF: op_unsupported(vm, regs EXT); break; // not implemented.
3285 case OP_SCLASS: op_sclass (vm, regs EXT); break;
3286 case OP_TCLASS: op_tclass (vm, regs EXT); break;
3287 case OP_DEBUG: op_unsupported(vm, regs EXT); break; // not implemented.
3288 case OP_ERR: op_unsupported(vm, regs EXT); break; // not implemented.
3289
3290#if defined(MRBC_SUPPORT_OP_EXT)
3291 case OP_EXT1: ext = 1; continue;
3292 case OP_EXT2: ext = 2; continue;
3293 case OP_EXT3: ext = 3; continue;
3294#else
3295 case OP_EXT1: // fall through
3296 case OP_EXT2: // fall through
3297 case OP_EXT3: op_ext (vm, regs EXT); break;
3298#endif
3299 case OP_STOP: op_stop (vm, regs EXT); break;
3300 default: op_unsupported(vm, regs EXT); break;
3301 } // end switch.
3302
3303#undef EXT
3304#if defined(MRBC_SUPPORT_OP_EXT)
3305 ext = 0;
3306#endif
3307 if( !vm->flag_preemption ) continue; // execute next ope code.
3308 if( !mrbc_israised(vm) ) return vm->flag_stop; // normal return.
3309
3310
3311 // Handle exception
3312 vm->flag_preemption = 0;
3313 const mrbc_irep_catch_handler *handler;
3314
3315 while( 1 ) {
3316 const mrbc_irep *irep = vm->cur_irep;
3317 const mrbc_irep_catch_handler *catch_table =
3318 (const mrbc_irep_catch_handler *)(irep->inst + irep->ilen);
3319 uint32_t inst = vm->inst - irep->inst;
3320 int cnt = irep->clen;
3321
3322 for( cnt--; cnt >= 0 ; cnt-- ) {
3323 handler = catch_table + cnt;
3324 if( (bin_to_uint32(handler->begin) < inst) &&
3325 (inst <= bin_to_uint32(handler->end)) ) goto JUMP_TO_HANDLER;
3326 }
3327
3328 if( !vm->callinfo_tail ) return 2; // return due to exception.
3329 mrbc_pop_callinfo( vm );
3330 }
3331
3332 JUMP_TO_HANDLER:
3333 // jump to handler (rescue or ensure).
3334 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
3335 }
3336}
void * mrbc_raw_alloc(unsigned int size)
Definition alloc.c:514
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:631
void mrbc_raw_free(void *ptr)
Definition alloc.c:707
static void mrbc_set_nil(mrbc_value *p)
Definition boxing_no.h:99
static void mrbc_set_symbol(mrbc_value *p, mrbc_sym sym_id)
Definition boxing_no.h:119
#define mrbc_immediate_value(...)
Definition boxing_no.h:75
#define mrbc_nil_value()
Definition boxing_no.h:70
static void mrbc_set_tt(mrbc_value *p, mrbc_vtype type)
Definition boxing_no.h:125
static void mrbc_set_bool(mrbc_value *p, int n)
Definition boxing_no.h:114
static void mrbc_set_float(mrbc_value *p, mrbc_float_t d)
Definition boxing_no.h:92
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
static void mrbc_set_true(mrbc_value *p)
Definition boxing_no.h:104
static void mrbc_set_false(mrbc_value *p)
Definition boxing_no.h:109
static void mrbc_set_integer(mrbc_value *p, mrbc_int_t n)
Definition boxing_no.h:85
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:243
int mrbc_array_set(mrbc_value *ary, int idx, mrbc_value *set_val)
Definition c_array.c:169
mrbc_value mrbc_array_get(const mrbc_value *ary, int idx)
Definition c_array.c:207
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
Definition c_array.c:83
mrbc_value mrbc_array_dup(mrbc_vm *vm, const mrbc_value *ary)
Definition c_array.c:486
int mrbc_array_resize(mrbc_value *ary, int size)
Definition c_array.c:147
static int mrbc_array_size(const mrbc_value *ary)
Definition c_array.h:84
mrbc_value mrbc_hash_dup(mrbc_vm *vm, mrbc_value *src)
Definition c_hash.c:305
mrbc_value mrbc_hash_remove_by_id(mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:245
mrbc_value mrbc_hash_new(mrbc_vm *vm, int size)
Definition c_hash.c:78
void mrbc_hash_delete(mrbc_value *hash)
Definition c_hash.c:100
mrbc_value * mrbc_hash_search_by_id(const mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:137
int mrbc_hash_set(mrbc_value *hash, mrbc_value *key, mrbc_value *val)
Definition c_hash.c:160
static mrbc_value * mrbc_hash_i_next(mrbc_hash_iterator *ite)
Definition c_hash.h:143
static int mrbc_hash_size(const mrbc_value *hash)
Definition c_hash.h:88
static int mrbc_hash_i_has_next(mrbc_hash_iterator *ite)
Definition c_hash.h:135
struct RHashIterator mrbc_hash_iterator
Define Hash iterator.
static mrbc_hash_iterator mrbc_hash_iterator_new(const mrbc_value *v)
Definition c_hash.h:122
mrbc_value mrbc_proc_new(struct VM *vm, void *irep, uint8_t b_or_m)
Definition c_proc.c:42
mrbc_value mrbc_range_new(mrbc_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:185
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:281
mrbc_class * mrbc_find_method(mrbc_method *r_method, mrbc_class *cls, mrbc_sym sym_id)
Definition class.c:417
mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
Definition class.c:235
int mrbc_obj_is_kind_of(const mrbc_value *obj, const mrbc_class *tcls)
Definition class.c:393
mrbc_value mrbc_instance_getiv(mrbc_value *target, mrbc_sym sym_id)
Definition class.c:350
mrbc_class * mrbc_traverse_class_tree(mrbc_class *cls, mrbc_class *nest_buf[], int *nest_idx)
Definition class.c:80
mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
Definition class.c:221
mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
Definition class.c:207
int mrbc_instance_setiv(mrbc_value *target, mrbc_sym sym_id, mrbc_value *v)
Definition class.c:322
mrbc_class *const mrbc_class_tbl[MRBC_TT_MAXVAL+1]
Definition class.c:42
mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
Definition class.c:191
#define MRBC_TRAVERSE_NEST_LEVEL
Definition class.h:35
struct RMethod mrbc_method
Method management structure.
#define MRBC_CLASS(cls)
Definition class.h:55
static mrbc_class * find_class_by_object(const mrbc_value *obj)
Definition class.h:265
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:205
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:231
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
#define mrbc_israised(vm)
Definition error.h:38
int mrbc_set_global(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:154
int mrbc_set_class_const(const mrbc_class *cls, mrbc_sym sym_id, mrbc_value *v)
Definition global.c:76
mrbc_value * mrbc_get_const(mrbc_sym sym_id)
Definition global.c:93
mrbc_value * mrbc_get_global(mrbc_sym sym_id)
Definition global.c:166
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:57
mrbc_value * mrbc_get_class_const(const mrbc_class *cls, mrbc_sym sym_id)
Definition global.c:106
mrbc_value mrbc_irep_pool_value(mrbc_vm *vm, int n)
Definition load.c:401
void mrbc_irep_free(mrbc_irep *irep)
Definition load.c:355
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:182
@ OP_SUBILV
BBB R[a] = R[a]-mrb_int(c); R[b],R[b+1] for method call.
Definition opcode.h:198
@ OP_DEBUG
BBB print a,b,c.
Definition opcode.h:237
@ OP_CALL
Z self.call(*, **, &) (But overlay the current call frame; tailcall).
Definition opcode.h:177
@ OP_EXT2
Z make 2nd operand (b) 16bit.
Definition opcode.h:240
@ OP_EXEC
BB R[a] = blockexec(R[a],Irep[b]).
Definition opcode.h:229
@ 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:173
@ OP_EQ
B R[a] = R[a]==R[a+1].
Definition opcode.h:201
@ OP_SETIDX
B R[a][R[a+1]] = R[a+2].
Definition opcode.h:161
@ 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:228
@ OP_RANGE_INC
B R[a] = range_new(R[a],R[a+1],FALSE).
Definition opcode.h:224
@ OP_EXT1
Z make 1st operand (a) 16bit.
Definition opcode.h:239
@ OP_RETTRUE
Z return true.
Definition opcode.h:189
@ OP_GETIDX0
BB R[a] = R[b][0]; a+1 for method call.
Definition opcode.h:160
@ OP_CLASS
BB R[a] = newclass(R[a],Syms[b],R[a+1]).
Definition opcode.h:227
@ 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:192
@ OP_LOADI_3
B R[a] = mrb_int(3).
Definition opcode.h:133
@ OP_ARYSPLAT
B R[a] = ary_splat(R[a]).
Definition opcode.h:210
@ OP_GE
B R[a] = R[a]>=R[a+1].
Definition opcode.h:205
@ 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:241
@ 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:196
@ OP_TCLASS
B R[a] = target_class.
Definition opcode.h:236
@ OP_STOP
Z stop VM.
Definition opcode.h:242
@ OP_AREF
BBB R[a] = R[b][c].
Definition opcode.h:211
@ OP_APOST
BBB *R[a],R[a+1]..R[a+c] = R[a][b..].
Definition opcode.h:213
@ OP_RETURN_BLK
B return R[a] (in-block return).
Definition opcode.h:186
@ 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:233
@ 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:171
@ OP_ADDILV
BBB R[a] = R[a]+mrb_int(c); R[b],R[b+1] for method call.
Definition opcode.h:197
@ 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:208
@ OP_LAMBDA
BB R[a] = lambda(Irep[b],L_LAMBDA).
Definition opcode.h:221
@ OP_RANGE_EXC
B R[a] = range_new(R[a],R[a+1],TRUE).
Definition opcode.h:225
@ OP_LOADI_5
B R[a] = mrb_int(5).
Definition opcode.h:135
@ OP_SEND0
BB R[a] = R[a].send(Syms[b]) (no args).
Definition opcode.h:175
@ 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:217
@ OP_LOADI8
BB R[a] = mrb_int(b).
Definition opcode.h:127
@ OP_RETSELF
Z return self.
Definition opcode.h:187
@ 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:174
@ OP_BREAK
B break R[a].
Definition opcode.h:191
@ 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:195
@ 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:200
@ OP_ASET
BBB R[b][c] = R[a].
Definition opcode.h:212
@ OP_RAISEIF
B raise(R[a]) if R[a].
Definition opcode.h:169
@ 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:207
@ 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:165
@ OP_RETFALSE
Z return false.
Definition opcode.h:190
@ OP_LT
B R[a] = R[a]<R[a+1].
Definition opcode.h:202
@ OP_JMPUW
S unwind_and_jump_to(a).
Definition opcode.h:166
@ OP_INTERN
B R[a] = intern(R[a]).
Definition opcode.h:214
@ OP_SETUPVAR
BBB uvset(b,c,R[a]).
Definition opcode.h:158
@ OP_ENTER
W arg setup according to flags (24=n1:m5:o5:r1:m5:k5:d1:b1).
Definition opcode.h:181
@ OP_UNDEF
B undef_method(target_class,Syms[a]).
Definition opcode.h:234
@ OP_KARG
BB R[a] = kdict[Syms[b]]; kdict.delete(Syms[b]).
Definition opcode.h:184
@ OP_GETCV
BB R[a] = cvget(Syms[b]).
Definition opcode.h:151
@ OP_LOADFALSE
B R[a] = false.
Definition opcode.h:144
@ OP_HASHADD
BB hash_push(R[a],R[a+1]..R[a+b*2]).
Definition opcode.h:219
@ OP_ARGARY
BS R[a] = argument array (16=m5:r1:m5:d1:lv4).
Definition opcode.h:180
@ OP_METHOD
BB R[a] = lambda(Irep[b],L_METHOD).
Definition opcode.h:223
@ OP_ARYPUSH
BB ary_push(R[a],R[a+1]..R[a+b]).
Definition opcode.h:209
@ OP_ADD
B R[a] = R[a]+R[a+1].
Definition opcode.h:193
@ OP_OCLASS
B R[a] = Object.
Definition opcode.h:226
@ OP_SYMBOL
BB R[a] = intern(Pool[b]).
Definition opcode.h:215
@ OP_MUL
B R[a] = R[a]*R[a+1].
Definition opcode.h:199
@ OP_MATCHERR
B raise NoMatchingPatternError unless R[a].
Definition opcode.h:170
@ OP_STRING
BB R[a] = str_dup(Pool[b]).
Definition opcode.h:216
@ OP_ERR
B raise(LocalJumpError, Pool[a]).
Definition opcode.h:238
@ OP_TDEF
BBB target_class.newmethod(Syms[b],Irep[c]); R[a] = Syms[b].
Definition opcode.h:231
@ OP_RESCUE
BB R[b] = R[a].isa?(R[b]).
Definition opcode.h:168
@ 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:164
@ OP_HASHCAT
B R[a] = hash_cat(R[a],R[a+1]).
Definition opcode.h:220
@ OP_DEF
BB R[a].newmethod(Syms[b],R[a+1]); R[a] = Syms[b].
Definition opcode.h:230
@ 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_SDEF
BBB R[a].singleton_class.newmethod(Syms[b],Irep[c]); R[a] = Syms[b].
Definition opcode.h:232
@ OP_GT
B R[a] = R[a]>R[a+1].
Definition opcode.h:204
@ OP_LOADTRUE
B R[a] = true.
Definition opcode.h:143
@ OP_KEYEND
Z raise unless kdict.empty?
Definition opcode.h:183
@ 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:203
@ OP_RETNIL
Z return nil.
Definition opcode.h:188
@ OP_GETGV
BB R[a] = getglobal(Syms[b]).
Definition opcode.h:145
@ OP_BLKCALL
BB R[a] = R[a].call(R[a+1],... ,R[a+b]); direct block call.
Definition opcode.h:178
@ OP_RETURN
B return R[a] (normal).
Definition opcode.h:185
@ OP_EXCEPT
B R[a] = exc.
Definition opcode.h:167
@ 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:206
@ OP_SSEND0
BB R[a] = self.send(Syms[b]) (no args).
Definition opcode.h:172
@ OP_ADDI
BB R[a] = R[a]+mrb_int(b).
Definition opcode.h:194
@ OP_SCLASS
B R[a] = R[a].singleton_class.
Definition opcode.h:235
@ OP_SUPER
BB R[a] = super(R[a+1],... ,R[a+b+1]).
Definition opcode.h:179
@ 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:176
@ OP_BLOCK
BB R[a] = lambda(Irep[b],L_BLOCK).
Definition opcode.h:222
@ 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:163
@ OP_JMP
S pc+=a.
Definition opcode.h:162
@ OP_HASH
BB R[a] = hash_new(R[a],R[a+1]..R[a+b*2-1]).
Definition opcode.h:218
#define FETCH_Z()
Definition opcode.h:27
#define FETCH_B()
Definition opcode.h:62
uint8_t is_called_super
flags when called by OP_SUPER.
Definition vm.h:137
const mrbc_irep * cur_irep
copy from mrbc_vm.
Definition vm.h:126
struct RClass * target_class
copy from mrbc_vm.
Definition vm.h:129
mrbc_sym method_id
called method ID.
Definition vm.h:134
struct RHash * karg_keep
keyword argument backup for OP_ARGARY.
Definition vm.h:133
uint8_t n_args
num of arguments.
Definition vm.h:136
struct CALLINFO * prev
previous linked list.
Definition vm.h:130
const uint8_t * inst
copy from mrbc_vm.
Definition vm.h:127
mrbc_value * cur_regs
copy from mrbc_vm.
Definition vm.h:128
struct RClass * own_class
class that owns method.
Definition vm.h:132
uint8_t reg_offset
register offset after call.
Definition vm.h:135
uint8_t is_called_block
flags when block calls.
Definition vm.h:138
uint8_t target[4]
The address to jump to if a match is made.
Definition vm.h:113
uint8_t begin[4]
The starting address to match the handler. Includes this.
Definition vm.h:111
uint8_t type
enum mrb_catch_type, 1 byte. 0=rescue, 1=ensure
Definition vm.h:110
uint8_t end[4]
The endpoint address that matches the handler. Not Includes this.
Definition vm.h:112
const uint8_t * inst
pointer to instruction in RITE binary
Definition vm.h:63
uint16_t ilen
num of bytes in OpCode
Definition vm.h:55
uint16_t ref_count
reference counter
Definition vm.h:48
uint16_t rlen
num of child IREP blocks
Definition vm.h:53
uint16_t clen
num of catch handlers
Definition vm.h:54
uint16_t nregs
num of register variables
Definition vm.h:52
uint16_t n_stored
num of stored.
Definition c_array.h:47
mrbc_value * data
pointer to allocated memory.
Definition c_array.h:48
struct RMethod * method_link
pointer to method link.
Definition class.h:107
unsigned int flag_alias
is module alias?
Definition class.h:101
struct RClass * super
pointer to super class.
Definition class.h:103
struct RClass * aliased
aliased class or module.
Definition class.h:108
mrbc_sym sym_id
class name's symbol ID
Definition class.h:97
unsigned int flag_nomethod
is built-in no method class? (= 0)
Definition class.h:99
mrbc_sym method_id
raised method, if it is known.
Definition error.h:52
uint16_t n_stored
num of stored.
Definition c_hash.h:48
mrbc_value * data
pointer to allocated memory.
Definition c_hash.h:49
struct RClass * cls
return value for mrbc_find_method.
Definition class.h:208
mrbc_sym sym_id
function names symbol ID
Definition class.h:201
uint8_t type
M:OP_DEF or OP_ALIAS, m:mrblib or define_method().
Definition class.h:199
struct IREP * irep
to IREP for ruby proc.
Definition class.h:203
struct RMethod * next
link to next method.
Definition class.h:207
uint8_t c_func
0:IREP, 1:C Func, 2:C Func (built-in)
Definition class.h:200
mrbc_func_t func
to C function.
Definition class.h:204
struct RProc * proc
Definition boxing_no.h:30
struct RException * exception
Definition boxing_no.h:35
mrbc_sym sym_id
Definition boxing_no.h:26
struct RHash * hash
Definition boxing_no.h:34
void * handle
Definition boxing_no.h:36
mrbc_vtype tt
Definition boxing_no.h:20
struct RClass * cls
Definition boxing_no.h:28
struct RArray * array
Definition boxing_no.h:31
mrbc_value ret_val
Return value of this block.
Definition c_proc.h:51
struct CALLINFO * callinfo
callinfo when proc was created.
Definition c_proc.h:47
struct CALLINFO * callinfo_self
callinfo of self object. Valid when 'B'.
Definition c_proc.h:48
unsigned int flag_need_memfree
Definition vm.h:156
mrbc_sym callee_sym_id
Current called method.
Definition vm.h:170
uint16_t regs_size
size of regs[]
Definition vm.h:171
const mrbc_irep * cur_irep
IREP currently running.
Definition vm.h:162
struct RProc * ret_blk
Return block.
Definition vm.h:168
unsigned int flag_stop
Definition vm.h:157
struct RClass * target_class
Target class.
Definition vm.h:165
mrbc_callinfo * callinfo_tail
Last point of CALLINFO link.
Definition vm.h:166
uint8_t vm_id
vm_id : 1..MAX_VM_COUNT
Definition vm.h:154
volatile int8_t flag_preemption
Definition vm.h:155
mrbc_value exception
Raised exception or nil.
Definition vm.h:169
unsigned int flag_permanence
Definition vm.h:158
const uint8_t * inst
Instruction pointer.
Definition vm.h:163
mrbc_value regs[]
Definition vm.h:172
mrbc_value * cur_regs
Current register top.
Definition vm.h:164
mrbc_irep * top_irep
IREP tree top.
Definition vm.h:160
mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
Definition symbol.c:335
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:218
void mrbc_separate_nested_symid(mrbc_sym sym_id, mrbc_sym *id1, mrbc_sym *id2)
Definition symbol.c:312
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:239
static int mrbc_is_nested_symid(mrbc_sym sym_id)
Definition symbol.h:74
#define MRBC_SYM(sym)
Definition symbol.h:34
int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition value.c:68
int32_t mrbc_int_t
Definition value.h:47
static void mrbc_decref(mrbc_value *v)
Definition value.h:572
static void mrbc_decref_empty(mrbc_value *v)
Definition value.h:590
static uint32_t bin_to_uint32(const void *s)
Definition value.h:646
#define MRBC_TT_MAXVAL
Definition value.h:104
static void mrbc_incref(mrbc_value *v)
Definition value.h:557
@ E_NOTIMP_ERROR
Definition value.h:123
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:62
@ MRBC_TT_FALSE
FalseClass.
Definition value.h:82
@ MRBC_TT_STRING
String.
Definition value.h:98
@ MRBC_TT_FLOAT
Float.
Definition value.h:88
@ MRBC_TT_INTEGER
Integer.
Definition value.h:86
@ MRBC_TT_RETURN
Definition value.h:76
@ MRBC_TT_EXCEPTION
Exception.
Definition value.h:101
@ MRBC_TT_EMPTY
Definition value.h:80
@ MRBC_TT_PROC
Proc.
Definition value.h:96
@ MRBC_TT_JMPUW
Definition value.h:73
@ MRBC_TT_OBJECT
General instance.
Definition value.h:95
@ MRBC_TT_BREAK
Definition value.h:74
@ MRBC_TT_ARRAY
Array.
Definition value.h:97
@ MRBC_TT_MODULE
Module.
Definition value.h:91
@ MRBC_TT_NIL
NilClass.
Definition value.h:81
@ MRBC_TT_RETURN_BLK
Definition value.h:75
@ MRBC_TT_HASH
Hash.
Definition value.h:100
@ MRBC_TT_CLASS
Class.
Definition value.h:90
static void op_send(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1278
static void send_by_name(mrbc_vm *vm, mrbc_sym sym_id, int a, int c)
Definition vm.c:57
static void op_loadsym(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:545
#define EXT
Definition vm.c:423
static void op_lt(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2326
static void op_getgv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:616
static void op_mul(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2204
void mrbc_vm_close(mrbc_vm *vm)
Definition vm.c:402
static void op_loadi8(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:470
static void op_array(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2410
static void op_move(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:441
static void op_sdef(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3039
static void op_loadfalse(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:602
static void op_retnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1858
static void op_strcat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2663
static void op_getidx0(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:898
static void op_jmpif(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:944
static void op_send0(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1291
static void op_def(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3003
static void op_stop(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3131
static void op_tdef(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3021
static void op_alias(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3057
static void op_setupvar(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:853
void mrbc_pop_callinfo(mrbc_vm *vm)
Definition vm.c:241
static void op_sendb(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1304
static void op_setidx(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:918
mrbc_vm * mrbc_vm_new(int regs_size)
Definition vm.c:287
static void op_symbol(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2628
static void op_ssendb(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1260
static void op_getconst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:695
static void op_matcherr(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1209
static void op_hash(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2689
static void op_jmpnot(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:959
static void op_loadi_n(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:498
static void op_add(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2006
static void op_except(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1023
static void op_addi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2050
static void op_ge(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2389
static void op_tclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3099
static void op_class(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2830
static void op_unsupported(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3144
static void op_sclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3087
static void op_gt(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2368
static void op_div(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2248
static void op_aref(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2523
static void op_module(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2890
static void sub_op_def(mrbc_vm *vm, mrbc_class *cls, mrbc_irep *irep, mrbc_sym sym_id)
Definition vm.c:2975
static void op_keyend(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1670
static void op_getiv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:650
#define FLAG_DICT
static void op_argary(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1426
static void op_super(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1330
static void op_ssend(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1224
static void op_setiv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:672
static void op_getidx(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:885
static void op_apost(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2569
static void sub_op_return(mrbc_vm *vm, mrbc_value *regs, int a)
Definition vm.c:1713
static void op_arypush(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2488
static void op_aset(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2553
#define CALL_MAXARGS
Definition vm.c:31
static void op_nop(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:430
static void op_ext(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:3117
static void op_setgv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:636
static void op_return(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1774
static void op_hashcat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2733
static void op_loadi16(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:516
static void op_jmpuw(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:989
static void sub_irep_inc_dec_ref(mrbc_irep *irep, int inc_dec)
Definition vm.c:2942
static void op_getupvar(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:820
static void sub_newmethod(mrbc_class *cls, mrbc_method *method, mrbc_sym sym_id)
Definition vm.c:2951
static void op_return_blk(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1787
static void op_karg(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1691
static void op_eq(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2305
static void op_key_p(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1652
static void op_intern(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2610
static void op_rescue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1038
static void op_loadineg(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:484
static void op_block(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2753
static void op_loadl(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:456
static void op_le(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2347
static void op_range_exc(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2800
static void op_loadtrue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:588
mrbc_vm * mrbc_vm_open(mrbc_vm *vm)
Definition vm.c:309
static void op_subi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2121
int mrbc_vm_run(mrbc_vm *vm)
Definition vm.c:3160
static void op_method(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2769
static void op_setconst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:753
static void op_addilv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2148
static void op_array2(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2430
static void op_arysplat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2508
static void op_arycat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2450
static void op_blkpush(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1953
static void op_enter(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1508
#define FLAG_KW
static const mrbc_irep_catch_handler * find_catch_handler_ensure(const mrbc_vm *vm)
Definition vm.c:172
void mrbc_vm_end(mrbc_vm *vm)
Definition vm.c:366
static void op_loadself(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:573
#define IS_CLASS_OR_MODULE(v)
Definition vm.c:35
#define FLAG_REST
void mrbc_cleanup_vm(void)
Definition vm.c:201
static void op_jmp(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:931
static void op_sub(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2077
static void op_rettrue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1874
static void op_range_inc(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2785
static void op_jmpnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:974
static void op_retself(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1841
static void op_retfalse(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1890
static void op_loadi32(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:531
static void op_hashadd(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2711
static void op_loadnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:559
static void op_exec(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2925
static void op_subilv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2176
static void op_getmcnst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:773
static void op_raiseif(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1055
static void op_break(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1906
static void op_string(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2649
static void op_blkcall(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1317
static void op_ssend0(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1242
void mrbc_vm_begin(mrbc_vm *vm)
Definition vm.c:340
static uint16_t free_vm_bitmap[MAX_VM_COUNT/16+1]
for getting the VM ID
Definition vm.c:43
#define FLAG_M2
static void op_oclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2815
mrbc_callinfo * mrbc_push_callinfo(mrbc_vm *vm, mrbc_sym method_id, int reg_offset, int n_args)
Definition vm.c:210
static mrbc_value * mrbc_get_self(mrbc_vm *vm, mrbc_value *regs)
Definition vm.h:203
#define mrbc_irep_pool_ptr(irep, n)
get a pointer to n'th pool data.
Definition vm.h:91
struct CALLINFO mrbc_callinfo
Call information.
#define mrbc_irep_symbol_id(irep, n)
get a n'th symbol id in irep
Definition vm.h:80
#define mrbc_irep_child_irep(irep, n)
get a n'th child irep
Definition vm.h:100
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:83
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:20
#define MAX_REGS_SIZE
Definition vm_config.h:25