RPA Toolkit
6101f46abccb04af8a1af2d8306a89dc5f8bf1d8
[rpatk.git] / rvm / rvmreg.c
1 #include "rmem.h"
2 #include "rvmreg.h"
3 #include "rref.h"
4
5
6 static void rvm_reg_array_oncopy(rarray_t *array)
7 {
8         ruint index;
9         rvmreg_t *r;
10
11         for (index = 0; index < r_array_length(array); index++) {
12                 r = (rvmreg_t *)r_array_slot(array, index);
13                 rvm_reg_copy(r, r);
14         }
15 }
16
17
18 static void rvm_reg_array_oncleanup(rarray_t *array)
19 {
20         ruint index;
21         rvmreg_t *r;
22
23         for (index = 0; index < r_array_length(array); index++) {
24                 r = (rvmreg_t *)r_array_slot(array, index);
25                 rvm_reg_cleanup(r);
26         }
27 }
28
29
30 static void rvm_reg_carray_oncopy(rcarray_t *array)
31 {
32         ruint index;
33         rvmreg_t *r;
34         ruint len = r_carray_length(array);
35
36
37         for (index = 0; index < len; index++) {
38                 r = (rvmreg_t *)r_carray_slot(array, index);
39                 rvm_reg_copy(r, r);
40         }
41 }
42
43
44 static void rvm_reg_carray_oncleanup(rcarray_t *array)
45 {
46         ruint index;
47         rvmreg_t *r;
48         ruint len = r_carray_length(array);
49
50
51         for (index = 0; index < len; index++) {
52                 r = (rvmreg_t *)r_carray_slot(array, index);
53                 rvm_reg_cleanup(r);
54         }
55 }
56
57
58 /*
59  * Recursively go over array data to unref any GC managed
60  * objects. We need this because when GC is destroying arrays,
61  * array's oncleanup might try to destroy the data, that should really
62  * be destroyed by the GC. To avoid any attempts the same data
63  * to be destroyed twice we remove the references of all GC managed
64  * data from the arrays and leave the destruction of such data to
65  * the GC.
66  */
67 void rvm_reg_array_unref_gcdata(robject_t *obj)
68 {
69         ruint size;
70         int i;
71         rvmreg_t *r;
72
73         if (obj->type == R_OBJECT_ARRAY) {
74                 rarray_t *array = (rarray_t*)obj;
75                 if ((size = r_array_length(array)) > 0) {
76                         /*
77                          * set the size to 0, to prevent circular references to come back here
78                          */
79                         r_array_setlength(array, 0);
80                         for (i = 0; i < size; i++) {
81                                 r = (rvmreg_t*) r_array_slot(array, i);
82                                 if (rvm_reg_tstflag(r, RVM_INFOBIT_ROBJECT)) {
83                                         robject_t *p = RVM_REG_GETP(r);
84                                         if (!r_list_empty(&p->lnk)) {
85                                                 /*
86                                                  * if this entry is robject_t that is on GC
87                                                  * list, it can be RVM_REG_CLEARed. It will be
88                                                  * cleaned up by the GC.
89                                                  */
90                                                 rvm_reg_array_unref_gcdata(p);
91                                                 RVM_REG_CLEAR(r);
92                                         }
93                                 }
94
95                         }
96                         /*
97                          * Restore the size
98                          */
99                         r_array_setlength(array, size);
100                 }
101         } else if (obj->type == R_OBJECT_CARRAY || obj->type == R_OBJECT_HARRAY) {
102                 rcarray_t *array = (rcarray_t*)obj;
103                 if (obj->type == R_OBJECT_HARRAY)
104                         array = ((rharray_t*)obj)->members;
105                 if ((size = r_carray_length(array)) > 0) {
106                         /*
107                          * set the size to 0, to prevent circular references to come back here
108                          */
109                         array->alloc_size = 0;
110                         for (i = 0; i < size; i++) {
111                                 r = (rvmreg_t*) r_carray_slot(array, i);
112                                 if (rvm_reg_tstflag(r, RVM_INFOBIT_ROBJECT)) {
113                                         robject_t *p = RVM_REG_GETP(r);
114                                         if (!r_list_empty(&p->lnk)) {
115                                                 /*
116                                                  * if this entry is robject_t that is on GC
117                                                  * list, it can be RVM_REG_CLEARed. It will be
118                                                  * cleaned up by the GC.
119                                                  */
120                                                 rvm_reg_array_unref_gcdata(p);
121                                                 RVM_REG_CLEAR(r);
122                                         }
123                                 }
124
125                         }
126                         /*
127                          * Restore the size
128                          */
129                         array->alloc_size = size;
130                 }
131         }
132 }
133
134
135
136 rarray_t *r_array_create_rvmreg()
137 {
138         rarray_t *array = r_array_create(sizeof(rvmreg_t));
139         if (array) {
140                 array->oncopy = rvm_reg_array_oncopy;
141                 array->oncleanup = rvm_reg_array_oncleanup;
142         }
143         return array;
144 }
145
146
147 rcarray_t *r_carray_create_rvmreg()
148 {
149         rcarray_t *array = r_carray_create(sizeof(rvmreg_t));
150         if (array) {
151                 array->oncopy = rvm_reg_carray_oncopy;
152                 array->oncleanup = rvm_reg_carray_oncleanup;
153         }
154         return array;
155 }
156
157
158 rharray_t *r_harray_create_rvmreg()
159 {
160         rharray_t *harray = r_harray_create(sizeof(rvmreg_t));
161         if (harray) {
162                 harray->members->oncopy = rvm_reg_carray_oncopy;
163                 harray->members->oncleanup = rvm_reg_carray_oncleanup;
164         }
165         return harray;
166 }
167
168
169 rvmreg_t rvm_reg_create_string_ansi(const rchar *s)
170 {
171         rvmreg_t r;
172         r_memset(&r, 0, sizeof(r));
173         RVM_REG_SETP(&r, r_string_create_from_ansistr(s));
174         RVM_REG_SETTYPE(&r, RVM_DTYPE_STRING);
175         RVM_REG_SETFLAG(&r, RVM_INFOBIT_ROBJECT);
176         return r;
177 }
178
179
180 rvmreg_t rvm_reg_create_string(const rstr_t *s)
181 {
182         rvmreg_t r;
183         r_memset(&r, 0, sizeof(r));
184         RVM_REG_SETP(&r, r_string_create_from_rstr(s));
185         RVM_REG_SETTYPE(&r, RVM_DTYPE_STRING);
186         RVM_REG_SETFLAG(&r, RVM_INFOBIT_ROBJECT);
187         return r;
188 }
189
190
191 rvmreg_t rvm_reg_create_array()
192 {
193         rvmreg_t r;
194         r_memset(&r, 0, sizeof(r));
195         rvm_reg_setarray(&r, (robject_t*)r_carray_create_rvmreg());
196         return r;
197 }
198
199
200 rvmreg_t rvm_reg_create_harray()
201 {
202         rvmreg_t r;
203         r_memset(&r, 0, sizeof(r));
204         rvm_reg_setharray(&r, (robject_t*)r_harray_create_rvmreg());
205         return r;
206 }
207
208
209 void rvm_reg_setstring(rvmreg_t *r, rstring_t *ptr)
210 {
211         RVM_REG_SETP(r, ptr);
212         RVM_REG_SETTYPE(r, RVM_DTYPE_STRING);
213         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
214 }
215
216
217 void rvm_reg_setpair(rvmreg_t *r, ruint p1, ruint p2)
218 {
219
220         RVM_REG_SETPAIR(r, p1, p2);
221         RVM_REG_SETTYPE(r, RVM_DTYPE_PAIR);
222         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
223 }
224
225
226 void rvm_reg_setstrptr(rvmreg_t *r, rchar *s, ruint size)
227 {
228         RVM_REG_SETSTR(r, s, size);
229         RVM_REG_SETTYPE(r, RVM_DTYPE_STRPTR);
230         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
231 }
232
233
234 void rvm_reg_setarray(rvmreg_t *r, robject_t *ptr)
235 {
236         RVM_REG_SETP(r, ptr);
237         RVM_REG_SETTYPE(r, RVM_DTYPE_ARRAY);
238         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
239 }
240
241
242 void rvm_reg_setjsobject(rvmreg_t *r, robject_t *ptr)
243 {
244         RVM_REG_SETP(r, ptr);
245         RVM_REG_SETTYPE(r, RVM_DTYPE_JSOBJECT);
246         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
247 }
248
249
250 void rvm_reg_setharray(rvmreg_t *r, robject_t *ptr)
251 {
252         RVM_REG_SETP(r, ptr);
253         RVM_REG_SETTYPE(r, RVM_DTYPE_HARRAY);
254         RVM_REG_SETFLAG(r, RVM_INFOBIT_ROBJECT);
255 }
256
257 rvmreg_t rvm_reg_create_pair(ruint p1, ruint p2)
258 {
259         rvmreg_t r;
260         r_memset(&r, 0, sizeof(r));
261         rvm_reg_setpair(&r, p1, p2);
262         return r;
263 }
264
265
266 rvmreg_t rvm_reg_create_strptr(rchar *s, ruint size)
267 {
268         rvmreg_t r;
269         r_memset(&r, 0, sizeof(r));
270         rvm_reg_setstrptr(&r, s, size);
271         return r;
272 }
273
274
275 rvmreg_t rvm_reg_create_double(rdouble d)
276 {
277         rvmreg_t r;
278         r_memset(&r, 0, sizeof(r));
279         RVM_REG_SETD(&r, d);
280         RVM_REG_SETTYPE(&r, RVM_DTYPE_DOUBLE);
281         return r;
282 }
283
284
285 rvmreg_t rvm_reg_create_long(rlong l)
286 {
287         rvmreg_t r;
288         r_memset(&r, 0, sizeof(r));
289         rvm_reg_setlong(&r, l);
290         return r;
291 }
292
293
294 void rvm_reg_cleanup(rvmreg_t *reg)
295 {
296         if (rvm_reg_tstflag(reg, RVM_INFOBIT_ROBJECT)) {
297                 r_object_destroy((robject_t*)RVM_REG_GETP(reg));
298         }
299         RVM_REG_CLEAR(reg);
300 }
301
302
303 void rvm_reg_init(rvmreg_t *reg)
304 {
305         RVM_REG_CLEAR(reg);
306 }
307
308
309 rvmreg_t *rvm_reg_copy(rvmreg_t *dst, const rvmreg_t *src)
310 {
311         if (dst != src)
312                 *dst = *src;
313         if (rvm_reg_tstflag(dst, RVM_INFOBIT_ROBJECT))
314                 dst->v.p = r_object_v_copy(dst->v.p);
315         return dst;
316 }
317
318
319 void rvm_reg_settype(rvmreg_t *r, ruint type)
320 {
321         RVM_REG_SETTYPE(r, type);
322 }
323
324
325 ruint rvm_reg_gettype(const rvmreg_t *r)
326 {
327         rulong type = RVM_REG_GETTYPE(r);
328         return type;
329 }
330
331
332 rboolean rvm_reg_tstflag(const rvmreg_t *r, ruint16 flag)
333 {
334         return RVM_REG_TSTFLAG(r, flag);
335 }
336
337
338 void rvm_reg_setflag(rvmreg_t *r, ruint16 flag)
339 {
340         RVM_REG_SETFLAG(r, flag);
341 }
342
343
344 void rvm_reg_clrflag(rvmreg_t *r, ruint16 flag)
345 {
346         RVM_REG_CLRFLAG(r, flag);
347 }
348
349
350 void rvm_reg_setundef(rvmreg_t *r)
351 {
352         RVM_REG_CLEAR(r);
353         RVM_REG_SETTYPE(r, RVM_DTYPE_UNDEF);
354 }
355
356
357 void rvm_reg_setunsigned(rvmreg_t *r, rword u)
358 {
359         RVM_REG_SETU(r, u);
360         RVM_REG_SETTYPE(r, RVM_DTYPE_UNSIGNED);
361         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
362 }
363
364
365 void rvm_reg_setlong(rvmreg_t *r, rlong l)
366 {
367         RVM_REG_SETL(r, l);
368         RVM_REG_SETTYPE(r, RVM_DTYPE_LONG);
369         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
370 }
371
372
373 void rvm_reg_setboolean(rvmreg_t *r, ruint b)
374 {
375         RVM_REG_SETU(r, b ? 1 : 0);
376         RVM_REG_SETTYPE(r, RVM_DTYPE_BOOLEAN);
377         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
378 }
379
380
381 void rvm_reg_setdouble(rvmreg_t *r, rdouble d)
382 {
383         RVM_REG_SETD(r, d);
384         RVM_REG_SETTYPE(r, RVM_DTYPE_DOUBLE);
385         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
386 }
387
388
389 void rvm_reg_setpointer(rvmreg_t *r, rpointer p)
390 {
391         RVM_REG_SETP(r, p);
392         RVM_REG_SETTYPE(r, RVM_DTYPE_POINTER);
393         RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
394 }
395
396
397 int rvm_reg_str2num(rvmreg_t *dst, const rvmreg_t *src)
398 {
399         rchar *dptr, *lptr;
400         rdouble d;
401         rlong l;
402
403         l = r_strtol(R_STRING2PTR(RVM_REG_GETP(src)), &lptr, 10);
404         if (!lptr)
405                 return -1;
406         if (*lptr != '.') {
407                 rvm_reg_setlong(dst, l);
408                 return 0;
409         }
410         d = r_strtod(R_STRING2PTR(RVM_REG_GETP(src)), &dptr);
411         if (!dptr)
412                 return -1;
413         rvm_reg_setdouble(dst, d);
414         return 0;
415 }
416
417
418 int rvm_reg_str2long(rvmreg_t *dst, const rvmreg_t *src)
419 {
420         rchar *dptr;
421         rdouble d;
422
423         d = r_strtod(R_STRING2PTR(RVM_REG_GETP(src)), &dptr);
424         if (!dptr)
425                 return -1;
426         rvm_reg_setlong(dst, (long)d);
427         return 0;
428 }
429
430
431 int rvm_reg_str2double(rvmreg_t *dst, const rvmreg_t *src)
432 {
433         rchar *dptr;
434         rdouble d;
435
436         d = r_strtod(R_STRING2PTR(RVM_REG_GETP(src)), &dptr);
437         if (!dptr)
438                 return -1;
439         rvm_reg_setdouble(dst, d);
440         return 0;
441 }
442
443
444 rint rvm_reg_int(const rvmreg_t *src)
445 {
446         R_ASSERT(src);
447         return (int)RVM_REG_GETL(src);
448 }
449
450
451 rlong rvm_reg_long(const rvmreg_t *src)
452 {
453         R_ASSERT(src);
454         return (rlong)RVM_REG_GETL(src);
455 }
456
457
458 ruchar rvm_reg_boolean(const rvmreg_t *src)
459 {
460         R_ASSERT(src);
461         return (ruchar)(RVM_REG_GETL(src) ? 1 : 0);
462 }
463
464
465 rdouble rvm_reg_double(const rvmreg_t *src)
466 {
467         R_ASSERT(src);
468         return (rdouble)RVM_REG_GETL(src);
469 }
470
471
472 rpointer rvm_reg_pointer(const rvmreg_t *src)
473 {
474         R_ASSERT(src);
475         return (rpointer)RVM_REG_GETP(src);
476 }
477
478
479 rstring_t *rvm_reg_string(const rvmreg_t *src)
480 {
481         R_ASSERT(src && rvm_reg_gettype(src) == RVM_DTYPE_STRING);
482         return (rstring_t*)RVM_REG_GETP(src);
483 }
484
485
486 rjs_object_t *rvm_reg_jsobject(const rvmreg_t *src)
487 {
488         R_ASSERT(src && rvm_reg_gettype(src) == RVM_DTYPE_JSOBJECT);
489         return (rjs_object_t*)RVM_REG_GETP(src);
490 }