Apply PIE to nghttpx
[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 MRB_API mrb_state*
23 mrb_open_core(mrb_allocf f, void *ud)
24 {
25   static const mrb_state mrb_state_zero = { 0 };
26   static const struct mrb_context mrb_context_zero = { 0 };
27   mrb_state *mrb;
28
29   if (f == NULL) f = mrb_default_allocf;
30   mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
31   if (mrb == NULL) return NULL;
32
33   *mrb = mrb_state_zero;
34   mrb->allocf_ud = ud;
35   mrb->allocf = f;
36   mrb->atexit_stack_len = 0;
37
38   mrb_gc_init(mrb, &mrb->gc);
39   mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
40   *mrb->c = mrb_context_zero;
41   mrb->root_c = mrb->c;
42
43   mrb_init_core(mrb);
44
45 #if !defined(MRB_DISABLE_STDIO) && defined(_MSC_VER) && _MSC_VER < 1900
46   _set_output_format(_TWO_DIGIT_EXPONENT);
47 #endif
48
49   return mrb;
50 }
51
52 void*
53 mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
54 {
55   if (size == 0) {
56     free(p);
57     return NULL;
58   }
59   else {
60     return realloc(p, size);
61   }
62 }
63
64 struct alloca_header {
65   struct alloca_header *next;
66   char buf[1];
67 };
68
69 MRB_API void*
70 mrb_alloca(mrb_state *mrb, size_t size)
71 {
72   struct alloca_header *p;
73
74   p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size);
75   p->next = mrb->mems;
76   mrb->mems = p;
77   return (void*)p->buf;
78 }
79
80 static void
81 mrb_alloca_free(mrb_state *mrb)
82 {
83   struct alloca_header *p;
84   struct alloca_header *tmp;
85
86   if (mrb == NULL) return;
87   p = mrb->mems;
88
89   while (p) {
90     tmp = p;
91     p = p->next;
92     mrb_free(mrb, tmp);
93   }
94 }
95
96 MRB_API mrb_state*
97 mrb_open(void)
98 {
99   mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL);
100
101   return mrb;
102 }
103
104 MRB_API mrb_state*
105 mrb_open_allocf(mrb_allocf f, void *ud)
106 {
107   mrb_state *mrb = mrb_open_core(f, ud);
108
109   if (mrb == NULL) {
110     return NULL;
111   }
112
113 #ifndef DISABLE_GEMS
114   mrb_init_mrbgems(mrb);
115   mrb_gc_arena_restore(mrb, 0);
116 #endif
117   return mrb;
118 }
119
120 void mrb_free_symtbl(mrb_state *mrb);
121
122 void
123 mrb_irep_incref(mrb_state *mrb, mrb_irep *irep)
124 {
125   irep->refcnt++;
126 }
127
128 void
129 mrb_irep_decref(mrb_state *mrb, mrb_irep *irep)
130 {
131   irep->refcnt--;
132   if (irep->refcnt == 0) {
133     mrb_irep_free(mrb, irep);
134   }
135 }
136
137 void
138 mrb_irep_cutref(mrb_state *mrb, mrb_irep *irep)
139 {
140   mrb_irep *tmp;
141   int i;
142
143   for (i=0; i<irep->rlen; i++) {
144     tmp = irep->reps[i];
145     irep->reps[i] = NULL;
146     if (tmp) mrb_irep_decref(mrb, tmp);
147   }
148 }
149
150 void
151 mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
152 {
153   int i;
154
155   if (!(irep->flags & MRB_ISEQ_NO_FREE))
156     mrb_free(mrb, irep->iseq);
157   if (irep->pool) for (i=0; i<irep->plen; i++) {
158     if (mrb_type(irep->pool[i]) == MRB_TT_STRING) {
159       mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
160       mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
161     }
162 #if defined(MRB_WORD_BOXING) && !defined(MRB_WITHOUT_FLOAT)
163     else if (mrb_type(irep->pool[i]) == MRB_TT_FLOAT) {
164       mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
165     }
166 #endif
167   }
168   mrb_free(mrb, irep->pool);
169   mrb_free(mrb, irep->syms);
170   for (i=0; i<irep->rlen; i++) {
171     if (irep->reps[i])
172       mrb_irep_decref(mrb, irep->reps[i]);
173   }
174   mrb_free(mrb, irep->reps);
175   mrb_free(mrb, irep->lv);
176   mrb_debug_info_free(mrb, irep->debug_info);
177   mrb_free(mrb, irep);
178 }
179
180 mrb_value
181 mrb_str_pool(mrb_state *mrb, mrb_value str)
182 {
183   struct RString *s = mrb_str_ptr(str);
184   struct RString *ns;
185   char *ptr;
186   mrb_int len;
187
188   ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
189   ns->tt = MRB_TT_STRING;
190   ns->c = mrb->string_class;
191
192   if (RSTR_NOFREE_P(s)) {
193     ns->flags = MRB_STR_NOFREE;
194     ns->as.heap.ptr = s->as.heap.ptr;
195     ns->as.heap.len = s->as.heap.len;
196     ns->as.heap.aux.capa = 0;
197   }
198   else {
199     ns->flags = 0;
200     if (RSTR_EMBED_P(s)) {
201       ptr = s->as.ary;
202       len = RSTR_EMBED_LEN(s);
203     }
204     else {
205       ptr = s->as.heap.ptr;
206       len = s->as.heap.len;
207     }
208
209     if (len < RSTRING_EMBED_LEN_MAX) {
210       RSTR_SET_EMBED_FLAG(ns);
211       RSTR_SET_EMBED_LEN(ns, len);
212       if (ptr) {
213         memcpy(ns->as.ary, ptr, len);
214       }
215       ns->as.ary[len] = '\0';
216     }
217     else {
218       ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
219       ns->as.heap.len = len;
220       ns->as.heap.aux.capa = len;
221       if (ptr) {
222         memcpy(ns->as.heap.ptr, ptr, len);
223       }
224       ns->as.heap.ptr[len] = '\0';
225     }
226   }
227   RSTR_SET_POOL_FLAG(ns);
228   MRB_SET_FROZEN_FLAG(ns);
229   return mrb_obj_value(ns);
230 }
231
232 void mrb_free_backtrace(mrb_state *mrb);
233
234 MRB_API void
235 mrb_free_context(mrb_state *mrb, struct mrb_context *c)
236 {
237   if (!c) return;
238   mrb_free(mrb, c->stbase);
239   mrb_free(mrb, c->cibase);
240   mrb_free(mrb, c->rescue);
241   mrb_free(mrb, c->ensure);
242   mrb_free(mrb, c);
243 }
244
245 MRB_API void
246 mrb_close(mrb_state *mrb)
247 {
248   if (!mrb) return;
249   if (mrb->atexit_stack_len > 0) {
250     mrb_int i;
251     for (i = mrb->atexit_stack_len; i > 0; --i) {
252       mrb->atexit_stack[i - 1](mrb);
253     }
254 #ifndef MRB_FIXED_STATE_ATEXIT_STACK
255     mrb_free(mrb, mrb->atexit_stack);
256 #endif
257   }
258
259   /* free */
260   mrb_gc_free_gv(mrb);
261   mrb_free_context(mrb, mrb->root_c);
262   mrb_free_symtbl(mrb);
263   mrb_alloca_free(mrb);
264   mrb_gc_destroy(mrb, &mrb->gc);
265   mrb_free(mrb, mrb);
266 }
267
268 MRB_API mrb_irep*
269 mrb_add_irep(mrb_state *mrb)
270 {
271   static const mrb_irep mrb_irep_zero = { 0 };
272   mrb_irep *irep;
273
274   irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
275   *irep = mrb_irep_zero;
276   irep->refcnt = 1;
277
278   return irep;
279 }
280
281 MRB_API mrb_value
282 mrb_top_self(mrb_state *mrb)
283 {
284   return mrb_obj_value(mrb->top_self);
285 }
286
287 MRB_API void
288 mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f)
289 {
290 #ifdef MRB_FIXED_STATE_ATEXIT_STACK
291   if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) {
292     mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit");
293   }
294 #else
295   size_t stack_size;
296
297   stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1);
298   if (mrb->atexit_stack_len == 0) {
299     mrb->atexit_stack = (mrb_atexit_func*)mrb_malloc(mrb, stack_size);
300   }
301   else {
302     mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size);
303   }
304 #endif
305
306   mrb->atexit_stack[mrb->atexit_stack_len++] = f;
307 }