qr_reader-native 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-mruby.txt +22 -0
  3. data/LICENSE-spinel.txt +19 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +61 -0
  6. data/ext/qr_reader_native/SPINEL_VERSION +1 -0
  7. data/ext/qr_reader_native/extconf.rb +8 -0
  8. data/ext/qr_reader_native/mruby/error.h +13 -0
  9. data/ext/qr_reader_native/mruby/internal.h +145 -0
  10. data/ext/qr_reader_native/mruby/string.h +22 -0
  11. data/ext/qr_reader_native/mruby.h +93 -0
  12. data/ext/qr_reader_native/mruby_shim.h +118 -0
  13. data/ext/qr_reader_native/qr_reader_native.c +13513 -0
  14. data/ext/qr_reader_native/qr_reader_native.h +29 -0
  15. data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
  16. data/ext/qr_reader_native/re_cased.h +71 -0
  17. data/ext/qr_reader_native/re_compile.c +5784 -0
  18. data/ext/qr_reader_native/re_ctype.h +3540 -0
  19. data/ext/qr_reader_native/re_exec.c +2190 -0
  20. data/ext/qr_reader_native/re_internal.h +671 -0
  21. data/ext/qr_reader_native/re_prop.h +4629 -0
  22. data/ext/qr_reader_native/re_spinel.c +363 -0
  23. data/ext/qr_reader_native/re_spinel.h +22 -0
  24. data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
  25. data/ext/qr_reader_native/re_utf8.c +156 -0
  26. data/ext/qr_reader_native/sp_alloc.c +1447 -0
  27. data/ext/qr_reader_native/sp_alloc.h +1196 -0
  28. data/ext/qr_reader_native/sp_argf.h +33 -0
  29. data/ext/qr_reader_native/sp_array.c +1052 -0
  30. data/ext/qr_reader_native/sp_array.h +456 -0
  31. data/ext/qr_reader_native/sp_bigint.c +5826 -0
  32. data/ext/qr_reader_native/sp_bigint.h +117 -0
  33. data/ext/qr_reader_native/sp_cold.c +5259 -0
  34. data/ext/qr_reader_native/sp_compat.h +402 -0
  35. data/ext/qr_reader_native/sp_core.c +818 -0
  36. data/ext/qr_reader_native/sp_core.h +56 -0
  37. data/ext/qr_reader_native/sp_crypto.c +877 -0
  38. data/ext/qr_reader_native/sp_crypto.h +169 -0
  39. data/ext/qr_reader_native/sp_dtoa.c +1533 -0
  40. data/ext/qr_reader_native/sp_dtoa.h +29 -0
  41. data/ext/qr_reader_native/sp_encoding_names.h +172 -0
  42. data/ext/qr_reader_native/sp_enum.h +86 -0
  43. data/ext/qr_reader_native/sp_exc.c +1185 -0
  44. data/ext/qr_reader_native/sp_exc.h +186 -0
  45. data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
  46. data/ext/qr_reader_native/sp_fiber.c +889 -0
  47. data/ext/qr_reader_native/sp_fiber.h +162 -0
  48. data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
  49. data/ext/qr_reader_native/sp_format.c +695 -0
  50. data/ext/qr_reader_native/sp_format.h +83 -0
  51. data/ext/qr_reader_native/sp_gc.c +1793 -0
  52. data/ext/qr_reader_native/sp_gc.h +762 -0
  53. data/ext/qr_reader_native/sp_hash.c +131 -0
  54. data/ext/qr_reader_native/sp_hash.h +131 -0
  55. data/ext/qr_reader_native/sp_inspect.c +215 -0
  56. data/ext/qr_reader_native/sp_inspect.h +128 -0
  57. data/ext/qr_reader_native/sp_io.c +1676 -0
  58. data/ext/qr_reader_native/sp_io.h +272 -0
  59. data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
  60. data/ext/qr_reader_native/sp_iobuffer.h +167 -0
  61. data/ext/qr_reader_native/sp_marshal.c +487 -0
  62. data/ext/qr_reader_native/sp_marshal.h +60 -0
  63. data/ext/qr_reader_native/sp_net.c +1029 -0
  64. data/ext/qr_reader_native/sp_net.h +205 -0
  65. data/ext/qr_reader_native/sp_pack.c +1254 -0
  66. data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
  67. data/ext/qr_reader_native/sp_proc.c +410 -0
  68. data/ext/qr_reader_native/sp_proc.h +327 -0
  69. data/ext/qr_reader_native/sp_process.c +547 -0
  70. data/ext/qr_reader_native/sp_process_status.c +211 -0
  71. data/ext/qr_reader_native/sp_process_status.h +66 -0
  72. data/ext/qr_reader_native/sp_random.c +287 -0
  73. data/ext/qr_reader_native/sp_random.h +52 -0
  74. data/ext/qr_reader_native/sp_range.h +144 -0
  75. data/ext/qr_reader_native/sp_re.c +1379 -0
  76. data/ext/qr_reader_native/sp_re.h +186 -0
  77. data/ext/qr_reader_native/sp_re_names.h +59 -0
  78. data/ext/qr_reader_native/sp_sched.c +4044 -0
  79. data/ext/qr_reader_native/sp_sched.h +295 -0
  80. data/ext/qr_reader_native/sp_slab.c +1507 -0
  81. data/ext/qr_reader_native/sp_str.c +1462 -0
  82. data/ext/qr_reader_native/sp_str.h +306 -0
  83. data/ext/qr_reader_native/sp_str_crypt.c +23 -0
  84. data/ext/qr_reader_native/sp_string.c +92 -0
  85. data/ext/qr_reader_native/sp_string.h +253 -0
  86. data/ext/qr_reader_native/sp_system.c +78 -0
  87. data/ext/qr_reader_native/sp_system.h +18 -0
  88. data/ext/qr_reader_native/sp_time.c +860 -0
  89. data/ext/qr_reader_native/sp_time.h +100 -0
  90. data/ext/qr_reader_native/sp_types.h +292 -0
  91. data/ext/qr_reader_native/spinel_rt.h +19017 -0
  92. data/ext/qr_reader_native/unicase.c +399 -0
  93. data/ext/qr_reader_native/unicase.h +901 -0
  94. data/lib/qr_reader/native.rb +6 -0
  95. metadata +153 -0
