Skip to content

Commit f8a5cd6

Browse files
vchuravytimholyfingolfin
authored andcommitted
Allow re-initialization and caching of foreign types (#47407)
Co-authored-by: Tim Holy <tim.holy@gmail.com> Co-authored-by: Max Horn <max@quendi.de> (cherry picked from commit e06a591)
1 parent d561447 commit f8a5cd6

File tree

17 files changed

+254
-6
lines changed

17 files changed

+254
-6
lines changed

src/datatype.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,22 @@ JL_DLLEXPORT jl_datatype_t * jl_new_foreign_type(jl_sym_t *name,
824824
return bt;
825825
}
826826

827+
JL_DLLEXPORT int jl_reinit_foreign_type(jl_datatype_t *dt,
828+
jl_markfunc_t markfunc,
829+
jl_sweepfunc_t sweepfunc)
830+
{
831+
if (!jl_is_foreign_type(dt))
832+
return 0;
833+
const jl_datatype_layout_t *layout = dt->layout;
834+
jl_fielddescdyn_t * desc =
835+
(jl_fielddescdyn_t *) ((char *)layout + sizeof(*layout));
836+
assert(!desc->markfunc);
837+
assert(!desc->sweepfunc);
838+
desc->markfunc = markfunc;
839+
desc->sweepfunc = sweepfunc;
840+
return 1;
841+
}
842+
827843
JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt)
828844
{
829845
return jl_is_datatype(dt) && dt->layout && dt->layout->fielddesc_type == 3;

src/jl_exported_funcs.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@
342342
XX(jl_new_code_info_uninit) \
343343
XX(jl_new_datatype) \
344344
XX(jl_new_foreign_type) \
345+
XX(jl_reinit_foreign_type) \
345346
XX(jl_new_method_instance_uninit) \
346347
XX(jl_new_method_table) \
347348
XX(jl_new_method_uninit) \

src/julia_gcext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ JL_DLLEXPORT jl_datatype_t *jl_new_foreign_type(
4949
int haspointers,
5050
int large);
5151

52+
53+
#define HAVE_JL_REINIT_FOREIGN_TYPE 1
54+
JL_DLLEXPORT int jl_reinit_foreign_type(
55+
jl_datatype_t *dt,
56+
jl_markfunc_t markfunc,
57+
jl_sweepfunc_t sweepfunc);
58+
5259
JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt);
5360

5461
JL_DLLEXPORT size_t jl_gc_max_internal_obj_size(void);

src/staticdata.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ External links:
7676

7777
#include "julia.h"
7878
#include "julia_internal.h"
79+
#include "julia_gcext.h"
7980
#include "builtin_proto.h"
8081
#include "processor.h"
8182
#include "serialize.h"
@@ -1248,6 +1249,9 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
12481249
ios_write(s->s, (char*)v, sizeof(void*) + jl_string_len(v));
12491250
write_uint8(s->s, '\0'); // null-terminated strings for easier C-compatibility
12501251
}
1252+
else if (jl_is_foreign_type(t) == 1) {
1253+
jl_error("Cannot serialize instances of foreign datatypes");
1254+
}
12511255
else if (jl_datatype_nfields(t) == 0) {
12521256
// The object has no fields, so we just snapshot its byte representation
12531257
assert(!t->layout->npointers);
@@ -1437,10 +1441,14 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
14371441
if (dt->layout != NULL) {
14381442
size_t nf = dt->layout->nfields;
14391443
size_t np = dt->layout->npointers;
1440-
size_t fieldsize = jl_fielddesc_size(dt->layout->fielddesc_type);
1444+
size_t fieldsize = 0;
1445+
uint8_t is_foreign_type = dt->layout->fielddesc_type == 3;
1446+
if (!is_foreign_type) {
1447+
fieldsize = jl_fielddesc_size(dt->layout->fielddesc_type);
1448+
}
14411449
char *flddesc = (char*)dt->layout;
14421450
size_t fldsize = sizeof(jl_datatype_layout_t) + nf * fieldsize;
1443-
if (dt->layout->first_ptr != -1)
1451+
if (!is_foreign_type && dt->layout->first_ptr != -1)
14441452
fldsize += np << dt->layout->fielddesc_type;
14451453
uintptr_t layout = LLT_ALIGN(ios_pos(s->const_data), sizeof(void*));
14461454
write_padding(s->const_data, layout - ios_pos(s->const_data)); // realign stream
@@ -1449,6 +1457,13 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
14491457
arraylist_push(&s->relocs_list, (void*)(reloc_offset + offsetof(jl_datatype_t, layout))); // relocation location
14501458
arraylist_push(&s->relocs_list, (void*)(((uintptr_t)ConstDataRef << RELOC_TAG_OFFSET) + layout)); // relocation target
14511459
ios_write(s->const_data, flddesc, fldsize);
1460+
if (is_foreign_type) {
1461+
// make sure we have space for the extra hidden pointers
1462+
// zero them since they will need to be re-initialized externally
1463+
assert(fldsize == sizeof(jl_datatype_layout_t));
1464+
jl_fielddescdyn_t dyn = {0, 0};
1465+
ios_write(s->const_data, (char*)&dyn, sizeof(jl_fielddescdyn_t));
1466+
}
14521467
}
14531468
}
14541469
else if (jl_is_typename(v)) {

test/gcext/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/gcext
22
/gcext-debug
3+
/Foreign/deps
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This file is machine-generated - editing it directly is not advised
2+
3+
julia_version = "1.8.3"
4+
manifest_format = "2.0"
5+
project_hash = "e7199d961a5f4ebad68a3deaf5beaa7406a0afcb"
6+
7+
[[deps.Foreign]]
8+
deps = ["Libdl"]
9+
path = "../Foreign"
10+
uuid = "de1f6f7a-d7b3-400f-91c2-33f248ee89c4"
11+
version = "0.1.0"
12+
13+
[[deps.Libdl]]
14+
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name = "DependsOnForeign"
2+
uuid = "4b0716e0-dfb5-4e00-8b44-e2685a41517f"
3+
version = "0.1.0"
4+
5+
[deps]
6+
Foreign = "de1f6f7a-d7b3-400f-91c2-33f248ee89c4"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module DependsOnForeign
2+
3+
using Foreign
4+
5+
f(obj::FObj) = Base.pointer_from_objref(obj)
6+
precompile(f, (FObj,))
7+
8+
const FObjRef = Ref{FObj}()
9+
10+
function __init__()
11+
FObjRef[] = FObj()
12+
end
13+
14+
end # module DependsOnForeign

test/gcext/Foreign/Manifest.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# This file is machine-generated - editing it directly is not advised
2+
3+
julia_version = "1.9.0-DEV"
4+
manifest_format = "2.0"
5+
project_hash = "7b70172a2edbdc772ed789e79d4411d7528eae86"
6+
7+
[[deps.Libdl]]
8+
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

test/gcext/Foreign/Project.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name = "Foreign"
2+
uuid = "de1f6f7a-d7b3-400f-91c2-33f248ee89c4"
3+
version = "0.1.0"
4+
5+
[deps]
6+
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

0 commit comments

Comments
 (0)