diff --git a/src/dump.c b/src/dump.c index d7bc0c76bc6a8..ac2cc7d8cd0af 100644 --- a/src/dump.c +++ b/src/dump.c @@ -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)) @@ -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); @@ -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); } @@ -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); @@ -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); diff --git a/src/julia_internal.h b/src/julia_internal.h index c83eb1ce5ea8a..292c7d83547b5 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -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); diff --git a/src/staticdata.c b/src/staticdata.c index e6fd6ff06c39c..4465e5ef5c683 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -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 { @@ -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; @@ -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); @@ -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); diff --git a/test/precompile.jl b/test/precompile.jl index 51a5833a31730..e347a4c93f409 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -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) @@ -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)")