// get binding for assignment DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b; if (*bp != HT_NOTFOUND) { if ((*bp)->owner == NULL) { (*bp)->owner = m; return *bp; } else if ((*bp)->owner != m) { // TODO: change this to an error soon jl_printf(JL_STDERR, "Warning: imported binding for %s overwritten in module %s\n", var->name, m->name->name); } else { return *bp; } } b = new_binding(var); b->owner = m; *bp = b; jl_gc_wb_buf(m, b); return *bp; }
// get binding for adding a method // like jl_get_binding_wr, but uses existing imports instead of warning // and overwriting. DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b = *bp; if (b != HT_NOTFOUND) { if (b->owner != m && b->owner != NULL) { jl_binding_t *b2 = jl_get_binding(b->owner, var); if (b2 == NULL) jl_errorf("invalid method definition: imported function %s.%s does not exist", b->owner->name->name, var->name); if (!b->imported && (b2->value==NULL || jl_is_function(b2->value))) { if (b2->value && !jl_is_gf(b2->value)) { jl_errorf("error in method definition: %s.%s cannot be extended", b->owner->name->name, var->name); } else { jl_errorf("error in method definition: function %s.%s must be explicitly imported to be extended", b->owner->name->name, var->name); } } return b2; } b->owner = m; return b; } b = new_binding(var); b->owner = m; *bp = b; jl_gc_wb_buf(m, b); return *bp; }
// get binding for adding a method // like jl_get_binding_wr, but uses existing imports instead of warning // and overwriting. JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b = *bp; if (b != HT_NOTFOUND) { if (b->owner != m && b->owner != NULL) { jl_binding_t *b2 = jl_get_binding(b->owner, var); if (b2 == NULL) jl_errorf("invalid method definition: imported function %s.%s does not exist", jl_symbol_name(b->owner->name), jl_symbol_name(var)); // TODO: we might want to require explicitly importing types to add constructors if (!b->imported && (b2->value == NULL || !jl_is_type(b2->value))) { jl_errorf("error in method definition: function %s.%s must be explicitly imported to be extended", jl_symbol_name(b->owner->name), jl_symbol_name(var)); } return b2; } b->owner = m; return b; } b = new_binding(var); b->owner = m; *bp = b; jl_gc_wb_buf(m, b, sizeof(jl_binding_t)); return *bp; }
// NOTE: we use explici since explicit is a C++ keyword static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, int explici) { if (to == from) return; jl_binding_t *b = jl_get_binding(from, s); if (b == NULL) { jl_printf(JL_STDERR, "Warning: could not import %s.%s into %s\n", from->name->name, s->name, to->name->name); } else { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&to->bindings, s); jl_binding_t *bto = *bp; if (bto != HT_NOTFOUND) { if (bto == b) { // importing a binding on top of itself. harmless. } else if (bto->owner == b->owner) { // already imported bto->imported = (explici!=0); } else if (bto->owner != to && bto->owner != NULL) { // already imported from somewhere else jl_binding_t *bval = jl_get_binding(to, s); if (bval->constp && bval->value && b->constp && b->value == bval->value) { // equivalent binding bto->imported = (explici!=0); return; } jl_printf(JL_STDERR, "Warning: ignoring conflicting import of %s.%s into %s\n", from->name->name, s->name, to->name->name); } else if (bto->constp || bto->value) { // conflict with name owned by destination module assert(bto->owner == to); if (bto->constp && bto->value && b->constp && b->value == bto->value) { // equivalent binding return; } jl_printf(JL_STDERR, "Warning: import of %s.%s into %s conflicts with an existing identifier; ignored.\n", from->name->name, s->name, to->name->name); } else { bto->owner = b->owner; bto->imported = (explici!=0); } } else { jl_binding_t *nb = new_binding(s); nb->owner = b->owner; nb->imported = (explici!=0); *bp = nb; jl_gc_wb_buf(to, nb); } } }
// get binding for adding a method // like jl_get_binding_wr, but uses existing imports instead of warning // and overwriting. JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m, jl_sym_t *var) { if (jl_base_module && m->std_imports && !jl_binding_resolved_p(m,var)) { jl_module_t *opmod = (jl_module_t*)jl_get_global(jl_base_module, jl_symbol("Operators")); if (opmod != NULL && jl_defines_or_exports_p(opmod, var)) { jl_printf(JL_STDERR, "WARNING: module %s should explicitly import %s from %s\n", jl_symbol_name(m->name), jl_symbol_name(var), jl_symbol_name(jl_base_module->name)); jl_module_import(m, opmod, var); } } jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b = *bp; if (b != HT_NOTFOUND) { if (b->owner != m && b->owner != NULL) { jl_binding_t *b2 = jl_get_binding(b->owner, var); if (b2 == NULL) jl_errorf("invalid method definition: imported function %s.%s does not exist", jl_symbol_name(b->owner->name), jl_symbol_name(var)); if (!b->imported && (b2->value==NULL || jl_is_function(b2->value))) { if (b2->value && !jl_is_gf(b2->value)) { jl_errorf("error in method definition: %s.%s cannot be extended", jl_symbol_name(b->owner->name), jl_symbol_name(var)); } else { if (jl_base_module && m->std_imports && b->owner == jl_base_module) { jl_module_t *opmod = (jl_module_t*)jl_get_global(jl_base_module, jl_symbol("Operators")); if (opmod != NULL && jl_defines_or_exports_p(opmod, var)) { jl_printf(JL_STDERR, "WARNING: module %s should explicitly import %s from %s\n", jl_symbol_name(m->name), jl_symbol_name(var), jl_symbol_name(b->owner->name)); return b2; } } jl_errorf("error in method definition: function %s.%s must be explicitly imported to be extended", jl_symbol_name(b->owner->name), jl_symbol_name(var)); } } return b2; } b->owner = m; return b; } b = new_binding(var); b->owner = m; *bp = b; jl_gc_wb_buf(m, b); return *bp; }
void jl_module_export(jl_module_t *from, jl_sym_t *s) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&from->bindings, s); if (*bp == HT_NOTFOUND) { jl_binding_t *b = new_binding(s); // don't yet know who the owner is b->owner = NULL; *bp = b; jl_gc_wb_buf(from, b); } assert(*bp != HT_NOTFOUND); (*bp)->exportp = 1; }
// Resize the buffer to a max size of `newlen` // The buffer can either be newly allocated or realloc'd, the return // value is 1 if a new buffer is allocated and 0 if it is realloc'd. // the caller needs to take care of moving the data from the old buffer // to the new one if necessary. // When this function returns, the `->data` pointer always points to // the **beginning** of the new buffer. static int NOINLINE array_resize_buffer(jl_array_t *a, size_t newlen) { jl_ptls_t ptls = jl_get_ptls_states(); assert(!a->flags.isshared || a->flags.how == 3); size_t elsz = a->elsize; size_t nbytes = newlen * elsz; size_t oldnbytes = a->maxsize * elsz; size_t oldoffsnb = a->offset * elsz; size_t oldlen = a->nrows; assert(nbytes >= oldnbytes); if (elsz == 1) { nbytes++; oldnbytes++; } int newbuf = 0; if (a->flags.how == 2) { // already malloc'd - use realloc char *olddata = (char*)a->data - oldoffsnb; a->data = jl_gc_managed_realloc(olddata, nbytes, oldnbytes, a->flags.isaligned, (jl_value_t*)a); } else { newbuf = 1; if ( #ifdef _P64 nbytes >= MALLOC_THRESH #else elsz > 4 #endif ) { a->data = jl_gc_managed_malloc(nbytes); jl_gc_track_malloced_array(ptls, a); a->flags.how = 2; a->flags.isaligned = 1; } else { a->data = jl_gc_alloc_buf(ptls, nbytes); a->flags.how = 1; jl_gc_wb_buf(a, a->data, nbytes); } } if (JL_ARRAY_IMPL_NUL && elsz == 1) memset((char*)a->data + oldnbytes - 1, 0, nbytes - oldnbytes + 1); (void)oldlen; assert(oldlen == a->nrows && "Race condition detected: recursive resizing on the same array."); a->flags.isshared = 0; a->maxsize = newlen; return newbuf; }
// allocate buffer of newlen elements, placing old data at given offset (in #elts) // newlen: new length (#elts), including offset // oldlen: old length (#elts), excluding offset // offs: new offset static void array_resize_buffer(jl_array_t *a, size_t newlen, size_t oldlen, size_t offs) { size_t es = a->elsize; size_t nbytes = newlen * es; size_t offsnb = offs * es; size_t oldnbytes = oldlen * es; size_t oldoffsnb = a->offset * es; if (es == 1) nbytes++; assert(!a->isshared || a->how==3); char *newdata; if (a->how == 2) { // already malloc'd - use realloc newdata = (char*)jl_gc_managed_realloc((char*)a->data - oldoffsnb, nbytes, oldnbytes+oldoffsnb, a->isaligned, (jl_value_t*)a); if (offs != a->offset) { memmove(&newdata[offsnb], &newdata[oldoffsnb], oldnbytes); } } else { if ( #ifdef _P64 nbytes >= MALLOC_THRESH #else es > 4 #endif ) { newdata = (char*)jl_gc_managed_malloc(nbytes); jl_gc_track_malloced_array(a); a->how = 2; a->isaligned = 1; } else { newdata = (char*)allocb(nbytes); a->how = 1; } memcpy(newdata + offsnb, (char*)a->data, oldnbytes); } a->data = newdata + offsnb; a->isshared = 0; if (a->ptrarray || es==1) memset(newdata+offsnb+oldnbytes, 0, nbytes-oldnbytes-offsnb); if (a->how == 1) jl_gc_wb_buf(a, newdata); a->maxsize = newlen; }
// get binding for assignment JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var, int error) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b = *bp; if (b != HT_NOTFOUND) { if (b->owner != m) { if (b->owner == NULL) { b->owner = m; } else if (error) { jl_errorf("cannot assign variable %s.%s from module %s", jl_symbol_name(b->owner->name), jl_symbol_name(var), jl_symbol_name(m->name)); } } return *bp; } b = new_binding(var); b->owner = m; *bp = b; jl_gc_wb_buf(m, b, sizeof(jl_binding_t)); return *bp; }