static jl_fptr_t jl_deserialize_fptr(ios_t *s) { int fptr = read_uint16(s); if (fptr == 0) return NULL; void **pbp = ptrhash_bp(&id_to_fptr, (void*)(ptrint_t)fptr); if (*pbp == HT_NOTFOUND) jl_error("unknown function pointer ID"); return *(jl_fptr_t*)pbp; }
void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) { jl_value_t **bp = (jl_value_t**)ptrhash_bp(&finalizer_table, v); if (*bp == HT_NOTFOUND) { *bp = (jl_value_t*)f; } else { *bp = (jl_value_t*)jl_tuple2((jl_value_t*)f, *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) { 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; } assert(*bp != HT_NOTFOUND); (*bp)->exportp = 1; }
static void module_import_(jl_module_t *to, jl_module_t *from, jl_sym_t *s, int explicit) { if (to == from) return; jl_binding_t *b = jl_get_binding(from, s); if (b == NULL) { ios_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 = (explicit!=0); } else if (bto->owner != to && bto->owner != NULL) { ios_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) { assert(bto->owner == to); if (bto->constp && bto->value && b->constp && b->value == bto->value) { // import of equivalent binding return; } ios_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 = (explicit!=0); } }
jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); if (*bp == HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)allocb(sizeof(jl_binding_t)); b->name = var; b->value = NULL; b->type = (jl_type_t*)jl_any_type; b->constp = 0; b->exportp = 0; *bp = b; // keep track of all variables added after the VARIABLES array // is defined if (varlist_binding && varlist_binding->value != NULL && jl_typeis(varlist_binding->value, jl_array_any_type)) { jl_array_t *a = (jl_array_t*)varlist_binding->value; jl_cell_1d_push(a, (jl_value_t*)var); } } return *bp; }
// get binding for adding a method // like jl_get_binding_wr, but uses existing imports instead of warning // and overwriting. 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) 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; return *bp; }
// 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; }
JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); if (*bp == HT_NOTFOUND) return 0; return (*bp)->exportp; }
void jl_set_expander(jl_module_t *m, jl_sym_t *macroname, jl_function_t *f) { jl_function_t **bp = (jl_function_t**)ptrhash_bp(&m->macros, macroname); *bp = f; }
static jl_value_t *jl_deserialize_value(ios_t *s) { int pos = ios_pos(s); int32_t tag = read_uint8(s); if (tag == Null_tag) return NULL; if (tag == 0) { tag = read_uint8(s); jl_value_t *v = ptrhash_get(&deser_tag, (void*)(ptrint_t)tag); assert(v != HT_NOTFOUND); return v; } if (tag == BackRef_tag || tag == ShortBackRef_tag) { assert(tree_literal_values == NULL); ptrint_t offs = (tag == BackRef_tag) ? read_int32(s) : read_uint16(s); void **bp = ptrhash_bp(&backref_table, (void*)(ptrint_t)offs); assert(*bp != HT_NOTFOUND); return (jl_value_t*)*bp; } jl_value_t *vtag=(jl_value_t*)ptrhash_get(&deser_tag,(void*)(ptrint_t)tag); if (tag >= VALUE_TAGS) { return vtag; } int usetable = (tree_literal_values == NULL); size_t i; if (vtag == (jl_value_t*)jl_tuple_type || vtag == (jl_value_t*)LongTuple_tag) { size_t len; if (vtag == (jl_value_t*)jl_tuple_type) len = read_uint8(s); else len = read_int32(s); jl_tuple_t *tu = jl_alloc_tuple_uninit(len); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)tu); for(i=0; i < len; i++) jl_tupleset(tu, i, jl_deserialize_value(s)); return (jl_value_t*)tu; } else if (vtag == (jl_value_t*)jl_symbol_type || vtag == (jl_value_t*)LongSymbol_tag) { size_t len; if (vtag == (jl_value_t*)jl_symbol_type) len = read_uint8(s); else len = read_int32(s); char *name = alloca(len+1); ios_read(s, name, len); name[len] = '\0'; jl_value_t *s = (jl_value_t*)jl_symbol(name); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, s); return s; } else if (vtag == (jl_value_t*)jl_array_type) { jl_value_t *aty = jl_deserialize_value(s); jl_value_t *elty = jl_tparam0(aty); int16_t ndims = jl_unbox_long(jl_tparam1(aty)); size_t *dims = alloca(ndims*sizeof(size_t)); for(i=0; i < ndims; i++) dims[i] = jl_unbox_long(jl_deserialize_value(s)); jl_array_t *a = jl_new_array_((jl_type_t*)aty, ndims, dims); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)a); if (jl_is_bits_type(elty)) { size_t tot = jl_array_len(a) * a->elsize; ios_read(s, jl_array_data(a), tot); } else { for(i=0; i < jl_array_len(a); i++) { ((jl_value_t**)a->data)[i] = jl_deserialize_value(s); } } return (jl_value_t*)a; } else if (vtag == (jl_value_t*)jl_expr_type || vtag == (jl_value_t*)LongExpr_tag) { size_t len; if (vtag == (jl_value_t*)jl_expr_type) len = read_uint8(s); else len = read_int32(s); jl_expr_t *e = jl_exprn((jl_sym_t*)jl_deserialize_value(s), len); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)e); e->etype = jl_deserialize_value(s); for(i=0; i < len; i++) { jl_cellset(e->args, i, jl_deserialize_value(s)); } return (jl_value_t*)e; } else if (vtag == (jl_value_t*)LiteralVal_tag) { return jl_cellref(tree_literal_values, read_uint16(s)); } else if (vtag == (jl_value_t*)jl_tvar_type) { jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_type_t*)jl_tvar_type, 4); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, tv); tv->name = (jl_sym_t*)jl_deserialize_value(s); tv->lb = jl_deserialize_value(s); tv->ub = jl_deserialize_value(s); tv->bound = read_int8(s); return (jl_value_t*)tv; } else if (vtag == (jl_value_t*)jl_function_type) { jl_function_t *f = (jl_function_t*)newobj((jl_type_t*)jl_function_type, 3); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, f); f->linfo = (jl_lambda_info_t*)jl_deserialize_value(s); f->env = jl_deserialize_value(s); f->fptr = jl_deserialize_fptr(s); return (jl_value_t*)f; } else if (vtag == (jl_value_t*)jl_lambda_info_type) { jl_lambda_info_t *li = (jl_lambda_info_t*)newobj((jl_type_t*)jl_lambda_info_type, LAMBDA_INFO_NW); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, li); li->ast = jl_deserialize_value(s); li->sparams = (jl_tuple_t*)jl_deserialize_value(s); li->tfunc = jl_deserialize_value(s); li->name = (jl_sym_t*)jl_deserialize_value(s); li->specTypes = (jl_tuple_t*)jl_deserialize_value(s); li->specializations = (jl_array_t*)jl_deserialize_value(s); li->inferred = read_int8(s); li->file = jl_deserialize_value(s); li->line = read_int32(s); li->module = (jl_module_t*)jl_deserialize_value(s); li->roots = (jl_array_t*)jl_deserialize_value(s); li->def = (jl_lambda_info_t*)jl_deserialize_value(s); li->capt = jl_deserialize_value(s); li->fptr = &jl_trampoline; li->functionObject = NULL; li->cFunctionObject = NULL; li->inInference = 0; li->inCompile = 0; li->unspecialized = NULL; return (jl_value_t*)li; } else if (vtag == (jl_value_t*)jl_module_type) { jl_sym_t *mname = (jl_sym_t*)jl_deserialize_value(s); jl_module_t *m = jl_new_module(mname); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, m); m->parent = (jl_module_t*)jl_deserialize_value(s); while (1) { jl_value_t *name = jl_deserialize_value(s); if (name == NULL) break; jl_binding_t *b = jl_get_binding_wr(m, (jl_sym_t*)name); b->value = jl_deserialize_value(s); b->type = (jl_type_t*)jl_deserialize_value(s); b->owner = (jl_module_t*)jl_deserialize_value(s); int8_t flags = read_int8(s); b->constp = (flags>>2) & 1; b->exportp = (flags>>1) & 1; b->imported = (flags) & 1; } size_t ni = read_int32(s); for(size_t i=0; i < ni; i++) { arraylist_push(&m->usings, jl_deserialize_value(s)); } return (jl_value_t*)m; }
// 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", jl_symbol_name(from->name), jl_symbol_name(s), jl_symbol_name(to->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", jl_symbol_name(from->name), jl_symbol_name(s), jl_symbol_name(to->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", jl_symbol_name(from->name), jl_symbol_name(s), jl_symbol_name(to->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); nb->deprecated = b->deprecated; *bp = nb; jl_gc_wb_buf(to, nb); } } }
static jl_value_t *jl_deserialize_value(ios_t *s) { int pos = ios_pos(s); int32_t tag = read_uint8(s); if (tag == Null_tag) return NULL; if (tag == 0) { tag = read_uint8(s); return (jl_value_t*)ptrhash_get(&deser_tag, (void*)(ptrint_t)tag); } if (tag == BackRef_tag) { assert(tree_literal_values == NULL); ptrint_t offs = read_int32(s); void **bp = ptrhash_bp(&backref_table, (void*)(ptrint_t)offs); assert(*bp != HT_NOTFOUND); return (jl_value_t*)*bp; } jl_value_t *vtag=(jl_value_t*)ptrhash_get(&deser_tag,(void*)(ptrint_t)tag); if (tag >= VALUE_TAGS) { return vtag; } int usetable = (tree_literal_values == NULL); size_t i; if (vtag == (jl_value_t*)jl_tuple_type || vtag == (jl_value_t*)LongTuple_tag) { size_t len; if (vtag == (jl_value_t*)jl_tuple_type) len = read_uint8(s); else len = read_int32(s); jl_tuple_t *tu = jl_alloc_tuple_uninit(len); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)tu); for(i=0; i < len; i++) jl_tupleset(tu, i, jl_deserialize_value(s)); return (jl_value_t*)tu; } else if (vtag == (jl_value_t*)jl_symbol_type || vtag == (jl_value_t*)LongSymbol_tag) { size_t len; if (vtag == (jl_value_t*)jl_symbol_type) len = read_uint8(s); else len = read_int32(s); char *name = alloca(len+1); ios_read(s, name, len); name[len] = '\0'; jl_value_t *s = (jl_value_t*)jl_symbol(name); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, s); return s; } else if (vtag == (jl_value_t*)jl_array_type) { jl_value_t *aty = jl_deserialize_value(s); jl_value_t *elty = jl_tparam0(aty); int16_t ndims = jl_unbox_long(jl_tparam1(aty)); size_t *dims = alloca(ndims*sizeof(size_t)); for(i=0; i < ndims; i++) dims[i] = jl_unbox_long(jl_deserialize_value(s)); jl_array_t *a = jl_new_array_((jl_type_t*)aty, ndims, dims); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)a); if (jl_is_bits_type(elty)) { size_t tot = a->length * a->elsize; ios_read(s, a->data, tot); } else { for(i=0; i < a->length; i++) { ((jl_value_t**)a->data)[i] = jl_deserialize_value(s); } } return (jl_value_t*)a; } else if (vtag == (jl_value_t*)jl_expr_type || vtag == (jl_value_t*)LongExpr_tag) { size_t len; if (vtag == (jl_value_t*)jl_expr_type) len = read_uint8(s); else len = read_int32(s); jl_expr_t *e = jl_exprn((jl_sym_t*)jl_deserialize_value(s), len); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, (jl_value_t*)e); e->etype = jl_deserialize_value(s); for(i=0; i < len; i++) { jl_cellset(e->args, i, jl_deserialize_value(s)); } return (jl_value_t*)e; } else if (vtag == (jl_value_t*)LiteralVal_tag) { return jl_cellref(tree_literal_values, read_uint16(s)); } else if (vtag == (jl_value_t*)jl_tvar_type) { jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_type_t*)jl_tvar_type, 4); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, tv); tv->name = (jl_sym_t*)jl_deserialize_value(s); tv->lb = jl_deserialize_value(s); tv->ub = jl_deserialize_value(s); tv->bound = read_int8(s); return (jl_value_t*)tv; } else if (vtag == (jl_value_t*)jl_func_kind) { jl_value_t *ftype = jl_deserialize_value(s); jl_function_t *f = (jl_function_t*)newobj((jl_type_t*)ftype, 3); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, f); f->linfo = (jl_lambda_info_t*)jl_deserialize_value(s); f->env = jl_deserialize_value(s); f->fptr = jl_deserialize_fptr(s); if (f->fptr == NULL) { f->fptr = &jl_trampoline; } return (jl_value_t*)f; } else if (vtag == (jl_value_t*)jl_lambda_info_type) { jl_lambda_info_t *li = (jl_lambda_info_t*)newobj((jl_type_t*)jl_lambda_info_type, LAMBDA_INFO_NW); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, li); li->ast = jl_deserialize_value(s); li->sparams = (jl_tuple_t*)jl_deserialize_value(s); li->tfunc = jl_deserialize_value(s); li->name = (jl_sym_t*)jl_deserialize_value(s); li->specTypes = jl_deserialize_value(s); li->specializations = (jl_array_t*)jl_deserialize_value(s); li->inferred = jl_deserialize_value(s); li->file = jl_deserialize_value(s); li->line = jl_deserialize_value(s); li->module = (jl_module_t*)jl_deserialize_value(s); li->fptr = NULL; li->roots = NULL; li->functionObject = NULL; li->inInference = 0; li->inCompile = 0; li->unspecialized = NULL; return (jl_value_t*)li; } else if (vtag == (jl_value_t*)jl_module_type) { jl_module_t *m = jl_new_module(anonymous_sym); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, m); m->name = (jl_sym_t*)jl_deserialize_value(s); while (1) { jl_value_t *name = jl_deserialize_value(s); if (name == NULL) break; jl_binding_t *b = jl_get_binding_wr(m, (jl_sym_t*)name); b->value = jl_deserialize_value(s); b->type = (jl_type_t*)jl_deserialize_value(s); b->constp = read_int8(s); b->exportp = read_int8(s); } while (1) { jl_value_t *name = jl_deserialize_value(s); if (name == NULL) break; jl_set_expander(m, (jl_sym_t*)name, (jl_function_t*)jl_deserialize_value(s)); } return (jl_value_t*)m; } else if (vtag == (jl_value_t*)jl_methtable_type) { jl_methtable_t *mt = (jl_methtable_t*)allocobj(sizeof(jl_methtable_t)); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, mt); mt->type = (jl_type_t*)jl_methtable_type; mt->defs = jl_deserialize_methlist(s); mt->cache = jl_deserialize_methlist(s); mt->cache_1arg = (jl_array_t*)jl_deserialize_value(s); mt->max_args = read_int32(s); return (jl_value_t*)mt; } else if (vtag == (jl_value_t*)SmallInt64_tag) { jl_value_t *v = jl_box_int64(read_int32(s)); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); return v; } else if (vtag == (jl_value_t*)jl_bits_kind) { jl_bits_type_t *bt = (jl_bits_type_t*)jl_deserialize_value(s); int nby = bt->nbits/8; char *data = alloca(nby); ios_read(s, data, nby); jl_value_t *v=NULL; if (bt == jl_int32_type) v = jl_box_int32(*(int32_t*)data); else if (bt == jl_int64_type) v = jl_box_int64(*(int64_t*)data); else if (bt == jl_bool_type) v = jl_box_bool(*(int8_t*)data); else { switch (bt->nbits) { case 8: v = jl_box8 (bt, *(int8_t*) data); break; case 16: v = jl_box16(bt, *(int16_t*)data); break; case 32: v = jl_box32(bt, *(int32_t*)data); break; case 64: v = jl_box64(bt, *(int64_t*)data); break; default: v = (jl_value_t*)allocobj(sizeof(void*)+nby); v->type = (jl_type_t*)bt; memcpy(jl_bits_data(v), data, nby); } } if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); return v; } else if (vtag == (jl_value_t*)jl_struct_kind) { jl_struct_type_t *typ = (jl_struct_type_t*)jl_deserialize_value(s); if (typ == jl_struct_kind || typ == jl_bits_kind) return jl_deserialize_tag_type(s, typ, pos); size_t nf = typ->names->length; jl_value_t *v = jl_new_struct_uninit(typ); if (usetable) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, v); for(i=0; i < nf; i++) { ((jl_value_t**)v)[i+1] = jl_deserialize_value(s); } // TODO: put WeakRefs on the weak_refs list return v; } else if (vtag == (jl_value_t*)jl_tag_kind) { return jl_deserialize_tag_type(s, jl_tag_kind, pos); } assert(0); return NULL; }
// TODO: add locks around global state mutation operations jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) { jl_ptls_t ptls = jl_get_ptls_states(); assert(ex->head == module_sym); if (jl_array_len(ex->args) != 3 || !jl_is_expr(jl_exprarg(ex, 2))) { jl_error("syntax: malformed module expression"); } int std_imports = (jl_exprarg(ex, 0) == jl_true); jl_sym_t *name = (jl_sym_t*)jl_exprarg(ex, 1); if (!jl_is_symbol(name)) { jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); } jl_module_t *newm = jl_new_module(name); jl_value_t *form = (jl_value_t*)newm; JL_GC_PUSH1(&form); ptrhash_put(&jl_current_modules, (void*)newm, (void*)((uintptr_t)HT_NOTFOUND + 1)); // copy parent environment info into submodule newm->uuid = parent_module->uuid; if (jl_base_module && (jl_value_t*)parent_module == jl_get_global(jl_base_module, jl_symbol("__toplevel__"))) { newm->parent = newm; jl_register_root_module(newm); } else { jl_binding_t *b = jl_get_binding_wr(parent_module, name, 1); jl_declare_constant(b); if (b->value != NULL) { if (!jl_is_module(b->value)) { jl_errorf("invalid redefinition of constant %s", jl_symbol_name(name)); } if (jl_generating_output()) { jl_errorf("cannot replace module %s during compilation", jl_symbol_name(name)); } jl_printf(JL_STDERR, "WARNING: replacing module %s.\n", jl_symbol_name(name)); // create a hidden gc root for the old module uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, (void*)b->value); *refcnt += 1; } newm->parent = parent_module; b->value = (jl_value_t*)newm; jl_gc_wb_binding(b, newm); } if (parent_module == jl_main_module && name == jl_symbol("Base")) { // pick up Base module during bootstrap jl_base_module = newm; } size_t last_age = ptls->world_age; // add standard imports unless baremodule if (std_imports) { if (jl_base_module != NULL) { jl_add_standard_imports(newm); } // add `eval` function form = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex, newm); ptls->world_age = jl_world_counter; jl_toplevel_eval_flex(newm, form, 0, 1); form = NULL; } jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args; for (int i = 0; i < jl_array_len(exprs); i++) { // process toplevel form ptls->world_age = jl_world_counter; form = jl_expand_stmt(jl_array_ptr_ref(exprs, i), newm); ptls->world_age = jl_world_counter; (void)jl_toplevel_eval_flex(newm, form, 1, 1); } ptls->world_age = last_age; #if 0 // some optional post-processing steps size_t i; void **table = newm->bindings.table; for(i=1; i < newm->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; // remove non-exported macros if (jl_symbol_name(b->name)[0]=='@' && !b->exportp && b->owner == newm) b->value = NULL; // error for unassigned exports /* if (b->exportp && b->owner==newm && b->value==NULL) jl_errorf("identifier %s exported from %s is not initialized", jl_symbol_name(b->name), jl_symbol_name(newm->name)); */ } } #endif uintptr_t *refcnt = (uintptr_t*)ptrhash_bp(&jl_current_modules, (void*)newm); assert(*refcnt > (uintptr_t)HT_NOTFOUND); *refcnt -= 1; // newm should be reachable from somewhere else by now if (jl_module_init_order == NULL) jl_module_init_order = jl_alloc_vec_any(0); jl_array_ptr_1d_push(jl_module_init_order, (jl_value_t*)newm); // defer init of children until parent is done being defined // then initialize all in definition-finished order // at build time, don't run them at all (defer for runtime) if (!jl_generating_output()) { if (!ptrhash_has(&jl_current_modules, (void*)newm->parent)) { size_t i, l = jl_array_len(jl_module_init_order); size_t ns = 0; form = (jl_value_t*)jl_alloc_vec_any(0); for (i = 0; i < l; i++) { jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(jl_module_init_order, i); if (jl_is_submodule(m, newm)) { jl_array_ptr_1d_push((jl_array_t*)form, (jl_value_t*)m); } else if (ns++ != i) { jl_array_ptr_set(jl_module_init_order, ns - 1, (jl_value_t*)m); } } if (ns < l) jl_array_del_end(jl_module_init_order, l - ns); l = jl_array_len(form); for (i = 0; i < l; i++) { jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(form, i); JL_GC_PROMISE_ROOTED(m); jl_module_run_initializer(m); } } } JL_GC_POP(); return (jl_value_t*)newm; }
int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); if (*bp == HT_NOTFOUND) return 0; return (*bp)->owner != NULL; }
// does module m explicitly import s? int jl_is_imported(jl_module_t *m, jl_sym_t *s) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, s); jl_binding_t *bto = *bp; return (bto != HT_NOTFOUND && bto->imported); }
static void push_root(jl_value_t *v, int d) { assert(v != NULL); jl_value_t *vt = (jl_value_t*)gc_typeof(v); #ifdef OBJPROFILE if (!gc_marked(v)) { void **bp = ptrhash_bp(&obj_counts, vt); if (*bp == HT_NOTFOUND) *bp = (void*)2; else (*((ptrint_t*)bp))++; } #endif gc_setmark(v); if (vt == (jl_value_t*)jl_weakref_type || (jl_is_datatype(vt) && ((jl_datatype_t*)vt)->pointerfree)) { return; } if (d >= MAX_MARK_DEPTH) goto queue_the_root; d++; // some values have special representations if (vt == (jl_value_t*)jl_tuple_type) { size_t l = jl_tuple_len(v); jl_value_t **data = ((jl_tuple_t*)v)->data; for(size_t i=0; i < l; i++) { jl_value_t *elt = data[i]; if (elt != NULL) gc_push_root(elt, d); } } else if (((jl_datatype_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; if (a->how == 3) { jl_value_t *owner = jl_array_data_owner(a); gc_push_root(owner, d); return; } else if (a->how == 1) { gc_setmark_buf((char*)a->data - a->offset*a->elsize); } if (a->ptrarray && a->data!=NULL) { size_t l = jl_array_len(a); if (l > 100000 && d > MAX_MARK_DEPTH-10) { // don't mark long arrays at high depth, to try to avoid // copying the whole array into the mark queue goto queue_the_root; } else { void *data = a->data; for(size_t i=0; i < l; i++) { jl_value_t *elt = ((jl_value_t**)data)[i]; if (elt != NULL) gc_push_root(elt, d); } } } } else if (vt == (jl_value_t*)jl_module_type) { gc_mark_module((jl_module_t*)v, d); } else if (vt == (jl_value_t*)jl_task_type) { gc_mark_task((jl_task_t*)v, d); } else { jl_datatype_t *dt = (jl_datatype_t*)vt; int nf = (int)jl_tuple_len(dt->names); for(int i=0; i < nf; i++) { if (dt->fields[i].isptr) { jl_value_t *fld = *(jl_value_t**)((char*)v + dt->fields[i].offset + sizeof(void*)); if (fld) gc_push_root(fld, d); } } } return; queue_the_root: if (mark_sp >= mark_stack_size) { size_t newsz = mark_stack_size>0 ? mark_stack_size*2 : 32000; mark_stack = (jl_value_t**)realloc(mark_stack,newsz*sizeof(void*)); if (mark_stack == NULL) exit(1); mark_stack_size = newsz; } mark_stack[mark_sp++] = v; }
int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); if (*bp == HT_NOTFOUND) return 0; return (*bp)->exportp || (*bp)->owner==m; }
static void gc_markval_(jl_value_t *v) { assert(v != NULL); //assert(v != lookforme); if (gc_marked_obj(v)) return; jl_value_t *vt = (jl_value_t*)jl_typeof(v); #ifdef OBJPROFILE void **bp = ptrhash_bp(&obj_counts, vt); if (*bp == HT_NOTFOUND) *bp = (void*)2; else (*((ptrint_t*)bp))++; #endif jl_value_t *vtt = gc_typeof(vt); gc_setmark_obj(v); if (vtt==(jl_value_t*)jl_bits_kind) return; // some values have special representations if (vt == (jl_value_t*)jl_tuple_type) { size_t i; for(i=0; i < ((jl_tuple_t*)v)->length; i++) { jl_value_t *elt = ((jl_tuple_t*)v)->data[i]; if (elt != NULL) GC_Markval(elt); } } else if (((jl_struct_type_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; int ndims = jl_array_ndims(a); int ndimwords = (ndims > 2 ? (ndims-2) : 0); #ifndef __LP64__ // on 32-bit, ndimwords must be odd to preserve 8-byte alignment ndimwords += (~ndimwords)&1; #endif void *data_area = &a->_space[0] + ndimwords*sizeof(size_t); if (a->reshaped) { GC_Markval(*((jl_value_t**)data_area)); } else if (a->data) { char *data = a->data; if (ndims == 1) data -= a->offset*a->elsize; if (data != data_area) { gc_setmark(data); } } jl_value_t *elty = jl_tparam0(vt); if (gc_typeof(elty) != (jl_value_t*)jl_bits_kind) { size_t i; for(i=0; i < a->length; i++) { jl_value_t *elt = ((jl_value_t**)a->data)[i]; if (elt != NULL) GC_Markval(elt); } } } else if (vt == (jl_value_t*)jl_module_type) { gc_mark_module((jl_module_t*)v); } else if (vt == (jl_value_t*)jl_task_type) { jl_task_t *ta = (jl_task_t*)v; GC_Markval(ta->on_exit); GC_Markval(ta->tls); if (ta->start) GC_Markval(ta->start); if (ta->result) GC_Markval(ta->result); GC_Markval(ta->state.eh_task); if (ta->stkbuf != NULL) gc_setmark(ta->stkbuf); #ifdef COPY_STACKS ptrint_t offset; if (ta == jl_current_task) { offset = 0; gc_mark_stack(jl_pgcstack, offset); } else { offset = ta->stkbuf - (ta->stackbase-ta->ssize); gc_mark_stack(ta->state.gcstack, offset); } jl_savestate_t *ss = &ta->state; while (ss != NULL) { GC_Markval(ss->ostream_obj); ss = ss->prev; if (ss != NULL) ss = (jl_savestate_t*)((char*)ss + offset); } #else gc_mark_stack(ta->state.gcstack, 0); jl_savestate_t *ss = &ta->state; while (ss != NULL) { GC_Markval(ss->ostream_obj); ss = ss->prev; } #endif } else if (vt == (jl_value_t*)jl_weakref_type) { // don't mark contents } else { assert(vtt == (jl_value_t*)jl_struct_kind); size_t nf = ((jl_struct_type_t*)vt)->names->length; size_t i=0; if (vt == (jl_value_t*)jl_struct_kind || vt == (jl_value_t*)jl_function_type) { i++; // skip fptr field } for(; i < nf; i++) { jl_value_t *fld = ((jl_value_t**)v)[i+1]; if (fld) GC_Markval(fld); } } }
// label is the backreference we'd like to fix up with this read static value_t do_read_sexpr(value_t label) { value_t v, sym, oldtokval, *head; value_t *pv; u_int32_t t; char c; t = peek(); take(); switch (t) { case TOK_CLOSE: lerror(ParseError, "read: unexpected ')'"); case TOK_CLOSEB: lerror(ParseError, "read: unexpected ']'"); case TOK_DOT: lerror(ParseError, "read: unexpected '.'"); case TOK_SYM: case TOK_NUM: return tokval; case TOK_COMMA: head = &COMMA; goto listwith; case TOK_COMMAAT: head = &COMMAAT; goto listwith; case TOK_COMMADOT: head = &COMMADOT; goto listwith; case TOK_BQ: head = &BACKQUOTE; goto listwith; case TOK_QUOTE: head = "E; listwith: v = cons_reserve(2); car_(v) = *head; cdr_(v) = tagptr(((cons_t*)ptr(v))+1, TAG_CONS); car_(cdr_(v)) = cdr_(cdr_(v)) = NIL; PUSH(v); if (label != UNBOUND) ptrhash_put(&readstate->backrefs, (void*)label, (void*)v); v = do_read_sexpr(UNBOUND); car_(cdr_(Stack[SP-1])) = v; return POP(); case TOK_SHARPQUOTE: // femtoLisp doesn't need symbol-function, so #' does nothing return do_read_sexpr(label); case TOK_OPEN: PUSH(NIL); read_list(&Stack[SP-1], label); return POP(); case TOK_SHARPSYM: sym = tokval; if (sym == tsym || sym == Tsym) return FL_T; else if (sym == fsym || sym == Fsym) return FL_F; // constructor notation c = nextchar(); if (c != '(') { take(); lerrorf(ParseError, "read: expected argument list for %s", symbol_name(tokval)); } PUSH(NIL); read_list(&Stack[SP-1], UNBOUND); if (sym == vu8sym) { sym = arraysym; Stack[SP-1] = fl_cons(uint8sym, Stack[SP-1]); } else if (sym == fnsym) { sym = FUNCTION; } v = symbol_value(sym); if (v == UNBOUND) fl_raise(fl_list2(UnboundError, sym)); return fl_apply(v, POP()); case TOK_OPENB: return read_vector(label, TOK_CLOSEB); case TOK_SHARPOPEN: return read_vector(label, TOK_CLOSE); case TOK_SHARPDOT: // eval-when-read // evaluated expressions can refer to existing backreferences, but they // cannot see pending labels. in other words: // (... #2=#.#0# ... ) OK // (... #2=#.(#2#) ... ) DO NOT WANT sym = do_read_sexpr(UNBOUND); if (issymbol(sym)) { v = symbol_value(sym); if (v == UNBOUND) fl_raise(fl_list2(UnboundError, sym)); return v; } return fl_toplevel_eval(sym); case TOK_LABEL: // create backreference label if (ptrhash_has(&readstate->backrefs, (void*)tokval)) lerrorf(ParseError, "read: label %ld redefined", numval(tokval)); oldtokval = tokval; v = do_read_sexpr(tokval); ptrhash_put(&readstate->backrefs, (void*)oldtokval, (void*)v); return v; case TOK_BACKREF: // look up backreference v = (value_t)ptrhash_get(&readstate->backrefs, (void*)tokval); if (v == (value_t)HT_NOTFOUND) lerrorf(ParseError, "read: undefined label %ld", numval(tokval)); return v; case TOK_GENSYM: pv = (value_t*)ptrhash_bp(&readstate->gensyms, (void*)tokval); if (*pv == (value_t)HT_NOTFOUND) *pv = fl_gensym(NULL, 0); return *pv; case TOK_DOUBLEQUOTE: return read_string(); } return FL_UNSPECIFIED; }
static void jl_serialize_value_(ios_t *s, jl_value_t *v) { if (v == NULL) { write_uint8(s, Null_tag); return; } void **bp = ptrhash_bp(&ser_tag, v); if (*bp != HT_NOTFOUND) { write_as_tag(s, (uint8_t)(ptrint_t)*bp); return; } if (tree_literal_values) { // compressing tree if (!is_ast_node(v)) { writetag(s, (jl_value_t*)LiteralVal_tag); write_uint16(s, literal_val_id(v)); return; } } else { bp = ptrhash_bp(&backref_table, v); if (*bp != HT_NOTFOUND) { write_uint8(s, BackRef_tag); write_int32(s, (ptrint_t)*bp); return; } ptrhash_put(&backref_table, v, (void*)(ptrint_t)ios_pos(s)); } size_t i; if (jl_is_tuple(v)) { size_t l = ((jl_tuple_t*)v)->length; if (l <= 255) { writetag(s, jl_tuple_type); write_uint8(s, (uint8_t)l); } else { writetag(s, (jl_value_t*)LongTuple_tag); write_int32(s, l); } for(i=0; i < l; i++) { jl_serialize_value(s, jl_tupleref(v, i)); } } else if (jl_is_symbol(v)) { size_t l = strlen(((jl_sym_t*)v)->name); if (l <= 255) { writetag(s, jl_symbol_type); write_uint8(s, (uint8_t)l); } else { writetag(s, (jl_value_t*)LongSymbol_tag); write_int32(s, l); } ios_write(s, ((jl_sym_t*)v)->name, l); } else if (jl_is_array(v)) { jl_array_t *ar = (jl_array_t*)v; writetag(s, (jl_value_t*)jl_array_type); jl_serialize_value(s, ar->type); jl_value_t *elty = jl_tparam0(ar->type); for (i=0; i < ar->ndims; i++) jl_serialize_value(s, jl_box_long(jl_array_dim(ar,i))); if (jl_is_bits_type(elty)) { size_t tot = ar->length * ar->elsize; ios_write(s, ar->data, tot); } else { for(i=0; i < ar->length; i++) { jl_serialize_value(s, jl_cellref(v, i)); } } } else if (jl_is_expr(v)) { jl_expr_t *e = (jl_expr_t*)v; size_t l = e->args->length; if (l <= 255) { writetag(s, jl_expr_type); write_uint8(s, (uint8_t)l); } else { writetag(s, (jl_value_t*)LongExpr_tag); write_int32(s, l); } jl_serialize_value(s, e->head); jl_serialize_value(s, e->etype); for(i=0; i < l; i++) { jl_serialize_value(s, jl_exprarg(e, i)); } } else if (jl_is_some_tag_type(v)) { jl_serialize_tag_type(s, v); } else if (jl_is_typevar(v)) { writetag(s, jl_tvar_type); jl_serialize_value(s, ((jl_tvar_t*)v)->name); jl_serialize_value(s, ((jl_tvar_t*)v)->lb); jl_serialize_value(s, ((jl_tvar_t*)v)->ub); write_int8(s, ((jl_tvar_t*)v)->bound); } else if (jl_is_function(v)) { writetag(s, jl_func_kind); jl_serialize_value(s, v->type); jl_function_t *f = (jl_function_t*)v; jl_serialize_value(s, (jl_value_t*)f->linfo); jl_serialize_value(s, f->env); if (f->linfo && f->linfo->ast && (jl_is_expr(f->linfo->ast) || jl_is_tuple(f->linfo->ast)) && f->fptr != &jl_trampoline) { write_int32(s, 0); } else { jl_serialize_fptr(s, f->fptr); } } else if (jl_is_lambda_info(v)) { writetag(s, jl_lambda_info_type); jl_lambda_info_t *li = (jl_lambda_info_t*)v; jl_serialize_value(s, li->ast); jl_serialize_value(s, (jl_value_t*)li->sparams); // don't save cached type info for code in the Base module, because // it might reference types in the old System module. if (li->module == jl_base_module) jl_serialize_value(s, (jl_value_t*)jl_null); else jl_serialize_value(s, (jl_value_t*)li->tfunc); jl_serialize_value(s, (jl_value_t*)li->name); jl_serialize_value(s, (jl_value_t*)li->specTypes); jl_serialize_value(s, (jl_value_t*)li->specializations); jl_serialize_value(s, (jl_value_t*)li->inferred); jl_serialize_value(s, (jl_value_t*)li->file); jl_serialize_value(s, (jl_value_t*)li->line); jl_serialize_value(s, (jl_value_t*)li->module); } else if (jl_typeis(v, jl_module_type)) { jl_serialize_module(s, (jl_module_t*)v); } else if (jl_typeis(v, jl_methtable_type)) { writetag(s, jl_methtable_type); jl_methtable_t *mt = (jl_methtable_t*)v; jl_serialize_methlist(s, mt->defs); jl_serialize_methlist(s, mt->cache); jl_serialize_value(s, mt->cache_1arg); write_int32(s, mt->max_args); } else if (jl_typeis(v, jl_task_type)) { jl_error("Task cannot be serialized"); } else { jl_value_t *t = (jl_value_t*)jl_typeof(v); if (jl_is_bits_type(t)) { void *data = jl_bits_data(v); if (t == (jl_value_t*)jl_int64_type && *(int64_t*)data >= S32_MIN && *(int64_t*)data <= S32_MAX) { writetag(s, (jl_value_t*)SmallInt64_tag); write_int32(s, (int32_t)*(int64_t*)data); } else { int nb = ((jl_bits_type_t*)t)->nbits; writetag(s, jl_bits_kind); jl_serialize_value(s, t); ios_write(s, data, nb/8); } } else if (jl_is_struct_type(t)) { writetag(s, jl_struct_kind); jl_serialize_value(s, t); size_t nf = ((jl_struct_type_t*)t)->names->length; size_t i; for(i=0; i < nf; i++) { jl_value_t *fld = ((jl_value_t**)v)[i+1]; jl_serialize_value(s, fld); } if (t == jl_idtable_type) { jl_cell_1d_push(idtable_list, v); } } else { assert(0); } } }