Beispiel #1
0
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;
}
Beispiel #2
0
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);
    }
}
Beispiel #3
0
// 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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
            }
        }
Beispiel #6
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;
}
Beispiel #7
0
// 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;
}
Beispiel #8
0
// 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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
    }
Beispiel #12
0
// 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);
        }
    }
}
Beispiel #13
0
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;
}
Beispiel #14
0
// 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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
// 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);
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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);
        }
    }
}
Beispiel #20
0
// 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 = &QUOTE;
    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;
}
Beispiel #21
0
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);
        }
    }
}