mruby/c VM Source Code release 4.0.0
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/***** Typedefs *************************************************************/
36/***** Function prototypes **************************************************/
37/***** Local variables ******************************************************/
39static uint16_t free_vm_bitmap[MAX_VM_COUNT / 16 + 1];
40
41
42/***** Global variables *****************************************************/
43/***** Signal catching functions ********************************************/
44/***** Local functions ******************************************************/
45//================================================================
53static void send_by_name( mrbc_vm *vm, mrbc_sym sym_id, int a, int c )
54{
55 int narg = c & 0x0f;
56 int karg = (c >> 4) & 0x0f;
57 int have_block = (c >> 8);
58 mrbc_value *recv = vm->cur_regs + a;
59
60 // If it's packed in an array, expand it.
61 if( narg == CALL_MAXARGS ) {
62 mrbc_value argary = recv[1];
63 int n_move = (karg == CALL_MAXARGS) ? 2 : karg * 2 + 1;
64
65 narg = mrbc_array_size(&argary);
66 for( int i = 0; i < narg; i++ ) {
67 mrbc_incref( &argary.array->data[i] );
68 }
69
70 memmove( recv + narg + 1, recv + 2, sizeof(mrbc_value) * n_move );
71 if( narg == 0 ) {
72 mrbc_set_tt( recv + n_move + 1, MRBC_TT_EMPTY );
73 } else {
74 memcpy( recv + 1, argary.array->data, sizeof(mrbc_value) * narg );
75 }
76 mrbc_decref(&argary);
77 }
78
79 mrbc_value *r1 = recv + narg + 1;
80
81 // Process keyword arguments
82 if( karg ) {
83 if( karg == CALL_MAXARGS ) {
84 assert( mrbc_type(r1[0]) == MRBC_TT_HASH );
85 if( mrbc_hash_size(&r1[0]) == 0 ) {
86 // delete zero size keyword hash.
87 mrbc_decref(&r1[0]);
88 r1[0] = r1[1]; // move block Proc
90 r1--;
91 }
92 } else {
93 // Convert keyword argument to hash.
94 mrbc_value hval = mrbc_hash_new( vm, karg );
95
96 memcpy( hval.hash->data, r1, sizeof(mrbc_value) * karg * 2 );
97 hval.hash->n_stored = karg * 2;
98
99 r1[0] = hval;
100 r1[1] = r1[karg * 2]; // move block Proc
101 memset( r1 + 2, 0, sizeof(mrbc_value) * (karg * 2 - 1) );
102 }
103 r1++;
104 }
105
106 // is not have block
107 if( !have_block ) {
108 mrbc_decref( r1 );
109 mrbc_set_nil( r1 );
110 }
111
112 // find a method
113 mrbc_class *cls = find_class_by_object(recv);
114 mrbc_method method;
115 if( mrbc_find_method( &method, cls, sym_id ) != 0 ) goto CALL_METHOD;
116
117 // method missing?
118 if( mrbc_find_method( &method, cls, MRBC_SYM(method_missing) ) == 0 ) {
119 mrbc_raisef(vm, MRBC_CLASS(NoMethodError),
120 "undefined local variable or method '%s' for %s",
122 if( vm->callinfo_tail != 0 ) {
124 }
125 return;
126 }
127
128 // prepare to call 'method_missing' method.
129 for( int i = narg+1; i != 0; i-- ) { // shift arguments
130 recv[i+1] = recv[i];
131 }
132 mrbc_set_symbol( &recv[1], sym_id );
133 sym_id = MRBC_SYM(method_missing);
134 narg++;
135
136
137 CALL_METHOD:
138 if( !method.c_func ) goto CALL_RUBY_METHOD;
139
140 vm->callee_sym_id = sym_id;
141 method.func(vm, recv, narg);
142
143 if( mrbc_israised(vm) && vm->exception.exception->method_id == 0 ) {
144 vm->exception.exception->method_id = sym_id;
145 }
146 if( sym_id == MRBC_SYM(call) ) return;
147 if( sym_id == MRBC_SYM(new) ) return;
148
149 for( int i = 1; i <= narg + !!karg + have_block; i++ ) {
150 mrbc_decref_empty( recv + i );
151 }
152 return;
153
154
155 CALL_RUBY_METHOD:;
156 mrbc_callinfo *callinfo = mrbc_push_callinfo(vm, sym_id, a, narg);
157 callinfo->own_class = method.cls;
158
159 vm->cur_irep = method.irep;
160 vm->inst = vm->cur_irep->inst;
161 vm->cur_regs = recv;
162}
163
164
165//================================================================
169{
170 const mrbc_irep *irep = vm->cur_irep;
171 int cnt = irep->clen;
172 if( cnt == 0 ) return NULL;
173
174 const mrbc_irep_catch_handler *catch_table =
175 (const mrbc_irep_catch_handler *)(irep->inst + irep->ilen);
176 uint32_t inst = vm->inst - irep->inst;
177
178 for( cnt--; cnt >= 0 ; cnt-- ) {
179 const mrbc_irep_catch_handler *handler = catch_table + cnt;
180 // Catch type and range check
181 if( (handler->type == 1) && // 1=CATCH_FILTER_ENSURE
182 (bin_to_uint32(handler->begin) < inst) &&
183 (inst <= bin_to_uint32(handler->end)) ) {
184 return handler;
185 }
186 }
187
188 return NULL;
189}
190
191
192/***** Global functions *****************************************************/
193
194//================================================================
198{
199 memset(free_vm_bitmap, 0, sizeof(free_vm_bitmap));
200}
201
202
203//================================================================
206mrbc_callinfo * mrbc_push_callinfo( mrbc_vm *vm, mrbc_sym method_id, int reg_offset, int n_args )
207{
208 mrbc_callinfo *callinfo = mrbc_alloc(vm, sizeof(mrbc_callinfo));
209
210 *callinfo = (mrbc_callinfo){
211#if defined(MRBC_DEBUG)
212 .obj_mark_ = "CI",
213#endif
214 .cur_irep = vm->cur_irep,
215 .inst = vm->inst,
216 .cur_regs = vm->cur_regs,
217 .target_class = vm->target_class,
218 .prev = vm->callinfo_tail,
219 .own_class = 0,
220 .karg_keep = 0,
221 .method_id = method_id,
222 .reg_offset = reg_offset,
223 .n_args = n_args,
224 .is_called_super = 0,
225 .is_called_block = 0,
226 };
227
228 vm->callinfo_tail = callinfo;
229
230 return callinfo;
231}
232
233
234//================================================================
238{
239 assert( vm->callinfo_tail );
240
241 // clear used register.
242 mrbc_callinfo *callinfo = vm->callinfo_tail;
243 mrbc_value *r0 = vm->cur_regs;
244
245 for( int i = 1; i < vm->cur_irep->nregs; i++ ) {
246 mrbc_decref_empty( r0+i );
247 }
248
249 if( callinfo->karg_keep ) {
251 }
252
253 // copy callinfo to vm
254 vm->cur_irep = callinfo->cur_irep;
255 vm->inst = callinfo->inst;
256 vm->cur_regs = callinfo->cur_regs;
257 vm->target_class = callinfo->target_class;
258 vm->callinfo_tail = callinfo->prev;
259
260 mrbc_free(vm, callinfo);
261}
262
263
264//================================================================
283mrbc_vm * mrbc_vm_new( int regs_size )
284{
285 unsigned int vm_total_size = sizeof(mrbc_vm) + sizeof(mrbc_value) * regs_size;
286 mrbc_vm *vm = mrbc_raw_alloc(vm_total_size);
287
288 memset(vm, 0, vm_total_size); // caution: assume NULL is zero.
289#if defined(MRBC_DEBUG)
290 memcpy(vm->obj_mark_, "VM", 2);
291#endif
292 vm->flag_need_memfree = 1;
293 vm->regs_size = regs_size;
294
295 return vm;
296}
297
298
299//================================================================
306{
307 if( !vm ) vm = mrbc_vm_new( MAX_REGS_SIZE );
308
309 // allocate vm id.
310 int vm_id;
311 for( vm_id = 0; vm_id < MAX_VM_COUNT; vm_id++ ) {
312 int idx = vm_id >> 4;
313 int bit = 1 << (vm_id & 0x0f);
314 if( (free_vm_bitmap[idx] & bit) == 0 ) {
315 free_vm_bitmap[idx] |= bit; // found
316 break;
317 }
318 }
319
320 if( vm_id == MAX_VM_COUNT ) {
321 if( vm->flag_need_memfree ) mrbc_raw_free(vm);
322 return NULL;
323 }
324
325 vm->vm_id = ++vm_id;
326
327 return vm;
328}
329
330
331//================================================================
337{
338 vm->cur_irep = vm->top_irep;
339 vm->inst = vm->cur_irep->inst;
340 vm->cur_regs = vm->regs;
341 vm->target_class = MRBC_CLASS(Object);
342 vm->callinfo_tail = NULL;
343 vm->ret_blk = NULL;
345 vm->flag_preemption = 0;
346 vm->flag_stop = 0;
347
348 // set self to reg[0], others nil
349 mrbc_decref( &vm->regs[0] );
350 vm->regs[0] = mrbc_instance_new(vm, MRBC_CLASS(Object), 0);
351 for( int i = 1; i < vm->regs_size; i++ ) {
352 mrbc_set_nil( &vm->regs[i] );
353 }
354}
355
356
357//================================================================
363{
364 if( mrbc_israised(vm) ) {
365#if defined(MRBC_ABORT_BY_EXCEPTION)
366 MRBC_ABORT_BY_EXCEPTION(vm);
367#else
370#endif
371 }
372 assert( vm->ret_blk == 0 );
373
374 int n_used = 0;
375 for( int i = 1; i < vm->regs_size; i++ ) {
376 //mrbc_printf("vm->regs[%d].tt = %d\n", i, mrbc_type(vm->regs[i]));
377 if( mrbc_type(vm->regs[i]) != MRBC_TT_NIL ) n_used = i;
378 mrbc_decref_empty(&vm->regs[i]);
379 }
380 (void)n_used; // avoid warning.
381#if defined(MRBC_DEBUG_REGS)
382 mrbc_printf("Finally number of registers used was %d in VM %d.\n",
383 n_used, vm->vm_id );
384#endif
385
386#if defined(MRBC_ALLOC_VMID)
387 mrbc_global_clear_vm_id();
388 mrbc_free_all(vm);
389#endif
390}
391
392
393//================================================================
399{
400 mrbc_decref( &vm->regs[0] );
401
402 // free vm id.
403 if( vm->vm_id != 0 ) {
404 int idx = (vm->vm_id-1) >> 4;
405 int bit = 1 << ((vm->vm_id-1) & 0x0f);
406 free_vm_bitmap[idx] &= ~bit;
407 }
408
409 // free irep and vm
410 if( vm->top_irep ) mrbc_irep_free( vm->top_irep );
411 if( vm->flag_need_memfree ) mrbc_raw_free(vm);
412}
413
414
415/***** opecode functions ****************************************************/
416#if defined(MRBC_SUPPORT_OP_EXT)
417#define EXT , int ext
418#else
419#define EXT
420#endif
421//================================================================
426static inline void op_nop( mrbc_vm *vm, mrbc_value *regs EXT )
427{
428 FETCH_Z();
429}
430
431
432//================================================================
437static inline void op_move( mrbc_vm *vm, mrbc_value *regs EXT )
438{
439 FETCH_BB();
440
441 mrbc_incref(&regs[b]);
442 mrbc_decref(&regs[a]);
443 regs[a] = regs[b];
444}
445
446
447//================================================================
452static inline void op_loadl( mrbc_vm *vm, mrbc_value *regs EXT )
453{
454 FETCH_BB();
455
456 mrbc_decref(&regs[a]);
457 regs[a] = mrbc_irep_pool_value(vm, b);
458}
459
460
461//================================================================
466static inline void op_loadi8( mrbc_vm *vm, mrbc_value *regs EXT )
467{
468 FETCH_BB();
469
470 mrbc_decref(&regs[a]);
471 mrbc_set_integer(&regs[a], b);
472}
473
474
475//================================================================
480static inline void op_loadineg( mrbc_vm *vm, mrbc_value *regs EXT )
481{
482 FETCH_BB();
483
484 mrbc_decref(&regs[a]);
485 mrbc_set_integer(&regs[a], -(mrbc_int_t)b);
486}
487
488
489//================================================================
494static inline void op_loadi_n( mrbc_vm *vm, mrbc_value *regs EXT )
495{
496 // get n
497 int opcode = vm->inst[-1];
498 int n = opcode - OP_LOADI_0;
499
500 FETCH_B();
501
502 mrbc_decref(&regs[a]);
503 mrbc_set_integer(&regs[a], n);
504}
505
506
507//================================================================
512static inline void op_loadi16( mrbc_vm *vm, mrbc_value *regs EXT )
513{
514 FETCH_BS();
515
516 mrbc_decref(&regs[a]);
517 int16_t signed_b = (int16_t)b;
518 mrbc_set_integer(&regs[a], signed_b);
519}
520
521
522//================================================================
527static inline void op_loadi32( mrbc_vm *vm, mrbc_value *regs EXT )
528{
529 FETCH_BSS();
530
531 mrbc_decref(&regs[a]);
532 mrbc_set_integer(&regs[a], (((int32_t)b<<16)+(int32_t)c));
533}
534
535
536//================================================================
541static inline void op_loadsym( mrbc_vm *vm, mrbc_value *regs EXT )
542{
543 FETCH_BB();
544
545 mrbc_decref(&regs[a]);
547}
548
549
550//================================================================
555static inline void op_loadnil( mrbc_vm *vm, mrbc_value *regs EXT )
556{
557 FETCH_B();
558
559 mrbc_decref(&regs[a]);
560 mrbc_set_nil(&regs[a]);
561}
562
563
564//================================================================
569static inline void op_loadself( mrbc_vm *vm, mrbc_value *regs EXT )
570{
571 FETCH_B();
572
573 mrbc_decref(&regs[a]);
574 regs[a] = *mrbc_get_self( vm, regs );
575 mrbc_incref( &regs[a] );
576}
577
578
579//================================================================
584static inline void op_loadtrue( mrbc_vm *vm, mrbc_value *regs EXT )
585{
586 FETCH_B();
587
588 mrbc_decref(&regs[a]);
589 mrbc_set_true(&regs[a]);
590}
591
592
593//================================================================
598static inline void op_loadfalse( mrbc_vm *vm, mrbc_value *regs EXT )
599{
600 FETCH_B();
601
602 mrbc_decref(&regs[a]);
603 mrbc_set_false(&regs[a]);
604}
605
606
607//================================================================
612static inline void op_getgv( mrbc_vm *vm, mrbc_value *regs EXT )
613{
614 FETCH_BB();
615
616 mrbc_decref(&regs[a]);
618 if( v == NULL ) {
619 mrbc_set_nil(&regs[a]);
620 } else {
621 mrbc_incref(v);
622 regs[a] = *v;
623 }
624}
625
626
627//================================================================
632static inline void op_setgv( mrbc_vm *vm, mrbc_value *regs EXT )
633{
634 FETCH_BB();
635
636 mrbc_incref(&regs[a]);
637 mrbc_set_global( mrbc_irep_symbol_id(vm->cur_irep, b), &regs[a] );
638}
639
640
641//================================================================
646static inline void op_getiv( mrbc_vm *vm, mrbc_value *regs EXT )
647{
648 FETCH_BB();
649
650 const char *sym_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
651 mrbc_sym sym_id = mrbc_str_to_symid(sym_name+1); // skip '@'
652 if( sym_id < 0 ) {
653 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
654 return;
655 }
656 mrbc_value *self = mrbc_get_self( vm, regs );
657 if( mrbc_type(*self) != MRBC_TT_OBJECT ) {
658 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), 0);
659 return;
660 }
661
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 mrbc_value *self = mrbc_get_self( vm, regs );
683 if( mrbc_type(*self) != MRBC_TT_OBJECT ) {
684 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), 0);
685 return;
686 }
687
688 mrbc_instance_setiv(self, sym_id, &regs[a]);
689}
690
691
692//================================================================
697static inline void op_getconst( mrbc_vm *vm, mrbc_value *regs EXT )
698{
699 FETCH_BB();
700
701 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
702 mrbc_class *crit_cls;
703 mrbc_value *ret;
704
705 if( vm->callinfo_tail && vm->callinfo_tail->own_class ) {
706 crit_cls = vm->callinfo_tail->own_class;
707 if( crit_cls->flag_alias ) crit_cls = crit_cls->aliased;
708 } else {
709 crit_cls = find_class_by_object( mrbc_get_self(vm, regs) );
710 }
711
712 // search in my class, then search nested outer class.
713 mrbc_class *cls = crit_cls;
714 while( 1 ) {
715 ret = mrbc_get_class_const(cls, sym_id);
716 if( ret ) goto DONE;
717 if( !mrbc_is_nested_symid(cls->sym_id) ) break;
718
719 mrbc_sym outer_id;
720 mrbc_separate_nested_symid( cls->sym_id, &outer_id, 0 );
721 cls = mrbc_get_const( outer_id )->cls;
722 }
723
724 // search in super class.
726 int nest_idx = 0;
727
728 cls = crit_cls;
729 while( (cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx )) ) {
730 if( cls->flag_alias ) cls = cls->aliased;
731 ret = mrbc_get_class_const(cls, sym_id);
732 if( ret ) goto DONE;
733 }
734
735 // is top level constant definition?
736 ret = mrbc_get_const(sym_id);
737 if( ret == NULL ) {
738 mrbc_raisef( vm, MRBC_CLASS(NameError),
739 "uninitialized constant %s", mrbc_symid_to_str(sym_id));
740 return;
741 }
742
743 DONE:
744 mrbc_incref(ret);
745 mrbc_decref(&regs[a]);
746 regs[a] = *ret;
747}
748
749
750//================================================================
755static inline void op_setconst( mrbc_vm *vm, mrbc_value *regs EXT )
756{
757 FETCH_BB();
758
759 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
760
761 mrbc_incref(&regs[a]);
762 if( mrbc_type(regs[0]) == MRBC_TT_CLASS ||
763 mrbc_type(regs[0]) == MRBC_TT_MODULE ) {
764 mrbc_set_class_const(regs[0].cls, sym_id, &regs[a]);
765 } else {
766 mrbc_set_const(sym_id, &regs[a]);
767 }
768}
769
770
771//================================================================
776static inline void op_getmcnst( mrbc_vm *vm, mrbc_value *regs EXT )
777{
778 FETCH_BB();
779
780 mrbc_sym sym_id = mrbc_irep_symbol_id(vm->cur_irep, b);
781 mrbc_class *cls = regs[a].cls;
782 mrbc_value *ret;
783
784 // ::CONST case
785 if( cls->sym_id == MRBC_SYM(Object) ) {
786 ret = mrbc_get_const(sym_id);
787 if( ret == NULL ) {
788 mrbc_raisef( vm, MRBC_CLASS(NameError), "uninitialized constant %s::%s",
789 "", mrbc_symid_to_str( sym_id ));
790 return;
791 }
792 goto DONE;
793 }
794
796 int nest_idx = 0;
797
798 while( !(ret = mrbc_get_class_const(cls, sym_id)) ) {
799 cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx );
800 if( !cls ) {
801 mrbc_raisef( vm, MRBC_CLASS(NameError), "uninitialized constant %s::%s",
802 mrbc_symid_to_str( regs[a].cls->sym_id ), mrbc_symid_to_str( sym_id ));
803 return;
804 }
805 if( cls->flag_alias ) cls = cls->aliased;
806 }
807
808 DONE:
809 mrbc_incref(ret);
810 mrbc_decref(&regs[a]);
811 regs[a] = *ret;
812}
813
814
815//================================================================
823static inline void op_getupvar( mrbc_vm *vm, mrbc_value *regs EXT )
824{
825 FETCH_BBB();
826
827 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
828 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
829
830 for( int i = 0; i < c; i++ ) {
831 assert( callinfo );
832 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
833
834 if( mrbc_type(*reg0) != MRBC_TT_PROC ) break; // What to do?
835 callinfo = reg0->proc->callinfo;
836 }
837
838 mrbc_value *p_val;
839 if( callinfo == 0 ) {
840 p_val = vm->regs + b;
841 } else {
842 p_val = callinfo->cur_regs + callinfo->reg_offset + b;
843 }
844 mrbc_incref( p_val );
845
846 mrbc_decref( &regs[a] );
847 regs[a] = *p_val;
848}
849
850
851//================================================================
856static inline void op_setupvar( mrbc_vm *vm, mrbc_value *regs EXT )
857{
858 FETCH_BBB();
859
860 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
861 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
862
863 for( int i = 0; i < c; i++ ) {
864 assert( callinfo );
865 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
866 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
867 callinfo = reg0->proc->callinfo;
868 }
869
870 mrbc_value *p_val;
871 if( callinfo == 0 ) {
872 p_val = vm->regs + b;
873 } else {
874 p_val = callinfo->cur_regs + callinfo->reg_offset + b;
875 }
876 mrbc_decref( p_val );
877
878 mrbc_incref( &regs[a] );
879 *p_val = regs[a];
880}
881
882
883//================================================================
888static inline void op_getidx( mrbc_vm *vm, mrbc_value *regs EXT )
889{
890 FETCH_B();
891
892 send_by_name( vm, MRBC_SYMID_BL_BR, a, 1 );
893}
894
895
896//================================================================
901static inline void op_getidx0( mrbc_vm *vm, mrbc_value *regs EXT )
902{
903 FETCH_BB();
904
905 if( a != b ) {
906 mrbc_decref( &regs[a] );
907 regs[a] = regs[b];
908 mrbc_incref( &regs[a] );
909 }
910 mrbc_decref( &regs[a+1] );
911 mrbc_set_integer( &regs[a+1], 0 );
912 send_by_name( vm, MRBC_SYMID_BL_BR, a, 1 );
913}
914
915
916//================================================================
921static inline void op_setidx( mrbc_vm *vm, mrbc_value *regs EXT )
922{
923 FETCH_B();
924
925 send_by_name( vm, MRBC_SYMID_BL_BR_EQ, a, 2 );
926}
927
928
929//================================================================
934static inline void op_jmp( mrbc_vm *vm, mrbc_value *regs EXT )
935{
936 FETCH_S();
937
938 vm->inst += (int16_t)a;
939}
940
941
942//================================================================
947static inline void op_jmpif( mrbc_vm *vm, mrbc_value *regs EXT )
948{
949 FETCH_BS();
950
951 if( mrbc_type(regs[a]) > MRBC_TT_FALSE ) {
952 vm->inst += (int16_t)b;
953 }
954}
955
956
957//================================================================
962static inline void op_jmpnot( mrbc_vm *vm, mrbc_value *regs EXT )
963{
964 FETCH_BS();
965
966 if( mrbc_type(regs[a]) <= MRBC_TT_FALSE ) {
967 vm->inst += (int16_t)b;
968 }
969}
970
971
972//================================================================
977static inline void op_jmpnil( mrbc_vm *vm, mrbc_value *regs EXT )
978{
979 FETCH_BS();
980
981 if( mrbc_type(regs[a]) == MRBC_TT_NIL ) {
982 vm->inst += (int16_t)b;
983 }
984}
985
986
987//================================================================
992static inline void op_jmpuw( mrbc_vm *vm, mrbc_value *regs EXT )
993{
994 FETCH_S();
995
996 const uint8_t *jump_inst = vm->inst + (int16_t)a;
997
998 // check catch handler (ensure)
1000 if( !handler ) {
1001 vm->inst = jump_inst;
1002 return;
1003 }
1004
1005 // check whether the jump point is inside or outside the catch handler.
1006 uint32_t jump_point = jump_inst - vm->cur_irep->inst;
1007 if( (bin_to_uint32(handler->begin) < jump_point) &&
1008 (jump_point <= bin_to_uint32(handler->end)) ) {
1009 vm->inst = jump_inst;
1010 return;
1011 }
1012
1013 // jump point is outside, thus jump to ensure.
1014 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1016 vm->exception.handle = (void*)jump_inst;
1017 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1018}
1019
1020
1021//================================================================
1026static inline void op_except( mrbc_vm *vm, mrbc_value *regs EXT )
1027{
1028 FETCH_B();
1029
1030 mrbc_decref( &regs[a] );
1031 regs[a] = vm->exception;
1032 mrbc_set_nil( &vm->exception );
1033}
1034
1035
1036//================================================================
1041static inline void op_rescue( mrbc_vm *vm, mrbc_value *regs EXT )
1042{
1043 FETCH_BB();
1044
1045 assert( mrbc_type(regs[a]) == MRBC_TT_EXCEPTION );
1046 assert( mrbc_type(regs[b]) == MRBC_TT_CLASS );
1047
1048 int res = mrbc_obj_is_kind_of( &regs[a], regs[b].cls );
1049 mrbc_set_bool( &regs[b], res );
1050}
1051
1052
1053//================================================================
1058static inline void op_raiseif( mrbc_vm *vm, mrbc_value *regs EXT )
1059{
1060 FETCH_B();
1061
1062 // save the parameter.
1063 mrbc_value ra = regs[a];
1064 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1065
1066 switch( mrbc_type(ra) ) {
1067 case MRBC_TT_RETURN: goto CASE_OP_RETURN;
1068 case MRBC_TT_RETURN_BLK: goto CASE_OP_RETURN_BLK;
1069 case MRBC_TT_BREAK: goto CASE_OP_BREAK;
1070 case MRBC_TT_JMPUW: goto CASE_OP_JMPUW;
1071 case MRBC_TT_EXCEPTION: goto CASE_OP_EXCEPTION;
1072 default: break;
1073 }
1074
1075 assert( mrbc_type(ra) == MRBC_TT_NIL );
1076 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1077 return;
1078
1079
1080CASE_OP_RETURN:
1081 {
1082 // find ensure that still needs to be executed.
1084 if( handler ) {
1085 vm->exception = ra;
1086 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1087 return;
1088 }
1089
1090 // set the return value and return to caller.
1091 mrbc_decref(&regs[0]);
1092 regs[0] = regs[ vm->cur_irep->nregs ];
1093 mrbc_set_tt( &regs[ vm->cur_irep->nregs ], MRBC_TT_EMPTY );
1094
1096 return;
1097 }
1098
1099
1100CASE_OP_RETURN_BLK:
1101 {
1102 assert( vm->ret_blk );
1103
1104 // return to the proc generated level.
1105 while( 1 ) {
1106 // find ensure that still needs to be executed.
1108 if( handler ) {
1109 vm->exception = ra;
1110 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1111 return;
1112 }
1113
1114 // Is it the origin (generator) of proc?
1115 if( vm->callinfo_tail == vm->ret_blk->callinfo_self ) break;
1116
1118 }
1119
1120 // top level return ?
1121 if( vm->callinfo_tail == NULL ) {
1123 vm->ret_blk = 0;
1124
1125 vm->flag_preemption = 1;
1126 vm->flag_stop = 1;
1127 return;
1128 }
1129
1130 // set the return value and return to caller.
1132 mrbc_decref(reg0);
1133 *reg0 = vm->ret_blk->ret_val;
1134
1136 vm->ret_blk = 0;
1137
1139 return;
1140 }
1141
1142
1143CASE_OP_BREAK:
1144 {
1145 assert( vm->ret_blk );
1146
1147 // return to the proc generated level.
1148 int reg_offset = 0;
1149 while( vm->callinfo_tail != vm->ret_blk->callinfo ) {
1150 // find ensure that still needs to be executed.
1152 if( handler ) {
1153 vm->exception = ra;
1154 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1155 return;
1156 }
1157
1158 reg_offset = vm->callinfo_tail->reg_offset;
1160 }
1161
1162 // set the return value.
1163 mrbc_value *reg0 = vm->cur_regs + reg_offset;
1164 mrbc_decref(reg0);
1165 *reg0 = vm->ret_blk->ret_val;
1166
1168 vm->ret_blk = 0;
1169 return;
1170 }
1171
1172
1173CASE_OP_JMPUW:
1174 {
1175 // find ensure that still needs to be executed.
1177 if( !handler ) {
1178 vm->inst = ra.handle;
1179 return;
1180 }
1181
1182 // check whether the jump point is inside or outside the catch handler.
1183 uint32_t jump_point = (uint8_t *)ra.handle - vm->cur_irep->inst;
1184 if( (bin_to_uint32(handler->begin) < jump_point) &&
1185 (jump_point <= bin_to_uint32(handler->end)) ) {
1186 vm->inst = ra.handle;
1187 return;
1188 }
1189
1190 // jump point is outside, thus jump to ensure.
1191 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1192 vm->exception = ra;
1193 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1194 return;
1195 }
1196
1197
1198CASE_OP_EXCEPTION:
1199 {
1200 vm->exception = ra;
1201 vm->flag_preemption = 2;
1202 return;
1203 }
1204}
1205
1206
1207//================================================================
1212static inline void op_matcherr( mrbc_vm *vm, mrbc_value *regs EXT )
1213{
1214 FETCH_B();
1215
1216 if( mrbc_type(regs[a]) <= MRBC_TT_FALSE ) {
1217 mrbc_raise( vm, MRBC_CLASS(NoMatchingPatternError), 0);
1218 }
1219}
1220
1221
1222//================================================================
1227static inline void op_ssend( mrbc_vm *vm, mrbc_value *regs EXT )
1228{
1229 FETCH_BBB();
1230
1231 mrbc_decref( &regs[a] );
1232 regs[a] = *mrbc_get_self( vm, regs );
1233 mrbc_incref( &regs[a] );
1234
1235 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c );
1236}
1237
1238
1239
1240//================================================================
1245static inline void op_ssend0( mrbc_vm *vm, mrbc_value *regs EXT )
1246{
1247 FETCH_BB();
1248
1249 mrbc_decref( &regs[a] );
1250 regs[a] = *mrbc_get_self( vm, regs );
1251 mrbc_incref( &regs[a] );
1252
1253 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, 0 );
1254}
1255
1256
1257
1258//================================================================
1263static inline void op_ssendb( mrbc_vm *vm, mrbc_value *regs EXT )
1264{
1265 FETCH_BBB();
1266
1267 mrbc_decref( &regs[a] );
1268 regs[a] = *mrbc_get_self( vm, regs );
1269 mrbc_incref( &regs[a] );
1270
1271 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c | 0x100 );
1272}
1273
1274
1275
1276//================================================================
1281static inline void op_send( mrbc_vm *vm, mrbc_value *regs EXT )
1282{
1283 FETCH_BBB();
1284
1285 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c );
1286}
1287
1288
1289//================================================================
1294static inline void op_send0( mrbc_vm *vm, mrbc_value *regs EXT )
1295{
1296 FETCH_BB();
1297
1298 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, 0 );
1299}
1300
1301
1302//================================================================
1307static inline void op_sendb( mrbc_vm *vm, mrbc_value *regs EXT )
1308{
1309 FETCH_BBB();
1310
1311 send_by_name( vm, mrbc_irep_symbol_id(vm->cur_irep, b), a, c | 0x100 );
1312}
1313
1314
1315//================================================================
1320static inline void op_blkcall( mrbc_vm *vm, mrbc_value *regs EXT )
1321{
1322 FETCH_BB();
1323
1324 send_by_name( vm, MRBC_SYM(call), a, b | 0x100 );
1325}
1326
1327
1328//================================================================
1333static inline void op_super( mrbc_vm *vm, mrbc_value *regs EXT )
1334{
1335 FETCH_BB();
1336
1337 int narg = b & 0x0f;
1338 int karg = (b >> 4) & 0x0f;
1339 mrbc_value *recv = regs + a; // new regs[0]
1340
1341 // set self to new regs[0]
1342 mrbc_value *self = mrbc_get_self(vm, regs);
1343 assert( mrbc_type(*self) != MRBC_TT_PROC );
1344
1345 mrbc_incref( self );
1346 mrbc_decref( recv );
1347 *recv = *self;
1348
1349 // If it's packed in an array, expand it.
1350 if( narg == CALL_MAXARGS ) {
1351 mrbc_value argary = recv[1];
1352 int n_move = (karg == CALL_MAXARGS) ? 2 : karg * 2 + 1;
1353
1354 narg = mrbc_array_size(&argary);
1355 for( int i = 0; i < narg; i++ ) {
1356 mrbc_incref( &argary.array->data[i] );
1357 }
1358
1359 memmove( recv + narg + 1, recv + 2, sizeof(mrbc_value) * n_move );
1360 if( narg == 0 ) {
1361 mrbc_set_tt( recv + 2, MRBC_TT_EMPTY );
1362 } else {
1363 memcpy( recv + 1, argary.array->data, sizeof(mrbc_value) * narg );
1364 }
1365 mrbc_decref(&argary);
1366 }
1367
1368 mrbc_value *r1 = recv + narg + 1;
1369
1370 // Convert keyword argument to hash.
1371 if( karg && karg != CALL_MAXARGS ) {
1372 mrbc_value hval = mrbc_hash_new( vm, karg );
1373
1374 memcpy( hval.hash->data, r1, sizeof(mrbc_value) * karg * 2 );
1375 hval.hash->n_stored = karg * 2;
1376
1377 r1[0] = hval;
1378 r1[1] = r1[karg * 2]; // move block Proc
1379 memset( r1 + 2, 0, sizeof(mrbc_value) * (karg * 2 - 1) );
1380 }
1381
1382 // find super class
1383 mrbc_callinfo *callinfo = vm->callinfo_tail;
1384 if( callinfo == NULL ) {
1385 mrbc_raise(vm, MRBC_CLASS(NoMethodError), "super called outside of method");
1386 return;
1387 }
1388 mrbc_class *cls = callinfo->own_class;
1389 mrbc_method method;
1390
1391 assert( cls );
1392 cls = cls->super;
1393 assert( cls );
1394 if( mrbc_find_method( &method, cls, callinfo->method_id ) == 0 ) {
1395 mrbc_raisef( vm, MRBC_CLASS(NoMethodError),
1396 "no superclass method '%s' for %s",
1397 mrbc_symid_to_str(callinfo->method_id),
1398 mrbc_symid_to_str(callinfo->own_class->sym_id));
1399 return;
1400 }
1401
1402 // call C function and return.
1403 if( method.c_func ) {
1404 method.func(vm, recv, narg - !!karg);
1405 for( int i = 1; i <= narg+1; i++ ) {
1406 mrbc_decref_empty( recv + i );
1407 }
1408 return;
1409 }
1410
1411 // call Ruby method.
1412 callinfo = mrbc_push_callinfo(vm, callinfo->method_id, a, narg);
1413 callinfo->own_class = method.cls;
1414 callinfo->is_called_super = 1;
1415
1416 vm->cur_irep = method.irep;
1417 vm->inst = vm->cur_irep->inst;
1418 vm->cur_regs = recv;
1419}
1420
1421
1422//================================================================
1429static inline void op_argary( mrbc_vm *vm, mrbc_value *regs EXT )
1430{
1431 FETCH_BS();
1432
1433 int m1 = (b >> 11) & 0x1f;
1434 int r = (b >> 10) & 0x01;
1435 int m2 = (b >> 5) & 0x1f;
1436 int d = (b >> 4) & 0x01;
1437 int lv = (b ) & 0x0f;
1438
1439 if( m2 ) {
1440 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1441 return;
1442 }
1443
1444 mrbc_value *reg0 = regs;
1445 mrbc_callinfo *callinfo = 0;
1446
1447 // rewind proc nest
1448 if( lv ) {
1449 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1450 callinfo = reg0->proc->callinfo;
1451 assert( callinfo );
1452
1453 for( int i = 1; i < lv; i ++ ) {
1454 reg0 = callinfo->cur_regs + callinfo->reg_offset;
1455 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1456 callinfo = reg0->proc->callinfo;
1457 assert( callinfo );
1458 }
1459
1460 reg0 = callinfo->cur_regs + callinfo->reg_offset;
1461 }
1462
1463 // create argument array.
1464 int rest_len = 0;
1465 mrbc_value *rest_data = NULL;
1466 if( r && mrbc_type(reg0[m1+1]) == MRBC_TT_ARRAY ) {
1467 rest_len = mrbc_array_size(&reg0[m1+1]);
1468 rest_data = reg0[m1+1].array->data;
1469 }
1470
1471 mrbc_value argary = mrbc_array_new( vm, m1 + rest_len + m2 );
1472
1473 for( int i = 1; i <= m1; i++ ) {
1474 mrbc_incref( &reg0[i] );
1475 mrbc_array_push( &argary, &reg0[i] );
1476 }
1477
1478 for( int i = 0; i < rest_len; i++ ) {
1479 mrbc_incref( &rest_data[i] );
1480 mrbc_array_push( &argary, &rest_data[i] );
1481 }
1482
1483 int block_reg = m1 + r + m2;
1484
1485 if( d ) {
1486 if( !callinfo ) callinfo = vm->callinfo_tail;
1487 assert( callinfo->karg_keep );
1488 mrbc_value karg = mrbc_immediate_value(MRBC_TT_HASH, .hash = callinfo->karg_keep);
1489 karg = mrbc_hash_dup(vm, &karg);
1490 mrbc_array_push( &argary, &karg );
1491 block_reg++;
1492 }
1493
1494 mrbc_decref( &regs[a] );
1495 regs[a] = argary;
1496
1497 // copy a block object
1498 mrbc_decref( &regs[a+1] );
1499 regs[a+1] = reg0[block_reg+1];
1500 mrbc_incref( &regs[a+1] );
1501}
1502
1503
1504//================================================================
1511static inline void op_enter( mrbc_vm *vm, mrbc_value *regs EXT )
1512{
1513#define FLAG_REST 0x1000
1514#define FLAG_M2 0x0f80
1515#define FLAG_KW 0x007c
1516#define FLAG_DICT 0x0002
1517#define FLAG_BLOCK 0x0001
1518
1519 FETCH_W();
1520
1521 // Check the number of registers to use.
1522 int reg_use_max = regs - vm->regs + vm->cur_irep->nregs;
1523 if( reg_use_max >= vm->regs_size ) {
1524 mrbc_raise( vm, MRBC_CLASS(Exception), "MAX_REGS_SIZE overflow");
1525 return;
1526 }
1527
1528 // Check m2 parameter.
1529 if( a & FLAG_M2 ) {
1530 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1531 return;
1532 }
1533
1534 int m1 = (a >> 18) & 0x1f; // num of required parameters 1
1535 int o = (a >> 13) & 0x1f; // num of optional parameters
1536 int argc = vm->callinfo_tail->n_args;
1537 int flag_kwarg = mrbc_type(regs[argc+1]) == MRBC_TT_HASH;
1538
1539 argc += flag_kwarg;
1540
1541 if( argc < m1 && mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1542 mrbc_raise( vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1543 return;
1544 }
1545
1546 // save proc (or nil) object.
1547 mrbc_value proc = regs[argc+1];
1548 mrbc_set_tt( &regs[argc+1], MRBC_TT_EMPTY );
1549
1550 // support yield [...] pattern, to expand array.
1551 if( mrbc_type(regs[0]) == MRBC_TT_PROC &&
1552 mrbc_type(regs[1]) == MRBC_TT_ARRAY &&
1553 argc == 1 && m1 > 1 ) {
1554 mrbc_value argary = regs[1];
1555 int argary_size = mrbc_array_size(&argary);
1556
1557 argc = argary_size > m1 ? argary_size : m1;
1558
1559 for( int i = argc; i > 0; i-- ) {
1560 if( i != 1 ) mrbc_decref( &regs[i] );
1561 if( argary_size >= i ) {
1562 regs[i] = argary.array->data[i-1];
1563 mrbc_incref(&regs[i]);
1564 } else {
1565 mrbc_set_nil( &regs[i] );
1566 }
1567 }
1568
1569 mrbc_decref(&argary);
1570 }
1571
1572 // dictionary, keyword or rest parameter exists.
1573 if( a & (FLAG_DICT|FLAG_KW|FLAG_REST) ) {
1574 mrbc_value dict;
1575 if( a & (FLAG_DICT|FLAG_KW) ) {
1576 if( (argc - m1) > 0 && mrbc_type(regs[argc]) == MRBC_TT_HASH ) {
1577 dict = regs[argc];
1578 mrbc_set_tt( &regs[argc--], MRBC_TT_EMPTY );
1579 } else {
1580 dict = mrbc_hash_new( vm, 0 );
1581 }
1582 }
1583
1584 mrbc_value rest;
1585 if( a & FLAG_REST ) {
1586 int rest_size = argc - m1 - o;
1587 if( rest_size < 0 ) rest_size = 0;
1588 rest = mrbc_array_new(vm, rest_size);
1589
1590 int rest_reg = m1 + o + 1;
1591 for( int i = 0; i < rest_size; i++ ) {
1592 mrbc_array_push( &rest, &regs[rest_reg] );
1593 mrbc_set_tt( &regs[rest_reg++], MRBC_TT_EMPTY );
1594 }
1595 }
1596
1597 // reorder arguments.
1598 for( int i = argc; i < m1; ) {
1599 mrbc_decref( &regs[++i] );
1600 mrbc_set_nil( &regs[i] );
1601 }
1602 int i = m1 + o;
1603 if( a & FLAG_REST ) {
1604 mrbc_decref(&regs[++i]);
1605 regs[i] = rest;
1606 }
1607 if( a & (FLAG_DICT|FLAG_KW) ) {
1608 mrbc_decref(&regs[++i]);
1609 regs[i] = dict;
1610 vm->callinfo_tail->karg_keep = mrbc_hash_dup(vm, &dict).hash;
1611 }
1612 mrbc_decref(&regs[i+1]);
1613 regs[i+1] = proc;
1614 vm->callinfo_tail->n_args = i;
1615
1616 } else {
1617 // reorder arguments.
1618 for( int i = argc; i < m1; ) {
1619 mrbc_decref( &regs[++i] );
1620 mrbc_set_nil( &regs[i] );
1621 }
1622 int i = m1 + o;
1623 mrbc_decref(&regs[i+1]);
1624 regs[i+1] = proc;
1625 vm->callinfo_tail->n_args = i;
1626 }
1627
1628 // prepare for get default arguments.
1629 int jmp_ofs = argc - m1;
1630 if( jmp_ofs > 0 ) {
1631 if( jmp_ofs > o ) {
1632 jmp_ofs = o;
1633
1634 if( !(a & FLAG_REST) && mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1635 mrbc_raise( vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1636 return;
1637 }
1638 }
1639 vm->inst += jmp_ofs * 3; // 3 = bytecode size of OP_JMP
1640 }
1641
1642#undef FLAG_REST
1643#undef FLAG_M2
1644#undef FLAG_KW
1645#undef FLAG_DICT
1646#undef FLAG_BLOCK
1647}
1648
1649
1650//================================================================
1655static inline void op_key_p( mrbc_vm *vm, mrbc_value *regs EXT )
1656{
1657 FETCH_BB();
1658
1659 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1660 mrbc_sym sym_id = mrbc_irep_symbol_id( vm->cur_irep, b );
1661 mrbc_value *v = mrbc_hash_search_by_id( kdict, sym_id );
1662
1663 mrbc_decref(&regs[a]);
1664 mrbc_set_bool(&regs[a], v != NULL);
1665}
1666
1667
1668//================================================================
1673static inline void op_keyend( mrbc_vm *vm, mrbc_value *regs EXT )
1674{
1675 FETCH_Z();
1676
1677 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1678
1679 if( mrbc_hash_size(kdict) != 0 ) {
1681 mrbc_value *kv = mrbc_hash_i_next(&ite);
1682
1683 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "unknown keyword: %s",
1685 }
1686}
1687
1688
1689//================================================================
1694static inline void op_karg( mrbc_vm *vm, mrbc_value *regs EXT )
1695{
1696 FETCH_BB();
1697
1698 mrbc_value *kdict = &regs[vm->callinfo_tail->n_args];
1699 mrbc_sym sym_id = mrbc_irep_symbol_id( vm->cur_irep, b );
1700 mrbc_value v = mrbc_hash_remove_by_id( kdict, sym_id );
1701
1702 if( mrbc_type(v) == MRBC_TT_EMPTY ) {
1703 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "missing keywords: %s",
1704 mrbc_symid_to_str(sym_id));
1705 return;
1706 }
1707
1708 mrbc_decref(&regs[a]);
1709 regs[a] = v;
1710}
1711
1712
1713//================================================================
1716static inline void sub_op_return( mrbc_vm *vm, mrbc_value *regs, int a )
1717{
1718 // If have a ensure, jump to it.
1719 if( vm->cur_irep->clen ) {
1721 if( handler ) {
1722 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1723
1724 // Save the return value in the last+1 register.
1725 regs[ vm->cur_irep->nregs ] = regs[a];
1726 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1727
1729 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1730 return;
1731 }
1732 }
1733
1734 // return without anything if top level.
1735 if( vm->callinfo_tail == NULL ) {
1736 if (vm->flag_permanence == 1) {
1737 mrbc_incref(&regs[a]);
1738 } else {
1739 mrbc_decref(&regs[0]);
1740 regs[0] = regs[a];
1741 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1742 }
1743 vm->flag_preemption = 1;
1744 vm->flag_stop = 1;
1745 return;
1746 }
1747
1748 /* set the return value
1749 (conditions)
1750 iniialize super block then
1751 0 0 0 Set
1752 0 0 1 Set
1753 0 1 0 Set
1754 0 1 1 N/A
1755 1 0 0 Skip
1756 1 0 1 Set
1757 1 1 0 Set
1758 1 1 1 N/A
1759 */
1760 if( vm->callinfo_tail->method_id != MRBC_SYM(initialize) ||
1763 mrbc_decref(&regs[0]);
1764 regs[0] = regs[a];
1765 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1766 }
1767
1769}
1770
1771
1772//================================================================
1777static inline void op_return( mrbc_vm *vm, mrbc_value *regs EXT )
1778{
1779 FETCH_B();
1780
1781 sub_op_return( vm, regs, a );
1782}
1783
1784
1785//================================================================
1790static inline void op_return_blk( mrbc_vm *vm, mrbc_value *regs EXT )
1791{
1792 FETCH_B();
1793
1794 if( mrbc_type(regs[0]) != MRBC_TT_PROC ) {
1795 sub_op_return( vm, regs, a );
1796 return;
1797 }
1798
1799 // Save the return value in the proc object.
1800 mrbc_incref( &regs[0] );
1801 vm->ret_blk = regs[0].proc;
1802 vm->ret_blk->ret_val = regs[a];
1803 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1804
1805 // return to the proc generated level.
1806 while( 1 ) {
1807 // If have a ensure, jump to it.
1809 if( handler ) {
1810 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1812 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1813 return;
1814 }
1815
1816 // Is it the origin (generator) of proc?
1817 if( vm->callinfo_tail == vm->ret_blk->callinfo_self ) break;
1818
1820 }
1821
1822 // top level return ?
1823 if( vm->callinfo_tail == NULL ) {
1824 vm->flag_preemption = 1;
1825 vm->flag_stop = 1;
1826 } else {
1827 // set the return value.
1828 mrbc_decref(&vm->cur_regs[0]);
1829 vm->cur_regs[0] = vm->ret_blk->ret_val;
1830
1832 }
1833
1835 vm->ret_blk = 0;
1836}
1837
1838
1839//================================================================
1844static inline void op_retself( mrbc_vm *vm, mrbc_value *regs EXT )
1845{
1846 FETCH_Z();
1847
1848 mrbc_decref(&regs[1]);
1849 regs[1] = *mrbc_get_self( vm, regs );
1850 mrbc_incref( &regs[1] );
1851
1852 sub_op_return( vm, regs, 1 );
1853}
1854
1855
1856//================================================================
1861static inline void op_retnil( mrbc_vm *vm, mrbc_value *regs EXT )
1862{
1863 FETCH_Z();
1864
1865 mrbc_decref(&regs[1]);
1866 mrbc_set_nil( &regs[1] );
1867
1868 sub_op_return( vm, regs, 1 );
1869}
1870
1871
1872//================================================================
1877static inline void op_rettrue( mrbc_vm *vm, mrbc_value *regs EXT )
1878{
1879 FETCH_Z();
1880
1881 mrbc_decref(&regs[1]);
1882 mrbc_set_true( &regs[1] );
1883
1884 sub_op_return( vm, regs, 1 );
1885}
1886
1887
1888//================================================================
1893static inline void op_retfalse( mrbc_vm *vm, mrbc_value *regs EXT )
1894{
1895 FETCH_Z();
1896
1897 mrbc_decref(&regs[1]);
1898 mrbc_set_false( &regs[1] );
1899
1900 sub_op_return( vm, regs, 1 );
1901}
1902
1903
1904//================================================================
1909static inline void op_break( mrbc_vm *vm, mrbc_value *regs EXT )
1910{
1911 FETCH_B();
1912
1913 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
1914
1915 // Save the return value in the proc object.
1916 mrbc_incref( &regs[0] );
1917 vm->ret_blk = regs[0].proc;
1918 vm->ret_blk->ret_val = regs[a];
1919 mrbc_set_tt( &regs[a], MRBC_TT_EMPTY );
1920
1921 // return to the proc generated level.
1922 int reg_offset = 0;
1923 while( 1 ) {
1924 // If have a ensure, jump to it.
1926 if( handler ) {
1927 assert( mrbc_type(vm->exception) == MRBC_TT_NIL );
1929 vm->inst = vm->cur_irep->inst + bin_to_uint32(handler->target);
1930 return;
1931 }
1932
1933 // Is it the origin (generator) of proc?
1934 if( vm->callinfo_tail == vm->ret_blk->callinfo ) break;
1935
1936 reg_offset = vm->callinfo_tail->reg_offset;
1938 }
1939
1940 // set the return value.
1941 mrbc_value *reg0 = vm->cur_regs + reg_offset;
1942 mrbc_decref(reg0);
1943 *reg0 = vm->ret_blk->ret_val;
1944
1946 vm->ret_blk = 0;
1947}
1948
1949
1950//================================================================
1955static inline void op_blkpush( mrbc_vm *vm, mrbc_value *regs EXT )
1956{
1957 FETCH_BS();
1958
1959 int m1 = (b >> 11) & 0x1f;
1960 int r = (b >> 10) & 0x01;
1961 int m2 = (b >> 5) & 0x1f;
1962 int d = (b >> 4) & 0x01;
1963 int lv = (b ) & 0x0f;
1964
1965 if( m2 ) {
1966 mrbc_raise( vm, MRBC_CLASS(NotImplementedError), "not support m2 argument");
1967 return;
1968 }
1969
1970 int offset = m1 + r + d + 1;
1971 mrbc_value *blk;
1972
1973 if( lv == 0 ) {
1974 // current env
1975 blk = regs + offset;
1976
1977 } else {
1978 // upper env
1979 assert( mrbc_type(regs[0]) == MRBC_TT_PROC );
1980 mrbc_callinfo *callinfo = regs[0].proc->callinfo;
1981
1982 for( int i = 0; i < lv-1; i++ ) {
1983 assert( callinfo );
1984 mrbc_value *reg0 = callinfo->cur_regs + callinfo->reg_offset;
1985 assert( mrbc_type(*reg0) == MRBC_TT_PROC );
1986 callinfo = reg0->proc->callinfo;
1987 }
1988
1989 blk = callinfo->cur_regs + callinfo->reg_offset + offset;
1990 }
1991
1992 if( mrbc_type(*blk) != MRBC_TT_PROC ) {
1993 mrbc_raise( vm, MRBC_CLASS(Exception), "no block given (yield)");
1994 return;
1995 }
1996
1997 mrbc_incref(blk);
1998 mrbc_decref(&regs[a]);
1999 regs[a] = *blk;
2000}
2001
2002
2003//================================================================
2008static inline void op_add( mrbc_vm *vm, mrbc_value *regs EXT )
2009{
2010 FETCH_B();
2011
2012 // in case of Integer + Integer
2013 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2014 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2015 regs[a].i += regs[a+1].i;
2016 return;
2017 }
2018
2019#if MRBC_USE_FLOAT
2020 // in case of Integer + Float
2021 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2022 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2023 mrbc_set_float( &regs[a], regs[a].i + regs[a+1].d );
2024 return;
2025 }
2026
2027 // in case of Float + Integer
2028 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2029 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2030 regs[a].d += regs[a+1].i;
2031 return;
2032 }
2033
2034 // in case of Float + Float
2035 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2036 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2037 regs[a].d += regs[a+1].d;
2038 return;
2039 }
2040#endif
2041
2042 // other case
2043 send_by_name( vm, MRBC_SYM(PLUS), a, 1 );
2044}
2045
2046
2047//================================================================
2052static inline void op_addi( mrbc_vm *vm, mrbc_value *regs EXT )
2053{
2054 FETCH_BB();
2055
2056 if( mrbc_type(regs[a]) == MRBC_TT_INTEGER ) {
2057 regs[a].i += b;
2058 return;
2059 }
2060
2061#if MRBC_USE_FLOAT
2062 if( mrbc_type(regs[a]) == MRBC_TT_FLOAT ) {
2063 regs[a].d += b;
2064 return;
2065 }
2066#endif
2067
2068 mrbc_decref(&regs[a+1]);
2069 mrbc_set_integer( &regs[a+1], b);
2070 send_by_name(vm, MRBC_SYM(PLUS), a, 1);
2071}
2072
2073
2074//================================================================
2079static inline void op_sub( mrbc_vm *vm, mrbc_value *regs EXT )
2080{
2081 FETCH_B();
2082
2083 // in case of Integer - Integer
2084 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2085 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2086 regs[a].i -= regs[a+1].i;
2087 return;
2088 }
2089
2090#if MRBC_USE_FLOAT
2091 // in case of Integer - Float
2092 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2093 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2094 mrbc_set_float( &regs[a], regs[a].i - regs[a+1].d );
2095 return;
2096 }
2097
2098 // in case of Float - Integer
2099 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2100 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2101 regs[a].d -= regs[a+1].i;
2102 return;
2103 }
2104
2105 // in case of Float - Float
2106 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2107 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2108 regs[a].d -= regs[a+1].d;
2109 return;
2110 }
2111#endif
2112
2113 // other case
2114 send_by_name( vm, MRBC_SYM(MINUS), a, 1 );
2115}
2116
2117
2118//================================================================
2123static inline void op_subi( mrbc_vm *vm, mrbc_value *regs EXT )
2124{
2125 FETCH_BB();
2126
2127 if( mrbc_type(regs[a]) == MRBC_TT_INTEGER ) {
2128 regs[a].i -= b;
2129 return;
2130 }
2131
2132#if MRBC_USE_FLOAT
2133 if( mrbc_type(regs[a]) == MRBC_TT_FLOAT ) {
2134 regs[a].d -= b;
2135 return;
2136 }
2137#endif
2138
2139 mrbc_decref(&regs[a+1]);
2140 mrbc_set_integer( &regs[a+1], b);
2141 send_by_name(vm, MRBC_SYM(MINUS), a, 1);
2142}
2143
2144
2145//================================================================
2150static inline void op_addilv( mrbc_vm *vm, mrbc_value *regs EXT )
2151{
2152 FETCH_BBB();
2153
2154 switch( mrbc_type(regs[a]) ) {
2155 case MRBC_TT_INTEGER:
2156 regs[a].i += c;
2157 break;
2158
2159#if MRBC_USE_FLOAT
2160 case MRBC_TT_FLOAT:
2161 regs[a].d += c;
2162 break;
2163#endif
2164
2165 default:
2166 mrbc_decref(&regs[a+1]);
2167 mrbc_set_integer( &regs[a+1], c);
2168 send_by_name(vm, MRBC_SYM(PLUS), a, 1);
2169 }
2170}
2171
2172
2173//================================================================
2178static inline void op_subilv( mrbc_vm *vm, mrbc_value *regs EXT )
2179{
2180 FETCH_BBB();
2181
2182 switch( mrbc_type(regs[a]) ) {
2183 case MRBC_TT_INTEGER:
2184 regs[a].i -= c;
2185 break;
2186
2187#if MRBC_USE_FLOAT
2188 case MRBC_TT_FLOAT:
2189 regs[a].d -= c;
2190 break;
2191#endif
2192
2193 default:
2194 mrbc_decref(&regs[a+1]);
2195 mrbc_set_integer( &regs[a+1], c);
2196 send_by_name(vm, MRBC_SYM(MINUS), a, 1);
2197 }
2198}
2199
2200
2201//================================================================
2206static inline void op_mul( mrbc_vm *vm, mrbc_value *regs EXT )
2207{
2208 FETCH_B();
2209
2210 // in case of Integer * Integer
2211 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2212 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2213 regs[a].i *= regs[a+1].i;
2214 return;
2215 }
2216
2217#if MRBC_USE_FLOAT
2218 // in case of Integer * Float
2219 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2220 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2221 mrbc_set_float( &regs[a], regs[a].i * regs[a+1].d );
2222 return;
2223 }
2224
2225 // in case of Float * Integer
2226 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2227 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2228 regs[a].d *= regs[a+1].i;
2229 return;
2230 }
2231
2232 // in case of Float * Float
2233 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2234 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2235 regs[a].d *= regs[a+1].d;
2236 return;
2237 }
2238#endif
2239
2240 // other case
2241 send_by_name( vm, MRBC_SYM(MUL), a, 1 );
2242}
2243
2244
2245//================================================================
2250static inline void op_div( mrbc_vm *vm, mrbc_value *regs EXT )
2251{
2252 FETCH_B();
2253
2254 // in case of Integer / Integer
2255 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2256 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2257 mrbc_int_t v0 = regs[a].i;
2258 mrbc_int_t v1 = regs[a+1].i;
2259
2260 if( v1 == 0 ) {
2261 mrbc_raise(vm, MRBC_CLASS(ZeroDivisionError), 0 );
2262 return;
2263 }
2264
2265 mrbc_int_t ret = v0 / v1;
2266 mrbc_int_t mod = v0 % v1;
2267
2268 if( (mod != 0) && ((v0 ^ v1) < 0) ) ret -= 1;
2269
2270 regs[a].i = ret;
2271 return;
2272 }
2273
2274#if MRBC_USE_FLOAT
2275 // in case of Integer / Float
2276 if( mrbc_type(regs[a ]) == MRBC_TT_INTEGER &&
2277 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2278 mrbc_set_float( &regs[a], regs[a].i / regs[a+1].d );
2279 return;
2280 }
2281
2282 // in case of Float / Integer
2283 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2284 mrbc_type(regs[a+1]) == MRBC_TT_INTEGER ) {
2285 regs[a].d /= regs[a+1].i;
2286 return;
2287 }
2288
2289 // in case of Float / Float
2290 if( mrbc_type(regs[a ]) == MRBC_TT_FLOAT &&
2291 mrbc_type(regs[a+1]) == MRBC_TT_FLOAT ) {
2292 regs[a].d /= regs[a+1].d;
2293 return;
2294 }
2295#endif
2296
2297 // other case
2298 send_by_name( vm, MRBC_SYM(DIV), a, 1 );
2299}
2300
2301
2302//================================================================
2307static inline void op_eq( mrbc_vm *vm, mrbc_value *regs EXT )
2308{
2309 FETCH_B();
2310
2311 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2312 send_by_name(vm, MRBC_SYM(EQ_EQ), a, 1);
2313 return;
2314 }
2315
2316 int result = mrbc_compare(&regs[a], &regs[a+1]);
2317
2318 mrbc_decref(&regs[a]);
2319 mrbc_set_bool( &regs[a], result == 0 );
2320}
2321
2322
2323//================================================================
2328static inline void op_lt( mrbc_vm *vm, mrbc_value *regs EXT )
2329{
2330 FETCH_B();
2331
2332 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2333 send_by_name(vm, MRBC_SYM(LT), a, 1);
2334 return;
2335 }
2336
2337 int result = mrbc_compare(&regs[a], &regs[a+1]);
2338
2339 mrbc_decref(&regs[a]);
2340 mrbc_set_bool( &regs[a], result < 0 );
2341}
2342
2343
2344//================================================================
2349static inline void op_le( mrbc_vm *vm, mrbc_value *regs EXT )
2350{
2351 FETCH_B();
2352
2353 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2354 send_by_name(vm, MRBC_SYM(LT_EQ), a, 1);
2355 return;
2356 }
2357
2358 int result = mrbc_compare(&regs[a], &regs[a+1]);
2359
2360 mrbc_decref(&regs[a]);
2361 mrbc_set_bool( &regs[a], result <= 0 );
2362}
2363
2364
2365//================================================================
2370static inline void op_gt( mrbc_vm *vm, mrbc_value *regs EXT )
2371{
2372 FETCH_B();
2373
2374 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2375 send_by_name(vm, MRBC_SYM(GT), a, 1);
2376 return;
2377 }
2378
2379 int result = mrbc_compare(&regs[a], &regs[a+1]);
2380
2381 mrbc_decref(&regs[a]);
2382 mrbc_set_bool( &regs[a], result > 0 );
2383}
2384
2385
2386//================================================================
2391static inline void op_ge( mrbc_vm *vm, mrbc_value *regs EXT )
2392{
2393 FETCH_B();
2394
2395 if( mrbc_type(regs[a]) == MRBC_TT_OBJECT ) {
2396 send_by_name(vm, MRBC_SYM(GT_EQ), a, 1);
2397 return;
2398 }
2399
2400 int result = mrbc_compare(&regs[a], &regs[a+1]);
2401
2402 mrbc_decref(&regs[a]);
2403 mrbc_set_bool( &regs[a], result >= 0 );
2404}
2405
2406
2407//================================================================
2412static inline void op_array( mrbc_vm *vm, mrbc_value *regs EXT )
2413{
2414 FETCH_BB();
2415
2416 mrbc_value ret = mrbc_array_new(vm, b);
2417
2418 memcpy( ret.array->data, &regs[a], sizeof(mrbc_value) * b );
2419 memset( &regs[a], 0, sizeof(mrbc_value) * b );
2420 ret.array->n_stored = b;
2421
2422 mrbc_decref(&regs[a]);
2423 regs[a] = ret;
2424}
2425
2426
2427//================================================================
2432static inline void op_array2( mrbc_vm *vm, mrbc_value *regs EXT )
2433{
2434 FETCH_BBB();
2435
2436 mrbc_value ret = mrbc_array_new(vm, c);
2437
2438 memcpy( ret.array->data, &regs[b], sizeof(mrbc_value) * c );
2439 memset( &regs[b], 0, sizeof(mrbc_value) * c );
2440 ret.array->n_stored = c;
2441
2442 mrbc_decref(&regs[a]);
2443 regs[a] = ret;
2444}
2445
2446
2447//================================================================
2452static inline void op_arycat( mrbc_vm *vm, mrbc_value *regs EXT )
2453{
2454 FETCH_B();
2455
2456 if( mrbc_type(regs[a]) == MRBC_TT_NIL ) {
2457 // arycat(nil, [...]) #=> [...]
2458 assert( mrbc_type(regs[a+1]) == MRBC_TT_ARRAY );
2459 regs[a] = regs[a+1];
2460 mrbc_set_nil( &regs[a+1] );
2461
2462 return;
2463 }
2464
2465 assert( mrbc_type(regs[a ]) == MRBC_TT_ARRAY );
2466 assert( mrbc_type(regs[a+1]) == MRBC_TT_ARRAY );
2467
2468 int size_1 = regs[a ].array->n_stored;
2469 int size_2 = regs[a+1].array->n_stored;
2470 int new_size = size_1 + regs[a+1].array->n_stored;
2471
2472 // need resize?
2473 if( regs[a].array->data_size < new_size ) {
2474 mrbc_array_resize(&regs[a], new_size);
2475 }
2476
2477 for( int i = 0; i < size_2; i++ ) {
2478 mrbc_incref( &regs[a+1].array->data[i] );
2479 regs[a].array->data[size_1+i] = regs[a+1].array->data[i];
2480 }
2481 regs[a].array->n_stored = new_size;
2482}
2483
2484
2485//================================================================
2490static inline void op_arypush( mrbc_vm *vm, mrbc_value *regs EXT )
2491{
2492 FETCH_BB();
2493
2494 int sz1 = mrbc_array_size(&regs[a]);
2495
2496 mrbc_array_resize(&regs[a], sz1 + b);
2497
2498 // data copy.
2499 memcpy( regs[a].array->data + sz1, &regs[a+1], sizeof(mrbc_value) * b );
2500 memset( &regs[a+1], 0, sizeof(mrbc_value) * b );
2501 regs[a].array->n_stored = sz1 + b;
2502}
2503
2504
2505//================================================================
2510static inline void op_arysplat( mrbc_vm *vm, mrbc_value *regs EXT )
2511{
2512 FETCH_B();
2513
2514 mrbc_value ret = mrbc_array_dup( vm, &regs[a] );
2515 mrbc_decref(&regs[a]);
2516 regs[a] = ret;
2517}
2518
2519
2520//================================================================
2525static inline void op_aref( mrbc_vm *vm, mrbc_value *regs EXT )
2526{
2527 FETCH_BBB();
2528
2529 mrbc_value *src = &regs[b];
2530 mrbc_value *dst = &regs[a];
2531
2532 mrbc_decref( dst );
2533
2534 if( mrbc_type(*src) == MRBC_TT_ARRAY ) {
2535 // src is Array
2536 *dst = mrbc_array_get(src, c);
2537 mrbc_incref(dst);
2538 } else {
2539 // src is not Array
2540 if( c == 0 ) {
2541 mrbc_incref(src);
2542 *dst = *src;
2543 } else {
2544 mrbc_set_nil( dst );
2545 }
2546 }
2547}
2548
2549
2550//================================================================
2555static inline void op_aset( mrbc_vm *vm, mrbc_value *regs EXT )
2556{
2557 FETCH_BBB();
2558
2559 assert( mrbc_type(regs[b]) == MRBC_TT_ARRAY );
2560
2561 mrbc_incref( &regs[b] );
2562 mrbc_array_set(&regs[a], c, &regs[b]);
2563}
2564
2565
2566//================================================================
2571static inline void op_apost( mrbc_vm *vm, mrbc_value *regs EXT )
2572{
2573 FETCH_BBB();
2574
2575 mrbc_value src = regs[a];
2576 if( mrbc_type(src) != MRBC_TT_ARRAY ) {
2577 src = mrbc_array_new(vm, 1);
2578 src.array->data[0] = regs[a];
2579 src.array->n_stored = 1;
2580 }
2581
2582 int pre = b;
2583 int post = c;
2584 int len = mrbc_array_size(&src);
2585
2586 if( len > pre + post ) {
2587 int ary_size = len - pre - post;
2588 regs[a] = mrbc_array_new(vm, ary_size);
2589
2590 // copy elements
2591 for( int i = 0; i < ary_size; i++ ) {
2592 regs[a].array->data[i] = src.array->data[pre+i];
2593 mrbc_incref( &regs[a].array->data[i] );
2594 }
2595 regs[a].array->n_stored = ary_size;
2596
2597 } else {
2598 assert(!"Not support this case in op_apost");
2599 // empty
2600 regs[a] = mrbc_array_new(vm, 0);
2601 }
2602
2603 mrbc_decref(&src);
2604}
2605
2606
2607//================================================================
2612static inline void op_intern( mrbc_vm *vm, mrbc_value *regs EXT )
2613{
2614 FETCH_B();
2615
2616 assert( mrbc_type(regs[a]) == MRBC_TT_STRING );
2617
2618 mrbc_value sym_val = mrbc_symbol_new(vm, (const char*)regs[a].string->data);
2619
2620 mrbc_decref( &regs[a] );
2621 regs[a] = sym_val;
2622}
2623
2624
2625//================================================================
2630static inline void op_symbol( mrbc_vm *vm, mrbc_value *regs EXT )
2631{
2632 FETCH_BB();
2633
2634 const char *p = (const char *)mrbc_irep_pool_ptr(vm->cur_irep, b);
2635 mrbc_sym sym_id = mrbc_str_to_symid( p+3 ); // 3 is TT and length
2636 if( sym_id < 0 ) {
2637 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
2638 return;
2639 }
2640
2641 mrbc_decref(&regs[a]);
2642 mrbc_set_symbol( &regs[a], sym_id );
2643}
2644
2645
2646//================================================================
2651static inline void op_string( mrbc_vm *vm, mrbc_value *regs EXT )
2652{
2653 FETCH_BB();
2654
2655 mrbc_decref(&regs[a]);
2656 regs[a] = mrbc_irep_pool_value(vm, b);
2657}
2658
2659
2660//================================================================
2665static inline void op_strcat( mrbc_vm *vm, mrbc_value *regs EXT )
2666{
2667 FETCH_B();
2668
2669#if MRBC_USE_STRING
2670 // call "to_s"
2671 mrbc_method method;
2672 if( mrbc_find_method( &method, find_class_by_object(&regs[a+1]),
2673 MRBC_SYM(to_s)) == 0 ) return;
2674 if( !method.c_func ) return; // TODO: Not support?
2675
2676 method.func( vm, regs + a + 1, 0 );
2677 mrbc_string_append( &regs[a], &regs[a+1] );
2678 mrbc_decref_empty( &regs[a+1] );
2679
2680#else
2681 mrbc_raise(vm, MRBC_CLASS(Exception), "Not support String");
2682#endif
2683}
2684
2685
2686//================================================================
2691static inline void op_hash( mrbc_vm *vm, mrbc_value *regs EXT )
2692{
2693 FETCH_BB();
2694
2695 mrbc_value value = mrbc_hash_new(vm, b);
2696
2697 // note: Do not detect duplicate keys.
2698 b *= 2;
2699 memcpy( value.hash->data, &regs[a], sizeof(mrbc_value) * b );
2700 memset( &regs[a], 0, sizeof(mrbc_value) * b );
2701 value.hash->n_stored = b;
2702
2703 mrbc_decref(&regs[a]);
2704 regs[a] = value;
2705}
2706
2707
2708//================================================================
2713static inline void op_hashadd( mrbc_vm *vm, mrbc_value *regs EXT )
2714{
2715 FETCH_BB();
2716
2717 int sz1 = mrbc_array_size(&regs[a]);
2718 int sz2 = b * 2;
2719
2720 mrbc_array_resize(&regs[a], sz1 + sz2);
2721
2722 // data copy.
2723 // note: Do not detect duplicate keys.
2724 memcpy( regs[a].hash->data + sz1, &regs[a+1], sizeof(mrbc_value) * sz2 );
2725 memset( &regs[a+1], 0, sizeof(mrbc_value) * sz2 );
2726 regs[a].hash->n_stored = sz1 + sz2;
2727}
2728
2729
2730//================================================================
2735static inline void op_hashcat( mrbc_vm *vm, mrbc_value *regs EXT )
2736{
2737 FETCH_B();
2738
2740
2741 while( mrbc_hash_i_has_next(&ite) ) {
2742 mrbc_value *kv = mrbc_hash_i_next(&ite);
2743 mrbc_hash_set( &regs[a], &kv[0], &kv[1] );
2744 mrbc_incref( &kv[0] );
2745 mrbc_incref( &kv[1] );
2746 }
2747}
2748
2749
2750//================================================================
2755static inline void op_block( mrbc_vm *vm, mrbc_value *regs EXT )
2756{
2757 FETCH_BB();
2758
2759 mrbc_value ret = mrbc_proc_new(vm, mrbc_irep_child_irep(vm->cur_irep, b), 'B');
2760
2761 mrbc_decref(&regs[a]);
2762 regs[a] = ret;
2763}
2764
2765
2766//================================================================
2771static inline void op_method( mrbc_vm *vm, mrbc_value *regs EXT )
2772{
2773 FETCH_BB();
2774
2775 mrbc_value ret = mrbc_proc_new(vm, mrbc_irep_child_irep(vm->cur_irep, b), 'M');
2776
2777 mrbc_decref(&regs[a]);
2778 regs[a] = ret;
2779}
2780
2781
2782//================================================================
2787static inline void op_range_inc( mrbc_vm *vm, mrbc_value *regs EXT )
2788{
2789 FETCH_B();
2790
2791 mrbc_value value = mrbc_range_new(vm, &regs[a], &regs[a+1], 0);
2792 regs[a] = value;
2793 mrbc_set_tt( &regs[a+1], MRBC_TT_EMPTY );
2794}
2795
2796
2797//================================================================
2802static inline void op_range_exc( mrbc_vm *vm, mrbc_value *regs EXT )
2803{
2804 FETCH_B();
2805
2806 mrbc_value value = mrbc_range_new(vm, &regs[a], &regs[a+1], 1);
2807 regs[a] = value;
2808 mrbc_set_tt( &regs[a+1], MRBC_TT_EMPTY );
2809}
2810
2811
2812//================================================================
2817static inline void op_oclass( mrbc_vm *vm, mrbc_value *regs EXT )
2818{
2819 FETCH_B();
2820
2821 mrbc_decref(&regs[a]);
2822 mrbc_set_tt(&regs[a], MRBC_TT_CLASS);
2823 regs[a].cls = MRBC_CLASS(Object);
2824}
2825
2826
2827//================================================================
2832static inline void op_class( mrbc_vm *vm, mrbc_value *regs EXT )
2833{
2834 FETCH_BB();
2835
2836 mrbc_class *super;
2837
2838 switch( mrbc_type(regs[a+1]) ) {
2839 case MRBC_TT_CLASS:
2840 super = regs[a+1].cls;
2841 break;
2842 case MRBC_TT_NIL:
2843 super = 0;
2844 break;
2845 default:
2846 mrbc_raise(vm, MRBC_CLASS(TypeError), "superclass must be a Class");
2847 return;
2848 }
2849
2850 // check unsupported pattern.
2851 if( super ) {
2852 for( int i = 1; i < MRBC_TT_MAXVAL; i++ ) {
2853 if( super == mrbc_class_tbl[i] ) {
2854 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Inherit the built-in class is not supported");
2855 return;
2856 }
2857 }
2858 }
2859
2860 mrbc_class *outer = 0;
2861
2862 if( mrbc_type(regs[a]) == MRBC_TT_CLASS || mrbc_type(regs[a]) == MRBC_TT_MODULE ) {
2863 outer = regs[a].cls;
2864 } else if( mrbc_type(vm->cur_regs[0]) == MRBC_TT_CLASS || mrbc_type(vm->cur_regs[0]) == MRBC_TT_MODULE ) {
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 mrbc_class *outer = 0;
2895
2896 if( mrbc_type(regs[a]) == MRBC_TT_CLASS || mrbc_type(regs[a]) == MRBC_TT_MODULE ) {
2897 outer = regs[a].cls;
2898 } else if( mrbc_type(vm->cur_regs[0]) == MRBC_TT_CLASS || mrbc_type(vm->cur_regs[0]) == MRBC_TT_MODULE ) {
2899 outer = vm->cur_regs[0].cls;
2900 }
2901
2902 const char *module_name = mrbc_irep_symbol_cstr(vm->cur_irep, b);
2903 mrbc_class *cls;
2904
2905 // define a new module (or get an already defined class)
2906 if( outer ) {
2907 cls = mrbc_define_module_under(vm, outer, module_name);
2908 } else {
2909 cls = mrbc_define_module(vm, module_name);
2910 }
2911
2912 // (note)
2913 // regs[a] was set to Class, Module or NIL by compiler. So, no need to release.
2914 mrbc_set_tt(&regs[a], MRBC_TT_MODULE);
2915 regs[a].cls = cls;
2916}
2917
2918
2919//================================================================
2924static inline void op_exec( mrbc_vm *vm, mrbc_value *regs EXT )
2925{
2926 FETCH_BB();
2927 assert( mrbc_type(regs[a]) == MRBC_TT_CLASS || mrbc_type(regs[a]) == MRBC_TT_MODULE );
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:93
static void mrbc_set_symbol(mrbc_value *p, mrbc_sym sym_id)
Definition boxing_no.h:113
#define mrbc_immediate_value(...)
Definition boxing_no.h:71
#define mrbc_nil_value()
Definition boxing_no.h:66
static void mrbc_set_tt(mrbc_value *p, mrbc_vtype type)
Definition boxing_no.h:119
static void mrbc_set_bool(mrbc_value *p, int n)
Definition boxing_no.h:108
static void mrbc_set_float(mrbc_value *p, mrbc_float_t d)
Definition boxing_no.h:87
#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:98
static void mrbc_set_false(mrbc_value *p)
Definition boxing_no.h:103
static void mrbc_set_integer(mrbc_value *p, mrbc_int_t n)
Definition boxing_no.h:81
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:184
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:306
mrbc_class * mrbc_find_method(mrbc_method *r_method, mrbc_class *cls, mrbc_sym sym_id)
Definition class.c:415
mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
Definition class.c:259
int mrbc_obj_is_kind_of(const mrbc_value *obj, const mrbc_class *tcls)
Definition class.c:391
mrbc_value mrbc_instance_getiv(mrbc_value *obj, mrbc_sym sym_id)
Definition class.c:360
mrbc_class * mrbc_traverse_class_tree(mrbc_class *cls, mrbc_class *nest_buf[], int *nest_idx)
Definition class.c:68
mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
Definition class.c:245
void mrbc_instance_setiv(mrbc_value *obj, mrbc_sym sym_id, mrbc_value *v)
Definition class.c:346
mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
Definition class.c:231
mrbc_class *const mrbc_class_tbl[MRBC_TT_MAXVAL+1]
Definition class.c:38
mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
Definition class.c:215
#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:262
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:201
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:153
int mrbc_set_class_const(const mrbc_class *cls, mrbc_sym sym_id, mrbc_value *v)
Definition global.c:75
mrbc_value * mrbc_get_const(mrbc_sym sym_id)
Definition global.c:92
mrbc_value * mrbc_get_global(mrbc_sym sym_id)
Definition global.c:165
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:105
mrbc_value mrbc_irep_pool_value(mrbc_vm *vm, int n)
Definition load.c:398
void mrbc_irep_free(mrbc_irep *irep)
Definition load.c:352
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:207
mrbc_sym sym_id
function names symbol ID
Definition class.h:200
uint8_t type
M:OP_DEF or OP_ALIAS, m:mrblib or define_method().
Definition class.h:198
struct IREP * irep
to IREP for ruby proc.
Definition class.h:202
struct RMethod * next
link to next method.
Definition class.h:206
uint8_t c_func
0:IREP, 1:C Func, 2:C Func (built-in)
Definition class.h:199
mrbc_func_t func
to C function.
Definition class.h:203
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:340
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:221
void mrbc_separate_nested_symid(mrbc_sym sym_id, mrbc_sym *id1, mrbc_sym *id2)
Definition symbol.c:309
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:242
static int mrbc_is_nested_symid(mrbc_sym sym_id)
Definition symbol.h:71
#define MRBC_SYM(sym)
Definition symbol.h:31
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:561
static void mrbc_decref_empty(mrbc_value *v)
Definition value.h:579
static uint32_t bin_to_uint32(const void *s)
Definition value.h:635
#define MRBC_TT_MAXVAL
Definition value.h:104
static void mrbc_incref(mrbc_value *v)
Definition value.h:546
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:1281
static void send_by_name(mrbc_vm *vm, mrbc_sym sym_id, int a, int c)
Definition vm.c:53
static void op_loadsym(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:541
#define EXT
Definition vm.c:419
static void op_lt(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2328
static void op_getgv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:612
static void op_mul(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2206
void mrbc_vm_close(mrbc_vm *vm)
Definition vm.c:398
static void op_loadi8(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:466
static void op_array(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2412
static void op_move(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:437
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:598
static void op_retnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1861
static void op_strcat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2665
static void op_getidx0(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:901
static void op_jmpif(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:947
static void op_send0(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1294
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:856
void mrbc_pop_callinfo(mrbc_vm *vm)
Definition vm.c:237
static void op_sendb(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1307
static void op_setidx(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:921
mrbc_vm * mrbc_vm_new(int regs_size)
Definition vm.c:283
static void op_symbol(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2630
static void op_ssendb(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1263
static void op_getconst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:697
static void op_matcherr(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1212
static void op_hash(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2691
static void op_jmpnot(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:962
static void op_loadi_n(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:494
static void op_add(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2008
static void op_except(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1026
static void op_addi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2052
static void op_ge(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2391
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:2832
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:2370
static void op_div(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2250
static void op_aref(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2525
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:1673
static void op_getiv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:646
#define FLAG_DICT
static void op_argary(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1429
static void op_super(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1333
static void op_ssend(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1227
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:888
static void op_apost(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2571
static void sub_op_return(mrbc_vm *vm, mrbc_value *regs, int a)
Definition vm.c:1716
static void op_arypush(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2490
static void op_aset(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2555
#define CALL_MAXARGS
Definition vm.c:31
static void op_nop(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:426
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:632
static void op_return(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1777
static void op_hashcat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2735
static void op_loadi16(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:512
static void op_jmpuw(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:992
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:823
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:1790
static void op_karg(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1694
static void op_eq(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2307
static void op_key_p(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1655
static void op_intern(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2612
static void op_rescue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1041
static void op_loadineg(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:480
static void op_block(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2755
static void op_loadl(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:452
static void op_le(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2349
static void op_range_exc(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2802
static void op_loadtrue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:584
mrbc_vm * mrbc_vm_open(mrbc_vm *vm)
Definition vm.c:305
static void op_subi(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2123
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:2771
static void op_setconst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:755
static void op_addilv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2150
static void op_array2(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2432
static void op_arysplat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2510
static void op_arycat(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2452
static void op_blkpush(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1955
static void op_enter(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1511
#define FLAG_KW
static const mrbc_irep_catch_handler * find_catch_handler_ensure(const mrbc_vm *vm)
Definition vm.c:168
void mrbc_vm_end(mrbc_vm *vm)
Definition vm.c:362
static void op_loadself(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:569
#define FLAG_REST
void mrbc_cleanup_vm(void)
Definition vm.c:197
static void op_jmp(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:934
static void op_sub(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2079
static void op_rettrue(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1877
static void op_range_inc(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2787
static void op_jmpnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:977
static void op_retself(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1844
static void op_retfalse(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1893
static void op_loadi32(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:527
static void op_hashadd(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2713
static void op_loadnil(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:555
static void op_exec(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2924
static void op_subilv(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2178
static void op_getmcnst(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:776
static void op_raiseif(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1058
static void op_break(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1909
static void op_string(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2651
static void op_blkcall(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1320
static void op_ssend0(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:1245
void mrbc_vm_begin(mrbc_vm *vm)
Definition vm.c:336
static uint16_t free_vm_bitmap[MAX_VM_COUNT/16+1]
for getting the VM ID
Definition vm.c:39
#define FLAG_M2
static void op_oclass(mrbc_vm *vm, mrbc_value *regs EXT)
Definition vm.c:2817
mrbc_callinfo * mrbc_push_callinfo(mrbc_vm *vm, mrbc_sym method_id, int reg_offset, int n_args)
Definition vm.c:206
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