@@ -0,0 +1,410 @@
1
+ /* sp_proc.c -- cold sp_Proc/sp_Curry ops (see sp_proc.h). 0 optcarrot uses. */
2
+ #include "sp_proc.h"
3
+ #include "sp_exc.h" /* sp_arity_check */
4
+
5
+ void sp_Proc_scan(void *p) { sp_Proc *pr = (sp_Proc *)p; if (pr->cap && pr->cap_scan) pr->cap_scan(pr->cap); }
6
+ sp_Proc *sp_proc_new_meta(void *fn, void *cap, void (*cap_scan)(void *), sp_int arity, sp_bool lambda_p, sp_int param_count, const sp_sym *param_kinds, const sp_sym *param_names) { sp_Proc *p = (sp_Proc *)sp_gc_alloc(sizeof(sp_Proc), NULL, sp_Proc_scan); p->fn = fn; p->cap = cap; p->cap_scan = cap_scan; p->arity = arity; p->lambda_p = lambda_p; p->param_count = param_count; p->param_kinds = param_kinds; p->param_names = param_names; return p; }
7
+ /* Proc#dup / #clone: a fresh shallow copy (distinct identity; the capture
8
+ environment is shared, like CRuby). dup drops the frozen flag, clone keeps
9
+ it (#3048). */
10
+ sp_Proc *sp_proc_dup(sp_Proc *p, int keep_frozen) {
11
+ if (!p) return p;
12
+ SP_GC_ROOT(p);
13
+ sp_Proc *r = (sp_Proc *)sp_gc_alloc(sizeof(sp_Proc), NULL, sp_Proc_scan);
14
+ *r = *p;
15
+ if (!keep_frozen) r->frozen = 0;
16
+ r->origin = sp_proc_root(p); /* share the lineage root so dup == original */
17
+ return r;
18
+ }
19
+ sp_Proc *sp_proc_new(void *fn, void *cap, void (*cap_scan)(void *)) { return sp_proc_new_meta(fn, cap, cap_scan, 0, FALSE, 0, NULL, NULL); }
20
+ sp_int sp_proc_arity(sp_Proc *p) { return p ? p->arity : 0; }
21
+ sp_bool sp_proc_lambda_p(sp_Proc *p) { return p ? p->lambda_p : FALSE; }
22
+ /* Proc#inspect: CRuby prints "#<Proc:0xADDR file:line (lambda)>"; the
23
+ source location is not tracked, so the address form (+ lambda marker) is
24
+ the best-effort rendering. */
25
+ const char *sp_proc_inspect(sp_Proc *p) {SP_GC_ROOT(p);
26
+ if (!p) return SPL("nil");
27
+ return sp_sprintf(p->lambda_p ? "#<Proc:0x%016llx (lambda)>" : "#<Proc:0x%016llx>",
28
+ (unsigned long long)(uintptr_t)p);
29
+ }
30
+ /* Proc#parameters with an explicit mode. Kinds are stored canonically
31
+ (lambda-style: a plain positional is "req"); printing for proc mode remaps
32
+ req -> opt, which leaves defaulted positionals (stored "opt") and every
33
+ non-positional kind untouched -- exactly CRuby's parameters(lambda:) rule.
34
+ mode: 1 = lambda view, 0 = proc view, -1 = the receiver's own nature.
35
+ req_id/opt_id are the generated TU's interned ids for those kinds. #2693 */
36
+ sp_PolyArray *sp_proc_parameters_ids(sp_Proc *p, int mode, sp_sym req_id, sp_sym opt_id) { SP_GC_ROOT(p);
37
+ sp_PolyArray *r = sp_PolyArray_new();
38
+ if (!p || p->param_count <= 0 || !p->param_kinds) return r;
39
+ SP_GC_ROOT(r);
40
+ int want_lambda = mode >= 0 ? mode : (p->lambda_p ? 1 : 0);
41
+ for (sp_int i = 0; i < p->param_count; i++) {
42
+ sp_sym k = p->param_kinds[i];
43
+ if (!want_lambda && k == req_id) k = opt_id;
44
+ sp_PolyArray *pair = sp_PolyArray_new();
45
+ sp_PolyArray_push(pair, sp_box_sym(k));
46
+ if (p->param_names && p->param_names[i] >= 0) sp_PolyArray_push(pair, sp_box_sym(p->param_names[i]));
47
+ sp_PolyArray_push(r, sp_box_poly_array(pair));
48
+ }
49
+ return r;
50
+ }
51
+ sp_PolyArray *sp_proc_parameters(sp_Proc *p) { SP_GC_ROOT(p); sp_PolyArray *r = sp_PolyArray_new(); if (!p || p->param_count <= 0 || !p->param_kinds) return r; SP_GC_ROOT(r); for (sp_int i = 0; i < p->param_count; i++) { sp_PolyArray *pair = sp_PolyArray_new(); sp_PolyArray_push(pair, sp_box_sym(p->param_kinds[i])); if (p->param_names && p->param_names[i] >= 0) sp_PolyArray_push(pair, sp_box_sym(p->param_names[i])); sp_PolyArray_push(r, sp_box_poly_array(pair)); } return r; }
52
+ void sp_curry_scan(void *p) { sp_Curry *c = (sp_Curry *)p; if (c->target) sp_gc_mark(c->target); for (sp_int i = 0; i < c->nargs && i < 16; i++) sp_mark_rbval(c->args[i]); }
53
+ sp_Curry *sp_curry_new(sp_Proc *p) {
54
+ SP_GC_ROOT(p); /* the target proc has no other root across this alloc */
55
+ sp_Curry *c = (sp_Curry *)sp_gc_alloc(sizeof(sp_Curry), NULL, sp_curry_scan);
56
+ c->target = p; c->nargs = 0;
57
+ /* no count given: realize at the target's required-parameter count (CRuby's
58
+ min arity; a negative arity encodes it as -req-1) */
59
+ c->arity = p ? (p->arity < 0 ? -p->arity - 1 : p->arity) : 0;
60
+ return c;
61
+ }
62
+ /* Proc#curry(n): the count overrides the default. CRuby validates n against
63
+ a lambda's min..max arity at the curry call, before anything is applied.
64
+ The min comes off the target's arity; the max only the compiler can see
65
+ (an optional widens it, a rest lifts it), so the call site passes it in --
66
+ max < 0 means unlimited-or-unknown, and the message then says "min+". */
67
+ sp_Curry *sp_curry_new_n(sp_Proc *p, sp_int n, sp_int max) {
68
+ /* an int-typed slot's nil sentinel is CRuby's nil count: no count at all */
69
+ if (n == SP_INT_NIL) return sp_curry_new(p);
70
+ if (p && p->lambda_p) {
71
+ sp_int min = p->arity < 0 ? -p->arity - 1 : p->arity;
72
+ sp_int mx = max >= 0 ? max : (p->arity >= 0 ? p->arity : -1);
73
+ /* the max is the compiler's guess from a visible parameter list; the min
74
+ is the target's own truth. A guess below it names a different write of
75
+ the same name -- trust the target, drop the guess. */
76
+ if (mx >= 0 && mx < min) mx = -1;
77
+ sp_arity_check(n, min, mx, NULL);
78
+ }
79
+ sp_Curry *c = sp_curry_new(p);
80
+ c->arity = n < 0 ? 0 : n;
81
+ return c;
82
+ }
83
+ /* Each accumulated argument is stored boxed so a non-int arg (a String, an
84
+ object, ...) keeps its type through the deferred call (#3183). */
85
+ sp_Curry *sp_curry_apply(sp_Curry *c, sp_RbVal arg) {SP_GC_ROOT_RBVAL(arg);
86
+ /* root the source accumulator: in a chained apply it is only referenced
87
+ from a C argument slot, and this allocation can collect */
88
+ SP_GC_ROOT(c);
89
+ sp_Curry *n = (sp_Curry *)sp_gc_alloc(sizeof(sp_Curry), NULL, sp_curry_scan);
90
+ *n = *c;
91
+ if (n->nargs < 16) n->args[n->nargs++] = arg;
92
+ return n;
93
+ }
94
+ /* Publish the accumulated (boxed) args on the side-channel: a poly-param
95
+ target reads its arguments back from there, keeping each arg's real type. */
96
+ void sp_curry_publish_args(sp_Curry *c) {
97
+ for (sp_int i = 0; i < c->nargs && i < 16; i++)
98
+ _sp_proc_poly_args[i] = c->args[i];
99
+ }
100
+
101
+ /* Method#to_proc: wrap the bound method in a Proc whose trampoline forwards
102
+ through the (void *self, sp_int...) ABI (the arity dispatches the cast). */
103
+ void sp_bm_cap_scan(void *p) { sp_gc_mark(p); }
104
+ /* Whether every fixed position of the stamped signature is a scalar-kind
105
+ token (the TY_UNKNOWN wildcard 0 through TY_NIL 4; see abi_sig_token in
106
+ codegen_call.c). A pointer token is 100000 + TyKind. The generic
107
+ Method#to_proc trampoline has only the raw sp_int register args the proc
108
+ ABI hands it and cannot check each argument's Ruby class the way a typed
109
+ call site's sp_bm_legacy_abi_ok does, so a pointer-typed parameter would
110
+ take an Integer argument as a raw address and dereference it -- e.g.
111
+ `[obj.method(:str_method)][0].to_proc.call(1)` reached sp_str_length(1)
112
+ and segfaulted (#4395). Decline such signatures here. */
113
+ static int sp_bm_sig_scalar_only(const char *sig, sp_int n) {
114
+ if (!sig) return 0;
115
+ for (sp_int k = 0; k < n; k++) {
116
+ sp_int code = 0;
117
+ for (int i = 0; i < 8; i++) code = code * 10 + (sig[8 * k + i] - '0');
118
+ if (code >= 100000) return 0;
119
+ }
120
+ return 1;
121
+ }
122
+ sp_int sp_method_proc_tramp(void *cap, sp_int argc, sp_int *args) {
123
+ sp_BoundMethod *m = (sp_BoundMethod *)cap;
124
+ /* A bind site that could not resolve a target (`self.class.method(:m)`) has
125
+ no callable address; dereferencing the NULL fn here segfaulted. Decline
126
+ with the same NoMethodError a resolved-but-incompatible target gets. */
127
+ if (!m || !m->fn) sp_raise_cls("NoMethodError", "undefined method 'call' for an instance of Method");
128
+ /* The bind site's thunk, when there is one, takes any count it binds: it
129
+ reads the boxed side-channel every caller publishes, converts each
130
+ argument to the parameter's real C type, fills defaults and packs a
131
+ rest, calls the target with its own signature and publishes the boxed
132
+ result -- every shape the stamped lanes below accept and the ones they
133
+ decline (#4542). A count outside its range is CRuby's ArgumentError,
134
+ raised by the thunk in CRuby's words. The generated call arms try their
135
+ stamped casts first and reach this trampoline only when those decline,
136
+ so the thunk is the general lane, not the hot one. */
137
+ if (m->thunk && !m->unbound && argc <= SP_PROC_ARG_SLOTS)
138
+ return ((sp_int (*)(void *, sp_int, sp_int *))(uintptr_t)m->thunk)(cap, argc, args);
139
+ /* A poly-ABI target (every slot an sp_RbVal; stamped at bind time) takes
140
+ the boxed side-channel values directly -- the same values the scalar
141
+ checks below read -- and publishes its boxed result. The raw sp_int
142
+ `args` are the laundered copies and carry no class, so the boxed
143
+ channel is the argument source here, exactly as in the legacy scalar
144
+ gate. Beyond eight slots there is no cast spelled below; decline. */
145
+ if (m->poly_abi) {
146
+ if (m->unbound || argc != m->poly_fixed || argc > 8)
147
+ sp_raise_cls("NoMethodError", "undefined method 'call' for an instance of Method");
148
+ /* The poly ABI shares the legacy stamp's ret kinds: a poly return takes
149
+ the sp_RbVal cast, a void body the void cast (wasm checks the callee
150
+ signature at the call), and every register kind the sp_int cast boxed
151
+ by the stamp -- over BOXED argument slots read from the side-channel
152
+ every caller publishes (the raw sp_int `args` are the laundered
153
+ copies and carry no class). */
154
+ #define PB(i) _sp_proc_poly_args[i]
155
+ sp_RbVal _pr;
156
+ if (m->legacy_ret == SP_BM_RET_POLY) {
157
+ if (m->recv_bound) {
158
+ switch (argc) {
159
+ case 0: _pr = ((sp_RbVal (*)(void *))(uintptr_t)m->fn)(m->self); break;
160
+ case 1: _pr = ((sp_RbVal (*)(void *, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0)); break;
161
+ case 2: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1)); break;
162
+ case 3: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2)); break;
163
+ case 4: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3)); break;
164
+ case 5: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4)); break;
165
+ case 6: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5)); break;
166
+ case 7: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6)); break;
167
+ default: _pr = ((sp_RbVal (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6), PB(7)); break;
168
+ }
169
+ }
170
+ else {
171
+ switch (argc) {
172
+ case 0: _pr = ((sp_RbVal (*)(void))(uintptr_t)m->fn)(); break;
173
+ case 1: _pr = ((sp_RbVal (*)(sp_RbVal))(uintptr_t)m->fn)(PB(0)); break;
174
+ case 2: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1)); break;
175
+ case 3: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2)); break;
176
+ case 4: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3)); break;
177
+ case 5: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4)); break;
178
+ case 6: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5)); break;
179
+ case 7: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6)); break;
180
+ default: _pr = ((sp_RbVal (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6), PB(7)); break;
181
+ }
182
+ }
183
+ }
184
+ else if (m->legacy_ret == SP_BM_RET_NIL) {
185
+ if (m->recv_bound) {
186
+ switch (argc) {
187
+ case 0: ((void (*)(void *))(uintptr_t)m->fn)(m->self); break;
188
+ case 1: ((void (*)(void *, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0)); break;
189
+ case 2: ((void (*)(void *, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1)); break;
190
+ case 3: ((void (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2)); break;
191
+ case 4: ((void (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3)); break;
192
+ case 5: ((void (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4)); break;
193
+ case 6: ((void (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5)); break;
194
+ case 7: ((void (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6)); break;
195
+ default: ((void (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6), PB(7)); break;
196
+ }
197
+ }
198
+ else {
199
+ switch (argc) {
200
+ case 0: ((void (*)(void))(uintptr_t)m->fn)(); break;
201
+ case 1: ((void (*)(sp_RbVal))(uintptr_t)m->fn)(PB(0)); break;
202
+ case 2: ((void (*)(sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1)); break;
203
+ case 3: ((void (*)(sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2)); break;
204
+ case 4: ((void (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3)); break;
205
+ case 5: ((void (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4)); break;
206
+ case 6: ((void (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5)); break;
207
+ case 7: ((void (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6)); break;
208
+ default: ((void (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6), PB(7)); break;
209
+ }
210
+ }
211
+ _pr = sp_box_nil();
212
+ }
213
+ else {
214
+ sp_int _ri;
215
+ if (m->recv_bound) {
216
+ switch (argc) {
217
+ case 0: _ri = ((sp_int (*)(void *))(uintptr_t)m->fn)(m->self); break;
218
+ case 1: _ri = ((sp_int (*)(void *, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0)); break;
219
+ case 2: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1)); break;
220
+ case 3: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2)); break;
221
+ case 4: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3)); break;
222
+ case 5: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4)); break;
223
+ case 6: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5)); break;
224
+ case 7: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6)); break;
225
+ default: _ri = ((sp_int (*)(void *, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(m->self, PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6), PB(7)); break;
226
+ }
227
+ }
228
+ else {
229
+ switch (argc) {
230
+ case 0: _ri = ((sp_int (*)(void))(uintptr_t)m->fn)(); break;
231
+ case 1: _ri = ((sp_int (*)(sp_RbVal))(uintptr_t)m->fn)(PB(0)); break;
232
+ case 2: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1)); break;
233
+ case 3: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2)); break;
234
+ case 4: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3)); break;
235
+ case 5: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4)); break;
236
+ case 6: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5)); break;
237
+ case 7: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6)); break;
238
+ default: _ri = ((sp_int (*)(sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal, sp_RbVal))(uintptr_t)m->fn)(PB(0), PB(1), PB(2), PB(3), PB(4), PB(5), PB(6), PB(7)); break;
239
+ }
240
+ }
241
+ _pr = sp_bm_box_ret(m, sp_bm_norm_ret(m, _ri));
242
+ }
243
+ #undef PB
244
+ _sp_proc_poly_ret = _pr;
245
+ return 0;
246
+ }
247
+ /* A Method read out of a poly slot carries no call-site types, so this
248
+ generic trampoline may only forward to a target whose stamped legacy ABI
249
+ is callable at the exact fixed arity the C signature reads, and whose
250
+ parameters are all scalar. Any other target -- a rest/optional/keyword
251
+ parameter, a float/poly/by-value-struct parameter, a pointer-typed
252
+ parameter (this route cannot check the argument's class), an unbound
253
+ Method, or a mismatched argument count (the 16-slot proc ABI caps the
254
+ count whatever legacy_fixed says) -- would take the sp_int register
255
+ as the wrong C type: the callee prologue roots a garbage rest pointer
256
+ (SP_GC_ROOT(lv_<rest>)) and the next collection dereferences it, or a
257
+ pointer parameter dereferences an Integer, a SIGSEGV (#4395). The typed
258
+ `.to_proc` path emits a per-signature trampoline and never reaches here,
259
+ so declining here only affects a Method that travelled through a poly
260
+ slot; raise the same NoMethodError the poly-call gate produces instead of
261
+ reading garbage. */
262
+ if (!m->legacy_int_abi || m->unbound || argc > 16 || m->legacy_fixed > 16 || (m->legacy_ret == SP_BM_RET_POLY && m->legacy_fixed > 8) ||
263
+ (m->legacy_rest ? argc < m->legacy_fixed : argc != m->legacy_fixed) ||
264
+ !sp_bm_sig_scalar_only(m->legacy_sig, m->legacy_fixed))
265
+ sp_raise_cls("NoMethodError", "undefined method 'call' for an instance of Method");
266
+ /* The raw sp_int slots carry no class, so the trampoline alone cannot tell
267
+ a pointer/float/string argument from an Integer; the boxed side-channel
268
+ every caller publishes (the poly spread loop, the generated proc call,
269
+ the runtime block invokers) can. Reject an argument whose scalar kind
270
+ does not match its stamped slot, the same way sp_bm_legacy_abi_ok does at
271
+ a statically-typed call site -- `[obj.method(:m)][0].call(a_string)` and
272
+ its `.to_proc`/spread forms otherwise fed the String pointer into an
273
+ sp_int parameter. The exact match is also what keeps a `false` argument
274
+ from reaching an int-inferred parameter: the raw slot would be 0, which
275
+ is TRUTHY as a Ruby Integer, so `x ? a : b` would answer the true branch
276
+ where CRuby answers the false one. Decline the kind change instead of
277
+ answering it wrong. */
278
+ for (sp_int i = 0; i < argc && i < m->legacy_fixed; i++)
279
+ if (!sp_bm_sig_pos_scalar_ok(sp_bm_boxed_scalar_token(_sp_proc_poly_args[i]), m->legacy_sig, i))
280
+ sp_raise_cls("NoMethodError", "undefined method 'call' for an instance of Method");
281
+ /* A proc publishes its result through the boxed side-channel, which every
282
+ generated proc body writes; this trampoline only returned it, so a caller
283
+ reading the slot saw a stale value (#3692). The casts below already assume
284
+ the target's sp_int ABI, so box the same answer. */
285
+ #define SP_BM_TRAMP_RET(EXPR) do { sp_int _r = sp_bm_norm_ret(m, (EXPR)); _sp_proc_poly_ret = sp_bm_box_ret(m, _r); return _r; } while (0)
286
+ /* A poly-returning target answers a 16-byte sp_RbVal in two registers that
287
+ no sp_int cast can read: take the sp_RbVal cast, publish the value in the
288
+ boxed slot and return 0, the way a generated poly-valued proc body does. */
289
+ #define SP_BM_TRAMP_POLY(EXPR) do { _sp_proc_poly_ret = (EXPR); return 0; } while (0)
290
+ if (m->legacy_ret == SP_BM_RET_POLY) {
291
+ if (!m->recv_bound) {
292
+ switch (argc) {
293
+ case 0: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void))(uintptr_t)m->fn)());
294
+ case 1: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int))(uintptr_t)m->fn)(args[0]));
295
+ case 2: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1]));
296
+ case 3: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2]));
297
+ case 4: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3]));
298
+ case 5: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4]));
299
+ case 6: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5]));
300
+ case 7: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6]));
301
+ default: SP_BM_TRAMP_POLY(((sp_RbVal (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]));
302
+ }
303
+ }
304
+ switch (argc) {
305
+ case 0: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *))(uintptr_t)m->fn)(m->self));
306
+ case 1: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int))(uintptr_t)m->fn)(m->self, args[0]));
307
+ case 2: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1]));
308
+ case 3: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2]));
309
+ case 4: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3]));
310
+ case 5: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4]));
311
+ case 6: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5]));
312
+ case 7: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6]));
313
+ default: SP_BM_TRAMP_POLY(((sp_RbVal (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]));
314
+ }
315
+ }
316
+ #undef SP_BM_TRAMP_POLY
317
+ /* A nil-returning target is a C void function: call it as one. The sp_int
318
+ casts below read a leftover register on a native target and box nil
319
+ regardless; wasm checks the callee's signature at the call and traps. */
320
+ if (m->legacy_ret == SP_BM_RET_NIL) {
321
+ #define SP_BM_TRAMP_VOID(EXPR) do { (EXPR); _sp_proc_poly_ret = sp_box_nil(); return 0; } while (0)
322
+ #define A(i) args[i]
323
+ if (!m->recv_bound) {
324
+ switch (argc) {
325
+ case 0: SP_BM_TRAMP_VOID(((void (*)(void))(uintptr_t)m->fn)());
326
+ case 1: SP_BM_TRAMP_VOID(((void (*)(sp_int))(uintptr_t)m->fn)(A(0)));
327
+ case 2: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1)));
328
+ case 3: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1), A(2)));
329
+ case 4: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1), A(2), A(3)));
330
+ case 5: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1), A(2), A(3), A(4)));
331
+ case 6: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1), A(2), A(3), A(4), A(5)));
332
+ case 7: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1), A(2), A(3), A(4), A(5), A(6)));
333
+ default: SP_BM_TRAMP_VOID(((void (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7)));
334
+ }
335
+ }
336
+ switch (argc) {
337
+ case 0: SP_BM_TRAMP_VOID(((void (*)(void *))(uintptr_t)m->fn)(m->self));
338
+ case 1: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int))(uintptr_t)m->fn)(m->self, A(0)));
339
+ case 2: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1)));
340
+ case 3: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1), A(2)));
341
+ case 4: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1), A(2), A(3)));
342
+ case 5: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1), A(2), A(3), A(4)));
343
+ case 6: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1), A(2), A(3), A(4), A(5)));
344
+ case 7: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1), A(2), A(3), A(4), A(5), A(6)));
345
+ default: SP_BM_TRAMP_VOID(((void (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7)));
346
+ }
347
+ #undef A
348
+ #undef SP_BM_TRAMP_VOID
349
+ }
350
+ /* A top-level method has no self parameter. The self-ful casts below would
351
+ put `m->self` (NULL) in the leading C slot, shifting every argument by
352
+ one -- `[method(:top_add)][0].to_proc.call(1, 2)` answered 1 instead of 3
353
+ (#4395). Select the cast by whether the Method carries a receiver, the
354
+ same way the emitted `.call`/`[]` arms do. */
355
+ if (!m->recv_bound) {
356
+ switch (argc) {
357
+ case 0: SP_BM_TRAMP_RET(((sp_int (*)(void))(uintptr_t)m->fn)());
358
+ case 1: SP_BM_TRAMP_RET(((sp_int (*)(sp_int))(uintptr_t)m->fn)(args[0]));
359
+ case 2: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1]));
360
+ case 3: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2]));
361
+ case 4: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3]));
362
+ case 5: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4]));
363
+ case 6: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5]));
364
+ case 7: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6]));
365
+ case 8: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]));
366
+ case 9: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]));
367
+ case 10: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]));
368
+ case 11: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]));
369
+ case 12: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]));
370
+ case 13: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]));
371
+ case 14: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]));
372
+ case 15: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]));
373
+ default: SP_BM_TRAMP_RET(((sp_int (*)(sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]));
374
+ }
375
+ }
376
+ switch (argc) {
377
+ case 0: SP_BM_TRAMP_RET(((sp_int (*)(void *))(uintptr_t)m->fn)(m->self));
378
+ case 1: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int))(uintptr_t)m->fn)(m->self, args[0]));
379
+ case 2: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1]));
380
+ case 3: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2]));
381
+ case 4: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3]));
382
+ case 5: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4]));
383
+ case 6: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5]));
384
+ case 7: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6]));
385
+ case 8: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]));
386
+ case 9: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]));
387
+ case 10: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]));
388
+ case 11: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]));
389
+ case 12: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]));
390
+ case 13: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]));
391
+ case 14: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]));
392
+ case 15: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]));
393
+ default: SP_BM_TRAMP_RET(((sp_int (*)(void *, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int, sp_int))(uintptr_t)m->fn)(m->self, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]));
394
+ }
395
+ #undef SP_BM_TRAMP_RET
396
+ }
397
+ sp_Proc *sp_method_to_proc(sp_BoundMethod *m) {
398
+ return sp_proc_new_meta((void *)sp_method_proc_tramp, m, sp_bm_cap_scan, 1, TRUE, 0, NULL, NULL);
399
+ }
400
+ /* Bound Method object: `obj.method(:foo)` / `method(:foo)`. `self` is the
401
+ bound receiver (NULL for a top-level method), `fn` the function address
402
+ (cast to the right signature at the call site), `name` the method name
403
+ (a string literal). `self_kind` says whether `self` is a reference
404
+ the collector should follow, and of which kind. */
405
+ void sp_BoundMethod_scan(void *p) {
406
+ sp_BoundMethod *m = (sp_BoundMethod *)p;
407
+ if (!m->self) return;
408
+ if (m->self_kind == SP_BM_SELF_OBJ) sp_gc_mark(m->self);
409
+ else if (m->self_kind == SP_BM_SELF_STR) sp_mark_string((const char *)m->self);
410
+ }