Skip to content

Commit e0cf3db

Browse files
committed
fix #15722, support BigInts in precompiled modules and sysimg
1 parent b0075cb commit e0cf3db

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

src/dump.c

+35
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ typedef struct {
149149

150150
static jl_value_t *jl_idtable_type = NULL;
151151
static jl_typename_t *jl_idtable_typename = NULL;
152+
static jl_value_t *jl_bigint_type = NULL;
153+
static int gmp_limb_size = 0;
152154
static arraylist_t builtin_typenames;
153155

154156
#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
921923
for (i = 0; i < jl_datatype_nfields(jl_lineinfonode_type); i++)
922924
jl_serialize_value(s, jl_get_nth_field(v, i));
923925
}
926+
else if (jl_bigint_type && jl_typeis(v, jl_bigint_type)) {
927+
write_uint8(s->s, TAG_SHORT_GENERAL);
928+
write_uint8(s->s, jl_datatype_size(jl_bigint_type));
929+
jl_serialize_value(s, jl_bigint_type);
930+
jl_value_t *sizefield = jl_get_nth_field(v, 1);
931+
jl_serialize_value(s, sizefield);
932+
void *data = jl_unbox_voidpointer(jl_get_nth_field(v, 2));
933+
int32_t sz = jl_unbox_int32(sizefield);
934+
size_t nb = (sz == 0 ? 1 : (sz < 0 ? -sz : sz)) * gmp_limb_size;
935+
ios_write(s->s, (char*)data, nb);
936+
}
924937
else {
925938
jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v);
926939
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,
19251938
int nby = jl_datatype_size(dt);
19261939
ios_read(s->s, (char*)jl_data_ptr(v), nby);
19271940
}
1941+
else if ((jl_value_t*)dt == jl_bigint_type) {
1942+
jl_value_t *sizefield = jl_deserialize_value(s, NULL);
1943+
int32_t sz = jl_unbox_int32(sizefield);
1944+
int32_t nw = (sz == 0 ? 1 : (sz < 0 ? -sz : sz));
1945+
size_t nb = nw * gmp_limb_size;
1946+
void *buf = jl_gc_counted_malloc(nb);
1947+
ios_read(s->s, (char*)buf, nb);
1948+
jl_set_nth_field(v, 0, jl_box_int32(nw));
1949+
jl_set_nth_field(v, 1, sizefield);
1950+
jl_set_nth_field(v, 2, jl_box_voidpointer(buf));
1951+
}
19281952
else {
19291953
jl_deserialize_struct(s, v, 0);
19301954
}
@@ -2631,6 +2655,11 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist)
26312655
backref_table_numel = 1;
26322656
jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("IdDict")) : NULL;
26332657
jl_idtable_typename = jl_base_module ? ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_idtable_type))->name : NULL;
2658+
jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
2659+
if (jl_bigint_type) {
2660+
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
2661+
jl_symbol("BITS_PER_LIMB"))) / 8;
2662+
}
26342663

26352664
int en = jl_gc_enable(0); // edges map is not gc-safe
26362665
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)
30083037
ios_skip(f, deplen);
30093038
}
30103039

3040+
jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
3041+
if (jl_bigint_type) {
3042+
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
3043+
jl_symbol("BITS_PER_LIMB"))) / 8;
3044+
}
3045+
30113046
// list of world counters of incremental dependencies
30123047
arraylist_t dependent_worlds;
30133048
arraylist_new(&dependent_worlds, 0);

src/julia_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ jl_svec_t *jl_perm_symsvec(size_t n, ...);
320320
#define jl_datatype_layout_n_nonptr(layout) ((uint32_t*)(layout))[-1]
321321

322322
jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz);
323+
JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz);
323324

324325
jl_code_info_t *jl_type_infer(jl_method_instance_t **pli JL_ROOTS_TEMPORARILY, size_t world, int force);
325326
jl_callptr_t jl_generate_fptr(jl_method_instance_t **pli, jl_llvm_functions_t decls, size_t world);

src/staticdata.c

+29
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ typedef struct {
9191

9292
static jl_value_t *jl_idtable_type = NULL;
9393
static jl_typename_t *jl_idtable_typename = NULL;
94+
static jl_value_t *jl_bigint_type = NULL;
95+
static int gmp_limb_size = 0;
9496
static arraylist_t builtin_typenames;
9597

9698
enum RefTags {
@@ -629,6 +631,23 @@ static void jl_write_values(jl_serializer_state *s)
629631
if (t->size > 0)
630632
ios_write(s->s, (char*)v, t->size);
631633
}
634+
else if (jl_bigint_type && jl_typeis(v, jl_bigint_type)) {
635+
jl_value_t *sizefield = jl_get_nth_field(v, 1);
636+
int32_t sz = jl_unbox_int32(sizefield);
637+
int32_t nw = (sz == 0 ? 1 : (sz < 0 ? -sz : sz));
638+
size_t nb = nw * gmp_limb_size;
639+
ios_write(s->s, (char*)&nw, sizeof(int32_t));
640+
ios_write(s->s, (char*)&sz, sizeof(int32_t));
641+
uintptr_t data = LLT_ALIGN(ios_pos(s->const_data), 8);
642+
write_padding(s->const_data, data - ios_pos(s->const_data));
643+
data /= sizeof(void*);
644+
assert(data < ((uintptr_t)1 << RELOC_TAG_OFFSET) && "offset to constant data too large");
645+
arraylist_push(&s->relocs_list, (void*)(reloc_offset + 8)); // relocation location
646+
arraylist_push(&s->relocs_list, (void*)(((uintptr_t)ConstDataRef << RELOC_TAG_OFFSET) + data)); // relocation target
647+
void *pdata = jl_unbox_voidpointer(jl_get_nth_field(v, 2));
648+
ios_write(s->const_data, (char*)pdata, nb);
649+
write_pointer(s->s);
650+
}
632651
else {
633652
size_t i, nf = jl_datatype_nfields(t);
634653
size_t tot = 0;
@@ -1243,6 +1262,11 @@ static void jl_save_system_image_to_stream(ios_t *f)
12431262

12441263
jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("IdDict")) : NULL;
12451264
jl_idtable_typename = jl_base_module ? ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_idtable_type))->name : NULL;
1265+
jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
1266+
if (jl_bigint_type) {
1267+
gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
1268+
jl_symbol("BITS_PER_LIMB"))) / 8;
1269+
}
12461270

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

14191448
// step 1: read section map and apply relocations
14201449
assert(ios_pos(f) == 0 && f->bm == bm_mem);

test/precompile.jl

+4
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ try
145145
146146
const abigfloat_f() = big"12.34"
147147
const abigfloat_x = big"43.21"
148+
const abigint_f() = big"123"
149+
const abigint_x = big"124"
148150
end
149151
""")
150152
@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
171173
# Issue #15722
172174
@test Foo.abigfloat_f()::BigFloat == big"12.34"
173175
@test (Foo.abigfloat_x::BigFloat + 21) == big"64.21"
176+
@test Foo.abigint_f()::BigInt == big"123"
177+
@test Foo.abigint_x::BigInt + 1 == big"125"
174178
end
175179

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

0 commit comments

Comments
 (0)