js 0.0.1 → 2.4.1.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,222 @@
1
+ #include <stdlib.h>
2
+ #include <rb-abi-guest.h>
3
+
4
+ __attribute__((weak, export_name("cabi_realloc")))
5
+ void *cabi_realloc(
6
+ void *ptr,
7
+ size_t orig_size,
8
+ size_t org_align,
9
+ size_t new_size
10
+ ) {
11
+ void *ret = realloc(ptr, new_size);
12
+ if (!ret)
13
+ abort();
14
+ return ret;
15
+ }
16
+
17
+ __attribute__((import_module("canonical_abi"), import_name("resource_drop_rb-iseq")))
18
+ void __resource_rb_iseq_drop(uint32_t idx);
19
+
20
+ void rb_abi_guest_rb_iseq_free(rb_abi_guest_rb_iseq_t *ptr) {
21
+ __resource_rb_iseq_drop(ptr->idx);
22
+ }
23
+
24
+ __attribute__((import_module("canonical_abi"), import_name("resource_clone_rb-iseq")))
25
+ uint32_t __resource_rb_iseq_clone(uint32_t idx);
26
+
27
+ rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_clone(rb_abi_guest_rb_iseq_t *ptr) {
28
+ return (rb_abi_guest_rb_iseq_t){__resource_rb_iseq_clone(ptr->idx)};
29
+ }
30
+
31
+ __attribute__((import_module("canonical_abi"), import_name("resource_new_rb-iseq")))
32
+ uint32_t __resource_rb_iseq_new(uint32_t val);
33
+
34
+ rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_new(void *data) {
35
+ return (rb_abi_guest_rb_iseq_t){__resource_rb_iseq_new((uint32_t) data)};
36
+ }
37
+
38
+ __attribute__((import_module("canonical_abi"), import_name("resource_get_rb-iseq")))
39
+ uint32_t __resource_rb_iseq_get(uint32_t idx);
40
+
41
+ void* rb_abi_guest_rb_iseq_get(rb_abi_guest_rb_iseq_t *ptr) {
42
+ return (void*) __resource_rb_iseq_get(ptr->idx);
43
+ }
44
+
45
+ __attribute__((export_name("canonical_abi_drop_rb-iseq")))
46
+ void __resource_rb_iseq_dtor(uint32_t val) {
47
+ if (rb_abi_guest_rb_iseq_dtor)
48
+ rb_abi_guest_rb_iseq_dtor((void*) val);
49
+ }
50
+
51
+ __attribute__((import_module("canonical_abi"), import_name("resource_drop_rb-abi-value")))
52
+ void __resource_rb_abi_value_drop(uint32_t idx);
53
+
54
+ void rb_abi_guest_rb_abi_value_free(rb_abi_guest_rb_abi_value_t *ptr) {
55
+ __resource_rb_abi_value_drop(ptr->idx);
56
+ }
57
+
58
+ __attribute__((import_module("canonical_abi"), import_name("resource_clone_rb-abi-value")))
59
+ uint32_t __resource_rb_abi_value_clone(uint32_t idx);
60
+
61
+ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_clone(rb_abi_guest_rb_abi_value_t *ptr) {
62
+ return (rb_abi_guest_rb_abi_value_t){__resource_rb_abi_value_clone(ptr->idx)};
63
+ }
64
+
65
+ __attribute__((import_module("canonical_abi"), import_name("resource_new_rb-abi-value")))
66
+ uint32_t __resource_rb_abi_value_new(uint32_t val);
67
+
68
+ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_new(void *data) {
69
+ return (rb_abi_guest_rb_abi_value_t){__resource_rb_abi_value_new((uint32_t) data)};
70
+ }
71
+
72
+ __attribute__((import_module("canonical_abi"), import_name("resource_get_rb-abi-value")))
73
+ uint32_t __resource_rb_abi_value_get(uint32_t idx);
74
+
75
+ void* rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *ptr) {
76
+ return (void*) __resource_rb_abi_value_get(ptr->idx);
77
+ }
78
+
79
+ __attribute__((export_name("canonical_abi_drop_rb-abi-value")))
80
+ void __resource_rb_abi_value_dtor(uint32_t val) {
81
+ if (rb_abi_guest_rb_abi_value_dtor)
82
+ rb_abi_guest_rb_abi_value_dtor((void*) val);
83
+ }
84
+ #include <string.h>
85
+
86
+ void rb_abi_guest_string_set(rb_abi_guest_string_t *ret, const char *s) {
87
+ ret->ptr = (char*) s;
88
+ ret->len = strlen(s);
89
+ }
90
+
91
+ void rb_abi_guest_string_dup(rb_abi_guest_string_t *ret, const char *s) {
92
+ ret->len = strlen(s);
93
+ ret->ptr = cabi_realloc(NULL, 0, 1, ret->len);
94
+ memcpy(ret->ptr, s, ret->len);
95
+ }
96
+
97
+ void rb_abi_guest_string_free(rb_abi_guest_string_t *ret) {
98
+ if (ret->len > 0) {
99
+ free(ret->ptr);
100
+ }
101
+ ret->ptr = NULL;
102
+ ret->len = 0;
103
+ }
104
+ void rb_abi_guest_list_string_free(rb_abi_guest_list_string_t *ptr) {
105
+ for (size_t i = 0; i < ptr->len; i++) {
106
+ rb_abi_guest_string_free(&ptr->ptr[i]);
107
+ }
108
+ if (ptr->len > 0) {
109
+ free(ptr->ptr);
110
+ }
111
+ }
112
+ void rb_abi_guest_tuple2_rb_abi_value_s32_free(rb_abi_guest_tuple2_rb_abi_value_s32_t *ptr) {
113
+ rb_abi_guest_rb_abi_value_free(&ptr->f0);
114
+ }
115
+ void rb_abi_guest_list_rb_abi_value_free(rb_abi_guest_list_rb_abi_value_t *ptr) {
116
+ for (size_t i = 0; i < ptr->len; i++) {
117
+ rb_abi_guest_rb_abi_value_free(&ptr->ptr[i]);
118
+ }
119
+ if (ptr->len > 0) {
120
+ free(ptr->ptr);
121
+ }
122
+ }
123
+
124
+ __attribute__((aligned(4)))
125
+ static uint8_t RET_AREA[8];
126
+ __attribute__((export_name("ruby-show-version: func() -> ()")))
127
+ void __wasm_export_rb_abi_guest_ruby_show_version(void) {
128
+ rb_abi_guest_ruby_show_version();
129
+ }
130
+ __attribute__((export_name("ruby-init: func() -> ()")))
131
+ void __wasm_export_rb_abi_guest_ruby_init(void) {
132
+ rb_abi_guest_ruby_init();
133
+ }
134
+ __attribute__((export_name("ruby-sysinit: func(args: list<string>) -> ()")))
135
+ void __wasm_export_rb_abi_guest_ruby_sysinit(int32_t arg, int32_t arg0) {
136
+ rb_abi_guest_list_string_t arg1 = (rb_abi_guest_list_string_t) { (rb_abi_guest_string_t*)(arg), (size_t)(arg0) };
137
+ rb_abi_guest_ruby_sysinit(&arg1);
138
+ }
139
+ __attribute__((export_name("ruby-options: func(args: list<string>) -> handle<rb-iseq>")))
140
+ int32_t __wasm_export_rb_abi_guest_ruby_options(int32_t arg, int32_t arg0) {
141
+ rb_abi_guest_list_string_t arg1 = (rb_abi_guest_list_string_t) { (rb_abi_guest_string_t*)(arg), (size_t)(arg0) };
142
+ rb_abi_guest_rb_iseq_t ret = rb_abi_guest_ruby_options(&arg1);
143
+ return (ret).idx;
144
+ }
145
+ __attribute__((export_name("ruby-script: func(name: string) -> ()")))
146
+ void __wasm_export_rb_abi_guest_ruby_script(int32_t arg, int32_t arg0) {
147
+ rb_abi_guest_string_t arg1 = (rb_abi_guest_string_t) { (char*)(arg), (size_t)(arg0) };
148
+ rb_abi_guest_ruby_script(&arg1);
149
+ }
150
+ __attribute__((export_name("ruby-init-loadpath: func() -> ()")))
151
+ void __wasm_export_rb_abi_guest_ruby_init_loadpath(void) {
152
+ rb_abi_guest_ruby_init_loadpath();
153
+ }
154
+ __attribute__((export_name("rb-eval-string-protect: func(str: string) -> tuple<handle<rb-abi-value>, s32>")))
155
+ int32_t __wasm_export_rb_abi_guest_rb_eval_string_protect(int32_t arg, int32_t arg0) {
156
+ rb_abi_guest_string_t arg1 = (rb_abi_guest_string_t) { (char*)(arg), (size_t)(arg0) };
157
+ rb_abi_guest_tuple2_rb_abi_value_s32_t ret;
158
+ rb_abi_guest_rb_eval_string_protect(&arg1, &ret);
159
+ int32_t ptr = (int32_t) &RET_AREA;
160
+ *((int32_t*)(ptr + 0)) = ((ret).f0).idx;
161
+ *((int32_t*)(ptr + 4)) = (ret).f1;
162
+ return ptr;
163
+ }
164
+ __attribute__((export_name("rb-funcallv-protect: func(recv: handle<rb-abi-value>, mid: u32, args: list<handle<rb-abi-value>>) -> tuple<handle<rb-abi-value>, s32>")))
165
+ int32_t __wasm_export_rb_abi_guest_rb_funcallv_protect(int32_t arg, int32_t arg0, int32_t arg1, int32_t arg2) {
166
+ rb_abi_guest_list_rb_abi_value_t arg3 = (rb_abi_guest_list_rb_abi_value_t) { (rb_abi_guest_rb_abi_value_t*)(arg1), (size_t)(arg2) };
167
+ rb_abi_guest_tuple2_rb_abi_value_s32_t ret;
168
+ rb_abi_guest_rb_funcallv_protect((rb_abi_guest_rb_abi_value_t){ arg }, (uint32_t) (arg0), &arg3, &ret);
169
+ int32_t ptr = (int32_t) &RET_AREA;
170
+ *((int32_t*)(ptr + 0)) = ((ret).f0).idx;
171
+ *((int32_t*)(ptr + 4)) = (ret).f1;
172
+ return ptr;
173
+ }
174
+ __attribute__((export_name("rb-intern: func(name: string) -> u32")))
175
+ int32_t __wasm_export_rb_abi_guest_rb_intern(int32_t arg, int32_t arg0) {
176
+ rb_abi_guest_string_t arg1 = (rb_abi_guest_string_t) { (char*)(arg), (size_t)(arg0) };
177
+ rb_abi_guest_rb_id_t ret = rb_abi_guest_rb_intern(&arg1);
178
+ return (int32_t) (ret);
179
+ }
180
+ __attribute__((export_name("rb-errinfo: func() -> handle<rb-abi-value>")))
181
+ int32_t __wasm_export_rb_abi_guest_rb_errinfo(void) {
182
+ rb_abi_guest_rb_abi_value_t ret = rb_abi_guest_rb_errinfo();
183
+ return (ret).idx;
184
+ }
185
+ __attribute__((export_name("rb-clear-errinfo: func() -> ()")))
186
+ void __wasm_export_rb_abi_guest_rb_clear_errinfo(void) {
187
+ rb_abi_guest_rb_clear_errinfo();
188
+ }
189
+ __attribute__((export_name("rstring-ptr: func(value: handle<rb-abi-value>) -> string")))
190
+ int32_t __wasm_export_rb_abi_guest_rstring_ptr(int32_t arg) {
191
+ rb_abi_guest_string_t ret;
192
+ rb_abi_guest_rstring_ptr((rb_abi_guest_rb_abi_value_t){ arg }, &ret);
193
+ int32_t ptr = (int32_t) &RET_AREA;
194
+ *((int32_t*)(ptr + 4)) = (int32_t) (ret).len;
195
+ *((int32_t*)(ptr + 0)) = (int32_t) (ret).ptr;
196
+ return ptr;
197
+ }
198
+ __attribute__((export_name("cabi_post_rstring-ptr")))
199
+ void __wasm_export_rb_abi_guest_rstring_ptr_post_return(int32_t arg0) {
200
+ if ((*((int32_t*) (arg0 + 4))) > 0) {
201
+ free((void*) (*((int32_t*) (arg0 + 0))));
202
+ }
203
+ }
204
+ __attribute__((export_name("rb-vm-bugreport: func() -> ()")))
205
+ void __wasm_export_rb_abi_guest_rb_vm_bugreport(void) {
206
+ rb_abi_guest_rb_vm_bugreport();
207
+ }
208
+ __attribute__((export_name("rb-gc-enable: func() -> bool")))
209
+ int32_t __wasm_export_rb_abi_guest_rb_gc_enable(void) {
210
+ bool ret = rb_abi_guest_rb_gc_enable();
211
+ return ret;
212
+ }
213
+ __attribute__((export_name("rb-gc-disable: func() -> bool")))
214
+ int32_t __wasm_export_rb_abi_guest_rb_gc_disable(void) {
215
+ bool ret = rb_abi_guest_rb_gc_disable();
216
+ return ret;
217
+ }
218
+ __attribute__((export_name("rb-set-should-prohibit-rewind: func(new-value: bool) -> bool")))
219
+ int32_t __wasm_export_rb_abi_guest_rb_set_should_prohibit_rewind(int32_t arg) {
220
+ bool ret = rb_abi_guest_rb_set_should_prohibit_rewind(arg);
221
+ return ret;
222
+ }
@@ -0,0 +1,77 @@
1
+ #ifndef __BINDINGS_RB_ABI_GUEST_H
2
+ #define __BINDINGS_RB_ABI_GUEST_H
3
+ #ifdef __cplusplus
4
+ extern "C"
5
+ {
6
+ #endif
7
+
8
+ #include <stdint.h>
9
+ #include <stdbool.h>
10
+
11
+ typedef struct {
12
+ uint32_t idx;
13
+ } rb_abi_guest_rb_iseq_t;
14
+ void rb_abi_guest_rb_iseq_free(rb_abi_guest_rb_iseq_t *ptr);
15
+ rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_clone(rb_abi_guest_rb_iseq_t *ptr);
16
+ rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_new(void *data);
17
+ void* rb_abi_guest_rb_iseq_get(rb_abi_guest_rb_iseq_t *ptr);
18
+
19
+ __attribute__((weak))
20
+ void rb_abi_guest_rb_iseq_dtor(void *data);
21
+
22
+ typedef struct {
23
+ uint32_t idx;
24
+ } rb_abi_guest_rb_abi_value_t;
25
+ void rb_abi_guest_rb_abi_value_free(rb_abi_guest_rb_abi_value_t *ptr);
26
+ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_clone(rb_abi_guest_rb_abi_value_t *ptr);
27
+ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_new(void *data);
28
+ void* rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *ptr);
29
+
30
+ __attribute__((weak))
31
+ void rb_abi_guest_rb_abi_value_dtor(void *data);
32
+
33
+ typedef struct {
34
+ char *ptr;
35
+ size_t len;
36
+ } rb_abi_guest_string_t;
37
+
38
+ void rb_abi_guest_string_set(rb_abi_guest_string_t *ret, const char *s);
39
+ void rb_abi_guest_string_dup(rb_abi_guest_string_t *ret, const char *s);
40
+ void rb_abi_guest_string_free(rb_abi_guest_string_t *ret);
41
+ typedef int32_t rb_abi_guest_rb_errno_t;
42
+ typedef uint32_t rb_abi_guest_rb_id_t;
43
+ typedef struct {
44
+ rb_abi_guest_string_t *ptr;
45
+ size_t len;
46
+ } rb_abi_guest_list_string_t;
47
+ void rb_abi_guest_list_string_free(rb_abi_guest_list_string_t *ptr);
48
+ typedef struct {
49
+ rb_abi_guest_rb_abi_value_t f0;
50
+ int32_t f1;
51
+ } rb_abi_guest_tuple2_rb_abi_value_s32_t;
52
+ void rb_abi_guest_tuple2_rb_abi_value_s32_free(rb_abi_guest_tuple2_rb_abi_value_s32_t *ptr);
53
+ typedef struct {
54
+ rb_abi_guest_rb_abi_value_t *ptr;
55
+ size_t len;
56
+ } rb_abi_guest_list_rb_abi_value_t;
57
+ void rb_abi_guest_list_rb_abi_value_free(rb_abi_guest_list_rb_abi_value_t *ptr);
58
+ void rb_abi_guest_ruby_show_version(void);
59
+ void rb_abi_guest_ruby_init(void);
60
+ void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args);
61
+ rb_abi_guest_rb_iseq_t rb_abi_guest_ruby_options(rb_abi_guest_list_string_t *args);
62
+ void rb_abi_guest_ruby_script(rb_abi_guest_string_t *name);
63
+ void rb_abi_guest_ruby_init_loadpath(void);
64
+ void rb_abi_guest_rb_eval_string_protect(rb_abi_guest_string_t *str, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0);
65
+ void rb_abi_guest_rb_funcallv_protect(rb_abi_guest_rb_abi_value_t recv, rb_abi_guest_rb_id_t mid, rb_abi_guest_list_rb_abi_value_t *args, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0);
66
+ rb_abi_guest_rb_id_t rb_abi_guest_rb_intern(rb_abi_guest_string_t *name);
67
+ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_errinfo(void);
68
+ void rb_abi_guest_rb_clear_errinfo(void);
69
+ void rb_abi_guest_rstring_ptr(rb_abi_guest_rb_abi_value_t value, rb_abi_guest_string_t *ret0);
70
+ void rb_abi_guest_rb_vm_bugreport(void);
71
+ bool rb_abi_guest_rb_gc_enable(void);
72
+ bool rb_abi_guest_rb_gc_disable(void);
73
+ bool rb_abi_guest_rb_set_should_prohibit_rewind(bool new_value);
74
+ #ifdef __cplusplus
75
+ }
76
+ #endif
77
+ #endif
@@ -0,0 +1,25 @@
1
+ resource rb-iseq
2
+ resource rb-abi-value
3
+ type rb-errno = s32
4
+ type rb-id = u32
5
+
6
+ ruby-show-version: func()
7
+ ruby-init: func()
8
+ ruby-sysinit: func(args: list<string>)
9
+ ruby-options: func(args: list<string>) -> rb-iseq
10
+ ruby-script: func(name: string)
11
+ ruby-init-loadpath: func()
12
+ rb-eval-string-protect: func(str: string) -> tuple<rb-abi-value, s32>
13
+ rb-funcallv-protect: func(recv: rb-abi-value, mid: rb-id, args: list<rb-abi-value>) -> tuple<rb-abi-value, s32>
14
+ rb-intern: func(name: string) -> rb-id
15
+ rb-errinfo: func() -> rb-abi-value
16
+ rb-clear-errinfo: func()
17
+
18
+ rstring-ptr: func(value: rb-abi-value) -> string
19
+
20
+ rb-vm-bugreport: func()
21
+
22
+ rb-gc-enable: func() -> bool
23
+ rb-gc-disable: func() -> bool
24
+
25
+ rb-set-should-prohibit-rewind: func(new-value: bool) -> bool
data/ext/witapi/depend ADDED
@@ -0,0 +1,11 @@
1
+ link.filelist:
2
+ echo $(foreach obj,$(OBJS),$(abspath $(obj))) > $@
3
+ echo -mexec-model=reactor >> $@
4
+
5
+ witapi.a: link.filelist
6
+
7
+ witapi-core.o: $(srcdir)/bindgen/rb-abi-guest.h
8
+
9
+ bindgen/%.o: $(srcdir)/bindgen/%.c
10
+ @mkdir -p "$(@D)"
11
+ $(CC) -c -I$(srcdir)/bindgen -o $@ $<
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+ $objs = %w[witapi-core.o bindgen/rb-abi-guest.o]
3
+ create_makefile("witapi")
@@ -0,0 +1,325 @@
1
+ #include <stdlib.h>
2
+
3
+ #include "ruby.h"
4
+ #include "ruby/version.h"
5
+
6
+ static VALUE rb_eval_string_value_protect_thunk(VALUE str) {
7
+ const ID id_eval = rb_intern("eval");
8
+ VALUE binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
9
+ const VALUE file = rb_utf8_str_new("eval", 4);
10
+ VALUE args[3] = {str, binding, file};
11
+ return rb_funcallv(rb_mKernel, id_eval, 3, args);
12
+ }
13
+
14
+ static VALUE rb_eval_string_value_protect(VALUE str, int *pstate) {
15
+ return rb_protect(rb_eval_string_value_protect_thunk, str, pstate);
16
+ }
17
+
18
+ #define TAG_NONE 0
19
+
20
+ #include "bindgen/rb-abi-guest.h"
21
+
22
+ __attribute__((import_module("asyncify"), import_name("start_unwind"))) void
23
+ asyncify_start_unwind(void *buf);
24
+ #define asyncify_start_unwind(buf) \
25
+ do { \
26
+ extern void *rb_asyncify_unwind_buf; \
27
+ rb_asyncify_unwind_buf = (buf); \
28
+ asyncify_start_unwind((buf)); \
29
+ } while (0)
30
+ __attribute__((import_module("asyncify"), import_name("stop_unwind"))) void
31
+ asyncify_stop_unwind(void);
32
+ #define asyncify_stop_unwind() \
33
+ do { \
34
+ extern void *rb_asyncify_unwind_buf; \
35
+ rb_asyncify_unwind_buf = NULL; \
36
+ asyncify_stop_unwind(); \
37
+ } while (0)
38
+ __attribute__((import_module("asyncify"), import_name("start_rewind"))) void
39
+ asyncify_start_rewind(void *buf);
40
+ __attribute__((import_module("asyncify"), import_name("stop_rewind"))) void
41
+ asyncify_stop_rewind(void);
42
+
43
+ void *rb_wasm_handle_jmp_unwind(void);
44
+ void *rb_wasm_handle_scan_unwind(void);
45
+ void *rb_wasm_handle_fiber_unwind(void (**new_fiber_entry)(void *, void *),
46
+ void **arg0, void **arg1,
47
+ bool *is_new_fiber_started);
48
+ #define RB_WASM_ENABLE_DEBUG_LOG 0
49
+
50
+ #if RB_WASM_ENABLE_DEBUG_LOG
51
+ # define RB_WASM_DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__)
52
+ #else
53
+ # define RB_WASM_DEBUG_LOG(...) (void)0
54
+ #endif
55
+
56
+ static bool rb_should_prohibit_rewind = false;
57
+
58
+ __attribute__((import_module("rb-js-abi-host"),
59
+ import_name("rb_wasm_throw_prohibit_rewind_exception")))
60
+ __attribute__((noreturn)) void
61
+ rb_wasm_throw_prohibit_rewind_exception(const char *c_msg, size_t msg_len);
62
+
63
+ #define RB_WASM_CHECK_REWIND_PROHIBITED(msg) \
64
+ /* \
65
+ If the unwond source and rewinding destination are same, it's acceptable \
66
+ to rewind even under nested VM operations. \
67
+ */ \
68
+ if (rb_should_prohibit_rewind && \
69
+ (asyncify_buf != asyncify_unwound_buf || fiber_entry_point)) { \
70
+ rb_wasm_throw_prohibit_rewind_exception(msg, sizeof(msg) - 1); \
71
+ }
72
+
73
+ #define RB_WASM_LIB_RT(MAIN_ENTRY) \
74
+ { \
75
+ \
76
+ void *arg0 = NULL, *arg1 = NULL; \
77
+ void (*fiber_entry_point)(void *, void *) = NULL; \
78
+ \
79
+ while (1) { \
80
+ if (fiber_entry_point) { \
81
+ fiber_entry_point(arg0, arg1); \
82
+ } else { \
83
+ MAIN_ENTRY; \
84
+ } \
85
+ \
86
+ bool new_fiber_started = false; \
87
+ void *asyncify_buf = NULL; \
88
+ extern void *rb_asyncify_unwind_buf; \
89
+ void *asyncify_unwound_buf = rb_asyncify_unwind_buf; \
90
+ if (asyncify_unwound_buf == NULL) \
91
+ break; \
92
+ asyncify_stop_unwind(); \
93
+ \
94
+ if ((asyncify_buf = rb_wasm_handle_jmp_unwind()) != NULL) { \
95
+ RB_WASM_CHECK_REWIND_PROHIBITED("rb_wasm_handle_jmp_unwind") \
96
+ asyncify_start_rewind(asyncify_buf); \
97
+ continue; \
98
+ } \
99
+ if ((asyncify_buf = rb_wasm_handle_scan_unwind()) != NULL) { \
100
+ RB_WASM_CHECK_REWIND_PROHIBITED("rb_wasm_handle_scan_unwind") \
101
+ asyncify_start_rewind(asyncify_buf); \
102
+ continue; \
103
+ } \
104
+ \
105
+ asyncify_buf = rb_wasm_handle_fiber_unwind(&fiber_entry_point, &arg0, \
106
+ &arg1, &new_fiber_started); \
107
+ if (asyncify_buf) { \
108
+ RB_WASM_CHECK_REWIND_PROHIBITED("rb_wasm_handle_fiber_unwind") \
109
+ asyncify_start_rewind(asyncify_buf); \
110
+ continue; \
111
+ } else if (new_fiber_started) { \
112
+ RB_WASM_CHECK_REWIND_PROHIBITED( \
113
+ "rb_wasm_handle_fiber_unwind but new fiber"); \
114
+ continue; \
115
+ } \
116
+ \
117
+ break; \
118
+ } \
119
+ }
120
+
121
+ #define c_strings_from_abi(list, new_args) \
122
+ { \
123
+ new_args = alloca(sizeof(char *) * ((list)->len + 1)); \
124
+ for (size_t i = 0; i < (list)->len; i++) { \
125
+ new_args[i] = (list)->ptr[i].ptr; \
126
+ } \
127
+ }
128
+
129
+ static VALUE rb_abi_guest_arena_hash;
130
+ static VALUE rb_abi_guest_refcount_hash;
131
+
132
+ static VALUE rb_abi_lend_object_internal(VALUE obj) {
133
+ VALUE object_id = rb_obj_id(obj);
134
+ VALUE ref_count = rb_hash_lookup(rb_abi_guest_refcount_hash, object_id);
135
+ if (NIL_P(ref_count)) {
136
+ rb_hash_aset(rb_abi_guest_arena_hash, object_id, obj);
137
+ rb_hash_aset(rb_abi_guest_refcount_hash, object_id, INT2FIX(1));
138
+ } else {
139
+ rb_hash_aset(rb_abi_guest_refcount_hash, object_id,
140
+ INT2FIX(FIX2INT(ref_count) + 1));
141
+ }
142
+ return Qundef;
143
+ }
144
+ void rb_abi_lend_object(VALUE obj) {
145
+ RB_WASM_DEBUG_LOG("rb_abi_lend_object: obj = %p\n", (void *)obj);
146
+ int state;
147
+ RB_WASM_LIB_RT(rb_protect(rb_abi_lend_object_internal, obj, &state));
148
+ assert(state == TAG_NONE && "rb_abi_lend_object_internal failed");
149
+ }
150
+
151
+ static VALUE rb_abi_guest_rb_abi_value_dtor_internal(VALUE obj) {
152
+ VALUE object_id = rb_obj_id(obj);
153
+ VALUE ref_count = rb_hash_lookup(rb_abi_guest_refcount_hash, object_id);
154
+ if (NIL_P(ref_count)) {
155
+ rb_warning("rb_abi_guest_rb_abi_value_dtor: double free detected");
156
+ return Qundef;
157
+ }
158
+ if (ref_count == INT2FIX(1)) {
159
+ RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: ref_count == 1\n");
160
+ rb_hash_delete(rb_abi_guest_refcount_hash, object_id);
161
+ rb_hash_delete(rb_abi_guest_arena_hash, object_id);
162
+ } else {
163
+ RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: ref_count = %d\n",
164
+ FIX2INT(ref_count));
165
+ rb_hash_aset(rb_abi_guest_refcount_hash, object_id,
166
+ INT2FIX(FIX2INT(ref_count) - 1));
167
+ }
168
+ return Qundef;
169
+ }
170
+
171
+ void rb_abi_guest_rb_abi_value_dtor(void *data) {
172
+ RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: data = %p\n", data);
173
+ int state;
174
+ RB_WASM_LIB_RT(
175
+ rb_protect(rb_abi_guest_rb_abi_value_dtor_internal, (VALUE)data, &state));
176
+ assert(state == TAG_NONE && "rb_abi_guest_rb_abi_value_dtor_internal failed");
177
+ }
178
+
179
+ // MARK: - Exported functions
180
+ // NOTE: Assume that callers always pass null terminated string by
181
+ // rb_abi_guest_string_t
182
+
183
+ void rb_abi_guest_ruby_show_version(void) { ruby_show_version(); }
184
+
185
+ void rb_abi_guest_ruby_init(void) {
186
+ RB_WASM_LIB_RT(ruby_init())
187
+
188
+ rb_abi_guest_arena_hash = rb_hash_new();
189
+ rb_abi_guest_refcount_hash = rb_hash_new();
190
+
191
+ rb_gc_register_mark_object(rb_abi_guest_arena_hash);
192
+ rb_gc_register_mark_object(rb_abi_guest_refcount_hash);
193
+ }
194
+
195
+ void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args) {
196
+ char **c_args;
197
+ int argc = args->len;
198
+ c_strings_from_abi(args, c_args);
199
+ RB_WASM_LIB_RT(ruby_sysinit(&argc, &c_args))
200
+ }
201
+
202
+ rb_abi_guest_rb_iseq_t
203
+ rb_abi_guest_ruby_options(rb_abi_guest_list_string_t *args) {
204
+ void *result;
205
+ char **c_args;
206
+ c_strings_from_abi(args, c_args);
207
+ RB_WASM_LIB_RT(result = ruby_options(args->len, c_args))
208
+ return rb_abi_guest_rb_iseq_new(result);
209
+ }
210
+
211
+ void rb_abi_guest_ruby_script(rb_abi_guest_string_t *name) {
212
+ RB_WASM_LIB_RT(ruby_script(name->ptr))
213
+ }
214
+
215
+ void rb_abi_guest_ruby_init_loadpath(void) {
216
+ RB_WASM_LIB_RT(ruby_init_loadpath())
217
+ }
218
+
219
+ void rb_abi_guest_rb_eval_string_protect(
220
+ rb_abi_guest_string_t *str, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0) {
221
+ VALUE retval;
222
+ RB_WASM_DEBUG_LOG("rb_eval_string_protect: str = %s\n", str->ptr);
223
+ VALUE utf8_str = rb_utf8_str_new(str->ptr, str->len);
224
+ RB_WASM_LIB_RT(retval = rb_eval_string_value_protect(utf8_str, &ret0->f1));
225
+ RB_WASM_DEBUG_LOG("rb_eval_string_protect: retval = %p, state = %d\n",
226
+ (void *)retval, ret0->f1);
227
+
228
+ if (ret0->f1 == TAG_NONE) {
229
+ rb_abi_lend_object(retval);
230
+ }
231
+ ret0->f0 = rb_abi_guest_rb_abi_value_new((void *)retval);
232
+ }
233
+
234
+ struct rb_funcallv_thunk_ctx {
235
+ VALUE recv;
236
+ ID mid;
237
+ rb_abi_guest_list_rb_abi_value_t *args;
238
+ };
239
+
240
+ VALUE rb_funcallv_thunk(VALUE arg) {
241
+ struct rb_funcallv_thunk_ctx *ctx = (struct rb_funcallv_thunk_ctx *)arg;
242
+ VALUE *c_argv = alloca(sizeof(VALUE) * ctx->args->len);
243
+ for (size_t i = 0; i < ctx->args->len; i++) {
244
+ c_argv[i] = (VALUE)rb_abi_guest_rb_abi_value_get(&ctx->args->ptr[i]);
245
+ }
246
+ return rb_funcallv(ctx->recv, ctx->mid, ctx->args->len, c_argv);
247
+ }
248
+
249
+ void rb_abi_guest_rb_funcallv_protect(
250
+ rb_abi_guest_rb_abi_value_t recv, rb_abi_guest_rb_id_t mid,
251
+ rb_abi_guest_list_rb_abi_value_t *args,
252
+ rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0) {
253
+ VALUE retval;
254
+ VALUE r_recv = (VALUE)rb_abi_guest_rb_abi_value_get(&recv);
255
+ struct rb_funcallv_thunk_ctx ctx = {.recv = r_recv, .mid = mid, .args = args};
256
+ RB_WASM_LIB_RT(retval =
257
+ rb_protect(rb_funcallv_thunk, (VALUE)&ctx, &ret0->f1));
258
+ RB_WASM_DEBUG_LOG(
259
+ "rb_abi_guest_rb_funcallv_protect: retval = %p, state = %d\n",
260
+ (void *)retval, ret0->f1);
261
+
262
+ if (ret0->f1 == TAG_NONE) {
263
+ rb_abi_lend_object(retval);
264
+ }
265
+ ret0->f0 = rb_abi_guest_rb_abi_value_new((void *)retval);
266
+ }
267
+
268
+ rb_abi_guest_rb_id_t rb_abi_guest_rb_intern(rb_abi_guest_string_t *name) {
269
+ return rb_intern(name->ptr);
270
+ }
271
+
272
+ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_errinfo(void) {
273
+ VALUE retval;
274
+ RB_WASM_LIB_RT(retval = rb_errinfo());
275
+ rb_abi_lend_object(retval);
276
+ return rb_abi_guest_rb_abi_value_new((void *)retval);
277
+ }
278
+
279
+ void rb_abi_guest_rb_clear_errinfo(void) { rb_set_errinfo(Qnil); }
280
+
281
+ void rb_abi_guest_rstring_ptr(rb_abi_guest_rb_abi_value_t value,
282
+ rb_abi_guest_string_t *ret0) {
283
+ VALUE r_str = (VALUE)rb_abi_guest_rb_abi_value_get(&value);
284
+ ret0->len = RSTRING_LEN(r_str);
285
+ ret0->ptr = xmalloc(ret0->len);
286
+ memcpy(ret0->ptr, RSTRING_PTR(r_str), ret0->len);
287
+ }
288
+
289
+ uint32_t rb_abi_guest_rb_abi_value_data_ptr(rb_abi_guest_rb_abi_value_t self) {
290
+ VALUE obj = (VALUE)rb_abi_guest_rb_abi_value_get(&self);
291
+ return (uint32_t)DATA_PTR(obj);
292
+ }
293
+
294
+ _Static_assert(RUBY_API_VERSION_MAJOR == 3, "unsupported Ruby version");
295
+ #if RUBY_API_VERSION_MINOR == 2
296
+ void rb_vm_bugreport(const void *);
297
+
298
+ void rb_abi_guest_rb_vm_bugreport(void) { rb_vm_bugreport(NULL); }
299
+ #elif RUBY_API_VERSION_MINOR >= 3
300
+ bool rb_vm_bugreport(const void *, FILE *);
301
+
302
+ void rb_abi_guest_rb_vm_bugreport(void) { rb_vm_bugreport(NULL, stderr); }
303
+ #else
304
+ # error "unsupported Ruby version"
305
+ #endif
306
+
307
+ bool rb_abi_guest_rb_gc_enable(void) { return rb_gc_enable() == Qtrue; }
308
+
309
+ VALUE rb_gc_disable_no_rest(void);
310
+ bool rb_abi_guest_rb_gc_disable(void) {
311
+ // NOTE: rb_gc_disable() is usually preferred to free up memory as much as
312
+ // possible before disabling GC. However it may trigger GC through gc_rest(),
313
+ // and triggering GC having a sandwitched JS frame is unsafe because it misses
314
+ // to mark some living objects in the frames behind the JS frame. So we use
315
+ // rb_gc_disable_no_rest(), which does not trigger GC, instead.
316
+ return rb_gc_disable_no_rest() == Qtrue;
317
+ }
318
+
319
+ bool rb_abi_guest_rb_set_should_prohibit_rewind(bool value) {
320
+ bool old = rb_should_prohibit_rewind;
321
+ rb_should_prohibit_rewind = value;
322
+ return old;
323
+ }
324
+
325
+ void Init_witapi(void) {}