static void jl_serialize_module(ios_t *s, jl_module_t *m) { // set on every startup; don't save jl_sym_t *jhsym = jl_symbol("JULIA_HOME"); writetag(s, jl_module_type); jl_serialize_value(s, m->name); jl_serialize_value(s, m->parent); size_t i; void **table = m->bindings.table; for(i=1; i < m->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND && !(table[i-1] == jhsym && m == jl_core_module)) { jl_binding_t *b = (jl_binding_t*)table[i]; if (!(b->owner != m && m == jl_main_module)) { jl_serialize_value(s, b->name); jl_serialize_value(s, b->value); jl_serialize_value(s, b->type); jl_serialize_value(s, b->owner); write_int8(s, (b->constp<<2) | (b->exportp<<1) | (b->imported)); } } } jl_serialize_value(s, NULL); if (m == jl_main_module) { write_int32(s, 1); jl_serialize_value(s, (jl_value_t*)jl_core_module); } else { write_int32(s, m->usings.len); for(i=0; i < m->usings.len; i++) { jl_serialize_value(s, (jl_value_t*)m->usings.items[i]); } } }
static void jl_serialize_methlist(ios_t *s, jl_methlist_t *ml) { while (ml != NULL) { jl_serialize_value(s, ml->sig); assert(jl_is_tuple(ml->sig)); write_int8(s, ml->va); jl_serialize_value(s, ml->tvars); jl_serialize_value(s, ml->func); jl_serialize_value(s, ml->invokes); ml = ml->next; } jl_serialize_value(s, NULL); }
static void jl_serialize_module(ios_t *s, jl_module_t *m) { writetag(s, jl_module_type); jl_serialize_value(s, m->name); size_t i; void **table = m->bindings.table; for(i=1; i < m->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; jl_serialize_value(s, b->name); jl_serialize_value(s, b->value); jl_serialize_value(s, b->type); write_int8(s, b->constp); write_int8(s, b->exportp); } } jl_serialize_value(s, NULL); table = m->macros.table; for(i=1; i < m->macros.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_serialize_value(s, table[i-1]); jl_serialize_value(s, table[i]); } } jl_serialize_value(s, NULL); }
DLLEXPORT jl_value_t *jl_compress_ast(jl_value_t *ast) { ios_t dest; jl_ios_mem(&dest, 0); int en = jl_gc_is_enabled(); jl_gc_disable(); tree_literal_values = jl_alloc_cell_1d(0); jl_serialize_value(&dest, ast); //ios_printf(ios_stderr, "%d bytes, %d values\n", dest.size, vals->length); jl_value_t *v = (jl_value_t*)jl_takebuf_array(&dest); if (tree_literal_values->length == 0) tree_literal_values = (jl_array_t*)jl_an_empty_cell; v = (jl_value_t*)jl_tuple(4, v, tree_literal_values, jl_lam_body((jl_expr_t*)ast)->etype, jl_lam_capt((jl_expr_t*)ast)); tree_literal_values = NULL; if (en) jl_gc_enable(); return v; }
DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast) { ios_t dest; ios_mem(&dest, 0); int en = jl_gc_is_enabled(); jl_gc_disable(); if (li->roots == NULL) li->roots = jl_alloc_cell_1d(0); tree_literal_values = li->roots; jl_serialize_value(&dest, ast); //JL_PRINTF(JL_STDERR, "%d bytes, %d values\n", dest.size, vals->length); jl_value_t *v = (jl_value_t*)jl_takebuf_array(&dest); if (jl_array_len(tree_literal_values) == 0) { tree_literal_values = (jl_array_t*)jl_an_empty_cell; li->roots = NULL; } v = (jl_value_t*)jl_tuple(4, v, tree_literal_values, jl_lam_body((jl_expr_t*)ast)->etype, jl_lam_capt((jl_expr_t*)ast)); tree_literal_values = NULL; if (en) jl_gc_enable(); return v; }
DLLEXPORT void jl_save_system_image(char *fname, char *startscriptname) { jl_gc_collect(); jl_gc_collect(); int en = jl_gc_is_enabled(); jl_gc_disable(); htable_reset(&backref_table, 50000); ios_t f; ios_file(&f, fname, 1, 1, 1, 1); // orphan old Base module if present jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")); // delete cached slow ASCIIString constructor if present jl_methtable_t *mt = jl_gf_mtable((jl_function_t*)jl_ascii_string_type); jl_array_t *spec = mt->defs->func->linfo->specializations; if (spec->length > 0 && ((jl_lambda_info_t*)jl_cellref(spec,0))->inferred == 0) { mt->cache = JL_NULL; mt->cache_arg1 = JL_NULL; mt->defs->func->linfo->tfunc = (jl_value_t*)jl_null; mt->defs->func->linfo->specializations = NULL; } jl_idtable_type = jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")); jl_serialize_value(&f, jl_array_type->env); jl_serialize_value(&f, jl_main_module); write_int32(&f, jl_get_t_uid_ctr()); write_int32(&f, jl_get_gs_ctr()); htable_reset(&backref_table, 0); ios_t ss; ios_file(&ss, startscriptname, 1, 0, 0, 0); ios_copyall(&f, &ss); ios_close(&ss); ios_putc(0, &f); ios_close(&f); if (en) jl_gc_enable(); }
DLLEXPORT void jl_save_system_image(char *fname, char *startscriptname) { jl_gc_collect(); jl_gc_collect(); int en = jl_gc_is_enabled(); jl_gc_disable(); htable_reset(&backref_table, 50000); ios_t f; ios_file(&f, fname, 1, 1, 1, 1); if (jl_current_module != jl_system_module) { // set up for stage 1 bootstrap, where the System module is already // loaded and we are loading an updated copy in a separate module. // step 1: set Base.System = current_module jl_binding_t *b = jl_get_binding_wr(jl_base_module, jl_symbol("System")); b->value = (jl_value_t*)jl_current_module; assert(b->constp); // step 2: set current_module.Base = Base jl_set_const(jl_current_module, jl_symbol("Base"), (jl_value_t*)jl_base_module); // step 3: current_module.System = current_module b = jl_get_binding_wr(jl_current_module, jl_symbol("System")); b->value = (jl_value_t*)jl_current_module; assert(b->constp); // step 4: remove current_module.current_module b = jl_get_binding_wr(jl_current_module, jl_current_module->name); b->value = NULL; b->constp = 0; // step 5: rename current_module to System jl_current_module->name = jl_symbol("System"); // step 6: orphan old system module jl_system_module = jl_current_module; } else { // delete cached slow ASCIIString constructor jl_methtable_t *mt = jl_gf_mtable((jl_function_t*)jl_ascii_string_type); mt->cache = NULL; mt->cache_1arg = NULL; mt->defs->func->linfo->tfunc = (jl_value_t*)jl_null; mt->defs->func->linfo->specializations = NULL; } jl_idtable_type = jl_get_global(jl_system_module, jl_symbol("IdTable")); idtable_list = jl_alloc_cell_1d(0); jl_serialize_value(&f, jl_array_type->env); jl_serialize_value(&f, jl_base_module); jl_serialize_value(&f, jl_current_module); jl_serialize_value(&f, idtable_list); //jl_serialize_finalizers(&f); write_int32(&f, jl_get_t_uid_ctr()); write_int32(&f, jl_get_gs_ctr()); htable_reset(&backref_table, 0); ios_t ss; ios_file(&ss, startscriptname, 1, 0, 0, 0); ios_copyall(&f, &ss); ios_close(&ss); ios_putc(0, &f); ios_close(&f); if (en) jl_gc_enable(); }
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); } } }
static void jl_serialize_tag_type(ios_t *s, jl_value_t *v) { if (jl_is_struct_type(v)) { writetag(s, (jl_value_t*)jl_struct_kind); jl_serialize_value(s, jl_struct_kind); jl_serialize_value(s, ((jl_struct_type_t*)v)->name); jl_serialize_value(s, ((jl_struct_type_t*)v)->parameters); jl_serialize_value(s, ((jl_struct_type_t*)v)->super); jl_serialize_value(s, ((jl_struct_type_t*)v)->names); jl_serialize_value(s, ((jl_struct_type_t*)v)->types); jl_serialize_value(s, ((jl_struct_type_t*)v)->ctor_factory); jl_serialize_value(s, ((jl_struct_type_t*)v)->env); jl_serialize_value(s, ((jl_struct_type_t*)v)->linfo); jl_serialize_fptr(s, ((jl_struct_type_t*)v)->fptr); write_int32(s, ((jl_struct_type_t*)v)->uid); } else if (jl_is_bits_type(v)) { writetag(s, jl_struct_kind); jl_serialize_value(s, jl_bits_kind); if (v == (jl_value_t*)jl_int32_type) write_uint8(s, 2); else if (v == (jl_value_t*)jl_bool_type) write_uint8(s, 3); else if (v == (jl_value_t*)jl_int64_type) write_uint8(s, 4); else write_uint8(s, 0); jl_serialize_value(s, ((jl_tag_type_t*)v)->name); jl_serialize_value(s, ((jl_bits_type_t*)v)->parameters); write_int32(s, ((jl_bits_type_t*)v)->nbits); jl_serialize_value(s, ((jl_bits_type_t*)v)->super); write_int32(s, ((jl_bits_type_t*)v)->uid); } else { assert(jl_is_tag_type(v)); writetag(s, jl_tag_kind); jl_serialize_value(s, ((jl_tag_type_t*)v)->name); jl_serialize_value(s, ((jl_tag_type_t*)v)->parameters); jl_serialize_value(s, ((jl_tag_type_t*)v)->super); } }
static void jl_serialize_tag_type(ios_t *s, jl_value_t *v) { if (jl_is_struct_type(v)) { writetag(s, (jl_value_t*)jl_struct_kind); jl_serialize_value(s, jl_struct_kind); write_uint16(s, jl_tuple_len(((jl_struct_type_t*)v)->names)); write_int32(s, ((jl_struct_type_t*)v)->uid); write_int32(s, ((jl_struct_type_t*)v)->size); write_int32(s, ((jl_struct_type_t*)v)->alignment); size_t nf = jl_tuple_len(((jl_struct_type_t*)v)->names); ios_write(s, (char*)&((jl_struct_type_t*)v)->fields[0], nf*sizeof(jl_fielddesc_t)); jl_serialize_value(s, ((jl_struct_type_t*)v)->name); jl_serialize_value(s, ((jl_struct_type_t*)v)->parameters); jl_serialize_value(s, ((jl_struct_type_t*)v)->super); jl_serialize_value(s, ((jl_struct_type_t*)v)->names); jl_serialize_value(s, ((jl_struct_type_t*)v)->types); jl_serialize_value(s, ((jl_struct_type_t*)v)->ctor_factory); jl_serialize_value(s, ((jl_struct_type_t*)v)->env); jl_serialize_value(s, ((jl_struct_type_t*)v)->linfo); jl_serialize_fptr(s, ((jl_struct_type_t*)v)->fptr); } else if (jl_is_bits_type(v)) { writetag(s, jl_struct_kind); jl_serialize_value(s, jl_bits_kind); if (v == (jl_value_t*)jl_int32_type) write_uint8(s, 2); else if (v == (jl_value_t*)jl_bool_type) write_uint8(s, 3); else if (v == (jl_value_t*)jl_int64_type) write_uint8(s, 4); else write_uint8(s, 0); jl_serialize_value(s, ((jl_tag_type_t*)v)->name); jl_serialize_value(s, ((jl_bits_type_t*)v)->parameters); write_int32(s, ((jl_bits_type_t*)v)->nbits); jl_serialize_value(s, ((jl_bits_type_t*)v)->super); write_int32(s, ((jl_bits_type_t*)v)->uid); } else { assert(jl_is_tag_type(v)); writetag(s, jl_tag_kind); jl_serialize_value(s, ((jl_tag_type_t*)v)->name); jl_serialize_value(s, ((jl_tag_type_t*)v)->parameters); jl_serialize_value(s, ((jl_tag_type_t*)v)->super); } }