Upgrade to 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / src / state.c
1 /*
2 ** state.c - mrb_state open/close functions
3 **
4 ** See Copyright Notice in mruby.h
5 */
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <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
16 void mrb_init_core(mrb_state*);
17 void mrb_init_mrbgems(mrb_state*);
18
19 void mrb_gc_init(mrb_state*, mrb_gc *gc);
20 void mrb_gc_destroy(mrb_state*, mrb_gc *gc);
21
22 int mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque);
23
24 static void
25 init_gc_and_core(mrb_state *mrb, void *opaque)
26 {
27   static const struct mrb_context mrb_context_zero = { 0 };
28
29   mrb_gc_init(mrb, &mrb->gc);
30   mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
31   *mrb->c = mrb_context_zero;
32   mrb->root_c = mrb->c;
33
34   mrb_init_core(mrb);
35 }
36
37 MRB_API mrb_state*
38 mrb_open_core(mrb_allocf f, void *ud)
39 {
40   static const mrb_state mrb_state_zero = { 0 };
41   mrb_state *mrb;
42
43   if (f == NULL) f = mrb_default_allocf;
44   mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
45   if (mrb == NULL) return NULL;
46
47   *mrb = mrb_state_zero;
48   mrb->allocf_ud = ud;
49   mrb->allocf = f;
50   mrb->atexit_stack_len = 0;
51
52   if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) {
53     mrb_close(mrb);
54     return NULL;
55   }
56
57   return mrb;
58 }
59
60 void*
61 mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
62 {
63   if (size == 0) {
64     free(p);
65     return NULL;
66   }
67   else {
68     return realloc(p, size);
69   }
70 }
71
72 MRB_API mrb_state*
73 mrb_open(void)
74 {
75   mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL);
76
77   return mrb;
78 }
79
80 static void
81 init_mrbgems(mrb_state *mrb, void *opaque)
82 {
83   mrb_init_mrbgems(mrb);
84 }
85
86 MRB_API mrb_state*
87 mrb_open_allocf(mrb_allocf f, void *ud)
88 {
89   mrb_state *mrb = mrb_open_core(f, ud);
90
91   if (mrb == NULL) {
92     return NULL;
93   }
94
95 #ifndef DISABLE_GEMS
96   if (mrb_core_init_protect(mrb, init_mrbgems, NULL)) {
97     mrb_close(mrb);
98     return NULL;
99   }
100   mrb_gc_arena_restore(mrb, 0);
101 #endif
102   return mrb;
103 }
104
105 void mrb_free_symtbl(mrb_state *mrb);
106
107 void
108 mrb_irep_incref(mrb_state *mrb, mrb_irep *irep)
109 {
110   irep->refcnt++;
111 }
112
113 void
114 mrb_irep_decref(mrb_state *mrb, mrb_irep *irep)
115 {
116   irep->refcnt--;
117   if (irep->refcnt == 0) {
118     mrb_irep_free(mrb, irep);
119   }
120 }
121
122 void
123 mrb_irep_cutref(mrb_state *mrb, mrb_irep *irep)
124 {
125   mrb_irep *tmp;
126   int i;
127
128   for (i=0; i<irep->rlen; i++) {
129     tmp = irep->reps[i];
130     irep->reps[i] = NULL;
131     if (tmp) mrb_irep_decref(mrb, tmp);
132   }
133 }
134
135 void
136 mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
137 {
138   int i;
139
140   if (!(irep->flags & MRB_ISEQ_NO_FREE))
141     mrb_free(mrb, (void*)irep->iseq);
142   if (irep->pool) for (i=0; i<irep->plen; i++) {
143     if (mrb_string_p(irep->pool[i])) {
144       mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
145       mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
146     }
147 #if defined(MRB_WORD_BOXING) && !defined(MRB_WITHOUT_FLOAT)
148     else if (mrb_float_p(irep->pool[i])) {
149       mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
150     }
151 #endif
152   }
153   mrb_free(mrb, irep->pool);
154   mrb_free(mrb, irep->syms);
155   if (irep->reps) {
156     for (i=0; i<irep->rlen; i++) {
157       if (irep->reps[i])
158         mrb_irep_decref(mrb, irep->reps[i]);
159     }
160   }
161   mrb_free(mrb, irep->reps);
162   mrb_free(mrb, irep->lv);
163   mrb_debug_info_free(mrb, irep->debug_info);
164   mrb_free(mrb, irep);
165 }
166
167 void mrb_free_backtrace(mrb_state *mrb);
168
169 MRB_API void
170 mrb_free_context(mrb_state *mrb, struct mrb_context *c)
171 {
172   if (!c) return;
173   mrb_free(mrb, c->stbase);
174   mrb_free(mrb, c->cibase);
175   mrb_free(mrb, c->rescue);
176   mrb_free(mrb, c->ensure);
177   mrb_free(mrb, c);
178 }
179
180 MRB_API void
181 mrb_close(mrb_state *mrb)
182 {
183   if (!mrb) return;
184   if (mrb->atexit_stack_len > 0) {
185     mrb_int i;
186     for (i = mrb->atexit_stack_len; i > 0; --i) {
187       mrb->atexit_stack[i - 1](mrb);
188     }
189 #ifndef MRB_FIXED_STATE_ATEXIT_STACK
190     mrb_free(mrb, mrb->atexit_stack);
191 #endif
192   }
193
194   /* free */
195   mrb_gc_destroy(mrb, &mrb->gc);
196   mrb_free_context(mrb, mrb->root_c);
197   mrb_gc_free_gv(mrb);
198   mrb_free_symtbl(mrb);
199   mrb_free(mrb, mrb);
200 }
201
202 MRB_API mrb_irep*
203 mrb_add_irep(mrb_state *mrb)
204 {
205   static const mrb_irep mrb_irep_zero = { 0 };
206   mrb_irep *irep;
207
208   irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
209   *irep = mrb_irep_zero;
210   irep->refcnt = 1;
211
212   return irep;
213 }
214
215 MRB_API mrb_value
216 mrb_top_self(mrb_state *mrb)
217 {
218   return mrb_obj_value(mrb->top_self);
219 }
220
221 MRB_API void
222 mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f)
223 {
224 #ifdef MRB_FIXED_STATE_ATEXIT_STACK
225   if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) {
226     mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit");
227   }
228 #else
229   size_t stack_size;
230
231   stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1);
232   if (mrb->atexit_stack_len == 0) {
233     mrb->atexit_stack = (mrb_atexit_func*)mrb_malloc(mrb, stack_size);
234   }
235   else {
236     mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size);
237   }
238 #endif
239
240   mrb->atexit_stack[mrb->atexit_stack_len++] = f;
241 }