Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : /*
4 : : evaluating top-level expressions, loading source files
5 : : */
6 : : #include "platform.h"
7 : :
8 : : #include <stdlib.h>
9 : : #include <string.h>
10 : : #include <setjmp.h>
11 : : #include <sys/types.h>
12 : : #include <errno.h>
13 : : #if defined(_OS_WINDOWS_)
14 : : #include <malloc.h>
15 : : #else
16 : : #include <unistd.h>
17 : : #endif
18 : : #include "julia.h"
19 : : #include "julia_internal.h"
20 : : #include "julia_assert.h"
21 : : #include "intrinsics.h"
22 : : #include "builtin_proto.h"
23 : :
24 : : #ifdef __cplusplus
25 : : extern "C" {
26 : : #endif
27 : :
28 : : // current line number in a file
29 : : JL_DLLEXPORT int jl_lineno = 0; // need to update jl_critical_error if this is TLS
30 : : // current file name
31 : : JL_DLLEXPORT const char *jl_filename = "none"; // need to update jl_critical_error if this is TLS
32 : :
33 : : htable_t jl_current_modules;
34 : : jl_mutex_t jl_modules_mutex;
35 : :
36 : : // During incremental compilation, the following gets set
37 : : JL_DLLEXPORT jl_module_t *jl_precompile_toplevel_module = NULL; // the toplevel module currently being defined
38 : :
39 : 801 : JL_DLLEXPORT void jl_add_standard_imports(jl_module_t *m)
40 : : {
41 : 801 : jl_module_t *base_module = jl_base_relative_to(m);
42 [ - + ]: 801 : assert(base_module != NULL);
43 : : // using Base
44 : 801 : jl_module_using(m, base_module);
45 : 801 : }
46 : :
47 : : // create a new top-level module
48 : 1 : void jl_init_main_module(void)
49 : : {
50 [ - + ]: 1 : assert(jl_main_module == NULL);
51 : 1 : jl_main_module = jl_new_module(jl_symbol("Main"));
52 : 1 : jl_main_module->parent = jl_main_module;
53 : 1 : jl_set_const(jl_main_module, jl_symbol("Core"),
54 : : (jl_value_t*)jl_core_module);
55 : 1 : jl_set_const(jl_core_module, jl_symbol("Main"),
56 : : (jl_value_t*)jl_main_module);
57 : 1 : }
58 : :
59 : 14086 : static jl_function_t *jl_module_get_initializer(jl_module_t *m JL_PROPAGATES_ROOT)
60 : : {
61 : 14086 : return (jl_function_t*)jl_get_global(m, jl_symbol("__init__"));
62 : : }
63 : :
64 : :
65 : 14086 : void jl_module_run_initializer(jl_module_t *m)
66 : : {
67 : : JL_TIMING(INIT_MODULE);
68 : 14086 : jl_function_t *f = jl_module_get_initializer(m);
69 [ + + ]: 14086 : if (f == NULL)
70 : 539 : return;
71 : 13547 : jl_task_t *ct = jl_current_task;
72 : 13547 : size_t last_age = ct->world_age;
73 [ + + + + ]: 27093 : JL_TRY {
74 : 13547 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
75 : 13547 : jl_apply(&f, 1);
76 : 13546 : ct->world_age = last_age;
77 : : }
78 [ + - ]: 1 : JL_CATCH {
79 [ - + ]: 1 : if (jl_initerror_type == NULL) {
80 : 0 : jl_rethrow();
81 : : }
82 : : else {
83 : 1 : jl_rethrow_other(jl_new_struct(jl_initerror_type, m->name,
84 : : jl_current_exception()));
85 : : }
86 : : }
87 : : }
88 : :
89 : 126 : static void jl_register_root_module(jl_module_t *m)
90 : : {
91 : : static jl_value_t *register_module_func = NULL;
92 [ - + ]: 126 : assert(jl_base_module);
93 [ + + ]: 126 : if (register_module_func == NULL)
94 : 87 : register_module_func = jl_get_global(jl_base_module, jl_symbol("register_root_module"));
95 [ - + ]: 126 : assert(register_module_func);
96 : : jl_value_t *args[2];
97 : 126 : args[0] = register_module_func;
98 : 126 : args[1] = (jl_value_t*)m;
99 : 126 : jl_apply(args, 2);
100 : 126 : }
101 : :
102 : 88 : jl_array_t *jl_get_loaded_modules(void)
103 : : {
104 : : static jl_value_t *loaded_modules_array = NULL;
105 [ + + + + ]: 88 : if (loaded_modules_array == NULL && jl_base_module != NULL)
106 : 83 : loaded_modules_array = jl_get_global(jl_base_module, jl_symbol("loaded_modules_array"));
107 [ + + ]: 88 : if (loaded_modules_array != NULL)
108 : 85 : return (jl_array_t*)jl_call0((jl_function_t*)loaded_modules_array);
109 : 3 : return NULL;
110 : : }
111 : :
112 : 863 : static int jl_is__toplevel__mod(jl_module_t *mod)
113 : : {
114 [ + + + + ]: 1716 : return jl_base_module &&
115 : 853 : (jl_value_t*)mod == jl_get_global(jl_base_module, jl_symbol("__toplevel__"));
116 : : }
117 : :
118 : : // TODO: add locks around global state mutation operations
119 : 777 : static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
120 : : {
121 : 777 : jl_task_t *ct = jl_current_task;
122 [ - + ]: 777 : assert(ex->head == jl_module_sym);
123 [ + - - + ]: 777 : if (jl_array_len(ex->args) != 3 || !jl_is_expr(jl_exprarg(ex, 2))) {
124 : 0 : jl_error("syntax: malformed module expression");
125 : : }
126 : :
127 [ + + ]: 777 : if (((jl_expr_t *)(jl_exprarg(ex, 2)))->head != jl_symbol("block")) {
128 : 3 : jl_error("syntax: module expression third argument must be a block");
129 : : }
130 : :
131 : 774 : int std_imports = (jl_exprarg(ex, 0) == jl_true);
132 : 774 : jl_sym_t *name = (jl_sym_t*)jl_exprarg(ex, 1);
133 [ - + ]: 774 : if (!jl_is_symbol(name)) {
134 : 0 : jl_type_error("module", (jl_value_t*)jl_symbol_type, (jl_value_t*)name);
135 : : }
136 : :
137 : 774 : jl_module_t *newm = jl_new_module(name);
138 : 774 : jl_value_t *form = (jl_value_t*)newm;
139 : 774 : JL_GC_PUSH1(&form);
140 : 774 : JL_LOCK(&jl_modules_mutex);
141 : 774 : ptrhash_put(&jl_current_modules, (void*)newm, (void*)((uintptr_t)HT_NOTFOUND + 1));
142 : 774 : JL_UNLOCK(&jl_modules_mutex);
143 : :
144 : 774 : jl_module_t *old_toplevel_module = jl_precompile_toplevel_module;
145 : :
146 : : // copy parent environment info into submodule
147 : 774 : newm->uuid = parent_module->uuid;
148 [ + + ]: 774 : if (jl_is__toplevel__mod(parent_module)) {
149 : 126 : newm->parent = newm;
150 : 126 : jl_register_root_module(newm);
151 [ + + ]: 126 : if (jl_options.incremental) {
152 : 82 : jl_precompile_toplevel_module = newm;
153 : : }
154 : : }
155 : : else {
156 : 648 : newm->parent = parent_module;
157 : 648 : jl_binding_t *b = jl_get_binding_wr(parent_module, name, 1);
158 : 648 : jl_declare_constant(b);
159 : 648 : jl_value_t *old = NULL;
160 [ - + ]: 648 : if (!jl_atomic_cmpswap(&b->value, &old, (jl_value_t*)newm)) {
161 [ # # ]: 0 : if (!jl_is_module(old)) {
162 : 0 : jl_errorf("invalid redefinition of constant %s", jl_symbol_name(name));
163 : : }
164 [ # # ]: 0 : if (jl_generating_output())
165 : 0 : jl_errorf("cannot replace module %s during compilation", jl_symbol_name(name));
166 : 0 : jl_printf(JL_STDERR, "WARNING: replacing module %s.\n", jl_symbol_name(name));
167 : 0 : old = jl_atomic_exchange(&b->value, (jl_value_t*)newm);
168 : : }
169 : 648 : jl_gc_wb_binding(b, newm);
170 [ - + ]: 648 : if (old != NULL) {
171 : : // create a hidden gc root for the old module
172 : 0 : JL_LOCK(&jl_modules_mutex);
173 : 0 : uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, (void*)old);
174 : 0 : *refcnt += 1;
175 : 0 : JL_UNLOCK(&jl_modules_mutex);
176 : : }
177 : : }
178 : :
179 [ + + + + ]: 774 : if (parent_module == jl_main_module && name == jl_symbol("Base")) {
180 : : // pick up Base module during bootstrap
181 : 1 : jl_base_module = newm;
182 : : }
183 : :
184 : 774 : size_t last_age = ct->world_age;
185 : :
186 : : // add standard imports unless baremodule
187 [ + + ]: 774 : if (std_imports) {
188 [ + + ]: 742 : if (jl_base_module != NULL) {
189 : 736 : jl_add_standard_imports(newm);
190 : : }
191 : : // add `eval` function
192 : 742 : form = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex, newm);
193 : 742 : jl_toplevel_eval_flex(newm, form, 0, 1);
194 : 742 : form = NULL;
195 : : }
196 : :
197 : 774 : jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args;
198 [ + + ]: 32132 : for (int i = 0; i < jl_array_len(exprs); i++) {
199 : : // process toplevel form
200 : 31370 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
201 : 31370 : form = jl_expand_stmt_with_loc(jl_array_ptr_ref(exprs, i), newm, jl_filename, jl_lineno);
202 : 31370 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
203 : 31370 : (void)jl_toplevel_eval_flex(newm, form, 1, 1);
204 : : }
205 : 762 : newm->primary_world = jl_atomic_load_acquire(&jl_world_counter);
206 : 762 : ct->world_age = last_age;
207 : :
208 : : #if 0
209 : : // some optional post-processing steps
210 : : size_t i;
211 : : void **table = newm->bindings.table;
212 : : for(i=1; i < newm->bindings.size; i+=2) {
213 : : if (table[i] != HT_NOTFOUND) {
214 : : jl_binding_t *b = (jl_binding_t*)table[i];
215 : : // remove non-exported macros
216 : : if (jl_symbol_name(b->name)[0]=='@' &&
217 : : !b->exportp && b->owner == newm)
218 : : b->value = NULL;
219 : : // error for unassigned exports
220 : : /*
221 : : if (b->exportp && b->owner==newm && b->value==NULL)
222 : : jl_errorf("identifier %s exported from %s is not initialized",
223 : : jl_symbol_name(b->name), jl_symbol_name(newm->name));
224 : : */
225 : : }
226 : : }
227 : : #endif
228 : :
229 : 762 : JL_LOCK(&jl_modules_mutex);
230 : 762 : uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, (void*)newm);
231 [ - + ]: 762 : assert(*refcnt > (uintptr_t)HT_NOTFOUND);
232 : 762 : *refcnt -= 1;
233 : : // newm should be reachable from somewhere else by now
234 : :
235 [ + + ]: 762 : if (jl_module_init_order == NULL)
236 : 121 : jl_module_init_order = jl_alloc_vec_any(0);
237 : 762 : jl_array_ptr_1d_push(jl_module_init_order, (jl_value_t*)newm);
238 : :
239 : : // defer init of children until parent is done being defined
240 : : // then initialize all in definition-finished order
241 : : // at build time, don't run them at all (defer for runtime)
242 : 762 : form = NULL;
243 [ + + ]: 762 : if (!jl_generating_output()) {
244 [ + + ]: 545 : if (!ptrhash_has(&jl_current_modules, (void*)newm->parent)) {
245 : 513 : size_t i, l = jl_array_len(jl_module_init_order);
246 : 513 : size_t ns = 0;
247 : 513 : form = (jl_value_t*)jl_alloc_vec_any(0);
248 [ + + ]: 1065 : for (i = 0; i < l; i++) {
249 : 552 : jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(jl_module_init_order, i);
250 [ + + ]: 552 : if (jl_is_submodule(m, newm)) {
251 : 541 : jl_array_ptr_1d_push((jl_array_t*)form, (jl_value_t*)m);
252 : : }
253 [ - + ]: 11 : else if (ns++ != i) {
254 : 0 : jl_array_ptr_set(jl_module_init_order, ns - 1, (jl_value_t*)m);
255 : : }
256 : : }
257 [ + - ]: 513 : if (ns < l)
258 : 513 : jl_array_del_end(jl_module_init_order, l - ns);
259 : : }
260 : : }
261 : 762 : JL_UNLOCK(&jl_modules_mutex);
262 : :
263 [ + + ]: 762 : if (form) {
264 : 513 : size_t i, l = jl_array_len(form);
265 [ + + ]: 1053 : for (i = 0; i < l; i++) {
266 : 541 : jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(form, i);
267 : : JL_GC_PROMISE_ROOTED(m);
268 : 541 : jl_module_run_initializer(m);
269 : : }
270 : : }
271 : :
272 : 761 : jl_precompile_toplevel_module = old_toplevel_module;
273 : :
274 : 761 : JL_GC_POP();
275 : 761 : return (jl_value_t*)newm;
276 : : }
277 : :
278 : 3028 : static jl_value_t *jl_eval_dot_expr(jl_module_t *m, jl_value_t *x, jl_value_t *f, int fast)
279 : : {
280 : 3028 : jl_task_t *ct = jl_current_task;
281 : : jl_value_t **args;
282 : 3028 : JL_GC_PUSHARGS(args, 3);
283 : 3028 : args[1] = jl_toplevel_eval_flex(m, x, fast, 0);
284 : 3028 : args[2] = jl_toplevel_eval_flex(m, f, fast, 0);
285 [ + + ]: 3028 : if (jl_is_module(args[1])) {
286 [ - + ]: 3012 : JL_TYPECHK(getglobal, symbol, args[2]);
287 : 3012 : args[0] = jl_eval_global_var((jl_module_t*)args[1], (jl_sym_t*)args[2]);
288 : : }
289 : : else {
290 : 16 : args[0] = jl_eval_global_var(jl_base_relative_to(m), jl_symbol("getproperty"));
291 : 16 : size_t last_age = ct->world_age;
292 : 16 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
293 : 16 : args[0] = jl_apply(args, 3);
294 : 16 : ct->world_age = last_age;
295 : : }
296 : 3027 : JL_GC_POP();
297 : 3027 : return args[0];
298 : : }
299 : :
300 : 28987 : void jl_eval_global_expr(jl_module_t *m, jl_expr_t *ex, int set_type) {
301 : : // create uninitialized mutable binding for "global x" decl sometimes or probably
302 : 28987 : size_t i, l = jl_array_len(ex->args);
303 [ + + ]: 57976 : for (i = 0; i < l; i++) {
304 : 28989 : jl_value_t *arg = jl_exprarg(ex, i);
305 : : jl_module_t *gm;
306 : : jl_sym_t *gs;
307 [ - + ]: 28989 : if (jl_is_globalref(arg)) {
308 : 0 : gm = jl_globalref_mod(arg);
309 : 0 : gs = jl_globalref_name(arg);
310 : : }
311 : : else {
312 [ - + ]: 28989 : assert(jl_is_symbol(arg));
313 : 28989 : gm = m;
314 : 28989 : gs = (jl_sym_t*)arg;
315 : : }
316 [ + + ]: 28989 : if (!jl_binding_resolved_p(gm, gs)) {
317 : 26335 : jl_binding_t *b = jl_get_binding_wr(gm, gs, 1);
318 [ + + ]: 26335 : if (set_type) {
319 : 32 : jl_value_t *old_ty = NULL;
320 : : // maybe set the type too, perhaps
321 : 32 : jl_atomic_cmpswap_relaxed(&b->ty, &old_ty, (jl_value_t*)jl_any_type);
322 : : }
323 : : }
324 : : }
325 : 28987 : }
326 : :
327 : : // module referenced by (top ...) from within m
328 : : // this is only needed because of the bootstrapping process:
329 : : // - initially Base doesn't exist and top === Core
330 : : // - later, it refers to either old Base or new Base
331 : 10046200 : JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m)
332 : : {
333 : : for (;;) {
334 [ + + ]: 10046200 : if (m->istopmod)
335 : 8468300 : return m;
336 [ + + ]: 1577940 : if (m == m->parent)
337 : 720297 : break;
338 : 857646 : m = m->parent;
339 : : }
340 : 720297 : return jl_top_module;
341 : : }
342 : :
343 : 3251280 : static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, int *has_opaque)
344 : : {
345 [ + + ]: 3251280 : if (!jl_is_expr(v))
346 : 762487 : return;
347 : 2488790 : jl_expr_t *e = (jl_expr_t*)v;
348 : 2488790 : jl_sym_t *head = e->head;
349 [ + + + + ]: 2488790 : if (head == jl_toplevel_sym || head == jl_thunk_sym) {
350 : 56154 : return;
351 : : }
352 [ + + ]: 2432640 : else if (head == jl_global_sym) {
353 : : // this could be considered has_defs, but loops that assign to globals
354 : : // might still need to be optimized.
355 : 28684 : return;
356 : : }
357 [ + + + + ]: 2403950 : else if (head == jl_const_sym || head == jl_copyast_sym) {
358 : : // Note: `copyast` is included here since it indicates the presence of
359 : : // `quote` and probably `eval`.
360 : 44941 : *has_defs = 1;
361 : 44941 : return;
362 : : }
363 [ + + + + ]: 2359010 : else if (head == jl_method_sym || jl_is_toplevel_only_expr(v)) {
364 : 109822 : *has_defs = 1;
365 : : }
366 [ + + ]: 2249190 : else if (head == jl_cfunction_sym) {
367 : 66 : *has_intrinsics = 1;
368 : 66 : return;
369 : : }
370 [ + + ]: 2249120 : else if (head == jl_foreigncall_sym) {
371 : 325 : *has_intrinsics = 1;
372 : 325 : return;
373 : : }
374 [ + + ]: 2248800 : else if (head == jl_new_opaque_closure_sym) {
375 : 19 : *has_opaque = 1;
376 : 19 : return;
377 : : }
378 [ + + + - ]: 2248780 : else if (head == jl_call_sym && jl_expr_nargs(e) > 0) {
379 : 1539760 : jl_value_t *called = NULL;
380 : 1539760 : jl_value_t *f = jl_exprarg(e, 0);
381 [ + + ]: 1539750 : if (jl_is_globalref(f)) {
382 : 1257360 : jl_module_t *mod = jl_globalref_mod(f);
383 : 1257360 : jl_sym_t *name = jl_globalref_name(f);
384 [ + + ]: 1257360 : if (jl_binding_resolved_p(mod, name)) {
385 : 1256450 : jl_binding_t *b = jl_get_binding(mod, name);
386 [ + - + - ]: 1256460 : if (b && b->constp) {
387 : 1256460 : called = jl_atomic_load_relaxed(&b->value);
388 : : }
389 : : }
390 : : }
391 [ + + ]: 282395 : else if (jl_is_quotenode(f)) {
392 : 1 : called = jl_quotenode_value(f);
393 : : }
394 [ + + ]: 1539770 : if (called != NULL) {
395 [ + + + + ]: 1256460 : if (jl_is_intrinsic(called) && jl_unbox_int32(called) == (int)llvmcall) {
396 : 1 : *has_intrinsics = 1;
397 : : }
398 [ + + ]: 1256460 : if (called == jl_builtin__typebody) {
399 : 26121 : *has_defs = 1;
400 : : }
401 : : }
402 : 1539770 : return;
403 : : }
404 : : int i;
405 [ + + ]: 2167720 : for (i = 0; i < jl_array_len(e->args); i++) {
406 : 1348870 : jl_value_t *a = jl_exprarg(e, i);
407 [ + + ]: 1348870 : if (jl_is_expr(a))
408 : 223723 : expr_attributes(a, has_intrinsics, has_defs, has_opaque);
409 : : }
410 : : }
411 : :
412 : 617 : int jl_code_requires_compiler(jl_code_info_t *src)
413 : : {
414 : 617 : jl_array_t *body = src->code;
415 [ - + ]: 617 : assert(jl_typeis(body, jl_array_any_type));
416 : : size_t i;
417 : 617 : int has_intrinsics = 0, has_defs = 0, has_opaque = 0;
418 [ - + ]: 617 : if (jl_has_meta(body, jl_force_compile_sym))
419 : 0 : return 1;
420 [ + + ]: 9175 : for(i=0; i < jl_array_len(body); i++) {
421 : 8578 : jl_value_t *stmt = jl_array_ptr_ref(body,i);
422 : 8578 : expr_attributes(stmt, &has_intrinsics, &has_defs, &has_opaque);
423 [ + + ]: 8578 : if (has_intrinsics)
424 : 20 : return 1;
425 : : }
426 : 597 : return 0;
427 : : }
428 : :
429 : 156289 : static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs, int *has_loops, int *has_opaque, int *forced_compile)
430 : : {
431 : : size_t i;
432 : 156289 : *has_loops = 0;
433 [ + + ]: 3175290 : for(i=0; i < jl_array_len(body); i++) {
434 : 3018980 : jl_value_t *stmt = jl_array_ptr_ref(body,i);
435 [ + + ]: 3018980 : if (!*has_loops) {
436 [ + + ]: 2600270 : if (jl_is_gotonode(stmt)) {
437 [ + + ]: 156903 : if (jl_gotonode_label(stmt) <= i)
438 : 1765 : *has_loops = 1;
439 : : }
440 [ + + ]: 2443370 : else if (jl_is_gotoifnot(stmt)) {
441 [ + + ]: 138194 : if (jl_gotoifnot_label(stmt) <= i)
442 : 4 : *has_loops = 1;
443 : : }
444 : : }
445 : 3018980 : expr_attributes(stmt, has_intrinsics, has_defs, has_opaque);
446 : : }
447 : 156314 : *forced_compile = jl_has_meta(body, jl_force_compile_sym);
448 : 156293 : }
449 : :
450 : 1706 : static jl_module_t *call_require(jl_module_t *mod, jl_sym_t *var) JL_GLOBALLY_ROOTED
451 : : {
452 : : static jl_value_t *require_func = NULL;
453 : 1706 : int build_mode = jl_generating_output();
454 : 1706 : jl_module_t *m = NULL;
455 : 1706 : jl_task_t *ct = jl_current_task;
456 [ + + + - ]: 1706 : if (require_func == NULL && jl_base_module != NULL) {
457 : 222 : require_func = jl_get_global(jl_base_module, jl_symbol("require"));
458 : : }
459 [ + - ]: 1706 : if (require_func != NULL) {
460 : 1706 : size_t last_age = ct->world_age;
461 [ + + ]: 1706 : ct->world_age = (build_mode ? jl_base_module->primary_world : jl_atomic_load_acquire(&jl_world_counter));
462 : : jl_value_t *reqargs[3];
463 : 1706 : reqargs[0] = require_func;
464 : 1706 : reqargs[1] = (jl_value_t*)mod;
465 : 1706 : reqargs[2] = (jl_value_t*)var;
466 : 1706 : m = (jl_module_t*)jl_apply(reqargs, 3);
467 : 1699 : ct->world_age = last_age;
468 : : }
469 [ + - - + ]: 1699 : if (m == NULL || !jl_is_module(m)) {
470 : 0 : jl_errorf("failed to load module %s", jl_symbol_name(var));
471 : : }
472 : 1699 : return m;
473 : : }
474 : :
475 : : // either:
476 : : // - sets *name and returns the module to import *name from
477 : : // - sets *name to NULL and returns a module to import
478 : 5795 : static jl_module_t *eval_import_path(jl_module_t *where, jl_module_t *from JL_PROPAGATES_ROOT,
479 : : jl_array_t *args, jl_sym_t **name, const char *keyword) JL_GLOBALLY_ROOTED
480 : : {
481 [ - + ]: 5795 : if (jl_array_len(args) == 0)
482 : 0 : jl_errorf("malformed \"%s\" statement", keyword);
483 : 5795 : jl_sym_t *var = (jl_sym_t*)jl_array_ptr_ref(args, 0);
484 : 5795 : size_t i = 1;
485 : 5795 : jl_module_t *m = NULL;
486 : 5795 : *name = NULL;
487 [ - + ]: 5795 : if (!jl_is_symbol(var))
488 : 0 : jl_type_error(keyword, (jl_value_t*)jl_symbol_type, (jl_value_t*)var);
489 : :
490 [ + + ]: 5795 : if (from != NULL) {
491 : 3066 : m = from;
492 : 3066 : i = 0;
493 : : }
494 [ + + ]: 2729 : else if (var != jl_dot_sym) {
495 : : // `A.B`: call the loader to obtain the root A in the current environment.
496 [ + - + + ]: 2225 : if (jl_core_module && var == jl_core_module->name) {
497 : 79 : m = jl_core_module;
498 : : }
499 [ + - + + ]: 2146 : else if (jl_base_module && var == jl_base_module->name) {
500 : 440 : m = jl_base_module;
501 : : }
502 : : else {
503 : 1706 : m = call_require(where, var);
504 : : }
505 [ + + ]: 2218 : if (i == jl_array_len(args))
506 : 1941 : return m;
507 : : }
508 : : else {
509 : : // `.A.B.C`: strip off leading dots by following parent links
510 : 504 : m = where;
511 : : while (1) {
512 [ + + ]: 695 : if (i >= jl_array_len(args))
513 : 1 : jl_error("invalid module path");
514 : 694 : var = (jl_sym_t*)jl_array_ptr_ref(args, i);
515 [ + + ]: 694 : if (var != jl_dot_sym)
516 : 503 : break;
517 : 191 : i++;
518 [ - + ]: 191 : assert(m);
519 : 191 : m = m->parent;
520 : : }
521 : : }
522 : :
523 : : while (1) {
524 : 3938 : var = (jl_sym_t*)jl_array_ptr_ref(args, i);
525 [ - + ]: 3938 : if (!jl_is_symbol(var))
526 : 0 : jl_type_error(keyword, (jl_value_t*)jl_symbol_type, (jl_value_t*)var);
527 [ - + ]: 3938 : if (var == jl_dot_sym)
528 : 0 : jl_errorf("invalid %s path: \".\" in identifier path", keyword);
529 [ + + ]: 3938 : if (i == jl_array_len(args)-1)
530 : 3846 : break;
531 : 92 : m = (jl_module_t*)jl_eval_global_var(m, var);
532 : : JL_GC_PROMISE_ROOTED(m);
533 [ - + ]: 92 : if (!jl_is_module(m))
534 : 0 : jl_errorf("invalid %s path: \"%s\" does not name a module", keyword, jl_symbol_name(var));
535 : 92 : i++;
536 : : }
537 : 3846 : *name = var;
538 : 3846 : return m;
539 : : }
540 : :
541 : 26950200 : int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT
542 : : {
543 [ + + ]: 53900100 : return jl_is_expr(e) &&
544 [ + # ]: 26949900 : (((jl_expr_t*)e)->head == jl_module_sym ||
545 [ + + ]: 26950000 : ((jl_expr_t*)e)->head == jl_import_sym ||
546 [ + + ]: 26949900 : ((jl_expr_t*)e)->head == jl_using_sym ||
547 [ + + ]: 26949800 : ((jl_expr_t*)e)->head == jl_export_sym ||
548 [ + + ]: 26949800 : ((jl_expr_t*)e)->head == jl_thunk_sym ||
549 [ + + ]: 26893600 : ((jl_expr_t*)e)->head == jl_global_sym ||
550 [ + + ]: 26864800 : ((jl_expr_t*)e)->head == jl_const_sym ||
551 [ + - ]: 26833200 : ((jl_expr_t*)e)->head == jl_toplevel_sym ||
552 [ + - ]: 26833200 : ((jl_expr_t*)e)->head == jl_error_sym ||
553 [ + + ]: 26833200 : ((jl_expr_t*)e)->head == jl_incomplete_sym);
554 : : }
555 : :
556 : 220239 : int jl_needs_lowering(jl_value_t *e) JL_NOTSAFEPOINT
557 : : {
558 [ - + ]: 220239 : if (!jl_is_expr(e))
559 : 0 : return 0;
560 : 220239 : jl_expr_t *ex = (jl_expr_t*)e;
561 : 220239 : jl_sym_t *head = ex->head;
562 [ + + + + : 220239 : if (head == jl_module_sym || head == jl_import_sym || head == jl_using_sym ||
+ + ]
563 [ + + + + : 218251 : head == jl_export_sym || head == jl_thunk_sym || head == jl_toplevel_sym ||
+ + ]
564 [ + + + + : 133665 : head == jl_error_sym || head == jl_incomplete_sym || head == jl_method_sym) {
- + ]
565 : 86588 : return 0;
566 : : }
567 [ + + + + ]: 133651 : if (head == jl_global_sym || head == jl_const_sym) {
568 : 63122 : size_t i, l = jl_array_len(ex->args);
569 [ + + ]: 123459 : for (i = 0; i < l; i++) {
570 : 63124 : jl_value_t *a = jl_exprarg(ex, i);
571 [ + + + - ]: 63124 : if (!jl_is_symbol(a) && !jl_is_globalref(a))
572 : 2787 : return 1;
573 : : }
574 : 60335 : return 0;
575 : : }
576 : 70529 : return 1;
577 : : }
578 : :
579 : 1141 : static jl_method_instance_t *method_instance_for_thunk(jl_code_info_t *src, jl_module_t *module)
580 : : {
581 : 1141 : jl_method_instance_t *li = jl_new_method_instance_uninit();
582 : 1141 : li->uninferred = (jl_value_t*)src;
583 : 1141 : li->specTypes = (jl_value_t*)jl_emptytuple_type;
584 : 1141 : li->def.module = module;
585 : 1141 : return li;
586 : : }
587 : :
588 : 382 : static void import_module(jl_module_t *JL_NONNULL m, jl_module_t *import, jl_sym_t *asname)
589 : : {
590 [ - + ]: 382 : assert(m);
591 [ + - ]: 382 : jl_sym_t *name = asname ? asname : import->name;
592 : : jl_binding_t *b;
593 [ + + ]: 382 : if (jl_binding_resolved_p(m, name)) {
594 : 46 : b = jl_get_binding(m, name);
595 : 46 : jl_value_t *bv = jl_atomic_load_relaxed(&b->value);
596 [ - + - - : 46 : if ((!b->constp && b->owner != m) || (bv && bv != (jl_value_t*)import)) {
+ - - + ]
597 : 0 : jl_errorf("importing %s into %s conflicts with an existing global",
598 : : jl_symbol_name(name), jl_symbol_name(m->name));
599 : : }
600 : : }
601 : : else {
602 : 336 : b = jl_get_binding_wr(m, name, 1);
603 : 336 : b->imported = 1;
604 : : }
605 [ + + ]: 382 : if (!b->constp) {
606 : : // TODO: constp is not threadsafe
607 : 336 : jl_atomic_store_release(&b->value, (jl_value_t*)import);
608 : 336 : b->constp = 1;
609 : 336 : jl_gc_wb(m, (jl_value_t*)import);
610 : : }
611 : 382 : }
612 : :
613 : : // in `import A.B: x, y, ...`, evaluate the `A.B` part if it exists
614 : 2158 : static jl_module_t *eval_import_from(jl_module_t *m JL_PROPAGATES_ROOT, jl_expr_t *ex, const char *keyword)
615 : : {
616 [ + + + + ]: 2158 : if (jl_expr_nargs(ex) == 1 && jl_is_expr(jl_exprarg(ex, 0))) {
617 : 1710 : jl_expr_t *fr = (jl_expr_t*)jl_exprarg(ex, 0);
618 [ + + ]: 1710 : if (fr->head == jl_colon_sym) {
619 [ + - + - ]: 701 : if (jl_expr_nargs(fr) > 0 && jl_is_expr(jl_exprarg(fr, 0))) {
620 : 701 : jl_expr_t *path = (jl_expr_t*)jl_exprarg(fr, 0);
621 [ + - ]: 701 : if (((jl_expr_t*)path)->head == jl_dot_sym) {
622 : 701 : jl_sym_t *name = NULL;
623 : 701 : jl_module_t *from = eval_import_path(m, NULL, path->args, &name, keyword);
624 [ + + ]: 701 : if (name != NULL) {
625 : 264 : from = (jl_module_t*)jl_eval_global_var(from, name);
626 [ - + ]: 264 : if (!jl_is_module(from))
627 : 0 : jl_errorf("invalid %s path: \"%s\" does not name a module", keyword, jl_symbol_name(name));
628 : : }
629 : 701 : return from;
630 : : }
631 : : }
632 : 0 : jl_errorf("malformed \"%s:\" statement", keyword);
633 : : }
634 : : }
635 : 1457 : return NULL;
636 : : }
637 : :
638 : 16 : static void check_macro_rename(jl_sym_t *from, jl_sym_t *to, const char *keyword)
639 : : {
640 : 16 : char *n1 = jl_symbol_name(from), *n2 = jl_symbol_name(to);
641 [ + + + + ]: 16 : if (n1[0] == '@' && n2[0] != '@')
642 : 2 : jl_errorf("cannot rename macro \"%s\" to non-macro \"%s\" in \"%s\"", n1, n2, keyword);
643 [ + + + + ]: 14 : if (n1[0] != '@' && n2[0] == '@')
644 : 2 : jl_errorf("cannot rename non-macro \"%s\" to macro \"%s\" in \"%s\"", n1, n2, keyword);
645 : 12 : }
646 : :
647 : : // Format msg and eval `throw(ErrorException(msg)))` in module `m`.
648 : : // Used in `jl_toplevel_eval_flex` instead of `jl_errorf` so that the error
649 : : // location in julia code gets into the backtrace.
650 : 36 : static void jl_eval_errorf(jl_module_t *m, const char* fmt, ...)
651 : : {
652 : 36 : jl_value_t *throw_ex = (jl_value_t*)jl_exprn(jl_call_sym, 2);
653 : 36 : JL_GC_PUSH1(&throw_ex);
654 : 36 : jl_exprargset(throw_ex, 0, jl_builtin_throw);
655 : : va_list args;
656 : 36 : va_start(args, fmt);
657 : 36 : jl_exprargset(throw_ex, 1, jl_vexceptionf(jl_errorexception_type, fmt, args));
658 : 36 : va_end(args);
659 : 36 : jl_toplevel_eval_flex(m, throw_ex, 0, 0);
660 : 0 : JL_GC_POP();
661 : 0 : }
662 : :
663 : 463064 : jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int fast, int expanded)
664 : : {
665 : 463064 : jl_task_t *ct = jl_current_task;
666 [ + + ]: 463064 : if (!jl_is_expr(e)) {
667 [ + + ]: 211450 : if (jl_is_linenode(e)) {
668 : 43446 : jl_lineno = jl_linenode_line(e);
669 : 43446 : jl_value_t *file = jl_linenode_file(e);
670 [ + - ]: 43446 : if (file != jl_nothing) {
671 [ - + ]: 43446 : assert(jl_is_symbol(file));
672 : 43446 : jl_filename = jl_symbol_name((jl_sym_t*)file);
673 : : }
674 : 43446 : return jl_nothing;
675 : : }
676 [ + + ]: 168004 : if (jl_is_symbol(e)) {
677 : 79810 : char *n = jl_symbol_name((jl_sym_t*)e), *n0 = n;
678 [ - + ]: 79810 : while (*n == '_') ++n;
679 [ + + - + ]: 79810 : if (*n == 0 && n > n0)
680 : 0 : jl_eval_errorf(m, "all-underscore identifier used as rvalue");
681 : : }
682 : 168004 : return jl_interpret_toplevel_expr_in(m, e, NULL, NULL);
683 : : }
684 : :
685 : 251614 : jl_expr_t *ex = (jl_expr_t*)e;
686 : :
687 [ + + + + ]: 251614 : if (ex->head == jl_dot_sym && jl_expr_nargs(ex) != 1) {
688 [ - + ]: 3031 : if (jl_expr_nargs(ex) != 2)
689 : 0 : jl_eval_errorf(m, "syntax: malformed \".\" expression");
690 : 3031 : jl_value_t *lhs = jl_exprarg(ex, 0);
691 : 3031 : jl_value_t *rhs = jl_exprarg(ex, 1);
692 : : // only handle `a.b` syntax here, so qualified names can be eval'd in pure contexts
693 [ + + + + ]: 3031 : if (jl_is_quotenode(rhs) && jl_is_symbol(jl_fieldref(rhs, 0))) {
694 : 3028 : return jl_eval_dot_expr(m, lhs, rhs, fast);
695 : : }
696 : : }
697 : :
698 [ - + ]: 248586 : if (ct->ptls->in_pure_callback) {
699 : 0 : jl_error("eval cannot be used in a generated function");
700 : : }
701 : :
702 : 248586 : jl_method_instance_t *mfunc = NULL;
703 : 248586 : jl_code_info_t *thk = NULL;
704 : 248586 : JL_GC_PUSH3(&mfunc, &thk, &ex);
705 : :
706 : 248586 : size_t last_age = ct->world_age;
707 [ + + + + ]: 248586 : if (!expanded && jl_needs_lowering(e)) {
708 : 73316 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
709 : 73316 : ex = (jl_expr_t*)jl_expand_with_loc_warn(e, m, jl_filename, jl_lineno);
710 : 73308 : ct->world_age = last_age;
711 : : }
712 [ + + ]: 248578 : jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL;
713 : :
714 [ + + ]: 248578 : if (head == jl_module_sym) {
715 : 777 : jl_value_t *val = jl_eval_module_expr(m, ex);
716 : 761 : JL_GC_POP();
717 : 761 : return val;
718 : : }
719 [ + + ]: 247801 : else if (head == jl_using_sym) {
720 : 1646 : jl_sym_t *name = NULL;
721 : 1646 : jl_module_t *from = eval_import_from(m, ex, "using");
722 : 1646 : size_t i = 0;
723 [ + + ]: 1646 : if (from) {
724 : 426 : i = 1;
725 : 426 : ex = (jl_expr_t*)jl_exprarg(ex, 0);
726 : : }
727 [ + + ]: 4744 : for (; i < jl_expr_nargs(ex); i++) {
728 : 3108 : jl_value_t *a = jl_exprarg(ex, i);
729 [ + + + + ]: 3108 : if (jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_dot_sym) {
730 : 3104 : name = NULL;
731 : 3104 : jl_module_t *import = eval_import_path(m, from, ((jl_expr_t*)a)->args, &name, "using");
732 : 3097 : jl_module_t *u = import;
733 [ + + ]: 3097 : if (name != NULL)
734 : 1705 : u = (jl_module_t*)jl_eval_global_var(import, name);
735 [ + + ]: 3097 : if (from) {
736 : : // `using A: B` syntax
737 : 1378 : jl_module_use(m, import, name);
738 : : }
739 : : else {
740 [ - + ]: 1719 : if (!jl_is_module(u))
741 : 0 : jl_eval_errorf(m, "invalid using path: \"%s\" does not name a module",
742 : : jl_symbol_name(name));
743 : : // `using A.B` syntax
744 : 1719 : jl_module_using(m, u);
745 [ + + + + ]: 1719 : if (m == jl_main_module && name == NULL) {
746 : : // TODO: for now, `using A` in Main also creates an explicit binding for `A`
747 : : // This will possibly be extended to all modules.
748 : 270 : import_module(m, u, NULL);
749 : : }
750 : : }
751 : 3097 : continue;
752 : : }
753 [ + + + - : 4 : else if (from && jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_as_sym && jl_expr_nargs(a) == 2 &&
+ - + - ]
754 [ + - + - ]: 3 : jl_is_expr(jl_exprarg(a, 0)) && ((jl_expr_t*)jl_exprarg(a, 0))->head == jl_dot_sym) {
755 : 3 : jl_sym_t *asname = (jl_sym_t*)jl_exprarg(a, 1);
756 [ + - ]: 3 : if (jl_is_symbol(asname)) {
757 : 3 : jl_expr_t *path = (jl_expr_t*)jl_exprarg(a, 0);
758 : 3 : name = NULL;
759 : 3 : jl_module_t *import = eval_import_path(m, from, ((jl_expr_t*)path)->args, &name, "using");
760 [ - + ]: 3 : assert(name);
761 : 3 : check_macro_rename(name, asname, "using");
762 : : // `using A: B as C` syntax
763 : 1 : jl_module_use_as(m, import, name, asname);
764 : 1 : continue;
765 : : }
766 : : }
767 : 1 : jl_eval_errorf(m, "syntax: malformed \"using\" statement");
768 : : }
769 : 1636 : JL_GC_POP();
770 : 1636 : return jl_nothing;
771 : : }
772 [ + + ]: 246155 : else if (head == jl_import_sym) {
773 : 512 : jl_sym_t *name = NULL;
774 : 512 : jl_module_t *from = eval_import_from(m, ex, "import");
775 : 512 : size_t i = 0;
776 [ + + ]: 512 : if (from) {
777 : 275 : i = 1;
778 : 275 : ex = (jl_expr_t*)jl_exprarg(ex, 0);
779 : : }
780 [ + + ]: 2496 : for (; i < jl_expr_nargs(ex); i++) {
781 : 1989 : jl_value_t *a = jl_exprarg(ex, i);
782 [ + + + + ]: 1989 : if (jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_dot_sym) {
783 : 1974 : name = NULL;
784 : 1974 : jl_module_t *import = eval_import_path(m, from, ((jl_expr_t*)a)->args, &name, "import");
785 [ + + ]: 1973 : if (name == NULL) {
786 : : // `import A` syntax
787 : 112 : import_module(m, import, NULL);
788 : : }
789 : : else {
790 : : // `import A.B` or `import A: B` syntax
791 : 1861 : jl_module_import(m, import, name);
792 : : }
793 : 1973 : continue;
794 : : }
795 [ + + + - : 15 : else if (jl_is_expr(a) && ((jl_expr_t*)a)->head == jl_as_sym && jl_expr_nargs(a) == 2 &&
+ - ]
796 [ + - + - ]: 14 : jl_is_expr(jl_exprarg(a, 0)) && ((jl_expr_t*)jl_exprarg(a, 0))->head == jl_dot_sym) {
797 : 14 : jl_sym_t *asname = (jl_sym_t*)jl_exprarg(a, 1);
798 [ + + ]: 14 : if (jl_is_symbol(asname)) {
799 : 13 : jl_expr_t *path = (jl_expr_t*)jl_exprarg(a, 0);
800 : 13 : name = NULL;
801 : 13 : jl_module_t *import = eval_import_path(m, from, ((jl_expr_t*)path)->args, &name, "import");
802 [ - + ]: 13 : if (name == NULL) {
803 : : // `import A as B` syntax
804 : 0 : import_module(m, import, asname);
805 : : }
806 : : else {
807 : 13 : check_macro_rename(name, asname, "import");
808 : : // `import A.B as C` syntax
809 : 11 : jl_module_import_as(m, import, name, asname);
810 : : }
811 : 11 : continue;
812 : : }
813 : : }
814 : 2 : jl_eval_errorf(m, "syntax: malformed \"import\" statement");
815 : : }
816 : 507 : JL_GC_POP();
817 : 507 : return jl_nothing;
818 : : }
819 [ + + ]: 245643 : else if (head == jl_export_sym) {
820 [ + + ]: 6313 : for (size_t i = 0; i < jl_array_len(ex->args); i++) {
821 : 4328 : jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, i);
822 [ - + ]: 4328 : if (!jl_is_symbol(name))
823 : 0 : jl_eval_errorf(m, "syntax: malformed \"export\" statement");
824 : 4328 : jl_module_export(m, name);
825 : : }
826 : 1985 : JL_GC_POP();
827 : 1985 : return jl_nothing;
828 : : }
829 [ + + ]: 243658 : else if (head == jl_global_sym) {
830 : 28740 : jl_eval_global_expr(m, ex, 0);
831 : 28740 : JL_GC_POP();
832 : 28740 : return jl_nothing;
833 : : }
834 [ + + ]: 214918 : else if (head == jl_const_sym) {
835 : 31602 : jl_sym_t *arg = (jl_sym_t*)jl_exprarg(ex, 0);
836 : : jl_module_t *gm;
837 : : jl_sym_t *gs;
838 [ - + ]: 31602 : if (jl_is_globalref(arg)) {
839 : 0 : gm = jl_globalref_mod(arg);
840 : 0 : gs = jl_globalref_name(arg);
841 : : }
842 : : else {
843 [ - + ]: 31602 : assert(jl_is_symbol(arg));
844 : 31602 : gm = m;
845 : 31602 : gs = (jl_sym_t*)arg;
846 : : }
847 : 31602 : jl_binding_t *b = jl_get_binding_wr(gm, gs, 1);
848 : 31602 : jl_declare_constant(b);
849 : 31601 : JL_GC_POP();
850 : 31601 : return jl_nothing;
851 : : }
852 [ + + ]: 183316 : else if (head == jl_toplevel_sym) {
853 : 26975 : jl_value_t *res = jl_nothing;
854 : : int i;
855 [ + + ]: 82614 : for (i = 0; i < jl_array_len(ex->args); i++) {
856 : 55784 : res = jl_toplevel_eval_flex(m, jl_array_ptr_ref(ex->args, i), fast, 0);
857 : : }
858 : 26830 : JL_GC_POP();
859 : 26830 : return res;
860 : : }
861 [ + + + + ]: 156341 : else if (head == jl_error_sym || head == jl_incomplete_sym) {
862 [ - + ]: 33 : if (jl_expr_nargs(ex) == 0)
863 : 0 : jl_eval_errorf(m, "malformed \"%s\" expression", jl_symbol_name(head));
864 [ + - ]: 33 : if (jl_is_string(jl_exprarg(ex, 0)))
865 : 33 : jl_eval_errorf(m, "syntax: %s", jl_string_data(jl_exprarg(ex, 0)));
866 : 0 : jl_throw(jl_exprarg(ex, 0));
867 : : }
868 [ + + ]: 156308 : else if (jl_is_symbol(ex)) {
869 : 1 : JL_GC_POP();
870 : 1 : return jl_eval_global_var(m, (jl_sym_t*)ex);
871 : : }
872 [ + + ]: 156307 : else if (head == NULL) {
873 : 20 : JL_GC_POP();
874 : 20 : return (jl_value_t*)ex;
875 : : }
876 : :
877 : 156287 : int has_intrinsics = 0, has_defs = 0, has_loops = 0, has_opaque = 0, forced_compile = 0;
878 [ - + ]: 156287 : assert(head == jl_thunk_sym);
879 : 156287 : thk = (jl_code_info_t*)jl_exprarg(ex, 0);
880 [ - + ]: 156289 : assert(jl_is_code_info(thk));
881 [ - + ]: 156289 : assert(jl_typeis(thk->code, jl_array_any_type));
882 : 156289 : body_attributes((jl_array_t*)thk->code, &has_intrinsics, &has_defs, &has_loops, &has_opaque, &forced_compile);
883 : :
884 : : jl_value_t *result;
885 [ + + + + ]: 156293 : if (forced_compile || has_intrinsics ||
886 [ + + + + : 156074 : (!has_defs && fast && has_loops &&
+ + ]
887 [ + - ]: 904 : jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF &&
888 [ + + + - ]: 1802 : jl_options.compile_enabled != JL_OPTIONS_COMPILE_MIN &&
889 [ + - ]: 1796 : jl_get_module_compile(m) != JL_OPTIONS_COMPILE_OFF &&
890 : 898 : jl_get_module_compile(m) != JL_OPTIONS_COMPILE_MIN)) {
891 : : // use codegen
892 : 1117 : mfunc = method_instance_for_thunk(thk, m);
893 : 1117 : jl_resolve_globals_in_ir((jl_array_t*)thk->code, m, NULL, 0);
894 : : // Don't infer blocks containing e.g. method definitions, since it's probably not
895 : : // worthwhile and also unsound (see #24316).
896 : : // TODO: This is still not correct since an `eval` can happen elsewhere, but it
897 : : // helps in common cases.
898 : 1117 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
899 : 1117 : ct->world_age = world;
900 [ + + + - ]: 1117 : if (!has_defs && jl_get_module_infer(m) != 0) {
901 : 1026 : (void)jl_type_infer(mfunc, world, 0);
902 : : }
903 : 1117 : result = jl_invoke(/*func*/NULL, /*args*/NULL, /*nargs*/0, mfunc);
904 : 1099 : ct->world_age = last_age;
905 : : }
906 : : else {
907 : : // use interpreter
908 [ - + ]: 155176 : assert(thk);
909 [ + + ]: 155176 : if (has_opaque) {
910 : 18 : jl_resolve_globals_in_ir((jl_array_t*)thk->code, m, NULL, 0);
911 : : }
912 : 155176 : result = jl_interpret_toplevel_thunk(m, thk);
913 : : }
914 : :
915 : 156056 : JL_GC_POP();
916 : 156056 : return result;
917 : : }
918 : :
919 : 356642 : JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v)
920 : : {
921 : 356642 : return jl_toplevel_eval_flex(m, v, 1, 0);
922 : : }
923 : :
924 : : // Check module `m` is open for `eval/include`, or throw an error.
925 : 152216 : static void jl_check_open_for(jl_module_t *m, const char* funcname)
926 : : {
927 [ + + + - ]: 152216 : if (jl_options.incremental && jl_generating_output()) {
928 [ + + ]: 2461 : if (m != jl_main_module) { // TODO: this was grand-fathered in
929 : 2375 : JL_LOCK(&jl_modules_mutex);
930 : 2375 : int open = ptrhash_has(&jl_current_modules, (void*)m);
931 [ + + + + ]: 2375 : if (!open && jl_module_init_order != NULL) {
932 : 2 : size_t i, l = jl_array_len(jl_module_init_order);
933 [ + - ]: 4 : for (i = 0; i < l; i++) {
934 [ + + ]: 4 : if (m == (jl_module_t*)jl_array_ptr_ref(jl_module_init_order, i)) {
935 : 2 : open = 1;
936 : 2 : break;
937 : : }
938 : : }
939 : : }
940 : 2375 : JL_UNLOCK(&jl_modules_mutex);
941 [ + + + + ]: 2375 : if (!open && !jl_is__toplevel__mod(m)) {
942 : 2 : const char* name = jl_symbol_name(m->name);
943 : 2 : jl_errorf("Evaluation into the closed module `%s` breaks incremental compilation "
944 : : "because the side effects will not be permanent. "
945 : : "This is likely due to some other module mutating `%s` with `%s` during "
946 : : "precompilation - don't do this.", name, name, funcname);
947 : : }
948 : : }
949 : : }
950 : 152214 : }
951 : :
952 : 4 : JL_DLLEXPORT void jl_check_top_level_effect(jl_module_t *m, char *fname)
953 : : {
954 [ - + ]: 4 : if (jl_current_task->ptls->in_pure_callback)
955 : 0 : jl_errorf("%s cannot be used in a generated function", fname);
956 : 4 : jl_check_open_for(m, fname);
957 : 4 : }
958 : :
959 : 151974 : JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex)
960 : : {
961 : 151974 : jl_task_t *ct = jl_current_task;
962 [ - + ]: 151974 : if (ct->ptls->in_pure_callback)
963 : 0 : jl_error("eval cannot be used in a generated function");
964 : 151974 : jl_check_open_for(m, "eval");
965 : 151972 : jl_value_t *v = NULL;
966 : 151972 : int last_lineno = jl_lineno;
967 : 151972 : const char *last_filename = jl_filename;
968 : 151972 : jl_lineno = 1;
969 : 151972 : jl_filename = "none";
970 [ + + + + ]: 303689 : JL_TRY {
971 : 151972 : v = jl_toplevel_eval(m, ex);
972 : : }
973 [ + - ]: 182 : JL_CATCH {
974 : 182 : jl_lineno = last_lineno;
975 : 182 : jl_filename = last_filename;
976 : 182 : jl_rethrow();
977 : : }
978 : 151717 : jl_lineno = last_lineno;
979 : 151717 : jl_filename = last_filename;
980 [ - + ]: 151717 : assert(v);
981 : 151717 : return v;
982 : : }
983 : :
984 : 24 : JL_DLLEXPORT jl_value_t *jl_infer_thunk(jl_code_info_t *thk, jl_module_t *m)
985 : : {
986 : 24 : jl_method_instance_t *li = method_instance_for_thunk(thk, m);
987 : 24 : JL_GC_PUSH1(&li);
988 : 24 : jl_resolve_globals_in_ir((jl_array_t*)thk->code, m, NULL, 0);
989 : 24 : jl_task_t *ct = jl_current_task;
990 : 24 : jl_code_info_t *src = jl_type_infer(li, ct->world_age, 0);
991 : 24 : JL_GC_POP();
992 [ + - ]: 24 : if (src)
993 : 24 : return src->rettype;
994 : 0 : return (jl_value_t*)jl_any_type;
995 : : }
996 : :
997 : :
998 : : //------------------------------------------------------------------------------
999 : : // Code loading: combined parse+eval for include()
1000 : :
1001 : : // Parse julia code from the string `text` at top level, attributing it to
1002 : : // `filename`. This is used during bootstrap, but the real Base.include() is
1003 : : // implemented in Julia code.
1004 : 238 : static jl_value_t *jl_parse_eval_all(jl_module_t *module, jl_value_t *text,
1005 : : jl_value_t *filename)
1006 : : {
1007 [ + - - + ]: 238 : if (!jl_is_string(text) || !jl_is_string(filename)) {
1008 : 0 : jl_errorf("Expected `String`s for `text` and `filename`");
1009 : : }
1010 : 238 : jl_task_t *ct = jl_current_task;
1011 [ - + ]: 238 : if (ct->ptls->in_pure_callback)
1012 : 0 : jl_error("cannot use include inside a generated function");
1013 : 238 : jl_check_open_for(module, "include");
1014 : :
1015 : 238 : jl_value_t *result = jl_nothing;
1016 : 238 : jl_value_t *ast = NULL;
1017 : 238 : jl_value_t *expression = NULL;
1018 : 238 : JL_GC_PUSH3(&ast, &result, &expression);
1019 : :
1020 : 238 : ast = jl_svecref(jl_parse(jl_string_data(text), jl_string_len(text),
1021 : : filename, 1, 0, (jl_value_t*)jl_all_sym), 0);
1022 [ + - - + ]: 238 : if (!jl_is_expr(ast) || ((jl_expr_t*)ast)->head != jl_toplevel_sym) {
1023 : 0 : jl_errorf("jl_parse_all() must generate a top level expression");
1024 : : }
1025 : :
1026 : 238 : int last_lineno = jl_lineno;
1027 : 238 : const char *last_filename = jl_filename;
1028 : 238 : size_t last_age = ct->world_age;
1029 : 238 : int lineno = 0;
1030 : 238 : jl_lineno = 0;
1031 : 238 : jl_filename = jl_string_data(filename);
1032 : 238 : int err = 0;
1033 : :
1034 [ + - + + ]: 476 : JL_TRY {
1035 [ + + ]: 25106 : for (size_t i = 0; i < jl_expr_nargs(ast); i++) {
1036 : 24868 : expression = jl_exprarg(ast, i);
1037 [ + + ]: 24868 : if (jl_is_linenode(expression)) {
1038 : : // filename is already set above.
1039 : 12434 : lineno = jl_linenode_line(expression);
1040 : 12434 : jl_lineno = lineno;
1041 : 12434 : continue;
1042 : : }
1043 : 12434 : expression = jl_expand_with_loc_warn(expression, module,
1044 : : jl_string_data(filename), lineno);
1045 : 12434 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
1046 : 12434 : result = jl_toplevel_eval_flex(module, expression, 1, 1);
1047 : : }
1048 : : }
1049 [ # # ]: 0 : JL_CATCH {
1050 : 0 : result = jl_box_long(jl_lineno); // (ab)use result to root error line
1051 : 0 : err = 1;
1052 : 0 : goto finally; // skip jl_restore_excstack
1053 : : }
1054 : 0 : finally:
1055 : 238 : ct->world_age = last_age;
1056 : 238 : jl_lineno = last_lineno;
1057 : 238 : jl_filename = last_filename;
1058 [ - + ]: 238 : if (err) {
1059 [ # # ]: 0 : if (jl_loaderror_type == NULL)
1060 : 0 : jl_rethrow();
1061 : : else
1062 : 0 : jl_rethrow_other(jl_new_struct(jl_loaderror_type, filename, result,
1063 : : jl_current_exception()));
1064 : : }
1065 : 238 : JL_GC_POP();
1066 : 238 : return result;
1067 : : }
1068 : :
1069 : : // Synchronously read content of entire file into a julia String
1070 : 238 : static jl_value_t *jl_file_content_as_string(jl_value_t *filename)
1071 : : {
1072 : 238 : const char *fname = jl_string_data(filename);
1073 : : ios_t f;
1074 [ - + ]: 238 : if (ios_file(&f, fname, 1, 0, 0, 0) == NULL)
1075 : 0 : jl_errorf("File \"%s\" not found", fname);
1076 : 238 : ios_bufmode(&f, bm_none);
1077 : 238 : ios_seek_end(&f);
1078 : 238 : size_t len = ios_pos(&f);
1079 : 238 : jl_value_t *text = jl_alloc_string(len);
1080 : 238 : ios_seek(&f, 0);
1081 [ - + ]: 238 : if (ios_readall(&f, jl_string_data(text), len) != len)
1082 : 0 : jl_errorf("Error reading file \"%s\"", fname);
1083 : 238 : ios_close(&f);
1084 : 238 : return text;
1085 : : }
1086 : :
1087 : : // Load and parse julia code from the file `filename`. Eval the resulting
1088 : : // statements into `module` after applying `mapexpr` to each one.
1089 : 238 : JL_DLLEXPORT jl_value_t *jl_load_(jl_module_t *module, jl_value_t *filename)
1090 : : {
1091 : 238 : jl_value_t *text = jl_file_content_as_string(filename);
1092 : 238 : JL_GC_PUSH1(&text);
1093 : 238 : jl_value_t *result = jl_parse_eval_all(module, text, filename);
1094 : 238 : JL_GC_POP();
1095 : 238 : return result;
1096 : : }
1097 : :
1098 : : // Code loading - julia.h C API with native C types
1099 : :
1100 : : // Parse julia code from `filename` and eval into `module`.
1101 : 3 : JL_DLLEXPORT jl_value_t *jl_load(jl_module_t *module, const char *filename)
1102 : : {
1103 : 3 : jl_value_t *filename_ = NULL;
1104 : 3 : JL_GC_PUSH1(&filename_);
1105 : 3 : filename_ = jl_cstr_to_string(filename);
1106 : 3 : jl_value_t *result = jl_load_(module, filename_);
1107 : 3 : JL_GC_POP();
1108 : 3 : return result;
1109 : : }
1110 : :
1111 : : // Parse julia code from the string `text` of length `len`, attributing it to
1112 : : // `filename`. Eval the resulting statements into `module`.
1113 : 0 : JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len,
1114 : : char *filename, jl_module_t *module)
1115 : : {
1116 : 0 : jl_value_t *text_ = NULL;
1117 : 0 : jl_value_t *filename_ = NULL;
1118 : 0 : JL_GC_PUSH2(&text_, &filename_);
1119 : 0 : text_ = jl_pchar_to_string(text, len);
1120 : 0 : filename_ = jl_cstr_to_string(filename);
1121 : 0 : jl_value_t *result = jl_parse_eval_all(module, text_, filename_);
1122 : 0 : JL_GC_POP();
1123 : 0 : return result;
1124 : : }
1125 : :
1126 : :
1127 : : //--------------------------------------------------
1128 : : // Code loading helpers for bootstrap
1129 : :
1130 : 128 : JL_DLLEXPORT jl_value_t *jl_prepend_cwd(jl_value_t *str)
1131 : : {
1132 : 128 : size_t sz = 1024;
1133 : : char path[1024];
1134 : 128 : int c = uv_cwd(path, &sz);
1135 [ - + ]: 128 : if (c < 0) {
1136 : 0 : jl_errorf("could not get current directory");
1137 : : }
1138 : 128 : path[sz] = '/'; // fix later with normpath if Windows
1139 : 128 : const char *fstr = (const char*)jl_string_data(str);
1140 [ - + ]: 128 : if (strlen(fstr) + sz >= 1024) {
1141 : 0 : jl_errorf("use a bigger buffer for jl_fullpath");
1142 : : }
1143 : 128 : strcpy(path + sz + 1, fstr);
1144 : 128 : return jl_cstr_to_string(path);
1145 : : }
1146 : :
1147 : : #ifdef __cplusplus
1148 : : }
1149 : : #endif
|