2 ** state.c - mrb_state open/close functions
4 ** See Copyright Notice in mruby.h
10 #include <mruby/irep.h>
11 #include <mruby/variable.h>
12 #include <mruby/debug.h>
13 #include <mruby/string.h>
14 #include <mruby/class.h>
15 #include <mruby/internal.h>
17 void mrb_init_core(mrb_state
*);
18 void mrb_init_mrbgems(mrb_state
*);
20 void mrb_gc_init(mrb_state
*, mrb_gc
*gc
);
21 void mrb_gc_destroy(mrb_state
*, mrb_gc
*gc
);
23 int mrb_core_init_protect(mrb_state
*mrb
, void (*body
)(mrb_state
*, void*), void *opaque
);
26 init_gc_and_core(mrb_state
*mrb
, void *opaque
)
28 static const struct mrb_context mrb_context_zero
= { 0 };
30 mrb_gc_init(mrb
, &mrb
->gc
);
31 mrb
->c
= (struct mrb_context
*)mrb_malloc(mrb
, sizeof(struct mrb_context
));
32 *mrb
->c
= mrb_context_zero
;
39 mrb_open_core(mrb_allocf f
, void *ud
)
41 static const mrb_state mrb_state_zero
= { 0 };
44 if (f
== NULL
) f
= mrb_default_allocf
;
45 mrb
= (mrb_state
*)(f
)(NULL
, NULL
, sizeof(mrb_state
), ud
);
46 if (mrb
== NULL
) return NULL
;
48 *mrb
= mrb_state_zero
;
51 mrb
->atexit_stack_len
= 0;
53 if (mrb_core_init_protect(mrb
, init_gc_and_core
, NULL
)) {
64 mrb_state
*mrb
= mrb_open_allocf(mrb_default_allocf
, NULL
);
71 init_mrbgems(mrb_state
*mrb
, void *opaque
)
73 mrb_init_mrbgems(mrb
);
78 mrb_open_allocf(mrb_allocf f
, void *ud
)
80 mrb_state
*mrb
= mrb_open_core(f
, ud
);
87 if (mrb_core_init_protect(mrb
, init_mrbgems
, NULL
)) {
91 mrb_gc_arena_restore(mrb
, 0);
96 void mrb_free_symtbl(mrb_state
*mrb
);
99 mrb_irep_incref(mrb_state
*mrb
, mrb_irep
*irep
)
101 if (irep
->flags
& MRB_IREP_NO_FREE
) return;
102 if (irep
->refcnt
== UINT16_MAX
) {
103 mrb_garbage_collect(mrb
);
104 if (irep
->refcnt
== UINT16_MAX
) {
105 mrb_raise(mrb
, E_RUNTIME_ERROR
, "too many irep references");
112 mrb_irep_decref(mrb_state
*mrb
, mrb_irep
*irep
)
114 if (irep
->flags
& MRB_IREP_NO_FREE
) return;
116 if (irep
->refcnt
== 0) {
117 mrb_irep_free(mrb
, irep
);
122 mrb_irep_cutref(mrb_state
*mrb
, mrb_irep
*irep
)
127 if (irep
->flags
& MRB_IREP_NO_FREE
) return;
128 reps
= (mrb_irep
**)irep
->reps
;
130 for (i
=0; i
<irep
->rlen
; i
++) {
131 mrb_irep
*tmp
= reps
[i
];
133 if (tmp
) mrb_irep_decref(mrb
, tmp
);
138 mrb_irep_free(mrb_state
*mrb
, mrb_irep
*irep
)
142 if (irep
->flags
& MRB_IREP_NO_FREE
) return;
143 if (!(irep
->flags
& MRB_ISEQ_NO_FREE
))
144 mrb_free(mrb
, (void*)irep
->iseq
);
146 for (i
=0; i
<irep
->plen
; i
++) {
147 if ((irep
->pool
[i
].tt
& 3) == IREP_TT_STR
||
148 irep
->pool
[i
].tt
== IREP_TT_BIGINT
) {
149 mrb_free(mrb
, (void*)irep
->pool
[i
].u
.str
);
152 mrb_free(mrb
, (void*)irep
->pool
);
154 mrb_free(mrb
, (void*)irep
->syms
);
156 for (i
=0; i
<irep
->rlen
; i
++) {
158 mrb_irep_decref(mrb
, (mrb_irep
*)irep
->reps
[i
]);
160 mrb_free(mrb
, (void*)irep
->reps
);
162 mrb_free(mrb
, (void*)irep
->lv
);
163 mrb_debug_info_free(mrb
, irep
->debug_info
);
165 memset(irep
, -1, sizeof(*irep
));
171 mrb_free_context(mrb_state
*mrb
, struct mrb_context
*c
)
174 mrb_free(mrb
, c
->stbase
);
175 mrb_free(mrb
, c
->cibase
);
179 void mrb_protect_atexit(mrb_state
*mrb
);
182 mrb_close(mrb_state
*mrb
)
185 mrb_protect_atexit(mrb
);
189 mrb_gc_destroy(mrb
, &mrb
->gc
);
190 mrb_free_context(mrb
, mrb
->root_c
);
191 mrb_free_symtbl(mrb
);
196 mrb_add_irep(mrb_state
*mrb
)
198 static const mrb_irep mrb_irep_zero
= { 0 };
201 irep
= (mrb_irep
*)mrb_malloc(mrb
, sizeof(mrb_irep
));
202 *irep
= mrb_irep_zero
;
209 mrb_top_self(mrb_state
*mrb
)
211 return mrb_obj_value(mrb
->top_self
);
215 mrb_state_atexit(mrb_state
*mrb
, mrb_atexit_func f
)
217 #ifdef MRB_FIXED_STATE_ATEXIT_STACK
218 if (mrb
->atexit_stack_len
+ 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE
) {
219 mrb_raise(mrb
, E_RUNTIME_ERROR
, "exceeded fixed state atexit stack limit");
224 stack_size
= sizeof(mrb_atexit_func
) * (mrb
->atexit_stack_len
+ 1);
225 if (mrb
->atexit_stack_len
== 0) {
226 mrb
->atexit_stack
= (mrb_atexit_func
*)mrb_malloc(mrb
, stack_size
);
229 mrb
->atexit_stack
= (mrb_atexit_func
*)mrb_realloc(mrb
, mrb
->atexit_stack
, stack_size
);
233 mrb
->atexit_stack
[mrb
->atexit_stack_len
++] = f
;