Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : /*
4 : : Defining and adding methods
5 : : */
6 : :
7 : : #include <stdlib.h>
8 : : #include <string.h>
9 : : #include <stdarg.h>
10 : : #include "julia.h"
11 : : #include "julia_internal.h"
12 : : #include "julia_assert.h"
13 : :
14 : : #ifdef __cplusplus
15 : : extern "C" {
16 : : #endif
17 : :
18 : : extern jl_value_t *jl_builtin_getfield;
19 : : extern jl_value_t *jl_builtin_tuple;
20 : :
21 : : jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name,
22 : : int nargs, jl_value_t *functionloc, jl_code_info_t *ci, int isva);
23 : :
24 : 3164 : static void check_c_types(const char *where, jl_value_t *rt, jl_value_t *at)
25 : : {
26 [ - + ]: 3164 : if (jl_is_svec(rt))
27 : 0 : jl_errorf("%s: missing return type", where);
28 [ - + ]: 3164 : JL_TYPECHKS(where, type, rt);
29 [ - + ]: 3164 : if (!jl_type_mappable_to_c(rt))
30 : 0 : jl_errorf("%s: return type doesn't correspond to a C type", where);
31 [ - + ]: 3164 : JL_TYPECHKS(where, simplevector, at);
32 : 3164 : int i, l = jl_svec_len(at);
33 [ + + ]: 15535 : for (i = 0; i < l; i++) {
34 : 12371 : jl_value_t *ati = jl_svecref(at, i);
35 [ - + ]: 12371 : if (jl_is_vararg(ati))
36 : 0 : jl_errorf("%s: Vararg not allowed for argument list", where);
37 [ - + ]: 12371 : JL_TYPECHKS(where, type, ati);
38 [ - + ]: 12371 : if (!jl_type_mappable_to_c(ati))
39 : 0 : jl_errorf("%s: argument %d type doesn't correspond to a C type", where, i + 1);
40 : : }
41 : 3164 : }
42 : :
43 : : // Resolve references to non-locally-defined variables to become references to global
44 : : // variables in `module` (unless the rvalue is one of the type parameters in `sparam_vals`).
45 : 5046370 : static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t *sparam_vals,
46 : : int binding_effects, int eager_resolve)
47 : : {
48 [ + + ]: 5046370 : if (jl_is_symbol(expr)) {
49 [ - + ]: 385774 : if (module == NULL)
50 : 0 : return expr;
51 : 385774 : return jl_module_globalref(module, (jl_sym_t*)expr);
52 : : }
53 [ + + ]: 4660590 : else if (jl_is_returnnode(expr)) {
54 : 88902 : jl_value_t *retval = jl_returnnode_value(expr);
55 [ + - ]: 88902 : if (retval) {
56 : 88902 : jl_value_t *val = resolve_globals(retval, module, sparam_vals, binding_effects, eager_resolve);
57 [ + + ]: 88902 : if (val != retval) {
58 : 2741 : JL_GC_PUSH1(&val);
59 : 2741 : expr = jl_new_struct(jl_returnnode_type, val);
60 : 2741 : JL_GC_POP();
61 : : }
62 : : }
63 : 88902 : return expr;
64 : : }
65 [ + + ]: 4571690 : else if (jl_is_gotoifnot(expr)) {
66 : 114370 : jl_value_t *cond = resolve_globals(jl_gotoifnot_cond(expr), module, sparam_vals, binding_effects, eager_resolve);
67 [ + + ]: 114370 : if (cond != jl_gotoifnot_cond(expr)) {
68 : 74 : intptr_t label = jl_gotoifnot_label(expr);
69 : 74 : JL_GC_PUSH1(&cond);
70 : 74 : expr = jl_new_struct_uninit(jl_gotoifnot_type);
71 : 74 : set_nth_field(jl_gotoifnot_type, expr, 0, cond, 0);
72 : 74 : jl_gotoifnot_label(expr) = label;
73 : 74 : JL_GC_POP();
74 : : }
75 : 114370 : return expr;
76 : : }
77 [ + + ]: 4457320 : else if (jl_is_expr(expr)) {
78 : 1206500 : jl_expr_t *e = (jl_expr_t*)expr;
79 [ + + + + ]: 1206500 : if (e->head == jl_global_sym && binding_effects) {
80 : : // execute the side-effects of "global x" decl immediately:
81 : : // creates uninitialized mutable binding in module for each global
82 : 247 : jl_eval_global_expr(module, e, 1);
83 : 247 : expr = jl_nothing;
84 : : }
85 [ + + + - ]: 1206500 : if (jl_is_toplevel_only_expr(expr) || e->head == jl_const_sym ||
86 [ + - + + ]: 1206150 : e->head == jl_coverageeffect_sym || e->head == jl_copyast_sym ||
87 [ + - + - ]: 1205070 : e->head == jl_quote_sym || e->head == jl_inert_sym ||
88 [ + + + - ]: 1205070 : e->head == jl_meta_sym || e->head == jl_inbounds_sym ||
89 [ + + + + ]: 1204990 : e->head == jl_boundscheck_sym || e->head == jl_loopinfo_sym ||
90 [ + + + + ]: 1204480 : e->head == jl_aliasscope_sym || e->head == jl_popaliasscope_sym ||
91 [ + - + - ]: 1204480 : e->head == jl_inline_sym || e->head == jl_noinline_sym) {
92 : : // ignore these
93 : : }
94 : : else {
95 : 1204480 : size_t i = 0, nargs = jl_array_len(e->args);
96 [ + + ]: 1204480 : if (e->head == jl_opaque_closure_method_sym) {
97 [ - + ]: 42 : if (nargs != 5) {
98 : 0 : jl_error("opaque_closure_method: invalid syntax");
99 : : }
100 : 42 : jl_value_t *name = jl_exprarg(e, 0);
101 : 42 : jl_value_t *nargs = jl_exprarg(e, 1);
102 : 42 : int isva = jl_exprarg(e, 2) == jl_true;
103 : 42 : jl_value_t *functionloc = jl_exprarg(e, 3);
104 : 42 : jl_value_t *ci = jl_exprarg(e, 4);
105 [ - + ]: 42 : if (!jl_is_code_info(ci)) {
106 : 0 : jl_error("opaque_closure_method: lambda should be a CodeInfo");
107 : : }
108 : 42 : jl_method_t *m = jl_make_opaque_closure_method(module, name, jl_unbox_long(nargs), functionloc, (jl_code_info_t*)ci, isva);
109 : 42 : return (jl_value_t*)m;
110 : : }
111 [ + + ]: 1204440 : if (e->head == jl_cfunction_sym) {
112 [ - + - + ]: 117 : JL_NARGS(cfunction method definition, 5, 5); // (type, func, rt, at, cc)
113 : 117 : jl_value_t *typ = jl_exprarg(e, 0);
114 [ - + ]: 117 : if (!jl_is_type(typ))
115 : 0 : jl_error("first parameter to :cfunction must be a type");
116 [ + + ]: 117 : if (typ == (jl_value_t*)jl_voidpointer_type) {
117 : 112 : jl_value_t *a = jl_exprarg(e, 1);
118 [ - + ]: 112 : JL_TYPECHK(cfunction method definition, quotenode, a);
119 : 112 : *(jl_value_t**)a = jl_toplevel_eval(module, *(jl_value_t**)a);
120 : 112 : jl_gc_wb(a, *(jl_value_t**)a);
121 : : }
122 : 117 : jl_value_t *rt = jl_exprarg(e, 2);
123 : 117 : jl_value_t *at = jl_exprarg(e, 3);
124 [ + + ]: 117 : if (!jl_is_type(rt)) {
125 [ + - + + ]: 214 : JL_TRY {
126 : 107 : rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals);
127 : : }
128 [ # # ]: 0 : JL_CATCH {
129 [ # # ]: 0 : if (jl_typeis(jl_current_exception(), jl_errorexception_type))
130 : 0 : jl_error("could not evaluate cfunction return type (it might depend on a local variable)");
131 : : else
132 : 0 : jl_rethrow();
133 : : }
134 : 107 : jl_exprargset(e, 2, rt);
135 : : }
136 [ + - ]: 117 : if (!jl_is_svec(at)) {
137 [ + - + + ]: 234 : JL_TRY {
138 : 117 : at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals);
139 : : }
140 [ # # ]: 0 : JL_CATCH {
141 [ # # ]: 0 : if (jl_typeis(jl_current_exception(), jl_errorexception_type))
142 : 0 : jl_error("could not evaluate cfunction argument type (it might depend on a local variable)");
143 : : else
144 : 0 : jl_rethrow();
145 : : }
146 : 117 : jl_exprargset(e, 3, at);
147 : : }
148 : 117 : check_c_types("cfunction method definition", rt, at);
149 [ - + ]: 117 : JL_TYPECHK(cfunction method definition, quotenode, jl_exprarg(e, 4));
150 [ - + ]: 117 : JL_TYPECHK(cfunction method definition, symbol, *(jl_value_t**)jl_exprarg(e, 4));
151 : 117 : return expr;
152 : : }
153 [ + + ]: 1204320 : if (e->head == jl_foreigncall_sym) {
154 [ - + ]: 3047 : JL_NARGSV(ccall method definition, 5); // (fptr, rt, at, nreq, (cc, effects))
155 : 3047 : jl_value_t *rt = jl_exprarg(e, 1);
156 : 3047 : jl_value_t *at = jl_exprarg(e, 2);
157 [ + + ]: 3047 : if (!jl_is_type(rt)) {
158 [ + - + + ]: 6070 : JL_TRY {
159 : 3035 : rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals);
160 : : }
161 [ # # ]: 0 : JL_CATCH {
162 [ # # ]: 0 : if (jl_typeis(jl_current_exception(), jl_errorexception_type))
163 : 0 : jl_error("could not evaluate ccall return type (it might depend on a local variable)");
164 : : else
165 : 0 : jl_rethrow();
166 : : }
167 : 3035 : jl_exprargset(e, 1, rt);
168 : : }
169 [ + + ]: 3047 : if (!jl_is_svec(at)) {
170 [ + - + + ]: 6092 : JL_TRY {
171 : 3046 : at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals);
172 : : }
173 [ # # ]: 0 : JL_CATCH {
174 [ # # ]: 0 : if (jl_typeis(jl_current_exception(), jl_errorexception_type))
175 : 0 : jl_error("could not evaluate ccall argument type (it might depend on a local variable)");
176 : : else
177 : 0 : jl_rethrow();
178 : : }
179 : 3046 : jl_exprargset(e, 2, at);
180 : : }
181 : 3047 : check_c_types("ccall method definition", rt, at);
182 [ - + ]: 3047 : JL_TYPECHK(ccall method definition, long, jl_exprarg(e, 3));
183 [ - + ]: 3047 : JL_TYPECHK(ccall method definition, quotenode, jl_exprarg(e, 4));
184 : 3047 : jl_value_t *cc = jl_quotenode_value(jl_exprarg(e, 4));
185 [ + + ]: 3047 : if (!jl_is_symbol(cc)) {
186 [ - + ]: 2 : JL_TYPECHK(ccall method definition, tuple, cc);
187 [ - + ]: 2 : if (jl_nfields(cc) != 2) {
188 : 0 : jl_error("In ccall calling convention, expected two argument tuple or symbol.");
189 : : }
190 [ - + ]: 2 : JL_TYPECHK(ccall method definition, symbol, jl_get_nth_field(cc, 0));
191 [ - + ]: 2 : JL_TYPECHK(ccall method definition, uint8, jl_get_nth_field(cc, 1));
192 : : }
193 : 3047 : jl_exprargset(e, 0, resolve_globals(jl_exprarg(e, 0), module, sparam_vals, binding_effects, 1));
194 : 3047 : i++;
195 : : }
196 [ + + - + ]: 1204320 : if (e->head == jl_method_sym || e->head == jl_module_sym) {
197 : 365 : i++;
198 : : }
199 [ + + ]: 4547590 : for (; i < nargs; i++) {
200 : : // TODO: this should be making a copy, not mutating the source
201 : 3343270 : jl_exprargset(e, i, resolve_globals(jl_exprarg(e, i), module, sparam_vals, binding_effects, eager_resolve));
202 : : }
203 [ + + + + ]: 1204320 : if (e->head == jl_call_sym && jl_expr_nargs(e) == 3 &&
204 [ + + ]: 455684 : jl_is_globalref(jl_exprarg(e, 0)) &&
205 [ + + ]: 429630 : jl_is_globalref(jl_exprarg(e, 1)) &&
206 [ + + ]: 82193 : jl_is_quotenode(jl_exprarg(e, 2))) {
207 : : // replace module_expr.sym with GlobalRef(module, sym)
208 : : // for expressions pattern-matching to `getproperty(module_expr, :sym)` in a top-module
209 : : // (this is expected to help inference performance)
210 : : // TODO: this was broken by linear-IR
211 : 35856 : jl_value_t *s = jl_fieldref(jl_exprarg(e, 2), 0);
212 : 35856 : jl_value_t *me = jl_exprarg(e, 1);
213 : 35856 : jl_value_t *fe = jl_exprarg(e, 0);
214 : 35856 : jl_module_t *fe_mod = jl_globalref_mod(fe);
215 : 35856 : jl_sym_t *fe_sym = jl_globalref_name(fe);
216 : 35856 : jl_module_t *me_mod = jl_globalref_mod(me);
217 : 35856 : jl_sym_t *me_sym = jl_globalref_name(me);
218 [ + + + + : 35856 : if (fe_mod->istopmod && !strcmp(jl_symbol_name(fe_sym), "getproperty") && jl_is_symbol(s)) {
+ - ]
219 [ + - + + ]: 35637 : if (eager_resolve || jl_binding_resolved_p(me_mod, me_sym)) {
220 : 34056 : jl_binding_t *b = jl_get_binding(me_mod, me_sym);
221 [ + - + + ]: 34056 : if (b && b->constp) {
222 : 34046 : jl_value_t *v = jl_atomic_load_relaxed(&b->value);
223 [ + - + + ]: 34046 : if (v && jl_is_module(v))
224 : 33941 : return jl_module_globalref((jl_module_t*)v, (jl_sym_t*)s);
225 : : }
226 : : }
227 : : }
228 : : }
229 [ + + + - ]: 1170380 : if (e->head == jl_call_sym && nargs > 0 &&
230 [ + + ]: 825436 : jl_is_globalref(jl_exprarg(e, 0))) {
231 : : // TODO: this hack should be deleted once llvmcall is fixed
232 : 743257 : jl_value_t *fe = jl_exprarg(e, 0);
233 : 743257 : jl_module_t *fe_mod = jl_globalref_mod(fe);
234 : 743257 : jl_sym_t *fe_sym = jl_globalref_name(fe);
235 [ + + ]: 743257 : if (jl_binding_resolved_p(fe_mod, fe_sym)) {
236 : : // look at some known called functions
237 : 669359 : jl_binding_t *b = jl_get_binding(fe_mod, fe_sym);
238 [ + - + + : 669359 : if (b && b->constp && jl_atomic_load_relaxed(&b->value) == jl_builtin_tuple) {
+ + ]
239 : : size_t j;
240 [ + + ]: 53445 : for (j = 1; j < nargs; j++) {
241 [ + + ]: 45463 : if (!jl_is_quotenode(jl_exprarg(e, j)))
242 : 35153 : break;
243 : : }
244 [ + + ]: 43135 : if (j == nargs) {
245 : 7982 : jl_value_t *val = NULL;
246 [ + - + + ]: 15964 : JL_TRY {
247 : 7982 : val = jl_interpret_toplevel_expr_in(module, (jl_value_t*)e, NULL, sparam_vals);
248 : : }
249 [ # # ]: 0 : JL_CATCH {
250 : : }
251 [ + - ]: 7982 : if (val)
252 : 7982 : return val;
253 : : }
254 : : }
255 : : }
256 : : }
257 : : }
258 : : }
259 : 4415240 : return expr;
260 : : }
261 : :
262 : 7435 : JL_DLLEXPORT void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *sparam_vals,
263 : : int binding_effects)
264 : : {
265 : 7435 : size_t i, l = jl_array_len(stmts);
266 [ + + ]: 641544 : for (i = 0; i < l; i++) {
267 : 634109 : jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
268 : 634109 : jl_array_ptr_set(stmts, i, resolve_globals(stmt, m, sparam_vals, binding_effects, 0));
269 : : }
270 : 7435 : }
271 : :
272 : 4780 : jl_value_t *expr_arg1(jl_value_t *expr) {
273 : 4780 : jl_array_t *args = ((jl_expr_t*)expr)->args;
274 : 4780 : return jl_array_ptr_ref(args, 0);
275 : : }
276 : :
277 : : // copy a :lambda Expr into its CodeInfo representation,
278 : : // including popping of known meta nodes
279 : 232609 : static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
280 : : {
281 [ - + ]: 232609 : assert(jl_is_expr(ir));
282 : 232609 : jl_expr_t *bodyex = (jl_expr_t*)jl_exprarg(ir, 2);
283 : 232609 : jl_value_t *codelocs = jl_exprarg(ir, 3);
284 : 232609 : li->linetable = jl_exprarg(ir, 4);
285 : 232609 : size_t nlocs = jl_array_len(codelocs);
286 : 232609 : li->codelocs = (jl_value_t*)jl_alloc_array_1d(jl_array_int32_type, nlocs);
287 : : size_t j;
288 [ + + ]: 4270290 : for (j = 0; j < nlocs; j++) {
289 : 4037680 : jl_arrayset((jl_array_t*)li->codelocs, jl_box_int32(jl_unbox_long(jl_arrayref((jl_array_t*)codelocs, j))),
290 : : j);
291 : : }
292 [ - + ]: 232615 : assert(jl_is_expr(bodyex));
293 : 232615 : jl_array_t *body = bodyex->args;
294 : 232615 : li->code = body;
295 : 232615 : jl_gc_wb(li, li->code);
296 : 232615 : size_t n = jl_array_len(body);
297 : 232615 : jl_value_t **bd = (jl_value_t**)jl_array_ptr_data((jl_array_t*)li->code);
298 : 232615 : li->ssaflags = jl_alloc_array_1d(jl_array_uint8_type, n);
299 : 232622 : jl_gc_wb(li, li->ssaflags);
300 : 232622 : int inbounds_depth = 0; // number of stacked inbounds
301 : : // isempty(inline_flags): no user annotation
302 : : // last(inline_flags) == 1: inline region
303 : : // last(inline_flags) == 0: noinline region
304 : 232622 : arraylist_t *inline_flags = arraylist_new((arraylist_t*)malloc_s(sizeof(arraylist_t)), 0);
305 [ + + ]: 4270310 : for (j = 0; j < n; j++) {
306 : 4037700 : jl_value_t *st = bd[j];
307 : 4037700 : int is_flag_stmt = 0;
308 : : // check :meta expression
309 [ + + + + ]: 4049310 : if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_meta_sym) {
310 : 11609 : size_t k, ins = 0, na = jl_expr_nargs(st);
311 : 11609 : jl_array_t *meta = ((jl_expr_t*)st)->args;
312 [ + + ]: 28354 : for (k = 0; k < na; k++) {
313 : 16745 : jl_value_t *ma = jl_array_ptr_ref(meta, k);
314 [ + + ]: 16745 : if (ma == (jl_value_t*)jl_pure_sym)
315 : 15 : li->pure = 1;
316 [ + + ]: 16730 : else if (ma == (jl_value_t*)jl_inline_sym)
317 : 5819 : li->inlineable = 1;
318 [ + + ]: 10911 : else if (ma == (jl_value_t*)jl_propagate_inbounds_sym)
319 : 414 : li->propagate_inbounds = 1;
320 [ + + ]: 10497 : else if (ma == (jl_value_t*)jl_aggressive_constprop_sym)
321 : 43 : li->constprop = 1;
322 [ + + ]: 10454 : else if (ma == (jl_value_t*)jl_no_constprop_sym)
323 : 43 : li->constprop = 2;
324 [ + + + + ]: 10411 : else if (jl_is_expr(ma) && ((jl_expr_t*)ma)->head == jl_purity_sym) {
325 [ + - ]: 122 : if (jl_expr_nargs(ma) == 6) {
326 : 122 : li->purity.overrides.ipo_consistent = jl_unbox_bool(jl_exprarg(ma, 0));
327 : 122 : li->purity.overrides.ipo_effect_free = jl_unbox_bool(jl_exprarg(ma, 1));
328 : 122 : li->purity.overrides.ipo_nothrow = jl_unbox_bool(jl_exprarg(ma, 2));
329 : 122 : li->purity.overrides.ipo_terminates = jl_unbox_bool(jl_exprarg(ma, 3));
330 : 122 : li->purity.overrides.ipo_terminates_locally = jl_unbox_bool(jl_exprarg(ma, 4));
331 : 122 : li->purity.overrides.ipo_notaskstate = jl_unbox_bool(jl_exprarg(ma, 5));
332 : : }
333 : : }
334 : : else
335 : 10289 : jl_array_ptr_set(meta, ins++, ma);
336 : : }
337 [ + + ]: 11609 : if (ins == 0)
338 : 6122 : bd[j] = jl_nothing;
339 : : else
340 : 5487 : jl_array_del_end(meta, na - ins);
341 : : }
342 : : // check other flag expressions
343 [ + + + + ]: 4026100 : else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_inbounds_sym) {
344 : 4700 : is_flag_stmt = 1;
345 : 4700 : jl_value_t *arg1 = expr_arg1(st);
346 [ + + ]: 4700 : if (arg1 == (jl_value_t*)jl_true) // push
347 : 2350 : inbounds_depth += 1;
348 [ - + ]: 2350 : else if (arg1 == (jl_value_t*)jl_false) // clear
349 : 0 : inbounds_depth = 0;
350 [ + - ]: 2350 : else if (inbounds_depth > 0) // pop
351 : 2350 : inbounds_depth -= 1;
352 : 4700 : bd[j] = jl_nothing;
353 : : }
354 [ + + + + ]: 4021400 : else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_inline_sym) {
355 : 50 : is_flag_stmt = 1;
356 : 50 : jl_value_t *arg1 = expr_arg1(st);
357 [ + + ]: 50 : if (arg1 == (jl_value_t*)jl_true) // enter inline region
358 : 25 : arraylist_push(inline_flags, (void*)1);
359 : : else { // exit inline region
360 [ - + ]: 25 : assert(arg1 == (jl_value_t*)jl_false);
361 : 25 : arraylist_pop(inline_flags);
362 : : }
363 : 50 : bd[j] = jl_nothing;
364 : : }
365 [ + + + + ]: 4021340 : else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_noinline_sym) {
366 : 30 : is_flag_stmt = 1;
367 : 30 : jl_value_t *arg1 = expr_arg1(st);
368 [ + + ]: 30 : if (arg1 == (jl_value_t*)jl_true) // enter noinline region
369 : 15 : arraylist_push(inline_flags, (void*)0);
370 : : else { // exit noinline region
371 [ - + ]: 15 : assert(arg1 == (jl_value_t*)jl_false);
372 : 15 : arraylist_pop(inline_flags);
373 : : }
374 : 30 : bd[j] = jl_nothing;
375 : : }
376 [ + + + + ]: 4021320 : else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_return_sym) {
377 : 251789 : jl_array_ptr_set(body, j, jl_new_struct(jl_returnnode_type, jl_exprarg(st, 0)));
378 : : }
379 : :
380 [ + + ]: 4037690 : if (is_flag_stmt)
381 : 4780 : jl_array_uint8_set(li->ssaflags, j, 0);
382 : : else {
383 : 4032910 : uint8_t flag = 0;
384 [ + + ]: 4032910 : if (inbounds_depth > 0)
385 : 58348 : flag |= 1 << 0;
386 [ + + ]: 4032910 : if (inline_flags->len > 0) {
387 : 66 : void* inline_flag = inline_flags->items[inline_flags->len - 1];
388 [ + + ]: 66 : flag |= 1 << (inline_flag ? 1 : 2);
389 : : }
390 : 4032910 : jl_array_uint8_set(li->ssaflags, j, flag);
391 : : }
392 : : }
393 [ - + ]: 232610 : assert(inline_flags->len == 0); // malformed otherwise
394 : 232610 : arraylist_free(inline_flags);
395 : 232610 : free(inline_flags);
396 : 232610 : jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ir, 1);
397 : 232610 : jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0);
398 : 232608 : size_t nslots = jl_array_len(vis);
399 : 232608 : jl_value_t *ssavalue_types = jl_array_ptr_ref(vinfo, 2);
400 [ - + ]: 232609 : assert(jl_is_long(ssavalue_types));
401 : 232609 : size_t nssavalue = jl_unbox_long(ssavalue_types);
402 : 232610 : li->slotnames = jl_alloc_array_1d(jl_array_symbol_type, nslots);
403 : 232622 : jl_gc_wb(li, li->slotnames);
404 : 232622 : li->slotflags = jl_alloc_array_1d(jl_array_uint8_type, nslots);
405 : 232622 : jl_gc_wb(li, li->slotflags);
406 : 232622 : li->ssavaluetypes = jl_box_long(nssavalue);
407 : 232622 : jl_gc_wb(li, li->ssavaluetypes);
408 : :
409 : : // Flags that need to be copied to slotflags
410 : 232621 : const uint8_t vinfo_mask = 8 | 16 | 32 | 64;
411 : : int i;
412 [ + + ]: 809148 : for (i = 0; i < nslots; i++) {
413 : 576526 : jl_value_t *vi = jl_array_ptr_ref(vis, i);
414 : 576526 : jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(vi, 0);
415 [ - + ]: 576526 : assert(jl_is_symbol(name));
416 : 576526 : char *str = jl_symbol_name(name);
417 [ + + + + ]: 576526 : if (i > 0 && name != jl_unused_sym) {
418 [ + + ]: 457596 : if (str[0] == '#') {
419 : : // convention for renamed variables: #...#original_name
420 : 283363 : char *nxt = strchr(str + 1, '#');
421 [ + + ]: 283363 : if (nxt)
422 : 142342 : name = jl_symbol(nxt+1);
423 [ + + ]: 141021 : else if (str[1] == 's') // compiler-generated temporaries, #sXXX
424 : 135819 : name = jl_empty_sym;
425 : : }
426 : : }
427 : 576526 : jl_array_ptr_set(li->slotnames, i, name);
428 : 576526 : jl_array_uint8_set(li->slotflags, i, vinfo_mask & jl_unbox_long(jl_array_ptr_ref(vi, 2)));
429 : : }
430 : 232622 : }
431 : :
432 : 2335590 : JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void)
433 : : {
434 : 2335590 : jl_task_t *ct = jl_current_task;
435 : : jl_method_instance_t *li =
436 : 2335590 : (jl_method_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_method_instance_t),
437 : : jl_method_instance_type);
438 : 2335590 : li->def.value = NULL;
439 : 2335590 : li->specTypes = NULL;
440 : 2335590 : li->sparam_vals = jl_emptysvec;
441 : 2335590 : li->uninferred = NULL;
442 : 2335590 : li->backedges = NULL;
443 : 2335590 : li->callbacks = NULL;
444 : 2335590 : jl_atomic_store_relaxed(&li->cache, NULL);
445 : 2335590 : li->inInference = 0;
446 : 2335590 : li->precompiled = 0;
447 : 2335590 : return li;
448 : : }
449 : :
450 : 14552400 : JL_DLLEXPORT jl_code_info_t *jl_new_code_info_uninit(void)
451 : : {
452 : 14552400 : jl_task_t *ct = jl_current_task;
453 : : jl_code_info_t *src =
454 : 14552400 : (jl_code_info_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_info_t),
455 : : jl_code_info_type);
456 : 14552400 : src->code = NULL;
457 : 14552400 : src->codelocs = NULL;
458 : 14552400 : src->ssavaluetypes = NULL;
459 : 14552400 : src->ssaflags = NULL;
460 : 14552400 : src->method_for_inference_limit_heuristics = jl_nothing;
461 : 14552400 : src->linetable = jl_nothing;
462 : 14552400 : src->slotflags = NULL;
463 : 14552400 : src->slotnames = NULL;
464 : 14552400 : src->slottypes = jl_nothing;
465 : 14552400 : src->parent = (jl_method_instance_t*)jl_nothing;
466 : 14552400 : src->rettype = (jl_value_t*)jl_any_type;
467 : 14552400 : src->min_world = 1;
468 : 14552400 : src->max_world = ~(size_t)0;
469 : 14552400 : src->inferred = 0;
470 : 14552400 : src->inlineable = 0;
471 : 14552400 : src->propagate_inbounds = 0;
472 : 14552400 : src->pure = 0;
473 : 14552400 : src->edges = jl_nothing;
474 : 14552400 : src->constprop = 0;
475 : 14552400 : src->purity.bits = 0;
476 : 14552400 : return src;
477 : : }
478 : :
479 : 232608 : jl_code_info_t *jl_new_code_info_from_ir(jl_expr_t *ir)
480 : : {
481 : 232608 : jl_code_info_t *src = NULL;
482 : 232608 : JL_GC_PUSH1(&src);
483 : 232608 : src = jl_new_code_info_uninit();
484 : 232609 : jl_code_info_set_ir(src, ir);
485 : 232610 : JL_GC_POP();
486 : 232610 : return src;
487 : : }
488 : :
489 : 76107 : void jl_add_function_name_to_lineinfo(jl_code_info_t *ci, jl_value_t *name)
490 : : {
491 : 76107 : jl_array_t *li = (jl_array_t*)ci->linetable;
492 : 76107 : size_t i, n = jl_array_len(li);
493 : 76107 : jl_value_t *rt = NULL, *lno = NULL, *inl = NULL;
494 : 76107 : JL_GC_PUSH3(&rt, &lno, &inl);
495 [ + + ]: 315418 : for (i = 0; i < n; i++) {
496 : 239311 : jl_value_t *ln = jl_array_ptr_ref(li, i);
497 [ - + ]: 239311 : assert(jl_typeis(ln, jl_lineinfonode_type));
498 : 239311 : jl_value_t *mod = jl_fieldref_noalloc(ln, 0);
499 : 239311 : jl_value_t *file = jl_fieldref_noalloc(ln, 2);
500 : 239311 : lno = jl_fieldref(ln, 3);
501 : 239311 : inl = jl_fieldref(ln, 4);
502 [ + - + + ]: 239311 : jl_value_t *ln_name = (jl_is_int32(inl) && jl_unbox_int32(inl) == 0) ? name : jl_fieldref_noalloc(ln, 1);
503 : 239311 : rt = jl_new_struct(jl_lineinfonode_type, mod, ln_name, file, lno, inl);
504 : 239311 : jl_array_ptr_set(li, i, rt);
505 : : }
506 : 76107 : JL_GC_POP();
507 : 76107 : }
508 : :
509 : : // invoke (compiling if necessary) the jlcall function pointer for a method template
510 : 6317 : STATIC_INLINE jl_value_t *jl_call_staged(jl_method_t *def, jl_value_t *generator, jl_svec_t *sparam_vals,
511 : : jl_value_t **args, uint32_t nargs)
512 : : {
513 : 6317 : size_t n_sparams = jl_svec_len(sparam_vals);
514 : : jl_value_t **gargs;
515 : 6317 : size_t totargs = 1 + n_sparams + nargs + def->isva;
516 : 6317 : JL_GC_PUSHARGS(gargs, totargs);
517 : 6317 : gargs[0] = generator;
518 : 6317 : memcpy(&gargs[1], jl_svec_data(sparam_vals), n_sparams * sizeof(void*));
519 : 6317 : memcpy(&gargs[1 + n_sparams], args, nargs * sizeof(void*));
520 [ + + ]: 6317 : if (def->isva) {
521 : 725 : gargs[totargs-1] = jl_f_tuple(NULL, &gargs[1 + n_sparams + def->nargs - 1], nargs - (def->nargs - 1));
522 : 725 : gargs[1 + n_sparams + def->nargs - 1] = gargs[totargs - 1];
523 : : }
524 : 6317 : jl_value_t *code = jl_apply(gargs, 1 + n_sparams + def->nargs);
525 : 6283 : JL_GC_POP();
526 : 6283 : return code;
527 : : }
528 : :
529 : : // Lower `ex` into Julia IR, and (if it expands into a CodeInfo) resolve global-variable
530 : : // references in light of the provided type parameters.
531 : : // Like `jl_expand`, if there is an error expanding the provided expression, the return value
532 : : // will be an error expression (an `Expr` with `error_sym` as its head), which should be eval'd
533 : : // in the caller's context.
534 : 6015 : JL_DLLEXPORT jl_code_info_t *jl_expand_and_resolve(jl_value_t *ex, jl_module_t *module,
535 : : jl_svec_t *sparam_vals) {
536 : 6015 : jl_code_info_t *func = (jl_code_info_t*)jl_expand((jl_value_t*)ex, module);
537 : 6014 : JL_GC_PUSH1(&func);
538 [ + + ]: 6014 : if (jl_is_code_info(func)) {
539 : 6008 : jl_array_t *stmts = (jl_array_t*)func->code;
540 : 6008 : jl_resolve_globals_in_ir(stmts, module, sparam_vals, 1);
541 : : }
542 : 6014 : JL_GC_POP();
543 : 6014 : return func;
544 : : }
545 : :
546 : : // Return a newly allocated CodeInfo for the function signature
547 : : // effectively described by the tuple (specTypes, env, Method) inside linfo
548 : 6317 : JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo)
549 : : {
550 [ - + ]: 6317 : if (linfo->uninferred) {
551 : 0 : return (jl_code_info_t*)jl_copy_ast((jl_value_t*)linfo->uninferred);
552 : : }
553 : :
554 : : JL_TIMING(STAGED_FUNCTION);
555 : 6317 : jl_value_t *tt = linfo->specTypes;
556 : 6317 : jl_method_t *def = linfo->def.method;
557 : 6317 : jl_value_t *generator = def->generator;
558 [ - + ]: 6317 : assert(generator != NULL);
559 [ - + ]: 6317 : assert(jl_is_method(def));
560 : 6317 : jl_code_info_t *func = NULL;
561 : 6317 : jl_value_t *ex = NULL;
562 : 6317 : JL_GC_PUSH2(&ex, &func);
563 : 6317 : jl_task_t *ct = jl_current_task;
564 : 6317 : int last_lineno = jl_lineno;
565 : 6317 : int last_in = ct->ptls->in_pure_callback;
566 : 6317 : size_t last_age = ct->world_age;
567 : :
568 [ + + + + ]: 12593 : JL_TRY {
569 : 6317 : ct->ptls->in_pure_callback = 1;
570 : : // and the right world
571 : 6317 : ct->world_age = def->primary_world;
572 : :
573 : : // invoke code generator
574 : 6317 : jl_tupletype_t *ttdt = (jl_tupletype_t*)jl_unwrap_unionall(tt);
575 : 6317 : ex = jl_call_staged(def, generator, linfo->sparam_vals, jl_svec_data(ttdt->parameters), jl_nparams(ttdt));
576 : :
577 [ + + ]: 6283 : if (jl_is_code_info(ex)) {
578 : 268 : func = (jl_code_info_t*)ex;
579 : 268 : jl_array_t *stmts = (jl_array_t*)func->code;
580 : 268 : jl_resolve_globals_in_ir(stmts, def->module, linfo->sparam_vals, 1);
581 : : }
582 : : else {
583 : : // Lower the user's expression and resolve references to the type parameters
584 : 6015 : func = jl_expand_and_resolve(ex, def->module, linfo->sparam_vals);
585 : :
586 [ + + ]: 6014 : if (!jl_is_code_info(func)) {
587 [ + - + + ]: 6 : if (jl_is_expr(func) && ((jl_expr_t*)func)->head == jl_error_sym) {
588 : 2 : ct->ptls->in_pure_callback = 0;
589 : 2 : jl_toplevel_eval(def->module, (jl_value_t*)func);
590 : : }
591 : 4 : jl_error("The function body AST defined by this @generated function is not pure. This likely means it contains a closure, a comprehension or a generator.");
592 : : }
593 : : }
594 : :
595 : : // If this generated function has an opaque closure, cache it for
596 : : // correctness of method identity
597 [ + + ]: 153577 : for (int i = 0; i < jl_array_len(func->code); ++i) {
598 : 147302 : jl_value_t *stmt = jl_array_ptr_ref(func->code, i);
599 [ + + + + ]: 147302 : if (jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == jl_new_opaque_closure_sym) {
600 : 1 : linfo->uninferred = jl_copy_ast((jl_value_t*)func);
601 : 1 : jl_gc_wb(linfo, linfo->uninferred);
602 : 1 : break;
603 : : }
604 : : }
605 : :
606 : 6276 : ct->ptls->in_pure_callback = last_in;
607 : 6276 : jl_lineno = last_lineno;
608 : 6276 : ct->world_age = last_age;
609 : 6276 : jl_add_function_name_to_lineinfo(func, (jl_value_t*)def->name);
610 : : }
611 [ + - ]: 41 : JL_CATCH {
612 : 41 : ct->ptls->in_pure_callback = last_in;
613 : 41 : jl_lineno = last_lineno;
614 : 41 : jl_rethrow();
615 : : }
616 : 6276 : JL_GC_POP();
617 : 6276 : return func;
618 : : }
619 : :
620 : 5281070 : JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src)
621 : : {
622 : 5281070 : jl_task_t *ct = jl_current_task;
623 : : jl_code_info_t *newsrc =
624 : 5281070 : (jl_code_info_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_info_t),
625 : : jl_code_info_type);
626 : 5281070 : *newsrc = *src;
627 : 5281070 : return newsrc;
628 : : }
629 : :
630 : : // return a new lambda-info that has some extra static parameters merged in
631 : 2334450 : jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp)
632 : : {
633 [ + + - + ]: 2334450 : assert((size_t)jl_subtype_env_size(m->sig) == jl_svec_len(sp) || sp == jl_emptysvec);
634 : 2334450 : jl_method_instance_t *new_linfo = jl_new_method_instance_uninit();
635 : 2334450 : new_linfo->def.method = m;
636 : 2334450 : new_linfo->specTypes = types;
637 : 2334450 : new_linfo->sparam_vals = sp;
638 : 2334450 : return new_linfo;
639 : : }
640 : :
641 : 69831 : static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src)
642 : : {
643 : : uint8_t j;
644 : 69831 : uint8_t called = 0;
645 : 69831 : int gen_only = 0;
646 [ + + + + ]: 174322 : for (j = 1; j < m->nargs && j <= sizeof(m->nospecialize) * 8; j++) {
647 : 104491 : jl_value_t *ai = jl_array_ptr_ref(src->slotnames, j);
648 [ + + ]: 104491 : if (ai == (jl_value_t*)jl_unused_sym) {
649 : : // TODO: enable this. currently it triggers a bug on arguments like
650 : : // ::Type{>:Missing}
651 : : //int sn = j-1;
652 : : //m->nospecialize |= (1 << sn);
653 : 7113 : continue;
654 : : }
655 [ + + ]: 97378 : if (j <= 8) {
656 [ + + ]: 96328 : if (jl_array_uint8_ref(src->slotflags, j) & 64)
657 : 657 : called |= (1 << (j - 1));
658 : : }
659 : : }
660 : 69831 : m->called = called;
661 : 69831 : m->pure = src->pure;
662 : 69831 : m->constprop = src->constprop;
663 : 69831 : m->purity.bits = src->purity.bits;
664 : 69831 : jl_add_function_name_to_lineinfo(src, (jl_value_t*)m->name);
665 : :
666 : 69831 : jl_array_t *copy = NULL;
667 : 69831 : jl_svec_t *sparam_vars = jl_outer_unionall_vars(m->sig);
668 : 69831 : JL_GC_PUSH3(©, &sparam_vars, &src);
669 [ - + ]: 69831 : assert(jl_typeis(src->code, jl_array_any_type));
670 : 69831 : jl_array_t *stmts = (jl_array_t*)src->code;
671 : 69831 : size_t i, n = jl_array_len(stmts);
672 : 69831 : copy = jl_alloc_vec_any(n);
673 [ + + ]: 937743 : for (i = 0; i < n; i++) {
674 : 867912 : jl_value_t *st = jl_array_ptr_ref(stmts, i);
675 [ + + + + ]: 873156 : if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_meta_sym) {
676 : 5244 : size_t nargs = jl_expr_nargs(st);
677 [ + - + + ]: 5244 : if (nargs >= 1 && jl_exprarg(st, 0) == (jl_value_t*)jl_nospecialize_sym) {
678 [ + + ]: 2161 : if (nargs == 1) // bare `@nospecialize` is special: it prevents specialization on all args
679 : 64 : m->nospecialize = -1;
680 : : size_t j;
681 [ + + ]: 4493 : for (j = 1; j < nargs; j++) {
682 : 2332 : jl_value_t *aj = jl_exprarg(st, j);
683 [ + + + - : 2332 : if (!jl_is_slot(aj) && !jl_is_argument(aj))
+ - ]
684 : 73 : continue;
685 : 2259 : int sn = (int)jl_slot_number(aj) - 2;
686 [ - + ]: 2259 : if (sn < 0) // @nospecialize on self is valid but currently ignored
687 : 0 : continue;
688 [ - + ]: 2259 : if (sn > (m->nargs - 2)) {
689 : 0 : jl_error("@nospecialize annotation applied to a non-argument");
690 : : }
691 [ - + ]: 2259 : if (sn >= sizeof(m->nospecialize) * 8) {
692 : 0 : jl_printf(JL_STDERR,
693 : : "WARNING: @nospecialize annotation only supported on the first %d arguments.\n",
694 : : (int)(sizeof(m->nospecialize) * 8));
695 : 0 : continue;
696 : : }
697 : 2259 : m->nospecialize |= (1 << sn);
698 : : }
699 : 2161 : st = jl_nothing;
700 : : }
701 [ + - + + ]: 3083 : else if (nargs >= 1 && jl_exprarg(st, 0) == (jl_value_t*)jl_specialize_sym) {
702 [ - + ]: 3 : if (nargs == 1) // bare `@specialize` is special: it causes specialization on all args
703 : 0 : m->nospecialize = 0;
704 : 3 : st = jl_nothing;
705 : : }
706 [ + + + + ]: 3080 : else if (nargs == 2 && jl_exprarg(st, 0) == (jl_value_t*)jl_generated_sym) {
707 : 88 : m->generator = NULL;
708 : 88 : jl_value_t *gexpr = jl_exprarg(st, 1);
709 [ + - ]: 88 : if (jl_expr_nargs(gexpr) == 7) {
710 : : // expects (new (core GeneratedFunctionStub) funcname argnames sp line file expandearly)
711 : 88 : jl_value_t *funcname = jl_exprarg(gexpr, 1);
712 [ - + ]: 88 : assert(jl_is_symbol(funcname));
713 [ + - ]: 88 : if (jl_get_global(m->module, (jl_sym_t*)funcname) != NULL) {
714 : 88 : m->generator = jl_toplevel_eval(m->module, gexpr);
715 : 88 : jl_gc_wb(m, m->generator);
716 : : }
717 : : }
718 [ - + ]: 88 : if (m->generator == NULL) {
719 : 0 : jl_error("invalid @generated function; try placing it in global scope");
720 : : }
721 : 88 : st = jl_nothing;
722 : : }
723 [ + + + + ]: 2992 : else if (nargs == 1 && jl_exprarg(st, 0) == (jl_value_t*)jl_generated_only_sym) {
724 : 74 : gen_only = 1;
725 : 74 : st = jl_nothing;
726 : : }
727 [ + + + - ]: 2918 : else if (nargs == 2 && jl_exprarg(st, 0) == (jl_value_t*)jl_symbol("nkw")) {
728 : 2285 : m->nkw = jl_unbox_long(jl_exprarg(st, 1));
729 : 2285 : st = jl_nothing;
730 : : }
731 : : }
732 : : else {
733 : 862668 : st = resolve_globals(st, m->module, sparam_vars, 1, 0);
734 : : }
735 : 867912 : jl_array_ptr_set(copy, i, st);
736 : : }
737 : 69831 : src = jl_copy_code_info(src);
738 : 69831 : src->code = copy;
739 : 69831 : jl_gc_wb(src, copy);
740 : 69831 : m->slot_syms = jl_compress_argnames(src->slotnames);
741 : 69831 : jl_gc_wb(m, m->slot_syms);
742 [ + + ]: 69831 : if (gen_only)
743 : 74 : m->source = NULL;
744 : : else
745 : 69757 : m->source = (jl_value_t*)jl_compress_ir(m, src);
746 : 69831 : jl_gc_wb(m, m->source);
747 : 69831 : JL_GC_POP();
748 : 69831 : }
749 : :
750 : 70251 : JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module)
751 : : {
752 : 70251 : jl_task_t *ct = jl_current_task;
753 : : jl_method_t *m =
754 : 70251 : (jl_method_t*)jl_gc_alloc(ct->ptls, sizeof(jl_method_t), jl_method_type);
755 : 70251 : jl_atomic_store_relaxed(&m->specializations, jl_emptysvec);
756 : 70251 : jl_atomic_store_relaxed(&m->speckeyset, (jl_array_t*)jl_an_empty_vec_any);
757 : 70251 : m->sig = NULL;
758 : 70251 : m->slot_syms = NULL;
759 : 70251 : m->roots = NULL;
760 : 70251 : m->root_blocks = NULL;
761 : 70251 : m->nroots_sysimg = 0;
762 : 70251 : m->ccallable = NULL;
763 : 70251 : m->module = module;
764 : 70251 : m->external_mt = NULL;
765 : 70251 : m->source = NULL;
766 : 70251 : jl_atomic_store_relaxed(&m->unspecialized, NULL);
767 : 70251 : m->generator = NULL;
768 : 70251 : m->name = NULL;
769 : 70251 : m->file = jl_empty_sym;
770 : 70251 : m->line = 0;
771 : 70251 : m->called = 0xff;
772 : 70251 : m->nospecialize = module->nospecialize;
773 : 70251 : m->nkw = 0;
774 : 70251 : jl_atomic_store_relaxed(&m->invokes, jl_nothing);
775 : 70251 : m->recursion_relation = NULL;
776 : 70251 : m->isva = 0;
777 : 70251 : m->nargs = 0;
778 : 70251 : m->primary_world = 1;
779 : 70251 : m->deleted_world = ~(size_t)0;
780 : 70251 : m->is_for_opaque_closure = 0;
781 : 70251 : m->constprop = 0;
782 : 70251 : JL_MUTEX_INIT(&m->writelock);
783 : 70251 : return m;
784 : : }
785 : :
786 : : // method definition ----------------------------------------------------------
787 : :
788 : 52 : jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name,
789 : : int nargs, jl_value_t *functionloc, jl_code_info_t *ci, int isva)
790 : : {
791 : 52 : jl_method_t *m = jl_new_method_uninit(module);
792 : 52 : JL_GC_PUSH1(&m);
793 : : // TODO: Maybe have a signature of (parent method, stmt#)?
794 : 52 : m->sig = (jl_value_t*)jl_anytuple_type;
795 : 52 : m->isva = isva;
796 : 52 : m->is_for_opaque_closure = 1;
797 [ + - ]: 52 : if (name == jl_nothing) {
798 : 52 : m->name = jl_symbol("opaque closure");
799 : : } else {
800 [ # # ]: 0 : assert(jl_is_symbol(name));
801 : 0 : m->name = (jl_sym_t*)name;
802 : : }
803 : 52 : m->nargs = nargs + 1;
804 [ - + ]: 52 : assert(jl_is_linenode(functionloc));
805 : 52 : jl_value_t *file = jl_linenode_file(functionloc);
806 [ + + ]: 52 : m->file = jl_is_symbol(file) ? (jl_sym_t*)file : jl_empty_sym;
807 : 52 : m->line = jl_linenode_line(functionloc);
808 : 52 : jl_method_set_source(m, ci);
809 : 52 : JL_GC_POP();
810 : 52 : return m;
811 : : }
812 : :
813 : : // empty generic function def
814 : 71473 : JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name,
815 : : jl_module_t *module,
816 : : _Atomic(jl_value_t*) *bp,
817 : : jl_value_t *bp_owner,
818 : : jl_binding_t *bnd)
819 : : {
820 : 71473 : jl_value_t *gf = NULL;
821 : :
822 [ + - + - ]: 71473 : assert(name && bp);
823 [ + - + + : 71473 : if (bnd && jl_atomic_load_relaxed(&bnd->value) != NULL && !bnd->constp)
- + ]
824 : 0 : jl_errorf("cannot define function %s; it already has a value", jl_symbol_name(bnd->name));
825 : 71473 : gf = jl_atomic_load_relaxed(bp);
826 [ + + ]: 71473 : if (gf != NULL) {
827 [ + + - + ]: 56450 : if (!jl_is_datatype_singleton((jl_datatype_t*)jl_typeof(gf)) && !jl_is_type(gf))
828 : 0 : jl_errorf("cannot define function %s; it already has a value", jl_symbol_name(name));
829 : : }
830 [ + - ]: 71473 : if (bnd)
831 : 71473 : bnd->constp = 1;
832 [ + + ]: 71473 : if (gf == NULL) {
833 : 15023 : gf = (jl_value_t*)jl_new_generic_function(name, module);
834 : 15023 : jl_atomic_store(bp, gf); // TODO: fix constp assignment data race
835 [ + - ]: 15023 : if (bp_owner) jl_gc_wb(bp_owner, gf);
836 : : }
837 : 71473 : return gf;
838 : : }
839 : :
840 : 139591000 : static jl_methtable_t *first_methtable(jl_value_t *a JL_PROPAGATES_ROOT, int got_tuple1) JL_NOTSAFEPOINT
841 : : {
842 [ + + ]: 139591000 : if (jl_is_datatype(a)) {
843 [ + + ]: 139007000 : if (got_tuple1) {
844 : 69602200 : jl_methtable_t *mt = ((jl_datatype_t*)a)->name->mt;
845 [ + + ]: 69602200 : if (mt != NULL)
846 : 69601900 : return mt;
847 : : }
848 [ + + ]: 69404700 : if (jl_is_tuple_type(a)) {
849 [ + - ]: 69404300 : if (jl_nparams(a) >= 1)
850 : 69404300 : return first_methtable(jl_tparam0(a), 1);
851 : : }
852 : : }
853 [ - + ]: 584028 : else if (jl_is_typevar(a)) {
854 : 0 : return first_methtable(((jl_tvar_t*)a)->ub, got_tuple1);
855 : : }
856 [ + + ]: 584028 : else if (jl_is_unionall(a)) {
857 : 584002 : return first_methtable(((jl_unionall_t*)a)->body, got_tuple1);
858 : : }
859 [ + + ]: 26 : else if (jl_is_uniontype(a)) {
860 : 25 : jl_uniontype_t *u = (jl_uniontype_t*)a;
861 : 25 : jl_methtable_t *m1 = first_methtable(u->a, got_tuple1);
862 [ + + ]: 25 : if ((jl_value_t*)m1 != jl_nothing) {
863 : 24 : jl_methtable_t *m2 = first_methtable(u->b, got_tuple1);
864 [ + + ]: 24 : if (m1 == m2)
865 : 11 : return m1;
866 : : }
867 : : }
868 : 390 : return (jl_methtable_t*)jl_nothing;
869 : : }
870 : :
871 : : // get the MethodTable for dispatch, or `nothing` if cannot be determined
872 : 69404300 : JL_DLLEXPORT jl_methtable_t *jl_method_table_for(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
873 : : {
874 : 69404300 : return first_methtable(argtypes, 0);
875 : : }
876 : :
877 : 25918 : JL_DLLEXPORT jl_methtable_t *jl_method_get_table(jl_method_t *method JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
878 : : {
879 [ + + ]: 25918 : return method->external_mt ? (jl_methtable_t*)method->external_mt : jl_method_table_for(method->sig);
880 : : }
881 : :
882 : : // get the MethodTable implied by a single given type, or `nothing`
883 : 197927 : JL_DLLEXPORT jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
884 : : {
885 : 197927 : return first_methtable(argt, 1);
886 : : }
887 : :
888 : : jl_array_t *jl_all_methods JL_GLOBALLY_ROOTED;
889 : :
890 : 69789 : JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata,
891 : : jl_methtable_t *mt,
892 : : jl_code_info_t *f,
893 : : jl_module_t *module)
894 : : {
895 : : // argdata is svec(svec(types...), svec(typevars...), functionloc)
896 : 69789 : jl_svec_t *atypes = (jl_svec_t*)jl_svecref(argdata, 0);
897 : 69789 : jl_svec_t *tvars = (jl_svec_t*)jl_svecref(argdata, 1);
898 : 69789 : jl_value_t *functionloc = jl_svecref(argdata, 2);
899 : 69789 : size_t nargs = jl_svec_len(atypes);
900 : 69789 : int isva = jl_is_vararg(jl_svecref(atypes, nargs - 1));
901 [ - + ]: 69789 : assert(jl_is_svec(atypes));
902 [ - + ]: 69789 : assert(nargs > 0);
903 [ - + ]: 69789 : assert(jl_is_svec(tvars));
904 [ + - + + : 69789 : if (!jl_is_type(jl_svecref(atypes, 0)) || (isva && nargs == 1))
- + ]
905 : 0 : jl_error("function type in method definition is not a type");
906 : : jl_sym_t *name;
907 : 69789 : jl_method_t *m = NULL;
908 : 69789 : jl_value_t *argtype = NULL;
909 : 69789 : JL_GC_PUSH3(&f, &m, &argtype);
910 : 69789 : size_t i, na = jl_svec_len(atypes);
911 : :
912 : 69789 : argtype = (jl_value_t*)jl_apply_tuple_type(atypes);
913 [ + + ]: 79857 : for (i = jl_svec_len(tvars); i > 0; i--) {
914 : 10068 : jl_value_t *tv = jl_svecref(tvars, i - 1);
915 [ - + ]: 10068 : if (!jl_is_typevar(tv))
916 : 0 : jl_type_error("method signature", (jl_value_t*)jl_tvar_type, tv);
917 : 10068 : argtype = jl_new_struct(jl_unionall_type, tv, argtype);
918 : : }
919 : :
920 : 69789 : jl_methtable_t *external_mt = mt;
921 [ + + ]: 69789 : if (!mt)
922 : 69782 : mt = jl_method_table_for(argtype);
923 [ + + ]: 69789 : if ((jl_value_t*)mt == jl_nothing)
924 : 7 : jl_error("Method dispatch is unimplemented currently for this method signature");
925 [ + + ]: 69782 : if (mt->frozen)
926 : 3 : jl_error("cannot add methods to a builtin function");
927 : :
928 : : // TODO: derive our debug name from the syntax instead of the type
929 : 69779 : name = mt->name;
930 [ + + + + : 69779 : if (mt == jl_type_type_mt || mt == jl_nonfunction_mt || external_mt) {
+ + ]
931 : : // our value for `name` is bad, try to guess what the syntax might have had,
932 : : // like `jl_static_show_func_sig` might have come up with
933 : 6087 : jl_datatype_t *dt = jl_first_argument_datatype(argtype);
934 [ + + ]: 6087 : if (dt != NULL) {
935 : 6086 : name = dt->name->name;
936 [ + + ]: 6086 : if (jl_is_type_type((jl_value_t*)dt)) {
937 : 5945 : dt = (jl_datatype_t*)jl_argument_datatype(jl_tparam0(dt));
938 [ + + ]: 5945 : if ((jl_value_t*)dt != jl_nothing) {
939 : 5935 : name = dt->name->name;
940 : : }
941 : : }
942 : : }
943 : : }
944 [ + + ]: 69779 : if (!jl_is_code_info(f)) {
945 : : // this occurs when there is a closure being added to an out-of-scope function
946 : : // the user should only do this at the toplevel
947 : : // the result is that the closure variables get interpolated directly into the IR
948 : 236 : f = jl_new_code_info_from_ir((jl_expr_t*)f);
949 : : }
950 : 69779 : m = jl_new_method_uninit(module);
951 : 69779 : m->external_mt = (jl_value_t*)external_mt;
952 [ + + ]: 69779 : if (external_mt)
953 : 7 : jl_gc_wb(m, external_mt);
954 : 69779 : m->sig = argtype;
955 : 69779 : m->name = name;
956 : 69779 : m->isva = isva;
957 : 69779 : m->nargs = nargs;
958 [ - + ]: 69779 : assert(jl_is_linenode(functionloc));
959 : 69779 : jl_value_t *file = jl_linenode_file(functionloc);
960 [ + - ]: 69779 : m->file = jl_is_symbol(file) ? (jl_sym_t*)file : jl_empty_sym;
961 : 69779 : m->line = jl_linenode_line(functionloc);
962 : 69779 : jl_method_set_source(m, f);
963 : :
964 [ - + ]: 69779 : if (jl_has_free_typevars(argtype)) {
965 : 0 : jl_exceptionf(jl_argumenterror_type,
966 : : "method definition for %s at %s:%d has free type variables",
967 : : jl_symbol_name(name),
968 : 0 : jl_symbol_name(m->file),
969 : 0 : m->line);
970 : : }
971 : :
972 [ + + ]: 245119 : for (i = 0; i < na; i++) {
973 : 175343 : jl_value_t *elt = jl_svecref(atypes, i);
974 [ + + + + : 175343 : if (!jl_is_type(elt) && !jl_is_typevar(elt) && !jl_is_vararg(elt)) {
+ + ]
975 : 2 : jl_sym_t *argname = (jl_sym_t*)jl_array_ptr_ref(f->slotnames, i);
976 [ + + ]: 2 : if (argname == jl_unused_sym)
977 : 1 : jl_exceptionf(jl_argumenterror_type,
978 : : "invalid type for argument number %d in method definition for %s at %s:%d",
979 : : i,
980 : : jl_symbol_name(name),
981 : 1 : jl_symbol_name(m->file),
982 : 1 : m->line);
983 : : else
984 : 1 : jl_exceptionf(jl_argumenterror_type,
985 : : "invalid type for argument %s in method definition for %s at %s:%d",
986 : : jl_symbol_name(argname),
987 : : jl_symbol_name(name),
988 : 1 : jl_symbol_name(m->file),
989 : 1 : m->line);
990 : : }
991 [ + + + + ]: 175341 : if (jl_is_vararg(elt) && i < na-1)
992 : 1 : jl_exceptionf(jl_argumenterror_type,
993 : : "Vararg on non-final argument in method definition for %s at %s:%d",
994 : : jl_symbol_name(name),
995 : 1 : jl_symbol_name(m->file),
996 : 1 : m->line);
997 : : }
998 : :
999 : : #ifdef RECORD_METHOD_ORDER
1000 : : if (jl_all_methods == NULL)
1001 : : jl_all_methods = jl_alloc_vec_any(0);
1002 : : #endif
1003 [ - + ]: 69776 : if (jl_all_methods != NULL) {
1004 [ # # ]: 0 : while (jl_array_len(jl_all_methods) < m->primary_world)
1005 : 0 : jl_array_ptr_1d_push(jl_all_methods, NULL);
1006 : 0 : jl_array_ptr_1d_push(jl_all_methods, (jl_value_t*)m);
1007 : : }
1008 : :
1009 : 69776 : jl_method_table_insert(mt, m, NULL);
1010 [ + + ]: 69776 : if (jl_newmeth_tracer)
1011 : 2 : jl_call_tracer(jl_newmeth_tracer, (jl_value_t*)m);
1012 : 69776 : JL_GC_POP();
1013 : :
1014 : 69776 : return m;
1015 : : }
1016 : :
1017 : : // root blocks
1018 : :
1019 : : // This section handles method roots. Roots are GC-preserved items needed to
1020 : : // represent lowered, type-inferred, and/or compiled code. These items are
1021 : : // stored in a flat list (`m.roots`), and during serialization and
1022 : : // deserialization of code we replace C-pointers to these items with a
1023 : : // relocatable reference. We use a bipartite reference, `(key, index)` pair,
1024 : : // where `key` identifies the module that added the root and `index` numbers
1025 : : // just those roots with the same `key`.
1026 : : //
1027 : : // During precompilation (serialization), we save roots that were added to
1028 : : // methods that are tagged with this package's module-key, even for "external"
1029 : : // methods not owned by a module currently being precompiled. During
1030 : : // deserialization, we load the new roots and append them to the method. When
1031 : : // code is deserialized (see ircode.c), we replace the bipartite reference with
1032 : : // the pointer to the memory address in the current session. The bipartite
1033 : : // reference allows us to cache both roots and references in precompilation .ji
1034 : : // files using a naming scheme that is independent of which packages are loaded
1035 : : // in arbitrary order.
1036 : : //
1037 : : // To track the module-of-origin for each root, methods also have a
1038 : : // `root_blocks` field that uses run-length encoding (RLE) storing `key` and the
1039 : : // (absolute) integer index within `roots` at which a block of roots with that
1040 : : // key begins. This makes it possible to look up an individual `(key, index)`
1041 : : // pair fairly efficiently. A given `key` may possess more than one block; the
1042 : : // `index` continues to increment regardless of block boundaries.
1043 : : //
1044 : : // Roots with `key = 0` are considered to be of unknown origin, and
1045 : : // CodeInstances referencing such roots will remain unserializable unless all
1046 : : // such roots were added at the time of system image creation. To track this
1047 : : // additional data, we use two fields:
1048 : : //
1049 : : // - methods have an `nroots_sysimg` field to count the number of roots defined
1050 : : // at the time of writing the system image (such occur first in the list of
1051 : : // roots). These are the cases with `key = 0` that do not prevent
1052 : : // serialization.
1053 : : // - CodeInstances have a `relocatability` field which when 1 indicates that
1054 : : // every root is "safe," meaning it was either added at sysimg creation or is
1055 : : // tagged with a non-zero `key`. Even a single unsafe root will cause this to
1056 : : // have value 0.
1057 : :
1058 : : // Get the key of the current (final) block of roots
1059 : 3755140 : static uint64_t current_root_id(jl_array_t *root_blocks)
1060 : : {
1061 [ + + ]: 3755140 : if (!root_blocks)
1062 : 3635140 : return 0;
1063 [ - + ]: 119999 : assert(jl_is_array(root_blocks));
1064 : 119999 : size_t nx2 = jl_array_len(root_blocks);
1065 [ + + ]: 119999 : if (nx2 == 0)
1066 : 3130 : return 0;
1067 : 116869 : uint64_t *blocks = (uint64_t*)jl_array_data(root_blocks);
1068 : 116869 : return blocks[nx2-2];
1069 : : }
1070 : :
1071 : : // Add a new block of `len` roots with key `modid` (module id)
1072 : 6677 : static void add_root_block(jl_array_t *root_blocks, uint64_t modid, size_t len)
1073 : : {
1074 [ - + ]: 6677 : assert(jl_is_array(root_blocks));
1075 : 6677 : jl_array_grow_end(root_blocks, 2);
1076 : 6677 : uint64_t *blocks = (uint64_t*)jl_array_data(root_blocks);
1077 : 6677 : int nx2 = jl_array_len(root_blocks);
1078 : 6677 : blocks[nx2-2] = modid;
1079 : 6677 : blocks[nx2-1] = len;
1080 : 6677 : }
1081 : :
1082 : : // Allocate storage for roots
1083 : 3755350 : static void prepare_method_for_roots(jl_method_t *m, uint64_t modid)
1084 : : {
1085 [ + + ]: 3755350 : if (!m->roots) {
1086 : 1 : m->roots = jl_alloc_vec_any(0);
1087 : 1 : jl_gc_wb(m, m->roots);
1088 : : }
1089 [ + + + + ]: 3755350 : if (!m->root_blocks && modid != 0) {
1090 : 3330 : m->root_blocks = jl_alloc_array_1d(jl_array_uint64_type, 0);
1091 : 3330 : jl_gc_wb(m, m->root_blocks);
1092 : : }
1093 : 3755350 : }
1094 : :
1095 : : // Add a single root with owner `mod` to a method
1096 : 3755140 : JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root)
1097 : : {
1098 : 3755140 : JL_GC_PUSH2(&m, &root);
1099 : 3755140 : uint64_t modid = 0;
1100 [ + + ]: 3755140 : if (mod) {
1101 [ - + ]: 15086 : assert(jl_is_module(mod));
1102 : 15086 : modid = mod->build_id;
1103 : : }
1104 [ - + ]: 3755140 : assert(jl_is_method(m));
1105 : 3755140 : prepare_method_for_roots(m, modid);
1106 [ + + ]: 3755140 : if (current_root_id(m->root_blocks) != modid)
1107 : 6460 : add_root_block(m->root_blocks, modid, jl_array_len(m->roots));
1108 : 3755140 : jl_array_ptr_1d_push(m->roots, root);
1109 : 3755140 : JL_GC_POP();
1110 : 3755140 : }
1111 : :
1112 : : // Add a list of roots with key `modid` to a method
1113 : 217 : void jl_append_method_roots(jl_method_t *m, uint64_t modid, jl_array_t* roots)
1114 : : {
1115 : 217 : JL_GC_PUSH2(&m, &roots);
1116 [ - + ]: 217 : assert(jl_is_method(m));
1117 [ - + ]: 217 : assert(jl_is_array(roots));
1118 : 217 : prepare_method_for_roots(m, modid);
1119 : 217 : add_root_block(m->root_blocks, modid, jl_array_len(m->roots));
1120 : 217 : jl_array_ptr_1d_append(m->roots, roots);
1121 : 217 : JL_GC_POP();
1122 : 217 : }
1123 : :
1124 : : // given the absolute index i of a root, retrieve its relocatable reference
1125 : : // returns 1 if the root is relocatable
1126 : 128259000 : int get_root_reference(rle_reference *rr, jl_method_t *m, size_t i)
1127 : : {
1128 [ + + ]: 128259000 : if (!m->root_blocks) {
1129 : 122976000 : rr->key = 0;
1130 : 122976000 : rr->index = i;
1131 : 122976000 : return i < m->nroots_sysimg;
1132 : : }
1133 : 5283600 : rle_index_to_reference(rr, i, (uint64_t*)jl_array_data(m->root_blocks), jl_array_len(m->root_blocks), 0);
1134 [ + + ]: 5283600 : if (rr->key)
1135 : 1354300 : return 1;
1136 : 3929300 : return i < m->nroots_sysimg;
1137 : : }
1138 : :
1139 : : // get a root, given its key and index relative to the key
1140 : : // this is the relocatable way to get a root from m->roots
1141 : 137837000 : jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index)
1142 : : {
1143 [ + + ]: 137837000 : if (!m->root_blocks) {
1144 [ - + ]: 133232000 : assert(key == 0);
1145 : 133232000 : return jl_array_ptr_ref(m->roots, index);
1146 : : }
1147 : 4604340 : rle_reference rr = {key, index};
1148 : 4604340 : size_t i = rle_reference_to_index(&rr, (uint64_t*)jl_array_data(m->root_blocks), jl_array_len(m->root_blocks), 0);
1149 : 4604340 : return jl_array_ptr_ref(m->roots, i);
1150 : : }
1151 : :
1152 : : // Count the number of roots added by module with id `key`
1153 : 3138 : int nroots_with_key(jl_method_t *m, uint64_t key)
1154 : : {
1155 : 3138 : size_t nroots = 0;
1156 [ + + ]: 3138 : if (m->roots)
1157 : 2647 : nroots = jl_array_len(m->roots);
1158 [ + + ]: 3138 : if (!m->root_blocks)
1159 [ - + ]: 3034 : return key == 0 ? nroots : 0;
1160 : 104 : uint64_t *rletable = (uint64_t*)jl_array_data(m->root_blocks);
1161 : 104 : size_t j, nblocks2 = jl_array_len(m->root_blocks);
1162 : 104 : int nwithkey = 0;
1163 [ + + ]: 221 : for (j = 0; j < nblocks2; j+=2) {
1164 [ + + ]: 117 : if (rletable[j] == key)
1165 [ + + ]: 85 : nwithkey += (j+3 < nblocks2 ? rletable[j+3] : nroots) - rletable[j+1];
1166 : : }
1167 : 104 : return nwithkey;
1168 : : }
1169 : :
1170 : : #ifdef __cplusplus
1171 : : }
1172 : : #endif
|