/
githubmirror
/
julia
Обзор
Документация
Войти
/
githubmirror
/
julia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/processor.h
295 строк
12 KB
Sam Schweigel
Split images: write the heap image to the .ji (#61649)
06 авг 2026, 19:15
Не верифицирован
06 авг 2026, 19:15
ad84450
Код
Авторство
О чём код?
// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef JL_PROCESSOR_H #define JL_PROCESSOR_H #include "support/dtypes.h" #include "julia.h" #include <stddef.h> #include <stdint.h> #ifdef __cplusplus extern "C" { #endif // Image metadata // Every image exports a `jl_image_pointers_t` as a global symbol `jl_image_pointers`. // This symbol acts as a root for all other code-related symbols in the image. // Feature indices come from the cpufeatures library's generated tables. // The actual constants are defined in base/features_h.jl (auto-generated). typedef uint32_t jl_cpu_feature_t; JL_DLLEXPORT int jl_test_cpu_feature(jl_cpu_feature_t feature); static const uint32_t jl_sysimg_tag_mask = 0x80000000u; static const uint32_t jl_sysimg_val_mask = ~((uint32_t)0x80000000u); // A parsed image file typedef struct _jl_image_fptrs_t { // number of functions uint32_t nptrs; // function pointers void **ptrs; // Following fields contain the information about the selected target. // All of these fields are 0 if the selected targets have all the functions cloned. // Instead the offsets are stored in `nptrs` and `ptrs`. // number of cloned functions uint32_t nclones; // function pointer of cloned functions void **clone_ptrs; // sorted indices of the cloned functions (including the tag bit) const uint32_t *clone_idxs; } jl_image_fptrs_t; struct _jl_image_t { uint64_t base; const char *gvars_base; const int32_t *gvars_offsets; uint32_t ngvars; jl_image_fptrs_t fptrs; void **jl_small_typeof; uint32_t heap_checksum; bool_t is_split; }; // The header for each image // Details important counts about the image typedef struct { // The version of the image format // Most up-to-date version is 1 uint32_t version; // The number of shards in this image uint32_t nshards; // The total number of fvars in this image among all shards uint32_t nfvars; // The total number of gvars in this image among all shards uint32_t ngvars; } jl_image_header_t; // Per-shard data for image shards. Each image contains header->nshards of these. typedef struct { // The array of function pointers (`void*`). // This includes all julia functions in sysimg as well as all other functions that are cloned. // The default function pointer is used if the function is cloned. // The first element is the size of the array, which should **NOT** be used is the number // of julia functions in the sysimg. // Each entry in this array uniquely identifies a function we are interested in // (the function may have multiple function pointers corresponding to different versions). const uintptr_t *fvar_count; void **fvar_ptrs; // This is the mapping of shard function index -> global function index // staticdata.c relies on the same order of functions in the global function array being // the same as what it saw when serializing the global function array. However, partitioning // into multiple shards will cause functions to be reordered. This array is used to map // back to the original function array for loading. const uint32_t *fvar_idxs; // This array of global variable offsets (`int32_t`) from the base pointer. // Similar to fvar_offsets, but for gvars // This is also the base data pointer // (all data pointers in this shard are stored as offsets to this address) const int32_t *gvar_offsets; // This is the mapping of shard global variable index -> global global variable index // Similar to fvar_idxs, but for gvars const uint32_t *gvar_idxs; // location and index of relocation slots. // Stored as pairs of function indices and `int32_t` offsets from `jl_sysimg_gvars_base`. // The first element is an `uint32_t` giving the number of relocations. // This is needed for functions whose address is used in a way that requires dispatch. // We currently only support one type of relocation (i.e. absolute pointer) which is enough // for all use in functions as well as GOT slot (for "PLT" callback). // Note that not all functions being cloned are assigned a slot. // This array is sorted by the function indices. // There can be more than one slot per-function, // i.e. there can be duplicated function indices. const int32_t *clone_slots; // Target-specific function pointer offsets. // This contains all the cloned functions that we are interested in and it needs to be decoded // and used along with `jl_dispatch_fvars_idxs`. // For the default target, there's no entries in this variable, if there's any relocations // needed for the default target, the function pointers are taken from the global offset // arrays directly. // For a `clone_all` target (i.e. with the length in `jl_dispatch_fvars_idxs` tagged), this // variable contains an offset array of the same length as the global one. Only the indices // appearing in `jl_dispatch_fvars_idxs` need relocation and the dispatch code should return // this array as the original/base function offsets. // For other targets, this variable contains an offset array with the length defined in // `jl_dispatch_fvars_idxs`. Tagged indices need relocations. void **clone_ptrs; // Target-specific function indices. // For each target, this includes a tagged `uint32_t` length, an optional `uint32_t` index // of the base target followed by an array of tagged function indices. // The base target index is required to be smaller than the index of the current target // and must be the default (`0`) or a `clone_all` target. // The tag bits for both the length and the indices are the top bit. // A tagged length indicates that all of the functions are cloned and the indices follows // are the ones that requires relocation. The base target index is omitted in this case. // Otherwise, the length is the total number of functions that we are interested in // for this target, which includes all cloned julia functions and // all other cloned functions that requires relocation. // A tagged index means that the function pointer should be filled into the GOT slots // identified by `jl_dispatch_reloc_slots`. There could be more than one slot per function. // (Note that a tagged index could corresponds to a function's pointer that's the same as // the base one since this is the only way we currently represent relocations.) const uint32_t *clone_idxs; } jl_image_shard_t; // The TLS data for each image typedef struct { void *pgcstack_func_slot; void *pgcstack_key_slot; size_t *tls_offset; } jl_image_ptls_t; //The root struct for images, points to all the other globals typedef struct { // The image header, contains numerical global data const jl_image_header_t *header; // The shard table, contains per-shard data 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 jl_small_typeof[] void **jl_small_typeof; // serialized target data // This contains the number of targets // in addition to the name and feature set of each target. const void *target_data; // Original CPU target string used to build this sysimage const char *cpu_target_string; } jl_image_pointers_t; /** * Initialize the processor dispatch system with sysimg `hdl` (also initialize the sysimg itself). * The dispatch system will find the best implementation to be used in this session. * The decision will be based on the host CPU and features as well as the `cpu_target` * option. This must be called before initializing JIT and should only be called once. * An error will be raised if this is called more than once or none of the implementation * supports the current system. * * Return the data about the function pointers selected. */ void jl_check_cpu_target(const char *cpu_target, int imaging); jl_image_t jl_load_sysimg(jl_image_buf_t image, const char *cpu_target); jl_image_t jl_load_pkgimg(jl_image_buf_t image); // Internal function to set the sysimage CPU target during initialization void jl_set_sysimage_cpu_target(const char *cpu_target) JL_NOTSAFEPOINT; // Return the name of the host CPU as a julia string. JL_DLLEXPORT jl_value_t *jl_get_cpu_name(void) JL_CANSAFEPOINT; // Return the features of the host CPU as a julia string. JL_DLLEXPORT jl_value_t *jl_get_cpu_features(void) JL_CANSAFEPOINT; // Return the CPU target string used to build the current sysimage JL_DLLEXPORT jl_value_t *jl_get_sysimage_cpu_target(void) JL_CANSAFEPOINT; // Check if the CPU has native FMA instructions; // For debugging only JL_DLLEXPORT jl_value_t *jl_cpu_has_fma(int bits); // Dump the name and feature set of the host CPU JL_DLLEXPORT void jl_dump_host_cpu(void); JL_DLLEXPORT jl_value_t* jl_check_pkgimage_clones(char* data) JL_CANSAFEPOINT; JL_DLLEXPORT int32_t jl_set_zero_subnormals(int8_t isZero) JL_NOTSAFEPOINT; JL_DLLEXPORT int32_t jl_get_zero_subnormals(void) JL_NOTSAFEPOINT; JL_DLLEXPORT int32_t jl_set_default_nans(int8_t isDefault) JL_NOTSAFEPOINT; JL_DLLEXPORT int32_t jl_get_default_nans(void) JL_NOTSAFEPOINT; /** * System image contents. * * These symbols are typically dummy values, unless statically linking * libjulia-* and the sysimage together (see null_sysimage.c), in which * case they allow accessing the local copy of the sysimage. **/ typedef void (JL_NOTSAFEPOINT *jl_image_unpack_func_t)(void *handle, jl_image_buf_t *image); extern jl_image_unpack_func_t jl_image_unpack; /** * CPU name and feature string for LLVM. * * The pointers reference storage with static lifetime; they remain valid * for the duration of the process and must not be freed by the caller. */ typedef struct { const char *cpu_name; const char *cpu_features; } jl_llvm_target_t; typedef struct { char *cpu_name; char *cpu_features; int32_t base; uint8_t clone_all; uint8_t opt_size; uint8_t min_size; // Enabled-feature bitset (hw-masked), for diffing against the base target uint64_t *en_features; size_t en_features_nwords; } jl_target_spec_t; typedef struct { jl_target_spec_t *specs; size_t nspecs; uint8_t *data; // serialized target identification blob size_t data_size; } jl_clone_targets_t; /** * Return the list of targets to clone and their serialized identification data. * * The result owns malloc-allocated memory; release it with jl_free_clone_targets. */ JL_DLLEXPORT jl_clone_targets_t jl_get_llvm_clone_targets(const char *cpu_target) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_free_clone_targets(jl_clone_targets_t *targets) JL_NOTSAFEPOINT; /** * If cpu_target starts with "sysimage", replace it with the target string stored * in the loaded sysimage. Otherwise return a copy of cpu_target as-is. * * The returned string is malloc-allocated; the caller must free() it. */ JL_DLLEXPORT char *jl_expand_sysimage_keyword(const char *cpu_target) JL_NOTSAFEPOINT; #ifdef __cplusplus } #include <utility> #include <string> #include <vector> #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) #include <cpufeatures/target_tables_x86_64.h> #elif defined(__aarch64__) || defined(_M_ARM64) #include <cpufeatures/target_tables_aarch64.h> #elif defined(__riscv) && __riscv_xlen == 64 #include <cpufeatures/target_tables_riscv64.h> #else #include <cpufeatures/target_tables_fallback.h> #endif #include <cpufeatures/target_parsing.h> /** * Returns the CPU name and feature string to be used by LLVM JIT. * * If the detected/specified CPU name is not available on the LLVM version specified, * a fallback CPU name will be used. Unsupported features will be ignored. */ extern "C" JL_DLLEXPORT jl_llvm_target_t jl_get_llvm_target(const char *cpu_target, bool imaging) JL_NOTSAFEPOINT; /** * Returns the CPU name and feature string to be used by LLVM disassembler. * * This will return a generic CPU name and a full feature string. */ extern "C" JL_DLLEXPORT jl_llvm_target_t jl_get_llvm_disasm_target(void) JL_NOTSAFEPOINT; extern "C" JL_DLLEXPORT jl_value_t* jl_reflect_clone_targets() JL_CANSAFEPOINT; extern "C" JL_DLLEXPORT jl_value_t *jl_feature_bits_to_string(const uint8_t *bits, int32_t nwords) JL_CANSAFEPOINT; #endif #endif