From 8a0b29a3ef6d2394361f89eaa4ee4ddcd0e6aac6 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Fri, 11 Aug 2023 05:07:34 -0400 Subject: [PATCH 1/4] Add JL_DLLIMPORT to `small_typeof` declaration Resolves #50714. --- src/julia.h | 3 +++ test/embedding/embedding.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/julia.h b/src/julia.h index 604433711478c..ec98e37de6887 100644 --- a/src/julia.h +++ b/src/julia.h @@ -750,6 +750,9 @@ enum jlsmall_typeof_tags { jl_bitstags_first = jl_char_tag, // n.b. bool is not considered a bitstype, since it can be compared by pointer jl_max_tags = 64 }; +#ifndef JL_LIBRARY_EXPORTS +JL_DLLIMPORT +#endif extern jl_datatype_t *small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; static inline jl_value_t *jl_to_typeof(uintptr_t t) { diff --git a/test/embedding/embedding.c b/test/embedding/embedding.c index 1294d4cdafb45..c5b8845b7c823 100644 --- a/test/embedding/embedding.c +++ b/test/embedding/embedding.c @@ -192,6 +192,12 @@ int main() checked_eval_string("f28825()"); } + { + // jl_typeof works (#50714) + jl_value_t *v = checked_eval_string("sqrt(2.0)"); + jl_value_t *t = jl_typeof(v); + } + JL_TRY { jl_error("exception thrown"); } From 637679d0fd7988edd3e00ed14b840cde563e0fc0 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Fri, 11 Aug 2023 06:01:42 -0400 Subject: [PATCH 2/4] Remove `export_small_typeof` I think this might have been part of a scheme to avoid an extra indirection when this symbol is exposed to the linker. We have a similar technique used for JIT'd modules, but I'm not sure how it's supposed to work here between libjulia and libjulia-internal. On Windows, this is broken for embedding currently, and on Linux this function was just copying from the `small_typeof` in libjulia to a seem- ingly unused copy of the symbol in libjulia-internal. For now, this removes the special machinery and replaces it with a single copy of the data. If we'd like to optimize this in the future, we might want to use the existing "ijl_" vs. "jl_" pattern --- src/jltypes.c | 14 -------------- src/staticdata.c | 2 -- 2 files changed, 16 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index 75bf828949329..54917e127bc2f 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -20,7 +20,6 @@ extern "C" { #endif _Atomic(jl_value_t*) cmpswap_names JL_GLOBALLY_ROOTED; -jl_datatype_t *small_typeof[(jl_max_tags << 4) / sizeof(*small_typeof)]; // 16-bit aligned, like the GC // compute empirical max-probe for a given size #define max_probe(size) ((size) <= 1024 ? 16 : (size) >> 6) @@ -2529,17 +2528,6 @@ static jl_tvar_t *tvar(const char *name) (jl_value_t*)jl_any_type); } -void export_small_typeof(void) -{ - void *copy; -#ifdef _OS_WINDOWS_ - jl_dlsym(jl_libjulia_handle, "small_typeof", ©, 1); -#else - jl_dlsym(jl_libjulia_internal_handle, "small_typeof", ©, 1); -#endif - memcpy(copy, &small_typeof, sizeof(small_typeof)); -} - #define XX(name) \ small_typeof[(jl_##name##_tag << 4) / sizeof(*small_typeof)] = jl_##name##_type; \ jl_##name##_type->smalltag = jl_##name##_tag; @@ -3363,7 +3351,6 @@ void jl_init_types(void) JL_GC_DISABLED // override the preferred layout for a couple types jl_lineinfonode_type->name->mayinlinealloc = 0; // FIXME: assumed to be a pointer by codegen - export_small_typeof(); } static jl_value_t *core(const char *name) @@ -3444,7 +3431,6 @@ void post_boot_hooks(void) } } } - export_small_typeof(); } void post_image_load_hooks(void) { diff --git a/src/staticdata.c b/src/staticdata.c index 93f0c8999c180..6fbee6b92df78 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2839,7 +2839,6 @@ JL_DLLEXPORT void jl_set_sysimg_so(void *handle) #endif extern void rebuild_image_blob_tree(void); -extern void export_small_typeof(void); static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl_array_t *depmods, uint64_t checksum, /* outputs */ jl_array_t **restored, jl_array_t **init_order, @@ -2918,7 +2917,6 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl small_typeof[(jl_##name##_tag << 4) / sizeof(*small_typeof)] = jl_##name##_type; JL_SMALL_TYPEOF(XX) #undef XX - export_small_typeof(); jl_global_roots_table = (jl_array_t*)jl_read_value(&s); // set typeof extra-special values now that we have the type set by tags above jl_astaggedvalue(jl_nothing)->header = (uintptr_t)jl_nothing_type | jl_astaggedvalue(jl_nothing)->header; From a8f1a988fa1ed07acbfccda00a4decf0a0e49370 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Mon, 14 Aug 2023 21:50:59 -0400 Subject: [PATCH 3/4] Rename `small_typeof` to `jl_small_typeof` --- cli/jl_exports.h | 2 +- src/aotcompile.cpp | 20 ++++++++++---------- src/builtins.c | 2 +- src/cgutils.cpp | 6 +++--- src/codegen.cpp | 6 +++--- src/gc.c | 4 ++-- src/jltypes.c | 2 +- src/julia.expmap.in | 1 - src/julia.h | 6 +++--- src/processor.cpp | 2 +- src/processor.h | 6 +++--- src/staticdata.c | 4 ++-- 12 files changed, 30 insertions(+), 31 deletions(-) diff --git a/cli/jl_exports.h b/cli/jl_exports.h index d28958c097edb..f1a05b504d9da 100644 --- a/cli/jl_exports.h +++ b/cli/jl_exports.h @@ -18,7 +18,7 @@ JL_EXPORTED_DATA_SYMBOLS(XX) // define a copy of exported data #define jl_max_tags 64 -JL_DLLEXPORT void *small_typeof[(jl_max_tags << 4) / sizeof(void*)]; // 16-bit aligned, like the GC +JL_DLLEXPORT void *jl_small_typeof[(jl_max_tags << 4) / sizeof(void*)]; // 16-bit aligned, like the GC // Declare list of exported functions (sans type) #define XX(name) JL_DLLEXPORT void name(void); diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index cf92130a3aaed..48fa2ca1038c6 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -1634,10 +1634,10 @@ void jl_dump_native_impl(void *native_code, // let the compiler know we are going to internalize a copy of this, // if it has a current usage with ExternalLinkage - auto small_typeof_copy = dataM.getGlobalVariable("small_typeof"); - if (small_typeof_copy) { - small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); - small_typeof_copy->setDSOLocal(true); + auto jl_small_typeof_copy = dataM.getGlobalVariable("jl_small_typeof"); + if (jl_small_typeof_copy) { + jl_small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); + jl_small_typeof_copy->setDSOLocal(true); } } @@ -1712,13 +1712,13 @@ void jl_dump_native_impl(void *native_code, auto shards = emit_shard_table(metadataM, T_size, T_psize, threads); auto ptls = emit_ptls_table(metadataM, T_size, T_psize); auto header = emit_image_header(metadataM, threads, nfvars, ngvars); - auto AT = ArrayType::get(T_size, sizeof(small_typeof) / sizeof(void*)); - auto small_typeof_copy = new GlobalVariable(metadataM, AT, false, + auto AT = ArrayType::get(T_size, sizeof(jl_small_typeof) / sizeof(void*)); + auto jl_small_typeof_copy = new GlobalVariable(metadataM, AT, false, GlobalVariable::ExternalLinkage, Constant::getNullValue(AT), - "small_typeof"); - small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); - small_typeof_copy->setDSOLocal(true); + "jl_small_typeof"); + jl_small_typeof_copy->setVisibility(GlobalValue::HiddenVisibility); + jl_small_typeof_copy->setDSOLocal(true); AT = ArrayType::get(T_psize, 5); auto pointers = new GlobalVariable(metadataM, AT, false, GlobalVariable::ExternalLinkage, @@ -1726,7 +1726,7 @@ void jl_dump_native_impl(void *native_code, ConstantExpr::getBitCast(header, T_psize), ConstantExpr::getBitCast(shards, T_psize), ConstantExpr::getBitCast(ptls, T_psize), - ConstantExpr::getBitCast(small_typeof_copy, T_psize), + ConstantExpr::getBitCast(jl_small_typeof_copy, T_psize), ConstantExpr::getBitCast(target_ids, T_psize) }), "jl_image_pointers"); diff --git a/src/builtins.c b/src/builtins.c index 81afa8bae482a..d0d4b3bf1dbef 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -222,7 +222,7 @@ JL_DLLEXPORT int jl_egal__unboxed(const jl_value_t *a JL_MAYBE_UNROOTED, const j JL_DLLEXPORT int jl_egal__bitstag(const jl_value_t *a JL_MAYBE_UNROOTED, const jl_value_t *b JL_MAYBE_UNROOTED, uintptr_t dtag) JL_NOTSAFEPOINT { if (dtag < jl_max_tags << 4) { - switch ((enum jlsmall_typeof_tags)(dtag >> 4)) { + switch ((enum jl_small_typeof_tags)(dtag >> 4)) { case jl_int8_tag: case jl_uint8_tag: return *(uint8_t*)a == *(uint8_t*)b; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index c6ba2d7551986..28a0aa33c49f6 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -410,7 +410,7 @@ static Constant *literal_pointer_val_slot(jl_codectx_t &ctx, jl_value_t *p) if (addr->smalltag) { // some common builtin datatypes have a special pool for accessing them by smalltag id Constant *tag = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), addr->smalltag << 4); - Constant *smallp = ConstantExpr::getInBoundsGetElementPtr(getInt8Ty(ctx.builder.getContext()), prepare_global_in(jl_Module, jlsmall_typeof_var), tag); + Constant *smallp = ConstantExpr::getInBoundsGetElementPtr(getInt8Ty(ctx.builder.getContext()), prepare_global_in(jl_Module, jl_small_typeof_var), tag); return ConstantExpr::getBitCast(smallp, ctx.types().T_ppjlvalue); } // DataTypes are prefixed with a + @@ -1086,7 +1086,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybenull if (jl_has_intersect_type_not_kind(typ)) return false; for (size_t i = 0; i < jl_tags_count; i++) { - jl_datatype_t *dt = small_typeof[(i << 4) / sizeof(*small_typeof)]; + jl_datatype_t *dt = jl_small_typeof[(i << 4) / sizeof(*jl_small_typeof)]; if (dt && !jl_has_empty_intersection((jl_value_t*)dt, typ)) return false; } @@ -1439,7 +1439,7 @@ static Value *emit_typeof(jl_codectx_t &ctx, Value *v, bool maybenull, bool just // we lied a bit: this wasn't really an object (though it was valid for GC rooting) // and we need to use it as an index to get the real object now Module *M = jl_Module; - Value *smallp = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), prepare_global_in(M, jlsmall_typeof_var), tag); + Value *smallp = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), prepare_global_in(M, jl_small_typeof_var), tag); smallp = ctx.builder.CreateBitCast(smallp, typetag->getType()->getPointerTo(0)); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); auto small = ctx.builder.CreateAlignedLoad(typetag->getType(), smallp, M->getDataLayout().getPointerABIAlignment(0)); diff --git a/src/codegen.cpp b/src/codegen.cpp index 2f381b3b76cfc..9d8fd8718e625 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -691,8 +691,8 @@ static const auto jldlli_var = new JuliaVariable{ true, [](Type *T_size) -> Type * { return getInt8PtrTy(T_size->getContext()); }, }; -static const auto jlsmall_typeof_var = new JuliaVariable{ - XSTR(small_typeof), +static const auto jl_small_typeof_var = new JuliaVariable{ + XSTR(jl_small_typeof), true, [](Type *T_size) -> Type * { return getInt8Ty(T_size->getContext()); }, }; @@ -9178,7 +9178,7 @@ static void init_f16_funcs(void) static void init_jit_functions(void) { - add_named_global(jlsmall_typeof_var, &small_typeof); + add_named_global(jl_small_typeof_var, &jl_small_typeof); add_named_global(jlstack_chk_guard_var, &__stack_chk_guard); add_named_global(jlRTLD_DEFAULT_var, &jl_RTLD_DEFAULT_handle); add_named_global(jlexe_var, &jl_exe_handle); diff --git a/src/gc.c b/src/gc.c index bbf996c98040a..885a218442531 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2427,7 +2427,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ vtag == (jl_vararg_tag << 4)) { // these objects have pointers in them, but no other special handling // so we want these to fall through to the end - vtag = (uintptr_t)small_typeof[vtag / sizeof(*small_typeof)]; + vtag = (uintptr_t)jl_small_typeof[vtag / sizeof(*jl_small_typeof)]; } else if (vtag < jl_max_tags << 4) { // these objects either have specialing handling @@ -2532,7 +2532,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ objprofile_count(jl_string_type, bits == GC_OLD_MARKED, dtsz); } else { - jl_datatype_t *vt = small_typeof[vtag / sizeof(*small_typeof)]; + jl_datatype_t *vt = jl_small_typeof[vtag / sizeof(*jl_small_typeof)]; size_t dtsz = jl_datatype_size(vt); if (update_meta) gc_setmark(ptls, o, bits, dtsz); diff --git a/src/jltypes.c b/src/jltypes.c index 54917e127bc2f..ea64cc8bdb01d 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2529,7 +2529,7 @@ static jl_tvar_t *tvar(const char *name) } #define XX(name) \ - small_typeof[(jl_##name##_tag << 4) / sizeof(*small_typeof)] = jl_##name##_type; \ + jl_small_typeof[(jl_##name##_tag << 4) / sizeof(*jl_small_typeof)] = jl_##name##_type; \ jl_##name##_type->smalltag = jl_##name##_tag; void jl_init_types(void) JL_GC_DISABLED { diff --git a/src/julia.expmap.in b/src/julia.expmap.in index 484c83a4b16b2..213d087fdc2ad 100644 --- a/src/julia.expmap.in +++ b/src/julia.expmap.in @@ -7,7 +7,6 @@ ios_*; arraylist_grow; small_arraylist_grow; - small_typeof; jl_*; ijl_*; _jl_mutex_*; diff --git a/src/julia.h b/src/julia.h index ec98e37de6887..1ba0ce6c91141 100644 --- a/src/julia.h +++ b/src/julia.h @@ -741,7 +741,7 @@ typedef struct { /* XX(slotnumber) */ \ /* XX(ssavalue) */ \ /* end of JL_SMALL_TYPEOF */ -enum jlsmall_typeof_tags { +enum jl_small_typeof_tags { jl_null_tag = 0, #define XX(name) jl_##name##_tag, JL_SMALL_TYPEOF(XX) @@ -753,11 +753,11 @@ enum jlsmall_typeof_tags { #ifndef JL_LIBRARY_EXPORTS JL_DLLIMPORT #endif -extern jl_datatype_t *small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +extern jl_datatype_t *jl_small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; static inline jl_value_t *jl_to_typeof(uintptr_t t) { if (t < (jl_max_tags << 4)) - return (jl_value_t*)small_typeof[t / sizeof(*small_typeof)]; + return (jl_value_t*)jl_small_typeof[t / sizeof(*jl_small_typeof)]; return (jl_value_t*)t; } diff --git a/src/processor.cpp b/src/processor.cpp index 9a602ba836f89..d2d91d3cd9966 100644 --- a/src/processor.cpp +++ b/src/processor.cpp @@ -812,7 +812,7 @@ static inline jl_image_t parse_sysimg(void *hdl, F &&callback) *tls_offset_idx = (uintptr_t)(jl_tls_offset == -1 ? 0 : jl_tls_offset); } - res.small_typeof = pointers->small_typeof; + res.jl_small_typeof = pointers->jl_small_typeof; return res; } diff --git a/src/processor.h b/src/processor.h index 74610cbe64b28..a3ebdf4f8c605 100644 --- a/src/processor.h +++ b/src/processor.h @@ -88,7 +88,7 @@ typedef struct { const int32_t *gvars_offsets; uint32_t ngvars; jl_image_fptrs_t fptrs; - void **small_typeof; + void **jl_small_typeof; } jl_image_t; // The header for each image @@ -197,8 +197,8 @@ typedef struct { const jl_image_shard_t *shards; // points to header->nshards length array // The TLS data pointer const jl_image_ptls_t *ptls; - // A copy of small_typeof[] - void **small_typeof; + // A copy of jl_small_typeof[] + void **jl_small_typeof; // serialized target data // This contains the number of targets diff --git a/src/staticdata.c b/src/staticdata.c index 6fbee6b92df78..98f37855fe317 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -1985,7 +1985,7 @@ static void jl_update_all_fptrs(jl_serializer_state *s, jl_image_t *image) if (fvars.base == NULL) return; - memcpy(image->small_typeof, &small_typeof, sizeof(small_typeof)); + memcpy(image->jl_small_typeof, &jl_small_typeof, sizeof(jl_small_typeof)); int img_fvars_max = s->fptr_record->size / sizeof(void*); size_t i; @@ -2914,7 +2914,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl *tag = jl_read_value(&s); } #define XX(name) \ - small_typeof[(jl_##name##_tag << 4) / sizeof(*small_typeof)] = jl_##name##_type; + jl_small_typeof[(jl_##name##_tag << 4) / sizeof(*jl_small_typeof)] = jl_##name##_type; JL_SMALL_TYPEOF(XX) #undef XX jl_global_roots_table = (jl_array_t*)jl_read_value(&s); From 0a372509f77bb9dfcb605fe3adf8e9e7c4c5d97d Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Wed, 30 Aug 2023 13:11:17 -0400 Subject: [PATCH 4/4] Add HIDDEN `ijl_small_typeof` as an optimization This allows us to avoid a linker indirection on, e.g., Linux and macOS where symbol interposition means that an extra load is incurred to support possible relocation of the symbol to a pre-empting library. --- src/Makefile | 7 ++++++- src/gc.c | 4 ++-- src/jltypes.c | 12 +++++++++++- src/julia.h | 15 +++++++++++---- src/staticdata.c | 4 +++- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/Makefile b/src/Makefile index 88b1e303cb329..54a81676c3144 100644 --- a/src/Makefile +++ b/src/Makefile @@ -528,7 +528,12 @@ clang-tidy-%: $(SRCDIR)/%.cpp $(build_shlibdir)/libImplicitAtomicsPlugin.$(SHLIB -- $(CLANGSA_FLAGS) $(CLANGSA_CXXFLAGS) $(LLVM_CXXFLAGS) $(JCPPFLAGS_CLANG) $(JCXXFLAGS_CLANG) $(JL_CXXFLAGS) $(DEBUGFLAGS_CLANG) -fcolor-diagnostics --system-header-prefix=llvm -Wno-deprecated-declarations -fno-caret-diagnostics -x c++) # set the exports for the source files based on where they are getting linked -clang-sa-% clang-sagc-% clang-tidy-%: DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS +$(addprefix clang-sa-,$(SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_INTERNAL +$(addprefix clang-sagc-,$(SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_INTERNAL +$(addprefix clang-tidy-,$(SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_INTERNAL +$(addprefix clang-sa-,$(CODEGEN_SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_CODEGEN +$(addprefix clang-sagc-,$(CODEGEN_SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_CODEGEN +$(addprefix clang-tidy-,$(CODEGEN_SRCS)): DEBUGFLAGS_CLANG += -DJL_LIBRARY_EXPORTS_CODEGEN # Add C files as a target of `analyzesrc` and `analyzegc` and `tidysrc` tidysrc: $(addprefix clang-tidy-,$(filter-out $(basename $(SKIP_IMPLICIT_ATOMICS)),$(CODEGEN_SRCS) $(SRCS))) diff --git a/src/gc.c b/src/gc.c index 885a218442531..e1bb3efc06a17 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2427,7 +2427,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ vtag == (jl_vararg_tag << 4)) { // these objects have pointers in them, but no other special handling // so we want these to fall through to the end - vtag = (uintptr_t)jl_small_typeof[vtag / sizeof(*jl_small_typeof)]; + vtag = (uintptr_t)ijl_small_typeof[vtag / sizeof(*ijl_small_typeof)]; } else if (vtag < jl_max_tags << 4) { // these objects either have specialing handling @@ -2532,7 +2532,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_ objprofile_count(jl_string_type, bits == GC_OLD_MARKED, dtsz); } else { - jl_datatype_t *vt = jl_small_typeof[vtag / sizeof(*jl_small_typeof)]; + jl_datatype_t *vt = ijl_small_typeof[vtag / sizeof(*ijl_small_typeof)]; size_t dtsz = jl_datatype_size(vt); if (update_meta) gc_setmark(ptls, o, bits, dtsz); diff --git a/src/jltypes.c b/src/jltypes.c index ea64cc8bdb01d..15da9448fa3e1 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -20,6 +20,7 @@ extern "C" { #endif _Atomic(jl_value_t*) cmpswap_names JL_GLOBALLY_ROOTED; +jl_datatype_t *ijl_small_typeof[(jl_max_tags << 4) / sizeof(*ijl_small_typeof)]; // 16-bit aligned, like the GC // compute empirical max-probe for a given size #define max_probe(size) ((size) <= 1024 ? 16 : (size) >> 6) @@ -2528,8 +2529,13 @@ static jl_tvar_t *tvar(const char *name) (jl_value_t*)jl_any_type); } +void export_jl_small_typeof(void) +{ + memcpy(&jl_small_typeof, &ijl_small_typeof, sizeof(jl_small_typeof)); +} + #define XX(name) \ - jl_small_typeof[(jl_##name##_tag << 4) / sizeof(*jl_small_typeof)] = jl_##name##_type; \ + ijl_small_typeof[(jl_##name##_tag << 4) / sizeof(*ijl_small_typeof)] = jl_##name##_type; \ jl_##name##_type->smalltag = jl_##name##_tag; void jl_init_types(void) JL_GC_DISABLED { @@ -3351,6 +3357,8 @@ void jl_init_types(void) JL_GC_DISABLED // override the preferred layout for a couple types jl_lineinfonode_type->name->mayinlinealloc = 0; // FIXME: assumed to be a pointer by codegen + + export_jl_small_typeof(); } static jl_value_t *core(const char *name) @@ -3431,6 +3439,8 @@ void post_boot_hooks(void) } } } + + export_jl_small_typeof(); } void post_image_load_hooks(void) { diff --git a/src/julia.h b/src/julia.h index 1ba0ce6c91141..95afb4cc5aee1 100644 --- a/src/julia.h +++ b/src/julia.h @@ -750,16 +750,23 @@ enum jl_small_typeof_tags { jl_bitstags_first = jl_char_tag, // n.b. bool is not considered a bitstype, since it can be compared by pointer jl_max_tags = 64 }; -#ifndef JL_LIBRARY_EXPORTS -JL_DLLIMPORT -#endif -extern jl_datatype_t *jl_small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +extern JL_DLLIMPORT jl_datatype_t *jl_small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +#ifndef JL_LIBRARY_EXPORTS_INTERNAL static inline jl_value_t *jl_to_typeof(uintptr_t t) { if (t < (jl_max_tags << 4)) return (jl_value_t*)jl_small_typeof[t / sizeof(*jl_small_typeof)]; return (jl_value_t*)t; } +#else +extern JL_HIDDEN jl_datatype_t *ijl_small_typeof[(jl_max_tags << 4) / sizeof(jl_datatype_t*)]; +static inline jl_value_t *jl_to_typeof(uintptr_t t) +{ + if (t < (jl_max_tags << 4)) + return (jl_value_t*)ijl_small_typeof[t / sizeof(*ijl_small_typeof)]; + return (jl_value_t*)t; +} +#endif // kinds diff --git a/src/staticdata.c b/src/staticdata.c index 98f37855fe317..0bd23b77a2fac 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2839,6 +2839,7 @@ JL_DLLEXPORT void jl_set_sysimg_so(void *handle) #endif extern void rebuild_image_blob_tree(void); +extern void export_jl_small_typeof(void); static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl_array_t *depmods, uint64_t checksum, /* outputs */ jl_array_t **restored, jl_array_t **init_order, @@ -2914,9 +2915,10 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl *tag = jl_read_value(&s); } #define XX(name) \ - jl_small_typeof[(jl_##name##_tag << 4) / sizeof(*jl_small_typeof)] = jl_##name##_type; + ijl_small_typeof[(jl_##name##_tag << 4) / sizeof(*ijl_small_typeof)] = jl_##name##_type; JL_SMALL_TYPEOF(XX) #undef XX + export_jl_small_typeof(); jl_global_roots_table = (jl_array_t*)jl_read_value(&s); // set typeof extra-special values now that we have the type set by tags above jl_astaggedvalue(jl_nothing)->header = (uintptr_t)jl_nothing_type | jl_astaggedvalue(jl_nothing)->header;