Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : /*
4 : : modules and top-level bindings
5 : : */
6 : : #include "julia.h"
7 : : #include "julia_internal.h"
8 : : #include "julia_assert.h"
9 : :
10 : : #ifdef __cplusplus
11 : : extern "C" {
12 : : #endif
13 : :
14 : 254 : JL_DLLEXPORT jl_module_t *jl_new_module_(jl_sym_t *name, uint8_t default_names)
15 : : {
16 : 254 : jl_task_t *ct = jl_current_task;
17 : 254 : const jl_uuid_t uuid_zero = {0, 0};
18 : 254 : jl_module_t *m = (jl_module_t*)jl_gc_alloc(ct->ptls, sizeof(jl_module_t),
19 : : jl_module_type);
20 [ - + ]: 254 : assert(jl_is_symbol(name));
21 : 254 : m->name = name;
22 : 254 : m->parent = NULL;
23 : 254 : m->istopmod = 0;
24 : 254 : m->uuid = uuid_zero;
25 : : static unsigned int mcounter; // simple counter backup, in case hrtime is not incrementing
26 : 254 : m->build_id = jl_hrtime() + (++mcounter);
27 [ - + ]: 254 : if (!m->build_id)
28 : 0 : m->build_id++; // build id 0 is invalid
29 : 254 : m->primary_world = 0;
30 : 254 : m->counter = 1;
31 : 254 : m->nospecialize = 0;
32 : 254 : m->optlevel = -1;
33 : 254 : m->compile = -1;
34 : 254 : m->infer = -1;
35 : 254 : m->max_methods = -1;
36 : 254 : JL_MUTEX_INIT(&m->lock);
37 : 254 : htable_new(&m->bindings, 0);
38 : 254 : arraylist_new(&m->usings, 0);
39 : 254 : JL_GC_PUSH1(&m);
40 [ + + + - ]: 254 : if (jl_core_module && default_names) {
41 : 253 : jl_module_using(m, jl_core_module);
42 : : }
43 : : // export own name, so "using Foo" makes "Foo" itself visible
44 [ + - ]: 254 : if (default_names) {
45 : 254 : jl_set_const(m, name, (jl_value_t*)m);
46 : : }
47 : 254 : jl_module_export(m, name);
48 : 254 : JL_GC_POP();
49 : 254 : return m;
50 : : }
51 : :
52 : 248 : JL_DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name)
53 : : {
54 : 248 : return jl_new_module_(name, 1);
55 : : }
56 : :
57 : 9511 : uint32_t jl_module_next_counter(jl_module_t *m)
58 : : {
59 : 9511 : return jl_atomic_fetch_add(&m->counter, 1);
60 : : }
61 : :
62 : 6 : JL_DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name, uint8_t std_imports, uint8_t default_names)
63 : : {
64 : : // TODO: should we prohibit this during incremental compilation?
65 : 6 : jl_module_t *m = jl_new_module_(name, default_names);
66 : 6 : JL_GC_PUSH1(&m);
67 : 6 : m->parent = jl_main_module; // TODO: this is a lie
68 : 6 : jl_gc_wb(m, m->parent);
69 [ + - ]: 6 : if (std_imports)
70 : 6 : jl_add_standard_imports(m);
71 : 6 : JL_GC_POP();
72 : : // TODO: should we somehow try to gc-root this correctly?
73 : 6 : return (jl_value_t*)m;
74 : : }
75 : :
76 : 37 : JL_DLLEXPORT void jl_set_module_nospecialize(jl_module_t *self, int on)
77 : : {
78 [ + + ]: 37 : self->nospecialize = (on ? -1 : 0);
79 : 37 : }
80 : :
81 : 18 : JL_DLLEXPORT void jl_set_module_optlevel(jl_module_t *self, int lvl)
82 : : {
83 : 18 : self->optlevel = lvl;
84 : 18 : }
85 : :
86 : 90315 : JL_DLLEXPORT int jl_get_module_optlevel(jl_module_t *m)
87 : : {
88 : 90315 : int lvl = m->optlevel;
89 [ + + + + : 130058 : while (lvl == -1 && m->parent != m && m != jl_base_module) {
+ + ]
90 : 39743 : m = m->parent;
91 : 39743 : lvl = m->optlevel;
92 : : }
93 : 90315 : return lvl;
94 : : }
95 : :
96 : 14 : JL_DLLEXPORT void jl_set_module_compile(jl_module_t *self, int value)
97 : : {
98 : 14 : self->compile = value;
99 : 14 : }
100 : :
101 : 77862700 : JL_DLLEXPORT int jl_get_module_compile(jl_module_t *m)
102 : : {
103 : 77862700 : int value = m->compile;
104 [ + + + + : 156603000 : while (value == -1 && m->parent != m && m != jl_base_module) {
+ + ]
105 : 78740100 : m = m->parent;
106 : 78740100 : value = m->compile;
107 : : }
108 : 77862700 : return value;
109 : : }
110 : :
111 : 14 : JL_DLLEXPORT void jl_set_module_infer(jl_module_t *self, int value)
112 : : {
113 : 14 : self->infer = value;
114 : : // no reason to specialize if inference is off
115 [ + - ]: 14 : if (!value)
116 : 14 : jl_set_module_nospecialize(self, 1);
117 : 14 : }
118 : :
119 : 235208 : JL_DLLEXPORT int jl_get_module_infer(jl_module_t *m)
120 : : {
121 : 235208 : int value = m->infer;
122 [ + + + + : 284642 : while (value == -1 && m->parent != m && m != jl_base_module) {
+ + ]
123 : 49434 : m = m->parent;
124 : 49434 : value = m->infer;
125 : : }
126 : 235208 : return value;
127 : : }
128 : :
129 : 0 : JL_DLLEXPORT void jl_set_module_max_methods(jl_module_t *self, int value)
130 : : {
131 : 0 : self->max_methods = value;
132 : 0 : }
133 : :
134 : 2821570 : JL_DLLEXPORT int jl_get_module_max_methods(jl_module_t *m)
135 : : {
136 : 2821570 : int value = m->max_methods;
137 [ + - + + : 3488380 : while (value == -1 && m->parent != m && m != jl_base_module) {
+ + ]
138 : 666810 : m = m->parent;
139 : 666810 : value = m->max_methods;
140 : : }
141 : 2821570 : return value;
142 : : }
143 : :
144 : 4 : JL_DLLEXPORT void jl_set_istopmod(jl_module_t *self, uint8_t isprimary)
145 : : {
146 : 4 : self->istopmod = 1;
147 [ + + ]: 4 : if (isprimary) {
148 : 3 : jl_top_module = self;
149 : : }
150 : 4 : }
151 : :
152 : 0 : JL_DLLEXPORT uint8_t jl_istopmod(jl_module_t *mod)
153 : : {
154 : 0 : return mod->istopmod;
155 : : }
156 : :
157 : 69076 : static jl_binding_t *new_binding(jl_sym_t *name)
158 : : {
159 : 69076 : jl_task_t *ct = jl_current_task;
160 [ - + ]: 69076 : assert(jl_is_symbol(name));
161 : 69076 : jl_binding_t *b = (jl_binding_t*)jl_gc_alloc_buf(ct->ptls, sizeof(jl_binding_t));
162 : 69076 : b->name = name;
163 : 69076 : b->value = NULL;
164 : 69076 : b->owner = NULL;
165 : 69076 : b->ty = NULL;
166 : 69076 : b->globalref = NULL;
167 : 69076 : b->constp = 0;
168 : 69076 : b->exportp = 0;
169 : 69076 : b->imported = 0;
170 : 69076 : b->deprecated = 0;
171 : 69076 : return b;
172 : : }
173 : :
174 : : // get binding for assignment
175 : 51561 : JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, int alloc)
176 : : {
177 : 51561 : JL_LOCK(&m->lock);
178 : 51561 : jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var);
179 : 51561 : jl_binding_t *b = *bp;
180 : :
181 [ + + ]: 51561 : if (b != HT_NOTFOUND) {
182 [ + + ]: 23363 : if (b->owner != m) {
183 [ + - ]: 2877 : if (b->owner == NULL) {
184 : 2877 : b->owner = m;
185 : : }
186 [ # # ]: 0 : else if (alloc) {
187 : 0 : JL_UNLOCK(&m->lock);
188 : 0 : jl_errorf("cannot assign a value to imported variable %s.%s from module %s",
189 : 0 : jl_symbol_name(b->owner->name), jl_symbol_name(var), jl_symbol_name(m->name));
190 : : }
191 : : }
192 : : }
193 [ + + ]: 28198 : else if (alloc) {
194 : 27672 : b = new_binding(var);
195 : 27672 : b->owner = m;
196 : 27672 : *bp = b;
197 : : JL_GC_PROMISE_ROOTED(b);
198 : 27672 : jl_gc_wb_buf(m, b, sizeof(jl_binding_t));
199 : : }
200 : : else {
201 : 526 : b = NULL;
202 : : }
203 : :
204 : 51561 : JL_UNLOCK(&m->lock);
205 : 51561 : return b;
206 : : }
207 : :
208 : : // Hash tables don't generically root their contents, but they do for bindings.
209 : : // Express this to the analyzer.
210 : : // NOTE: Must hold m->lock while calling these.
211 : : #ifdef __clang_gcanalyzer__
212 : : jl_binding_t *_jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT;
213 : : #else
214 : 223027000 : static inline jl_binding_t *_jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var) JL_NOTSAFEPOINT
215 : : {
216 : 223027000 : return (jl_binding_t*)ptrhash_get(&m->bindings, var);
217 : : }
218 : : #endif
219 : :
220 : :
221 : : // return module of binding
222 : 6466 : JL_DLLEXPORT jl_module_t *jl_get_module_of_binding(jl_module_t *m, jl_sym_t *var)
223 : : {
224 : 6466 : jl_binding_t *b = jl_get_binding(m, var);
225 [ + + ]: 6466 : if (b == NULL)
226 : 12 : return NULL;
227 : 6454 : return b->owner;
228 : : }
229 : :
230 : : // get binding for adding a method
231 : : // like jl_get_binding_wr, but has different error paths
232 : 89783 : JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var)
233 : : {
234 : 89783 : JL_LOCK(&m->lock);
235 : 89783 : jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var);
236 : 89783 : jl_binding_t *b = *bp;
237 : : JL_GC_PROMISE_ROOTED(b);
238 : :
239 [ + + ]: 89783 : if (b != HT_NOTFOUND) {
240 [ + + ]: 77125 : if (b->owner != m) {
241 [ + + ]: 13064 : if (b->owner == NULL) {
242 : 2694 : b->owner = m;
243 : : }
244 : : else {
245 : 10370 : JL_UNLOCK(&m->lock);
246 : 10370 : jl_binding_t *b2 = jl_get_binding(b->owner, b->name);
247 [ + - - + ]: 10370 : if (b2 == NULL || b2->value == NULL)
248 : 0 : jl_errorf("invalid method definition: imported function %s.%s does not exist",
249 : 0 : jl_symbol_name(b->owner->name), jl_symbol_name(b->name));
250 : : // TODO: we might want to require explicitly importing types to add constructors
251 [ + + - + ]: 10370 : if (!b->imported && !jl_is_type(b2->value)) {
252 : 0 : jl_errorf("error in method definition: function %s.%s must be explicitly imported to be extended",
253 : 0 : jl_symbol_name(b->owner->name), jl_symbol_name(b->name));
254 : : }
255 : 10370 : return b2;
256 : : }
257 : : }
258 : : }
259 : : else {
260 : 12658 : b = new_binding(var);
261 : 12658 : b->owner = m;
262 : 12658 : *bp = b;
263 : : JL_GC_PROMISE_ROOTED(b);
264 : 12658 : jl_gc_wb_buf(m, b, sizeof(jl_binding_t));
265 : : }
266 : :
267 : 79413 : JL_UNLOCK(&m->lock);
268 : 79413 : return b;
269 : : }
270 : :
271 : : static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname,
272 : : int explici);
273 : :
274 : : typedef struct _modstack_t {
275 : : jl_module_t *m;
276 : : jl_sym_t *var;
277 : : struct _modstack_t *prev;
278 : : } modstack_t;
279 : :
280 : : static jl_binding_t *jl_get_binding_(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, modstack_t *st);
281 : :
282 : : static inline jl_module_t *module_usings_getidx(jl_module_t *m JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;
283 : :
284 : : #ifndef __clang_gcanalyzer__
285 : : // The analyzer doesn't like looking through the arraylist, so just model the
286 : : // access for it using this function
287 : 151402 : static inline jl_module_t *module_usings_getidx(jl_module_t *m JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT {
288 : 151402 : return (jl_module_t*)m->usings.items[i];
289 : : }
290 : : #endif
291 : :
292 : : // find a binding from a module's `usings` list
293 : : // called while holding m->lock
294 : 31622 : static jl_binding_t *using_resolve_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, modstack_t *st, int warn)
295 : : {
296 : 31622 : jl_binding_t *b = NULL;
297 : 31622 : jl_module_t *owner = NULL;
298 [ + + ]: 183024 : for(int i=(int)m->usings.len-1; i >= 0; --i) {
299 : 151402 : jl_module_t *imp = module_usings_getidx(m, i);
300 : : // TODO: make sure this can't deadlock
301 : 151402 : JL_LOCK(&imp->lock);
302 : 151402 : jl_binding_t *tempb = _jl_get_module_binding(imp, var);
303 : 151402 : JL_UNLOCK(&imp->lock);
304 [ + + + + ]: 151402 : if (tempb != HT_NOTFOUND && tempb->exportp) {
305 : 20601 : tempb = jl_get_binding_(imp, var, st);
306 [ + + - + ]: 20601 : if (tempb == NULL || tempb->owner == NULL)
307 : : // couldn't resolve; try next using (see issue #6105)
308 : 126 : continue;
309 [ + + + + ]: 20475 : if (owner != NULL && tempb->owner != b->owner &&
310 [ + - + - ]: 10 : !tempb->deprecated && !b->deprecated &&
311 [ + - + - : 10 : !(tempb->constp && tempb->value && b->constp && b->value == tempb->value)) {
+ - - + ]
312 [ # # ]: 0 : if (warn) {
313 : : // mark this binding resolved (by creating it or setting the owner), to avoid repeating the warning
314 : 0 : (void)jl_get_binding_wr(m, var, 1);
315 : 0 : JL_UNLOCK(&m->lock);
316 : 0 : jl_printf(JL_STDERR,
317 : : "WARNING: both %s and %s export \"%s\"; uses of it in module %s must be qualified\n",
318 : : jl_symbol_name(owner->name),
319 : : jl_symbol_name(imp->name), jl_symbol_name(var),
320 : : jl_symbol_name(m->name));
321 : 0 : JL_LOCK(&m->lock);
322 : : }
323 : 0 : return NULL;
324 : : }
325 [ + + + - ]: 20475 : if (owner == NULL || !tempb->deprecated) {
326 : 20475 : owner = imp;
327 : 20475 : b = tempb;
328 : : }
329 : : }
330 : : }
331 : 31622 : return b;
332 : : }
333 : :
334 : : // get binding for reading. might return NULL for unbound.
335 : 221764000 : static jl_binding_t *jl_get_binding_(jl_module_t *m, jl_sym_t *var, modstack_t *st)
336 : : {
337 : 221764000 : modstack_t top = { m, var, st };
338 : 221764000 : modstack_t *tmp = st;
339 [ + + ]: 306033000 : while (tmp != NULL) {
340 [ - + - - ]: 84268100 : if (tmp->m == m && tmp->var == var) {
341 : : // import cycle without finding actual location
342 : 0 : return NULL;
343 : : }
344 : 84268100 : tmp = tmp->prev;
345 : : }
346 : 221764000 : JL_LOCK(&m->lock);
347 : 221764000 : jl_binding_t *b = _jl_get_module_binding(m, var);
348 [ + + + + ]: 221764000 : if (b == HT_NOTFOUND || b->owner == NULL) {
349 : 27591 : b = using_resolve_binding(m, var, &top, 1);
350 : 27591 : JL_UNLOCK(&m->lock);
351 [ + + ]: 27591 : if (b != NULL) {
352 : : // do a full import to prevent the result of this lookup
353 : : // from changing, for example if this var is assigned to
354 : : // later.
355 : 20247 : module_import_(m, b->owner, b->name, var, 0);
356 : 20247 : return b;
357 : : }
358 : 7344 : return NULL;
359 : : }
360 : 221737000 : JL_UNLOCK(&m->lock);
361 [ + + - + ]: 221737000 : if (b->owner != m || b->name != var)
362 : 84245900 : return jl_get_binding_(b->owner, b->name, &top);
363 : 137491000 : return b;
364 : : }
365 : :
366 : : // get owner of binding when accessing m.var, without resolving the binding
367 : 598 : JL_DLLEXPORT jl_value_t *jl_binding_owner(jl_module_t *m, jl_sym_t *var)
368 : : {
369 : 598 : JL_LOCK(&m->lock);
370 : 598 : jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var);
371 [ + + - + ]: 598 : if (b == HT_NOTFOUND || b->owner == NULL)
372 : 91 : b = using_resolve_binding(m, var, NULL, 0);
373 : 598 : JL_UNLOCK(&m->lock);
374 [ + + - + ]: 598 : if (b == NULL || b->owner == NULL)
375 : 43 : return jl_nothing;
376 : 555 : return (jl_value_t*)b->owner;
377 : : }
378 : :
379 : : // get type of binding m.var, without resolving the binding
380 : 20498 : JL_DLLEXPORT jl_value_t *jl_binding_type(jl_module_t *m, jl_sym_t *var)
381 : : {
382 : 20498 : JL_LOCK(&m->lock);
383 : 20498 : jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var);
384 [ + + + + ]: 20498 : if (b == HT_NOTFOUND || b->owner == NULL)
385 : 3940 : b = using_resolve_binding(m, var, NULL, 0);
386 : 20498 : JL_UNLOCK(&m->lock);
387 [ + + ]: 20498 : if (b == NULL)
388 : 3940 : return jl_nothing;
389 : 16558 : jl_value_t *ty = jl_atomic_load_relaxed(&b->ty);
390 [ + + ]: 16558 : return ty ? ty : jl_nothing;
391 : : }
392 : :
393 : 13930 : JL_DLLEXPORT jl_binding_t *jl_get_binding_wr_or_error(jl_module_t *m, jl_sym_t *var)
394 : : {
395 : 13930 : return jl_get_binding_wr(m, var, 1);
396 : : }
397 : :
398 : 137498000 : JL_DLLEXPORT jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var)
399 : : {
400 : 137498000 : return jl_get_binding_(m, var, NULL);
401 : : }
402 : :
403 : 92 : JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var)
404 : : {
405 : 92 : jl_binding_t *b = jl_get_binding(m, var);
406 [ - + ]: 92 : if (b == NULL)
407 : 0 : jl_undefined_var_error(var);
408 [ - + ]: 92 : if (b->deprecated)
409 : 0 : jl_binding_deprecation_warning(m, b);
410 : 92 : return b;
411 : : }
412 : :
413 : 11441800 : JL_DLLEXPORT jl_value_t *jl_module_globalref(jl_module_t *m, jl_sym_t *var)
414 : : {
415 : 11441800 : JL_LOCK(&m->lock);
416 : 11441800 : jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var);
417 [ + + ]: 11441800 : if (b == HT_NOTFOUND) {
418 : 120946 : JL_UNLOCK(&m->lock);
419 : 120946 : return jl_new_struct(jl_globalref_type, m, var);
420 : : }
421 : 11320800 : jl_value_t *globalref = jl_atomic_load_relaxed(&b->globalref);
422 [ + + ]: 11320800 : if (globalref == NULL) {
423 : 35700 : jl_value_t *newref = jl_new_struct(jl_globalref_type, m, var);
424 [ + - ]: 35700 : if (jl_atomic_cmpswap_relaxed(&b->globalref, &globalref, newref)) {
425 : : JL_GC_PROMISE_ROOTED(newref);
426 : 35700 : globalref = newref;
427 : 35700 : jl_gc_wb(m, globalref);
428 : : }
429 : : }
430 : 11320800 : JL_UNLOCK(&m->lock); // may GC
431 : 11320800 : return globalref;
432 : : }
433 : :
434 : 139 : static int eq_bindings(jl_binding_t *a, jl_binding_t *b)
435 : : {
436 [ - + ]: 139 : if (a==b) return 1;
437 [ + - + + ]: 139 : if (a->name == b->name && a->owner == b->owner) return 1;
438 [ + - + - : 69 : if (a->constp && a->value && b->constp && b->value == a->value) return 1;
+ - + - ]
439 : 0 : return 0;
440 : : }
441 : :
442 : : // does module m explicitly import s?
443 : 0 : JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s)
444 : : {
445 : 0 : JL_LOCK(&m->lock);
446 : 0 : jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, s);
447 : 0 : JL_UNLOCK(&m->lock);
448 [ # # # # ]: 0 : return (b != HT_NOTFOUND && b->imported);
449 : : }
450 : :
451 : : // NOTE: we use explici since explicit is a C++ keyword
452 : 23602 : static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname, int explici)
453 : : {
454 : 23602 : jl_binding_t *b = jl_get_binding(from, s);
455 [ - + ]: 23602 : if (b == NULL) {
456 : 0 : jl_printf(JL_STDERR,
457 : : "WARNING: could not import %s.%s into %s\n",
458 : : jl_symbol_name(from->name), jl_symbol_name(s),
459 : : jl_symbol_name(to->name));
460 : : }
461 : : else {
462 [ - + ]: 23602 : if (b->deprecated) {
463 [ # # ]: 0 : if (b->value == jl_nothing) {
464 : 0 : return;
465 : : }
466 [ # # # # ]: 0 : else if (to != jl_main_module && to != jl_base_module &&
467 [ # # ]: 0 : jl_options.depwarn != JL_OPTIONS_DEPWARN_OFF) {
468 : : /* with #22763, external packages wanting to replace
469 : : deprecated Base bindings should simply export the new
470 : : binding */
471 : 0 : jl_printf(JL_STDERR,
472 : : "WARNING: importing deprecated binding %s.%s into %s.\n",
473 : : jl_symbol_name(from->name), jl_symbol_name(s),
474 : : jl_symbol_name(to->name));
475 : : }
476 : : }
477 : :
478 : 23602 : JL_LOCK(&to->lock);
479 : 23602 : jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&to->bindings, asname);
480 : 23602 : jl_binding_t *bto = *bp;
481 [ + + ]: 23602 : if (bto != HT_NOTFOUND) {
482 [ + + ]: 1008 : if (bto == b) {
483 : : // importing a binding on top of itself. harmless.
484 : : }
485 [ - + ]: 1005 : else if (bto->name != s) {
486 : 0 : JL_UNLOCK(&to->lock);
487 : 0 : jl_printf(JL_STDERR,
488 : : "WARNING: ignoring conflicting import of %s.%s into %s\n",
489 : : jl_symbol_name(from->name), jl_symbol_name(s),
490 : : jl_symbol_name(to->name));
491 : 0 : return;
492 : : }
493 [ + + ]: 1005 : else if (bto->owner == b->owner) {
494 : : // already imported
495 : 72 : bto->imported = (explici!=0);
496 : : }
497 [ + - - + ]: 933 : else if (bto->owner != to && bto->owner != NULL) {
498 : : // already imported from somewhere else
499 : 0 : jl_binding_t *bval = jl_get_binding(to, asname);
500 [ # # # # : 0 : if (bval->constp && bval->value && b->constp && b->value == bval->value) {
# # # # ]
501 : : // equivalent binding
502 : 0 : bto->imported = (explici!=0);
503 : 0 : JL_UNLOCK(&to->lock);
504 : : }
505 : : else {
506 : 0 : JL_UNLOCK(&to->lock);
507 : 0 : jl_printf(JL_STDERR,
508 : : "WARNING: ignoring conflicting import of %s.%s into %s\n",
509 : : jl_symbol_name(from->name), jl_symbol_name(s),
510 : : jl_symbol_name(to->name));
511 : : }
512 : 0 : return;
513 : : }
514 [ + - - + ]: 933 : else if (bto->constp || bto->value) {
515 : : // conflict with name owned by destination module
516 [ # # ]: 0 : assert(bto->owner == to);
517 [ # # # # : 0 : if (bto->constp && bto->value && b->constp && b->value == bto->value) {
# # # # ]
518 : : // equivalent binding
519 : 0 : JL_UNLOCK(&to->lock);
520 : : }
521 : : else {
522 : 0 : JL_UNLOCK(&to->lock);
523 : 0 : jl_printf(JL_STDERR,
524 : : "WARNING: import of %s.%s into %s conflicts with an existing identifier; ignored.\n",
525 : : jl_symbol_name(from->name), jl_symbol_name(s),
526 : : jl_symbol_name(to->name));
527 : : }
528 : 0 : return;
529 : : }
530 : : else {
531 : 933 : bto->owner = b->owner;
532 : 933 : bto->imported = (explici!=0);
533 : : }
534 : : }
535 : : else {
536 : 22594 : jl_binding_t *nb = new_binding(b->name);
537 : 22594 : nb->owner = b->owner;
538 : 22594 : nb->imported = (explici!=0);
539 : 22594 : nb->deprecated = b->deprecated;
540 : 22594 : *bp = nb;
541 : 22594 : jl_gc_wb_buf(to, nb, sizeof(jl_binding_t));
542 : : }
543 : 23602 : JL_UNLOCK(&to->lock);
544 : : }
545 : : }
546 : :
547 : 2121 : JL_DLLEXPORT void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s)
548 : : {
549 : 2121 : module_import_(to, from, s, s, 1);
550 : 2121 : }
551 : :
552 : 0 : JL_DLLEXPORT void jl_module_import_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname)
553 : : {
554 : 0 : module_import_(to, from, s, asname, 1);
555 : 0 : }
556 : :
557 : 1234 : JL_DLLEXPORT void jl_module_use(jl_module_t *to, jl_module_t *from, jl_sym_t *s)
558 : : {
559 : 1234 : module_import_(to, from, s, s, 0);
560 : 1234 : }
561 : :
562 : 0 : JL_DLLEXPORT void jl_module_use_as(jl_module_t *to, jl_module_t *from, jl_sym_t *s, jl_sym_t *asname)
563 : : {
564 : 0 : module_import_(to, from, s, asname, 0);
565 : 0 : }
566 : :
567 : 797 : JL_DLLEXPORT void jl_module_using(jl_module_t *to, jl_module_t *from)
568 : : {
569 [ - + ]: 797 : if (to == from)
570 : 0 : return;
571 : 797 : JL_LOCK(&to->lock);
572 [ + + ]: 2526 : for(size_t i=0; i < to->usings.len; i++) {
573 [ + + ]: 1731 : if (from == to->usings.items[i]) {
574 : 2 : JL_UNLOCK(&to->lock);
575 : 2 : return;
576 : : }
577 : : }
578 : : // TODO: make sure this can't deadlock
579 : 795 : JL_LOCK(&from->lock);
580 : : // print a warning if something visible via this "using" conflicts with
581 : : // an existing identifier. note that an identifier added later may still
582 : : // silently override a "using" name. see issue #2054.
583 : 795 : void **table = from->bindings.table;
584 [ + + ]: 4101840 : for(size_t i=1; i < from->bindings.size; i+=2) {
585 [ + + ]: 4101040 : if (table[i] != HT_NOTFOUND) {
586 : 1470880 : jl_binding_t *b = (jl_binding_t*)table[i];
587 [ + + + + : 1470880 : if (b->exportp && (b->owner==from || b->imported)) {
+ + ]
588 : 209839 : jl_sym_t *var = (jl_sym_t*)table[i-1];
589 : 209839 : jl_binding_t **tobp = (jl_binding_t**)ptrhash_bp(&to->bindings, var);
590 [ + + + + ]: 209839 : if (*tobp != HT_NOTFOUND && (*tobp)->owner != NULL &&
591 : : // don't warn for conflicts with the module name itself.
592 : : // see issue #4715
593 [ + + - + ]: 300 : var != to->name &&
594 : 139 : !eq_bindings(jl_get_binding(to,var), b)) {
595 : : // TODO: not ideal to print this while holding module locks
596 : 0 : jl_printf(JL_STDERR,
597 : : "WARNING: using %s.%s in module %s conflicts with an existing identifier.\n",
598 : : jl_symbol_name(from->name), jl_symbol_name(var),
599 : : jl_symbol_name(to->name));
600 : : }
601 : : }
602 : : }
603 : : }
604 : 795 : JL_UNLOCK(&from->lock);
605 : :
606 : 795 : arraylist_push(&to->usings, from);
607 : 795 : jl_gc_wb(to, from);
608 : 795 : JL_UNLOCK(&to->lock);
609 : : }
610 : :
611 : 7463 : JL_DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s)
612 : : {
613 : 7463 : JL_LOCK(&from->lock);
614 : 7463 : jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&from->bindings, s);
615 [ + + ]: 7463 : if (*bp == HT_NOTFOUND) {
616 : 6152 : jl_binding_t *b = new_binding(s);
617 : : // don't yet know who the owner is
618 : 6152 : b->owner = NULL;
619 : 6152 : *bp = b;
620 : 6152 : jl_gc_wb_buf(from, b, sizeof(jl_binding_t));
621 : : }
622 [ - + ]: 7463 : assert(*bp != HT_NOTFOUND);
623 : 7463 : (*bp)->exportp = 1;
624 : 7463 : JL_UNLOCK(&from->lock);
625 : 7463 : }
626 : :
627 : 45810200 : JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var)
628 : : {
629 : 45810200 : jl_binding_t *b = jl_get_binding(m, var);
630 [ + + + + ]: 45810200 : return b && (b->value != NULL);
631 : : }
632 : :
633 : 0 : JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var)
634 : : {
635 : 0 : JL_LOCK(&m->lock);
636 : 0 : jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var);
637 : 0 : JL_UNLOCK(&m->lock);
638 [ # # # # : 0 : return b != HT_NOTFOUND && (b->exportp || b->owner==m);
# # ]
639 : : }
640 : :
641 : 10904 : JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var)
642 : : {
643 : 10904 : JL_LOCK(&m->lock);
644 : 10904 : jl_binding_t *b = _jl_get_module_binding(m, var);
645 : 10904 : JL_UNLOCK(&m->lock);
646 [ + - + + ]: 10904 : return b != HT_NOTFOUND && b->exportp;
647 : : }
648 : :
649 : 1073260 : JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var)
650 : : {
651 : 1073260 : JL_LOCK(&m->lock);
652 : 1073260 : jl_binding_t *b = _jl_get_module_binding(m, var);
653 : 1073260 : JL_UNLOCK(&m->lock);
654 [ + + + + ]: 1073260 : return b != HT_NOTFOUND && b->owner != NULL;
655 : : }
656 : :
657 : 26720 : JL_DLLEXPORT jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var)
658 : : {
659 : 26720 : JL_LOCK(&m->lock);
660 : 26720 : jl_binding_t *b = _jl_get_module_binding(m, var);
661 : 26720 : JL_UNLOCK(&m->lock);
662 [ + + ]: 26720 : return b == HT_NOTFOUND ? NULL : b;
663 : : }
664 : :
665 : 41147100 : JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var)
666 : : {
667 : 41147100 : jl_binding_t *b = jl_get_binding(m, var);
668 [ + + ]: 41147100 : if (b == NULL) return NULL;
669 [ - + ]: 41146800 : if (b->deprecated) jl_binding_deprecation_warning(m, b);
670 : 41146800 : return b->value;
671 : : }
672 : :
673 : 17036 : JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT)
674 : : {
675 : 17036 : jl_binding_t *bp = jl_get_binding_wr(m, var, 1);
676 [ + - ]: 17036 : if (bp->value == NULL) {
677 : 17036 : uint8_t constp = 0;
678 : : // if (jl_atomic_cmpswap(&bp->constp, &constp, 1)) {
679 [ + - ]: 17036 : if (constp = bp->constp, bp->constp = 1, constp == 0) {
680 : 17036 : jl_value_t *old = NULL;
681 [ + - ]: 17036 : if (jl_atomic_cmpswap(&bp->value, &old, val)) {
682 : 17036 : jl_gc_wb_binding(bp, val);
683 : 17036 : return;
684 : : }
685 : : }
686 : 0 : jl_value_t *old_ty = NULL;
687 : 0 : jl_atomic_cmpswap_relaxed(&bp->ty, &old_ty, (jl_value_t*)jl_any_type);
688 : : }
689 : 0 : jl_errorf("invalid redefinition of constant %s",
690 : : jl_symbol_name(bp->name));
691 : : }
692 : :
693 : 45733500 : JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var)
694 : : {
695 : 45733500 : jl_binding_t *b = jl_get_binding(m, var);
696 [ + - + + ]: 45733500 : return b && b->constp;
697 : : }
698 : :
699 : : // set the deprecated flag for a binding:
700 : : // 0=not deprecated, 1=renamed, 2=moved to another package
701 : 0 : JL_DLLEXPORT void jl_deprecate_binding(jl_module_t *m, jl_sym_t *var, int flag)
702 : : {
703 : 0 : jl_binding_t *b = jl_get_binding(m, var);
704 [ # # ]: 0 : if (b) b->deprecated = flag;
705 : 0 : }
706 : :
707 : 75716 : JL_DLLEXPORT int jl_is_binding_deprecated(jl_module_t *m, jl_sym_t *var)
708 : : {
709 [ + - ]: 75716 : if (jl_binding_resolved_p(m, var)) {
710 : 75716 : jl_binding_t *b = jl_get_binding(m, var);
711 [ + - - + ]: 75716 : return b && b->deprecated;
712 : : }
713 : 0 : return 0;
714 : : }
715 : :
716 : : extern const char *jl_filename;
717 : : extern int jl_lineno;
718 : :
719 : : static char const dep_message_prefix[] = "_dep_message_";
720 : :
721 : 0 : static jl_binding_t *jl_get_dep_message_binding(jl_module_t *m, jl_binding_t *deprecated_binding)
722 : : {
723 : 0 : size_t prefix_len = strlen(dep_message_prefix);
724 : 0 : size_t name_len = strlen(jl_symbol_name(deprecated_binding->name));
725 : 0 : char *dep_binding_name = (char*)alloca(prefix_len+name_len+1);
726 : 0 : memcpy(dep_binding_name, dep_message_prefix, prefix_len);
727 : 0 : memcpy(dep_binding_name + prefix_len, jl_symbol_name(deprecated_binding->name), name_len);
728 : 0 : dep_binding_name[prefix_len+name_len] = '\0';
729 : 0 : return jl_get_binding(m, jl_symbol(dep_binding_name));
730 : : }
731 : :
732 : 0 : void jl_binding_deprecation_warning(jl_module_t *m, jl_binding_t *b)
733 : : {
734 : : // Only print a warning for deprecated == 1 (renamed).
735 : : // For deprecated == 2 (moved to a package) the binding is to a function
736 : : // that throws an error, so we don't want to print a warning too.
737 [ # # # # ]: 0 : if (b->deprecated == 1 && jl_options.depwarn) {
738 [ # # ]: 0 : if (jl_options.depwarn != JL_OPTIONS_DEPWARN_ERROR)
739 : 0 : jl_printf(JL_STDERR, "WARNING: ");
740 : 0 : jl_binding_t *dep_message_binding = NULL;
741 [ # # ]: 0 : if (b->owner) {
742 : 0 : jl_printf(JL_STDERR, "%s.%s is deprecated",
743 : 0 : jl_symbol_name(b->owner->name), jl_symbol_name(b->name));
744 : 0 : dep_message_binding = jl_get_dep_message_binding(b->owner, b);
745 : : }
746 : : else {
747 : 0 : jl_printf(JL_STDERR, "%s is deprecated", jl_symbol_name(b->name));
748 : : }
749 : :
750 [ # # # # ]: 0 : if (dep_message_binding && dep_message_binding->value) {
751 [ # # ]: 0 : if (jl_isa(dep_message_binding->value, (jl_value_t*)jl_string_type)) {
752 : 0 : jl_uv_puts(JL_STDERR, jl_string_data(dep_message_binding->value),
753 : 0 : jl_string_len(dep_message_binding->value));
754 : : }
755 : : else {
756 : 0 : jl_static_show(JL_STDERR, dep_message_binding->value);
757 : : }
758 : : }
759 : : else {
760 : 0 : jl_value_t *v = b->value;
761 [ # # ]: 0 : if (v) {
762 [ # # # # ]: 0 : if (jl_is_type(v) || jl_is_module(v)) {
763 : 0 : jl_printf(JL_STDERR, ", use ");
764 : 0 : jl_static_show(JL_STDERR, v);
765 : 0 : jl_printf(JL_STDERR, " instead.");
766 : : }
767 : : else {
768 : 0 : jl_methtable_t *mt = jl_gf_mtable(v);
769 [ # # # # : 0 : if (mt != NULL && (mt->defs != jl_nothing ||
# # ]
770 : 0 : jl_isa(v, (jl_value_t*)jl_builtin_type))) {
771 : 0 : jl_printf(JL_STDERR, ", use ");
772 [ # # ]: 0 : if (mt->module != jl_core_module) {
773 : 0 : jl_static_show(JL_STDERR, (jl_value_t*)mt->module);
774 : 0 : jl_printf(JL_STDERR, ".");
775 : : }
776 : 0 : jl_printf(JL_STDERR, "%s", jl_symbol_name(mt->name));
777 : 0 : jl_printf(JL_STDERR, " instead.");
778 : : }
779 : : }
780 : : }
781 : : }
782 : 0 : jl_printf(JL_STDERR, "\n");
783 : :
784 [ # # ]: 0 : if (jl_options.depwarn != JL_OPTIONS_DEPWARN_ERROR) {
785 [ # # ]: 0 : if (jl_lineno == 0) {
786 : 0 : jl_printf(JL_STDERR, " in module %s\n", jl_symbol_name(m->name));
787 : : }
788 : : else {
789 : 0 : jl_printf(JL_STDERR, " likely near %s:%d\n", jl_filename, jl_lineno);
790 : : }
791 : : }
792 : :
793 [ # # ]: 0 : if (jl_options.depwarn == JL_OPTIONS_DEPWARN_ERROR) {
794 [ # # ]: 0 : if (b->owner)
795 : 0 : jl_errorf("deprecated binding: %s.%s",
796 : 0 : jl_symbol_name(b->owner->name),
797 : : jl_symbol_name(b->name));
798 : : else
799 : 0 : jl_errorf("deprecated binding: %s", jl_symbol_name(b->name));
800 : : }
801 : : }
802 : 0 : }
803 : :
804 : 13927 : JL_DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs)
805 : : {
806 : 13927 : jl_value_t *old_ty = NULL;
807 [ + + ]: 13927 : if (!jl_atomic_cmpswap_relaxed(&b->ty, &old_ty, (jl_value_t*)jl_any_type)) {
808 [ + + + + ]: 847 : if (old_ty != (jl_value_t*)jl_any_type && jl_typeof(rhs) != old_ty) {
809 : 6 : JL_GC_PUSH1(&rhs);
810 [ - + ]: 6 : if (!jl_isa(rhs, old_ty))
811 : 0 : jl_errorf("cannot assign an incompatible value to the global %s.",
812 : : jl_symbol_name(b->name));
813 : 6 : JL_GC_POP();
814 : : }
815 : : }
816 [ + + ]: 13927 : if (b->constp) {
817 : 13204 : jl_value_t *old = NULL;
818 [ + + ]: 13204 : if (jl_atomic_cmpswap(&b->value, &old, rhs)) {
819 : 12756 : jl_gc_wb_binding(b, rhs);
820 : 13204 : return;
821 : : }
822 [ + - ]: 448 : if (jl_egal(rhs, old))
823 : 448 : return;
824 [ # # # # : 0 : if (jl_typeof(rhs) != jl_typeof(old) || jl_is_type(rhs) || jl_is_module(rhs)) {
# # ]
825 : : #ifndef __clang_gcanalyzer__
826 : 0 : jl_errorf("invalid redefinition of constant %s",
827 : : jl_symbol_name(b->name));
828 : : #endif
829 : : }
830 : 0 : jl_safe_printf("WARNING: redefinition of constant %s. This may fail, cause incorrect answers, or produce other errors.\n",
831 : : jl_symbol_name(b->name));
832 : : }
833 : 723 : jl_atomic_store_release(&b->value, rhs);
834 : 723 : jl_gc_wb_binding(b, rhs);
835 : : }
836 : :
837 : 13473 : JL_DLLEXPORT void jl_declare_constant(jl_binding_t *b)
838 : : {
839 [ + + - + ]: 13473 : if (b->value != NULL && !b->constp) {
840 : 0 : jl_errorf("cannot declare %s constant; it already has a value",
841 : : jl_symbol_name(b->name));
842 : : }
843 : 13473 : b->constp = 1;
844 : 13473 : }
845 : :
846 : 2 : JL_DLLEXPORT jl_value_t *jl_module_usings(jl_module_t *m)
847 : : {
848 : 2 : jl_array_t *a = jl_alloc_array_1d(jl_array_any_type, 0);
849 : 2 : JL_GC_PUSH1(&a);
850 : 2 : JL_LOCK(&m->lock);
851 [ + + ]: 8 : for(int i=(int)m->usings.len-1; i >= 0; --i) {
852 : 6 : jl_array_grow_end(a, 1);
853 : 6 : jl_module_t *imp = (jl_module_t*)m->usings.items[i];
854 : 6 : jl_array_ptr_set(a,jl_array_dim0(a)-1, (jl_value_t*)imp);
855 : : }
856 : 2 : JL_UNLOCK(&m->lock);
857 : 2 : JL_GC_POP();
858 : 2 : return (jl_value_t*)a;
859 : : }
860 : :
861 : 128 : JL_DLLEXPORT jl_value_t *jl_module_names(jl_module_t *m, int all, int imported)
862 : : {
863 : 128 : jl_array_t *a = jl_alloc_array_1d(jl_array_symbol_type, 0);
864 : 128 : JL_GC_PUSH1(&a);
865 : : size_t i;
866 : 128 : JL_LOCK(&m->lock);
867 : 128 : void **table = m->bindings.table;
868 [ + + ]: 1307840 : for (i = 1; i < m->bindings.size; i+=2) {
869 [ + + ]: 1307710 : if (table[i] != HT_NOTFOUND) {
870 : 485010 : jl_binding_t *b = (jl_binding_t*)table[i];
871 : 485010 : int hidden = jl_symbol_name(b->name)[0]=='#';
872 [ + + + + ]: 485010 : if ((b->exportp ||
873 [ + + ]: 36 : (imported && b->imported) ||
874 [ + + + + : 485010 : (b->owner == m && !b->imported && (all || m == jl_main_module))) &&
+ + - + +
+ ]
875 [ + - + - ]: 77604 : (all || (!b->deprecated && !hidden))) {
876 : 77622 : jl_sym_t *in_module_name = (jl_sym_t*)table[i-1]; // the name in the module may not be b->name, use the httable key instead
877 : 77622 : jl_array_grow_end(a, 1);
878 : : //XXX: change to jl_arrayset if array storage allocation for Array{Symbols,1} changes:
879 : 77622 : jl_array_ptr_set(a, jl_array_dim0(a)-1, (jl_value_t*)in_module_name);
880 : : }
881 : : }
882 : : }
883 : 128 : JL_UNLOCK(&m->lock);
884 : 128 : JL_GC_POP();
885 : 128 : return (jl_value_t*)a;
886 : : }
887 : :
888 : 7935 : JL_DLLEXPORT jl_sym_t *jl_module_name(jl_module_t *m) { return m->name; }
889 : 807 : JL_DLLEXPORT jl_module_t *jl_module_parent(jl_module_t *m) { return m->parent; }
890 : 80 : JL_DLLEXPORT uint64_t jl_module_build_id(jl_module_t *m) { return m->build_id; }
891 : 582 : JL_DLLEXPORT jl_uuid_t jl_module_uuid(jl_module_t* m) { return m->uuid; }
892 : :
893 : : // TODO: make this part of the module constructor and read-only?
894 : 164 : JL_DLLEXPORT void jl_set_module_uuid(jl_module_t *m, jl_uuid_t uuid) { m->uuid = uuid; }
895 : :
896 : 4682090 : int jl_is_submodule(jl_module_t *child, jl_module_t *parent) JL_NOTSAFEPOINT
897 : : {
898 : : while (1) {
899 [ + + ]: 4682090 : if (parent == child)
900 : 2943620 : return 1;
901 [ + - + + ]: 1738460 : if (child == NULL || child == child->parent)
902 : 1047150 : return 0;
903 : 691314 : child = child->parent;
904 : : }
905 : : }
906 : :
907 : : // Remove implicitly imported identifiers, effectively resetting all the binding
908 : : // resolution decisions for a module. This is dangerous, and should only be
909 : : // done for modules that are essentially empty anyway. The only use case for this
910 : : // is to leave `Main` as empty as possible in the default system image.
911 : 2 : JL_DLLEXPORT void jl_clear_implicit_imports(jl_module_t *m)
912 : : {
913 : : size_t i;
914 : 2 : JL_LOCK(&m->lock);
915 : 2 : void **table = m->bindings.table;
916 [ + + ]: 130 : for (i = 1; i < m->bindings.size; i+=2) {
917 [ + + ]: 128 : if (table[i] != HT_NOTFOUND) {
918 : 86 : jl_binding_t *b = (jl_binding_t*)table[i];
919 [ + + + + ]: 86 : if (b->owner != m && !b->imported)
920 : 74 : table[i] = HT_NOTFOUND;
921 : : }
922 : : }
923 : 2 : JL_UNLOCK(&m->lock);
924 : 2 : }
925 : :
926 : : #ifdef __cplusplus
927 : : }
928 : : #endif
|