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.
- checksums.yaml +7 -0
- data/LICENSE-mruby.txt +22 -0
- data/LICENSE-spinel.txt +19 -0
- data/LICENSE.txt +21 -0
- data/README.md +61 -0
- data/ext/qr_reader_native/SPINEL_VERSION +1 -0
- data/ext/qr_reader_native/extconf.rb +8 -0
- data/ext/qr_reader_native/mruby/error.h +13 -0
- data/ext/qr_reader_native/mruby/internal.h +145 -0
- data/ext/qr_reader_native/mruby/string.h +22 -0
- data/ext/qr_reader_native/mruby.h +93 -0
- data/ext/qr_reader_native/mruby_shim.h +118 -0
- data/ext/qr_reader_native/qr_reader_native.c +13513 -0
- data/ext/qr_reader_native/qr_reader_native.h +29 -0
- data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
- data/ext/qr_reader_native/re_cased.h +71 -0
- data/ext/qr_reader_native/re_compile.c +5784 -0
- data/ext/qr_reader_native/re_ctype.h +3540 -0
- data/ext/qr_reader_native/re_exec.c +2190 -0
- data/ext/qr_reader_native/re_internal.h +671 -0
- data/ext/qr_reader_native/re_prop.h +4629 -0
- data/ext/qr_reader_native/re_spinel.c +363 -0
- data/ext/qr_reader_native/re_spinel.h +22 -0
- data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
- data/ext/qr_reader_native/re_utf8.c +156 -0
- data/ext/qr_reader_native/sp_alloc.c +1447 -0
- data/ext/qr_reader_native/sp_alloc.h +1196 -0
- data/ext/qr_reader_native/sp_argf.h +33 -0
- data/ext/qr_reader_native/sp_array.c +1052 -0
- data/ext/qr_reader_native/sp_array.h +456 -0
- data/ext/qr_reader_native/sp_bigint.c +5826 -0
- data/ext/qr_reader_native/sp_bigint.h +117 -0
- data/ext/qr_reader_native/sp_cold.c +5259 -0
- data/ext/qr_reader_native/sp_compat.h +402 -0
- data/ext/qr_reader_native/sp_core.c +818 -0
- data/ext/qr_reader_native/sp_core.h +56 -0
- data/ext/qr_reader_native/sp_crypto.c +877 -0
- data/ext/qr_reader_native/sp_crypto.h +169 -0
- data/ext/qr_reader_native/sp_dtoa.c +1533 -0
- data/ext/qr_reader_native/sp_dtoa.h +29 -0
- data/ext/qr_reader_native/sp_encoding_names.h +172 -0
- data/ext/qr_reader_native/sp_enum.h +86 -0
- data/ext/qr_reader_native/sp_exc.c +1185 -0
- data/ext/qr_reader_native/sp_exc.h +186 -0
- data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
- data/ext/qr_reader_native/sp_fiber.c +889 -0
- data/ext/qr_reader_native/sp_fiber.h +162 -0
- data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
- data/ext/qr_reader_native/sp_format.c +695 -0
- data/ext/qr_reader_native/sp_format.h +83 -0
- data/ext/qr_reader_native/sp_gc.c +1793 -0
- data/ext/qr_reader_native/sp_gc.h +762 -0
- data/ext/qr_reader_native/sp_hash.c +131 -0
- data/ext/qr_reader_native/sp_hash.h +131 -0
- data/ext/qr_reader_native/sp_inspect.c +215 -0
- data/ext/qr_reader_native/sp_inspect.h +128 -0
- data/ext/qr_reader_native/sp_io.c +1676 -0
- data/ext/qr_reader_native/sp_io.h +272 -0
- data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
- data/ext/qr_reader_native/sp_iobuffer.h +167 -0
- data/ext/qr_reader_native/sp_marshal.c +487 -0
- data/ext/qr_reader_native/sp_marshal.h +60 -0
- data/ext/qr_reader_native/sp_net.c +1029 -0
- data/ext/qr_reader_native/sp_net.h +205 -0
- data/ext/qr_reader_native/sp_pack.c +1254 -0
- data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
- data/ext/qr_reader_native/sp_proc.c +410 -0
- data/ext/qr_reader_native/sp_proc.h +327 -0
- data/ext/qr_reader_native/sp_process.c +547 -0
- data/ext/qr_reader_native/sp_process_status.c +211 -0
- data/ext/qr_reader_native/sp_process_status.h +66 -0
- data/ext/qr_reader_native/sp_random.c +287 -0
- data/ext/qr_reader_native/sp_random.h +52 -0
- data/ext/qr_reader_native/sp_range.h +144 -0
- data/ext/qr_reader_native/sp_re.c +1379 -0
- data/ext/qr_reader_native/sp_re.h +186 -0
- data/ext/qr_reader_native/sp_re_names.h +59 -0
- data/ext/qr_reader_native/sp_sched.c +4044 -0
- data/ext/qr_reader_native/sp_sched.h +295 -0
- data/ext/qr_reader_native/sp_slab.c +1507 -0
- data/ext/qr_reader_native/sp_str.c +1462 -0
- data/ext/qr_reader_native/sp_str.h +306 -0
- data/ext/qr_reader_native/sp_str_crypt.c +23 -0
- data/ext/qr_reader_native/sp_string.c +92 -0
- data/ext/qr_reader_native/sp_string.h +253 -0
- data/ext/qr_reader_native/sp_system.c +78 -0
- data/ext/qr_reader_native/sp_system.h +18 -0
- data/ext/qr_reader_native/sp_time.c +860 -0
- data/ext/qr_reader_native/sp_time.h +100 -0
- data/ext/qr_reader_native/sp_types.h +292 -0
- data/ext/qr_reader_native/spinel_rt.h +19017 -0
- data/ext/qr_reader_native/unicase.c +399 -0
- data/ext/qr_reader_native/unicase.h +901 -0
- data/lib/qr_reader/native.rb +6 -0
- 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
|
+
}
|