1 #include "be_inl.h"
2
3 /*
4 * Create a global array refs in the heap stash.
5 */
be_ref_setup(duk_context * ctx)6 void be_ref_setup(duk_context *ctx)
7 {
8 duk_push_heap_stash(ctx);
9
10 /* Create a new array with one `0` at index `0`. */
11 duk_push_array(ctx);
12 duk_push_int(ctx, 0);
13 duk_put_prop_index(ctx, -2, 0);
14 /* Store it as "refs" in the heap stash */
15 duk_put_prop_string(ctx, -2, "refs");
16
17 duk_pop(ctx);
18 }
19
be_ref(duk_context * ctx)20 int be_ref(duk_context *ctx)
21 {
22 int ref;
23 if (duk_is_undefined(ctx, -1)) {
24 duk_pop(ctx);
25 return 0;
26 }
27 /* Get the "refs" array in the heap stash */
28 duk_push_heap_stash(ctx);
29 duk_get_prop_string(ctx, -1, "refs");
30 duk_remove(ctx, -2);
31
32 /* ref = refs[0] */
33 duk_get_prop_index(ctx, -1, 0);
34 ref = duk_get_int(ctx, -1);
35 duk_pop(ctx);
36
37 /* If there was a free slot, remove it from the list */
38 if (ref != 0) {
39 /* refs[0] = refs[ref] */
40 duk_get_prop_index(ctx, -1, ref);
41 duk_put_prop_index(ctx, -2, 0);
42 }
43 /* Otherwise use the end of the list */
44 else {
45 /* ref = refs.length; */
46 ref = duk_get_length(ctx, -1);
47 }
48
49 /* swap the array and the user value in the stack */
50 duk_insert(ctx, -2);
51
52 /* refs[ref] = value */
53 duk_put_prop_index(ctx, -2, ref);
54
55 /* Remove the refs array from the stack. */
56 duk_pop(ctx);
57
58 return ref;
59 }
60
be_push_ref(duk_context * ctx,int ref)61 void be_push_ref(duk_context *ctx, int ref)
62 {
63 if (!ref) {
64 duk_push_undefined(ctx);
65 return;
66 }
67 /* Get the "refs" array in the heap stash */
68 duk_push_heap_stash(ctx);
69 duk_get_prop_string(ctx, -1, "refs");
70 duk_remove(ctx, -2);
71
72 duk_get_prop_index(ctx, -1, ref);
73
74 duk_remove(ctx, -2);
75 }
76
be_unref(duk_context * ctx,int ref)77 void be_unref(duk_context *ctx, int ref)
78 {
79 if (!ref) return;
80
81 /* Get the "refs" array in the heap stash */
82 duk_push_heap_stash(ctx);
83 duk_get_prop_string(ctx, -1, "refs");
84 duk_remove(ctx, -2);
85
86 /* Insert a new link in the freelist */
87
88 /* refs[ref] = refs[0] */
89 duk_get_prop_index(ctx, -1, 0);
90 duk_put_prop_index(ctx, -2, ref);
91 /* refs[0] = ref */
92 duk_push_int(ctx, ref);
93 duk_put_prop_index(ctx, -2, 0);
94
95 duk_pop(ctx);
96 }
97