Skip to content

Commit

Permalink
fix #15722, support BigInts in precompiled modules and sysimg
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Jul 27, 2018
1 parent b0075cb commit e0cf3db
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ typedef struct {

static jl_value_t *jl_idtable_type = NULL;
static jl_typename_t *jl_idtable_typename = NULL;
static jl_value_t *jl_bigint_type = NULL;
static int gmp_limb_size = 0;
static arraylist_t builtin_typenames;

#define write_uint8(s, n) ios_putc((n), (s))
Expand Down Expand Up @@ -921,6 +923,17 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li
for (i = 0; i < jl_datatype_nfields(jl_lineinfonode_type); i++)
jl_serialize_value(s, jl_get_nth_field(v, i));
}
else if (jl_bigint_type && jl_typeis(v, jl_bigint_type)) {
write_uint8(s->s, TAG_SHORT_GENERAL);
write_uint8(s->s, jl_datatype_size(jl_bigint_type));
jl_serialize_value(s, jl_bigint_type);
jl_value_t *sizefield = jl_get_nth_field(v, 1);
jl_serialize_value(s, sizefield);
void *data = jl_unbox_voidpointer(jl_get_nth_field(v, 2));
int32_t sz = jl_unbox_int32(sizefield);
size_t nb = (sz == 0 ? 1 : (sz < 0 ? -sz : sz)) * gmp_limb_size;
ios_write(s->s, (char*)data, nb);
}
else {
jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v);
void *data = jl_data_ptr(v);
Expand Down Expand Up @@ -1925,6 +1938,17 @@ static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag,
int nby = jl_datatype_size(dt);
ios_read(s->s, (char*)jl_data_ptr(v), nby);
}
else if ((jl_value_t*)dt == jl_bigint_type) {
jl_value_t *sizefield = jl_deserialize_value(s, NULL);
int32_t sz = jl_unbox_int32(sizefield);
int32_t nw = (sz == 0 ? 1 : (sz < 0 ? -sz : sz));
size_t nb = nw * gmp_limb_size;
void *buf = jl_gc_counted_malloc(nb);
ios_read(s->s, (char*)buf, nb);
jl_set_nth_field(v, 0, jl_box_int32(nw));
jl_set_nth_field(v, 1, sizefield);
jl_set_nth_field(v, 2, jl_box_voidpointer(buf));
}
else {
jl_deserialize_struct(s, v, 0);
}
Expand Down Expand Up @@ -2631,6 +2655,11 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist)
backref_table_numel = 1;
jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("IdDict")) : NULL;
jl_idtable_typename = jl_base_module ? ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_idtable_type))->name : NULL;
jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
if (jl_bigint_type) {
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
jl_symbol("BITS_PER_LIMB"))) / 8;
}

int en = jl_gc_enable(0); // edges map is not gc-safe
jl_array_t *lambdas = jl_alloc_vec_any(0);
Expand Down Expand Up @@ -3008,6 +3037,12 @@ static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array)
ios_skip(f, deplen);
}

jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
if (jl_bigint_type) {
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
jl_symbol("BITS_PER_LIMB"))) / 8;
}

// list of world counters of incremental dependencies
arraylist_t dependent_worlds;
arraylist_new(&dependent_worlds, 0);
Expand Down
1 change: 1 addition & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ jl_svec_t *jl_perm_symsvec(size_t n, ...);
#define jl_datatype_layout_n_nonptr(layout) ((uint32_t*)(layout))[-1]

jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz);
JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz);

jl_code_info_t *jl_type_infer(jl_method_instance_t **pli JL_ROOTS_TEMPORARILY, size_t world, int force);
jl_callptr_t jl_generate_fptr(jl_method_instance_t **pli, jl_llvm_functions_t decls, size_t world);
Expand Down
29 changes: 29 additions & 0 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ typedef struct {

static jl_value_t *jl_idtable_type = NULL;
static jl_typename_t *jl_idtable_typename = NULL;
static jl_value_t *jl_bigint_type = NULL;
static int gmp_limb_size = 0;
static arraylist_t builtin_typenames;

enum RefTags {
Expand Down Expand Up @@ -629,6 +631,23 @@ static void jl_write_values(jl_serializer_state *s)
if (t->size > 0)
ios_write(s->s, (char*)v, t->size);
}
else if (jl_bigint_type && jl_typeis(v, jl_bigint_type)) {
jl_value_t *sizefield = jl_get_nth_field(v, 1);
int32_t sz = jl_unbox_int32(sizefield);
int32_t nw = (sz == 0 ? 1 : (sz < 0 ? -sz : sz));
size_t nb = nw * gmp_limb_size;
ios_write(s->s, (char*)&nw, sizeof(int32_t));
ios_write(s->s, (char*)&sz, sizeof(int32_t));
uintptr_t data = LLT_ALIGN(ios_pos(s->const_data), 8);
write_padding(s->const_data, data - ios_pos(s->const_data));
data /= sizeof(void*);
assert(data < ((uintptr_t)1 << RELOC_TAG_OFFSET) && "offset to constant data too large");
arraylist_push(&s->relocs_list, (void*)(reloc_offset + 8)); // relocation location
arraylist_push(&s->relocs_list, (void*)(((uintptr_t)ConstDataRef << RELOC_TAG_OFFSET) + data)); // relocation target
void *pdata = jl_unbox_voidpointer(jl_get_nth_field(v, 2));
ios_write(s->const_data, (char*)pdata, nb);
write_pointer(s->s);
}
else {
size_t i, nf = jl_datatype_nfields(t);
size_t tot = 0;
Expand Down Expand Up @@ -1243,6 +1262,11 @@ static void jl_save_system_image_to_stream(ios_t *f)

jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("IdDict")) : NULL;
jl_idtable_typename = jl_base_module ? ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_idtable_type))->name : NULL;
jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
if (jl_bigint_type) {
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
jl_symbol("BITS_PER_LIMB"))) / 8;
}

{ // step 1: record values (recursively) that need to go in the image
jl_serialize_value(&s, jl_core_module);
Expand Down Expand Up @@ -1415,6 +1439,11 @@ static void jl_restore_system_image_from_stream(ios_t *f)
s.ptls = jl_get_ptls_states();
arraylist_new(&s.relocs_list, 0);
arraylist_new(&s.gctags_list, 0);
jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
if (jl_bigint_type) {
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
jl_symbol("BITS_PER_LIMB"))) / 8;
}

// step 1: read section map and apply relocations
assert(ios_pos(f) == 0 && f->bm == bm_mem);
Expand Down
4 changes: 4 additions & 0 deletions test/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ try
const abigfloat_f() = big"12.34"
const abigfloat_x = big"43.21"
const abigint_f() = big"123"
const abigint_x = big"124"
end
""")
@test_throws ErrorException Core.kwfunc(Base.nothing) # make sure `nothing` didn't have a kwfunc (which would invalidate the attempted test)
Expand All @@ -171,6 +173,8 @@ try
# Issue #15722
@test Foo.abigfloat_f()::BigFloat == big"12.34"
@test (Foo.abigfloat_x::BigFloat + 21) == big"64.21"
@test Foo.abigint_f()::BigInt == big"123"
@test Foo.abigint_x::BigInt + 1 == big"125"
end

cachedir = joinpath(dir, "compiled", "v$(VERSION.major).$(VERSION.minor)")
Expand Down

0 comments on commit e0cf3db

Please sign in to comment.