LCOV - code coverage report
Current view: top level - src - init.c (source / functions) Hit Total Coverage
Test: [build process] commit ef510b1f346f4c9f9d86eaceace5ca54961a1dbc Lines: 303 410 73.9 %
Date: 2022-07-17 01:01:28 Functions: 20 22 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 119 207 57.5 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : /*
       4                 :            :   init.c
       5                 :            :   system initialization and global state
       6                 :            : */
       7                 :            : #include "platform.h"
       8                 :            : 
       9                 :            : #include <stdlib.h>
      10                 :            : #include <string.h>
      11                 :            : #include <stdio.h>
      12                 :            : #include <fcntl.h>
      13                 :            : #include <errno.h>
      14                 :            : #include <libgen.h> // defines dirname
      15                 :            : 
      16                 :            : #if !defined(_OS_WINDOWS_) || defined(_COMPILER_GCC_)
      17                 :            : #include <getopt.h>
      18                 :            : #endif
      19                 :            : 
      20                 :            : #if defined(_OS_FREEBSD_)
      21                 :            : #include <pthread_np.h>
      22                 :            : #endif
      23                 :            : 
      24                 :            : #include "julia.h"
      25                 :            : #include "julia_internal.h"
      26                 :            : #define DEFINE_BUILTIN_GLOBALS
      27                 :            : #include "builtin_proto.h"
      28                 :            : #undef DEFINE_BUILTIN_GLOBALS
      29                 :            : #include "threading.h"
      30                 :            : #include "julia_assert.h"
      31                 :            : #include "processor.h"
      32                 :            : 
      33                 :            : #ifdef __cplusplus
      34                 :            : extern "C" {
      35                 :            : #endif
      36                 :            : 
      37                 :            : #ifdef _OS_WINDOWS_
      38                 :            : extern int needsSymRefreshModuleList;
      39                 :            : extern BOOL (WINAPI *hSymRefreshModuleList)(HANDLE);
      40                 :            : #else
      41                 :            : #include <sys/resource.h>
      42                 :            : #include <unistd.h>
      43                 :            : #endif
      44                 :            : 
      45                 :            : // list of modules being deserialized with __init__ methods
      46                 :            : jl_array_t *jl_module_init_order;
      47                 :            : 
      48                 :            : JL_DLLEXPORT size_t jl_page_size;
      49                 :            : 
      50                 :         15 : void jl_init_stack_limits(int ismaster, void **stack_lo, void **stack_hi)
      51                 :            : {
      52                 :            : #ifdef _OS_WINDOWS_
      53                 :            :     (void)ismaster;
      54                 :            :     // https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
      55                 :            : #  ifdef _P64
      56                 :            :     *stack_hi = (void**)__readgsqword(0x08); // Stack Base / Bottom of stack (high address)
      57                 :            :     *stack_lo = (void**)__readgsqword(0x10); // Stack Limit / Ceiling of stack (low address)
      58                 :            : #  else // !_P64
      59                 :            :     *stack_hi = (void**)__readfsdword(0x04); // Stack Base / Bottom of stack (high address)
      60                 :            :     *stack_lo = (void**)__readfsdword(0x08); // Stack Limit / Ceiling of stack (low address)
      61                 :            : #  endif // _P64
      62                 :            : #else // !_OS_WINDOWS_
      63                 :            :     // Only use pthread_*_np functions to get stack address for non-master
      64                 :            :     // threads since it seems to return bogus values for master thread on Linux
      65                 :            :     // and possibly OSX.
      66         [ -  + ]:         15 :     if (!ismaster) {
      67                 :            : #  if defined(_OS_LINUX_)
      68                 :            :         pthread_attr_t attr;
      69                 :          0 :         pthread_getattr_np(pthread_self(), &attr);
      70                 :            :         void *stackaddr;
      71                 :            :         size_t stacksize;
      72                 :          0 :         pthread_attr_getstack(&attr, &stackaddr, &stacksize);
      73                 :          0 :         pthread_attr_destroy(&attr);
      74                 :          0 :         *stack_lo = (void*)stackaddr;
      75                 :            : #pragma GCC diagnostic push
      76                 :            : #if defined(_COMPILER_GCC_) && __GNUC__ >= 12
      77                 :            : #pragma GCC diagnostic ignored "-Wdangling-pointer"
      78                 :            : #endif
      79                 :          0 :         *stack_hi = (void*)&stacksize;
      80                 :            : #pragma GCC diagnostic pop
      81                 :          0 :         return;
      82                 :            : #  elif defined(_OS_DARWIN_)
      83                 :            :         extern void *pthread_get_stackaddr_np(pthread_t thread);
      84                 :            :         extern size_t pthread_get_stacksize_np(pthread_t thread);
      85                 :            :         pthread_t thread = pthread_self();
      86                 :            :         void *stackaddr = pthread_get_stackaddr_np(thread);
      87                 :            :         size_t stacksize = pthread_get_stacksize_np(thread);
      88                 :            :         *stack_lo = (void*)stackaddr;
      89                 :            :         *stack_hi = (void*)&stacksize;
      90                 :            :         return;
      91                 :            : #  elif defined(_OS_FREEBSD_)
      92                 :            :         pthread_attr_t attr;
      93                 :            :         pthread_attr_init(&attr);
      94                 :            :         pthread_attr_get_np(pthread_self(), &attr);
      95                 :            :         void *stackaddr;
      96                 :            :         size_t stacksize;
      97                 :            :         pthread_attr_getstack(&attr, &stackaddr, &stacksize);
      98                 :            :         pthread_attr_destroy(&attr);
      99                 :            :         *stack_lo = (void*)stackaddr;
     100                 :            :         *stack_hi = (void*)&stacksize;
     101                 :            :         return;
     102                 :            : #  else
     103                 :            : #      warning "Getting precise stack size for thread is not supported."
     104                 :            : #  endif
     105                 :            :     }
     106                 :            :     struct rlimit rl;
     107                 :         15 :     getrlimit(RLIMIT_STACK, &rl);
     108                 :         15 :     size_t stacksize = rl.rlim_cur;
     109                 :            : // We intentionally leak a stack address here core.StackAddressEscape
     110                 :            : #  ifndef __clang_analyzer__
     111                 :         15 :     *stack_hi = (void*)&stacksize;
     112                 :            : #pragma GCC diagnostic push
     113                 :            : #if defined(_COMPILER_GCC_) && __GNUC__ >= 12
     114                 :            : #pragma GCC diagnostic ignored "-Wdangling-pointer"
     115                 :            : #endif
     116                 :         15 :     *stack_lo = (void*)((char*)*stack_hi - stacksize);
     117                 :            : #pragma GCC diagnostic pop
     118                 :            : #  else
     119                 :            :     *stack_hi = 0;
     120                 :            :     *stack_lo = 0;
     121                 :            : #  endif
     122                 :            : #endif
     123                 :            : }
     124                 :            : 
     125                 :         15 : static void jl_prep_sanitizers(void)
     126                 :            : {
     127                 :            : #if !defined(_OS_WINDOWS_)
     128                 :            : #if defined(_COMPILER_ASAN_ENABLED_) || defined(_COMPILER_MSAN_ENABLED_)
     129                 :            :     struct rlimit rl;
     130                 :            : 
     131                 :            :     // When using the sanitizers, increase stack size because they bloat
     132                 :            :     // stack usage
     133                 :            :     const rlim_t kStackSize = 64 * 1024 * 1024;   // 64MiB stack
     134                 :            :     int result;
     135                 :            : 
     136                 :            :     result = getrlimit(RLIMIT_STACK, &rl);
     137                 :            :     if (result == 0) {
     138                 :            :         if (rl.rlim_cur < kStackSize) {
     139                 :            :             rl.rlim_cur = kStackSize;
     140                 :            :             result = setrlimit(RLIMIT_STACK, &rl);
     141                 :            :             if (result != 0) {
     142                 :            :                 fprintf(stderr, "setrlimit returned result = %d\n", result);
     143                 :            :             }
     144                 :            :         }
     145                 :            :     }
     146                 :            : #endif
     147                 :            : #endif
     148                 :         15 : }
     149                 :            : 
     150                 :            : struct uv_shutdown_queue_item { uv_handle_t *h; struct uv_shutdown_queue_item *next; };
     151                 :            : struct uv_shutdown_queue { struct uv_shutdown_queue_item *first; struct uv_shutdown_queue_item *last; };
     152                 :            : 
     153                 :         64 : static void jl_uv_exitcleanup_add(uv_handle_t *handle, struct uv_shutdown_queue *queue)
     154                 :            : {
     155                 :         64 :     struct uv_shutdown_queue_item *item = (struct uv_shutdown_queue_item*)malloc_s(sizeof(struct uv_shutdown_queue_item));
     156                 :         64 :     item->h = handle;
     157                 :         64 :     item->next = NULL;
     158         [ +  + ]:         64 :     if (queue->last)
     159                 :         49 :         queue->last->next = item;
     160         [ +  + ]:         64 :     if (!queue->first)
     161                 :         15 :         queue->first = item;
     162                 :         64 :     queue->last = item;
     163                 :         64 : }
     164                 :            : 
     165                 :         64 : static void jl_uv_exitcleanup_walk(uv_handle_t *handle, void *arg)
     166                 :            : {
     167                 :         64 :     jl_uv_exitcleanup_add(handle, (struct uv_shutdown_queue*)arg);
     168                 :         64 : }
     169                 :            : 
     170                 :         64 : static struct uv_shutdown_queue_item *next_shutdown_queue_item(struct uv_shutdown_queue_item *item)
     171                 :            : {
     172                 :         64 :     struct uv_shutdown_queue_item *rv = item->next;
     173                 :         64 :     free(item);
     174                 :         64 :     return rv;
     175                 :            : }
     176                 :            : 
     177                 :         64 : static void jl_close_item_atexit(uv_handle_t *handle)
     178                 :            : {
     179   [ +  -  +  + ]:         64 :     if (handle->type != UV_FILE && uv_is_closing(handle))
     180                 :         40 :         return;
     181      [ -  +  - ]:         24 :     switch(handle->type) {
     182                 :          0 :     case UV_PROCESS:
     183                 :            :         // cause Julia to forget about the Process object
     184                 :          0 :         handle->data = NULL;
     185                 :            :         // and make libuv think it is already dead
     186                 :          0 :         ((uv_process_t*)handle)->pid = 0;
     187                 :            :         // fall-through
     188                 :         24 :     case UV_TTY:
     189                 :            :     case UV_UDP:
     190                 :            :     case UV_TCP:
     191                 :            :     case UV_NAMED_PIPE:
     192                 :            :     case UV_POLL:
     193                 :            :     case UV_TIMER:
     194                 :            :     case UV_ASYNC:
     195                 :            :     case UV_FS_EVENT:
     196                 :            :     case UV_FS_POLL:
     197                 :            :     case UV_IDLE:
     198                 :            :     case UV_PREPARE:
     199                 :            :     case UV_CHECK:
     200                 :            :     case UV_SIGNAL:
     201                 :            :     case UV_FILE:
     202                 :            :         // These will be shutdown as appropriate by jl_close_uv
     203                 :         24 :         jl_close_uv(handle);
     204                 :         24 :         break;
     205                 :          0 :     case UV_HANDLE:
     206                 :            :     case UV_STREAM:
     207                 :            :     default:
     208                 :          0 :         assert(0 && "not a valid libuv handle");
     209                 :            :     }
     210                 :            : }
     211                 :            : 
     212                 :         15 : JL_DLLEXPORT void jl_atexit_hook(int exitcode)
     213                 :            : {
     214         [ -  + ]:         15 :     if (jl_all_tls_states == NULL)
     215                 :          0 :         return;
     216                 :            : 
     217                 :         15 :     jl_task_t *ct = jl_current_task;
     218                 :            : 
     219         [ +  - ]:         15 :     if (exitcode == 0)
     220                 :         15 :         jl_write_compiler_output();
     221                 :         15 :     jl_print_gc_stats(JL_STDERR);
     222         [ -  + ]:         15 :     if (jl_options.code_coverage)
     223                 :          0 :         jl_write_coverage_data(jl_options.output_code_coverage);
     224         [ -  + ]:         15 :     if (jl_options.malloc_log)
     225                 :          0 :         jl_write_malloc_log();
     226         [ +  + ]:         15 :     if (jl_base_module) {
     227                 :         14 :         jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit"));
     228         [ +  - ]:         14 :         if (f != NULL) {
     229   [ +  -  +  + ]:         28 :             JL_TRY {
     230                 :         14 :                 size_t last_age = ct->world_age;
     231                 :         14 :                 ct->world_age = jl_get_world_counter();
     232                 :         14 :                 jl_apply(&f, 1);
     233                 :         14 :                 ct->world_age = last_age;
     234                 :            :             }
     235         [ #  # ]:          0 :             JL_CATCH {
     236                 :          0 :                 jl_printf((JL_STREAM*)STDERR_FILENO, "\natexit hook threw an error: ");
     237                 :          0 :                 jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
     238                 :          0 :                 jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
     239                 :          0 :                 jlbacktrace(); // written to STDERR_FILENO
     240                 :            :             }
     241                 :            :         }
     242                 :            :     }
     243                 :            : 
     244                 :            :     // replace standard output streams with something that we can still print to
     245                 :            :     // after the finalizers from base/stream.jl close the TTY
     246                 :         15 :     JL_STDOUT = (uv_stream_t*) STDOUT_FILENO;
     247                 :         15 :     JL_STDERR = (uv_stream_t*) STDERR_FILENO;
     248                 :            : 
     249                 :         15 :     jl_gc_run_all_finalizers(ct);
     250                 :            : 
     251                 :         15 :     uv_loop_t *loop = jl_global_event_loop();
     252         [ +  - ]:         15 :     if (loop != NULL) {
     253                 :         15 :         struct uv_shutdown_queue queue = {NULL, NULL};
     254                 :         15 :         JL_UV_LOCK();
     255                 :         15 :         uv_walk(loop, jl_uv_exitcleanup_walk, &queue);
     256                 :         15 :         struct uv_shutdown_queue_item *item = queue.first;
     257         [ +  - ]:         15 :         if (ct != NULL) {
     258         [ +  + ]:         30 :             while (item) {
     259   [ +  -  +  + ]:         30 :                 JL_TRY {
     260         [ +  + ]:         79 :                     while (item) {
     261                 :         64 :                         jl_close_item_atexit(item->h);
     262                 :         64 :                         item = next_shutdown_queue_item(item);
     263                 :            :                     }
     264                 :            :                 }
     265         [ #  # ]:          0 :                 JL_CATCH {
     266                 :            :                     //error handling -- continue cleanup, as much as possible
     267         [ #  # ]:          0 :                     assert(item);
     268                 :          0 :                     uv_unref(item->h);
     269                 :          0 :                     jl_printf((JL_STREAM*)STDERR_FILENO, "error during exit cleanup: close: ");
     270                 :          0 :                     jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
     271                 :          0 :                     jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
     272                 :          0 :                     jlbacktrace(); // written to STDERR_FILENO
     273                 :          0 :                     item = next_shutdown_queue_item(item);
     274                 :            :                 }
     275                 :            :             }
     276                 :            :         }
     277                 :            :         else {
     278         [ #  # ]:          0 :             while (item) {
     279                 :          0 :                 jl_close_item_atexit(item->h);
     280                 :          0 :                 item = next_shutdown_queue_item(item);
     281                 :            :             }
     282                 :            :         }
     283                 :            : 
     284                 :            :         // force libuv to spin until everything has finished closing
     285                 :         15 :         loop->stop_flag = 0;
     286         [ -  + ]:         15 :         while (uv_run(loop, UV_RUN_DEFAULT)) { }
     287                 :         15 :         JL_UV_UNLOCK();
     288                 :            :     }
     289                 :            : 
     290                 :            :     // TODO: Destroy threads
     291                 :            : 
     292                 :         15 :     jl_destroy_timing();
     293                 :            : #ifdef ENABLE_TIMINGS
     294                 :            :     jl_print_timings();
     295                 :            : #endif
     296                 :            : 
     297                 :         15 :     jl_teardown_codegen();
     298                 :            : }
     299                 :            : 
     300                 :          2 : JL_DLLEXPORT void jl_postoutput_hook(void)
     301                 :            : {
     302         [ -  + ]:          2 :     if (jl_all_tls_states == NULL)
     303                 :          0 :         return;
     304                 :            : 
     305         [ +  - ]:          2 :     if (jl_base_module) {
     306                 :          2 :         jl_task_t *ct = jl_get_current_task();
     307                 :          2 :         jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_postoutput"));
     308         [ +  - ]:          2 :         if (f != NULL) {
     309   [ +  -  +  + ]:          4 :             JL_TRY {
     310                 :          2 :                 size_t last_age = ct->world_age;
     311                 :          2 :                 ct->world_age = jl_get_world_counter();
     312                 :          2 :                 jl_apply(&f, 1);
     313                 :          2 :                 ct->world_age = last_age;
     314                 :            :             }
     315         [ #  # ]:          0 :             JL_CATCH {
     316                 :          0 :                 jl_printf((JL_STREAM*)STDERR_FILENO, "\npostoutput hook threw an error: ");
     317                 :          0 :                 jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
     318                 :          0 :                 jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
     319                 :          0 :                 jlbacktrace(); // written to STDERR_FILENO
     320                 :            :             }
     321                 :            :         }
     322                 :            :     }
     323                 :          2 :     return;
     324                 :            : }
     325                 :            : 
     326                 :            : static void post_boot_hooks(void);
     327                 :            : 
     328                 :            : JL_DLLEXPORT void *jl_libjulia_internal_handle;
     329                 :            : JL_DLLEXPORT void *jl_libjulia_handle;
     330                 :            : JL_DLLEXPORT void *jl_RTLD_DEFAULT_handle;
     331                 :            : JL_DLLEXPORT void *jl_exe_handle;
     332                 :            : #ifdef _OS_WINDOWS_
     333                 :            : void *jl_ntdll_handle;
     334                 :            : void *jl_kernel32_handle;
     335                 :            : void *jl_crtdll_handle;
     336                 :            : void *jl_winsock_handle;
     337                 :            : extern const char *jl_crtdll_name;
     338                 :            : #endif
     339                 :            : 
     340                 :            : uv_loop_t *jl_io_loop;
     341                 :            : 
     342                 :            : #ifdef _OS_WINDOWS_
     343                 :            : static int uv_dup(uv_os_fd_t fd, uv_os_fd_t* dupfd) {
     344                 :            :     HANDLE current_process;
     345                 :            : 
     346                 :            :     if (fd == UV_STDIN_FD || fd == UV_STDOUT_FD || fd == UV_STDERR_FD)
     347                 :            :         fd = GetStdHandle((DWORD)(uintptr_t) fd);
     348                 :            : 
     349                 :            :     /* _get_osfhandle will sometimes return -2 in case of an error. This seems */
     350                 :            :     /* to happen when fd <= 2 and the process' corresponding stdio handle is */
     351                 :            :     /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */
     352                 :            :     /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */
     353                 :            :     /* use the duplicate. Therefore we filter out known-invalid handles here. */
     354                 :            :     if (fd == INVALID_HANDLE_VALUE ||
     355                 :            :         fd == NULL ||
     356                 :            :         fd == (HANDLE) -2) {
     357                 :            :         *dupfd = INVALID_HANDLE_VALUE;
     358                 :            :         return 0; // allow the execution to continue even if stdio is not available as in batchmode or without a console
     359                 :            :     }
     360                 :            : 
     361                 :            :     current_process = GetCurrentProcess();
     362                 :            : 
     363                 :            :     if (!DuplicateHandle(current_process,
     364                 :            :                          fd,
     365                 :            :                          current_process,
     366                 :            :                          dupfd,
     367                 :            :                          0,
     368                 :            :                          TRUE,
     369                 :            :                          DUPLICATE_SAME_ACCESS)) {
     370                 :            :         *dupfd = INVALID_HANDLE_VALUE;
     371                 :            :         return GetLastError();
     372                 :            :     }
     373                 :            : 
     374                 :            :     return 0;
     375                 :            : }
     376                 :            : #else
     377                 :         45 : static int uv_dup(uv_os_fd_t fd, uv_os_fd_t* dupfd) {
     378         [ -  + ]:         45 :     if ((*dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 3)) == -1)
     379                 :          0 :         return -errno;
     380                 :         45 :     return 0;
     381                 :            : }
     382                 :            : #endif
     383                 :            : 
     384                 :         45 : static void *init_stdio_handle(const char *stdio, uv_os_fd_t fd, int readable)
     385                 :            : {
     386                 :            :     void *handle;
     387                 :            :     int err;
     388                 :            :     // Duplicate the file descriptor so we can later dup it over if we want to redirect
     389                 :            :     // STDIO without having to worry about closing the associated libuv object.
     390                 :            :     // This also helps limit the impact other libraries can cause on our file handle.
     391         [ -  + ]:         45 :     if ((err = uv_dup(fd, &fd)))
     392                 :          0 :         jl_errorf("error initializing %s in uv_dup: %s (%s %d)", stdio, uv_strerror(err), uv_err_name(err), err);
     393   [ +  -  -  +  :         45 :     switch(uv_guess_handle(fd)) {
                   +  - ]
     394                 :         37 :     case UV_TTY:
     395                 :         37 :         handle = malloc_s(sizeof(uv_tty_t));
     396         [ -  + ]:         37 :         if ((err = uv_tty_init(jl_io_loop, (uv_tty_t*)handle, fd, 0))) {
     397                 :          0 :             jl_errorf("error initializing %s in uv_tty_init: %s (%s %d)", stdio, uv_strerror(err), uv_err_name(err), err);
     398                 :            :         }
     399                 :         37 :         ((uv_tty_t*)handle)->data = NULL;
     400                 :         37 :         uv_tty_set_mode((uv_tty_t*)handle, UV_TTY_MODE_NORMAL); // initialized cooked stdio
     401                 :         37 :         break;
     402                 :          0 :     default:
     403                 :          0 :         assert(0 && "missing case for uv_guess_handle return handling");
     404                 :            :         JL_FALLTHROUGH;
     405                 :            :     case UV_UDP:
     406                 :            :         JL_FALLTHROUGH;
     407                 :            :     case UV_UNKNOWN_HANDLE:
     408                 :            :         // dup the descriptor with a new one pointing at the bit bucket ...
     409                 :            : #if defined(_OS_WINDOWS_)
     410                 :            :         CloseHandle(fd);
     411                 :            :         fd = CreateFile("NUL", readable ? FILE_GENERIC_READ : FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES,
     412                 :            :                 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
     413                 :            : #else
     414                 :            :         {
     415                 :            :             int nullfd;
     416                 :          0 :             nullfd = open("/dev/null", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH /* 0666 */);
     417         [ #  # ]:          0 :             assert(nullfd != -1);
     418                 :          0 :             dup2(nullfd, fd);
     419                 :          0 :             close(nullfd);
     420                 :            :         }
     421                 :            : #endif
     422                 :            :         // ...and continue on as in the UV_FILE case
     423                 :            :         JL_FALLTHROUGH;
     424                 :          2 :     case UV_FILE:
     425                 :          2 :         handle = malloc_s(sizeof(jl_uv_file_t));
     426                 :            :         {
     427                 :          2 :             jl_uv_file_t *file = (jl_uv_file_t*)handle;
     428                 :          2 :             file->loop = jl_io_loop;
     429                 :          2 :             file->type = UV_FILE;
     430                 :          2 :             file->file = fd;
     431                 :          2 :             file->data = NULL;
     432                 :            :         }
     433                 :          2 :         break;
     434                 :          6 :     case UV_NAMED_PIPE:
     435                 :          6 :         handle = malloc_s(sizeof(uv_pipe_t));
     436         [ -  + ]:          6 :         if ((err = uv_pipe_init(jl_io_loop, (uv_pipe_t*)handle, 0))) {
     437                 :          0 :             jl_errorf("error initializing %s in uv_pipe_init: %s (%s %d)", stdio, uv_strerror(err), uv_err_name(err), err);
     438                 :            :         }
     439         [ -  + ]:          6 :         if ((err = uv_pipe_open((uv_pipe_t*)handle, fd))) {
     440                 :          0 :             jl_errorf("error initializing %s in uv_pipe_open: %s (%s %d)", stdio, uv_strerror(err), uv_err_name(err), err);
     441                 :            :         }
     442                 :          6 :         ((uv_pipe_t*)handle)->data = NULL;
     443                 :          6 :         break;
     444                 :          0 :     case UV_TCP:
     445                 :          0 :         handle = malloc_s(sizeof(uv_tcp_t));
     446         [ #  # ]:          0 :         if ((err = uv_tcp_init(jl_io_loop, (uv_tcp_t*)handle))) {
     447                 :          0 :             jl_errorf("error initializing %s in uv_tcp_init: %s (%s %d)", stdio, uv_strerror(err), uv_err_name(err), err);
     448                 :            :         }
     449         [ #  # ]:          0 :         if ((err = uv_tcp_open((uv_tcp_t*)handle, (uv_os_sock_t)fd))) {
     450                 :          0 :             jl_errorf("error initializing %s in uv_tcp_open: %s (%s %d)", stdio, uv_strerror(err), uv_err_name(err), err);
     451                 :            :         }
     452                 :          0 :         ((uv_tcp_t*)handle)->data = NULL;
     453                 :          0 :         break;
     454                 :            :     }
     455                 :         45 :     return handle;
     456                 :            : }
     457                 :            : 
     458                 :         15 : static void init_stdio(void)
     459                 :            : {
     460                 :         15 :     JL_STDIN  = (uv_stream_t*)init_stdio_handle("stdin", UV_STDIN_FD, 1);
     461                 :         15 :     JL_STDOUT = (uv_stream_t*)init_stdio_handle("stdout", UV_STDOUT_FD, 0);
     462                 :         15 :     JL_STDERR = (uv_stream_t*)init_stdio_handle("stderr", UV_STDERR_FD, 0);
     463                 :         15 :     jl_flush_cstdio();
     464                 :         15 : }
     465                 :            : 
     466                 :        221 : int jl_isabspath(const char *in) JL_NOTSAFEPOINT
     467                 :            : {
     468                 :            : #ifdef _OS_WINDOWS_
     469                 :            :     char c0 = in[0];
     470                 :            :     if (c0 == '/' || c0 == '\\') {
     471                 :            :         return 1; // absolute path relative to %CD% (current drive), or UNC
     472                 :            :     }
     473                 :            :     else if (c0 && in[1] == ':') {
     474                 :            :         char c2 = in[2];
     475                 :            :         return c2 == '/' || c2 == '\\'; // absolute path with drive name
     476                 :            :     }
     477                 :            : #else
     478         [ +  + ]:        221 :     if (in[0] == '/') return 1; // absolute path
     479                 :            : #endif
     480                 :        167 :     return 0; // relative path
     481                 :            : }
     482                 :            : 
     483                 :         38 : static char *abspath(const char *in, int nprefix)
     484                 :            : { // compute an absolute realpath location, so that chdir doesn't change the file reference
     485                 :            :   // ignores (copies directly over) nprefix characters at the start of abspath
     486                 :            : #ifndef _OS_WINDOWS_
     487                 :         38 :     char *out = realpath(in + nprefix, NULL);
     488         [ +  + ]:         38 :     if (out) {
     489         [ -  + ]:         29 :         if (nprefix > 0) {
     490                 :          0 :             size_t sz = strlen(out) + 1;
     491                 :          0 :             char *cpy = (char*)malloc_s(sz + nprefix);
     492                 :          0 :             memcpy(cpy, in, nprefix);
     493                 :          0 :             memcpy(cpy + nprefix, out, sz);
     494                 :          0 :             free(out);
     495                 :          0 :             out = cpy;
     496                 :            :         }
     497                 :            :     }
     498                 :            :     else {
     499                 :          9 :         size_t sz = strlen(in + nprefix) + 1;
     500         [ +  - ]:          9 :         if (in[nprefix] == PATHSEPSTRING[0]) {
     501                 :          9 :             out = (char*)malloc_s(sz + nprefix);
     502                 :          9 :             memcpy(out, in, sz + nprefix);
     503                 :            :         }
     504                 :            :         else {
     505                 :          0 :             size_t path_size = JL_PATH_MAX;
     506                 :          0 :             char *path = (char*)malloc_s(JL_PATH_MAX);
     507         [ #  # ]:          0 :             if (uv_cwd(path, &path_size)) {
     508                 :          0 :                 jl_error("fatal error: unexpected error while retrieving current working directory");
     509                 :            :             }
     510                 :          0 :             out = (char*)malloc_s(path_size + 1 + sz + nprefix);
     511                 :          0 :             memcpy(out, in, nprefix);
     512                 :          0 :             memcpy(out + nprefix, path, path_size);
     513                 :          0 :             out[nprefix + path_size] = PATHSEPSTRING[0];
     514                 :          0 :             memcpy(out + nprefix + path_size + 1, in + nprefix, sz);
     515                 :          0 :             free(path);
     516                 :            :         }
     517                 :            :     }
     518                 :            : #else
     519                 :            :     DWORD n = GetFullPathName(in + nprefix, 0, NULL, NULL);
     520                 :            :     if (n <= 0) {
     521                 :            :         jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed");
     522                 :            :     }
     523                 :            :     char *out = (char*)malloc_s(n + nprefix);
     524                 :            :     DWORD m = GetFullPathName(in + nprefix, n, out + nprefix, NULL);
     525                 :            :     if (n != m + 1) {
     526                 :            :         jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed");
     527                 :            :     }
     528                 :            :     memcpy(out, in, nprefix);
     529                 :            : #endif
     530                 :         38 :     return out;
     531                 :            : }
     532                 :            : 
     533                 :            : // create an absolute-path copy of the input path format string
     534                 :            : // formed as `joinpath(replace(pwd(), "%" => "%%"), in)`
     535                 :            : // unless `in` starts with `%`
     536                 :          0 : static const char *absformat(const char *in)
     537                 :            : {
     538   [ #  #  #  # ]:          0 :     if (in[0] == '%' || jl_isabspath(in))
     539                 :          0 :         return in;
     540                 :            :     // get an escaped copy of cwd
     541                 :          0 :     size_t path_size = JL_PATH_MAX;
     542                 :            :     char path[JL_PATH_MAX];
     543         [ #  # ]:          0 :     if (uv_cwd(path, &path_size)) {
     544                 :          0 :         jl_error("fatal error: unexpected error while retrieving current working directory");
     545                 :            :     }
     546                 :          0 :     size_t sz = strlen(in) + 1;
     547                 :          0 :     size_t i, fmt_size = 0;
     548         [ #  # ]:          0 :     for (i = 0; i < path_size; i++)
     549         [ #  # ]:          0 :         fmt_size += (path[i] == '%' ? 2 : 1);
     550                 :          0 :     char *out = (char*)malloc_s(fmt_size + 1 + sz);
     551                 :          0 :     fmt_size = 0;
     552         [ #  # ]:          0 :     for (i = 0; i < path_size; i++) { // copy-replace pwd portion
     553                 :          0 :         char c = path[i];
     554                 :          0 :         out[fmt_size++] = c;
     555         [ #  # ]:          0 :         if (c == '%')
     556                 :          0 :             out[fmt_size++] = '%';
     557                 :            :     }
     558                 :          0 :     out[fmt_size++] = PATHSEPSTRING[0]; // path sep
     559                 :          0 :     memcpy(out + fmt_size, in, sz); // copy over format, including nul
     560                 :          0 :     return out;
     561                 :            : }
     562                 :            : 
     563                 :         15 : static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel)
     564                 :            : {   // this function resolves the paths in jl_options to absolute file locations as needed
     565                 :            :     // and it replaces the pointers to `julia_bindir`, `julia_bin`, `image_file`, and output file paths
     566                 :            :     // it may fail, print an error, and exit(1) if any of these paths are longer than JL_PATH_MAX
     567                 :            :     //
     568                 :            :     // note: if you care about lost memory, you should call the appropriate `free()` function
     569                 :            :     // on the original pointer for each `char*` you've inserted into `jl_options`, after
     570                 :            :     // calling `julia_init()`
     571                 :         15 :     char *free_path = (char*)malloc_s(JL_PATH_MAX);
     572                 :         15 :     size_t path_size = JL_PATH_MAX;
     573         [ -  + ]:         15 :     if (uv_exepath(free_path, &path_size)) {
     574                 :          0 :         jl_error("fatal error: unexpected error while retrieving exepath");
     575                 :            :     }
     576         [ -  + ]:         15 :     if (path_size >= JL_PATH_MAX) {
     577                 :          0 :         jl_error("fatal error: jl_options.julia_bin path too long");
     578                 :            :     }
     579                 :         15 :     jl_options.julia_bin = (char*)malloc_s(path_size + 1);
     580                 :         15 :     memcpy((char*)jl_options.julia_bin, free_path, path_size);
     581                 :         15 :     ((char*)jl_options.julia_bin)[path_size] = '\0';
     582         [ +  - ]:         15 :     if (!jl_options.julia_bindir) {
     583                 :         15 :         jl_options.julia_bindir = getenv("JULIA_BINDIR");
     584         [ +  + ]:         15 :         if (!jl_options.julia_bindir) {
     585                 :          1 :             jl_options.julia_bindir = dirname(free_path);
     586                 :            :         }
     587                 :            :     }
     588         [ +  - ]:         15 :     if (jl_options.julia_bindir)
     589                 :         15 :         jl_options.julia_bindir = abspath(jl_options.julia_bindir, 0);
     590                 :         15 :     free(free_path);
     591                 :         15 :     free_path = NULL;
     592         [ +  + ]:         15 :     if (jl_options.image_file) {
     593   [ +  +  +  - ]:         14 :         if (rel == JL_IMAGE_JULIA_HOME && !jl_isabspath(jl_options.image_file)) {
     594                 :            :             // build time path, relative to JULIA_BINDIR
     595                 :          2 :             free_path = (char*)malloc_s(JL_PATH_MAX);
     596                 :          2 :             int n = snprintf(free_path, JL_PATH_MAX, "%s" PATHSEPSTRING "%s",
     597                 :            :                              jl_options.julia_bindir, jl_options.image_file);
     598   [ +  -  -  + ]:          2 :             if (n >= JL_PATH_MAX || n < 0) {
     599                 :          0 :                 jl_error("fatal error: jl_options.image_file path too long");
     600                 :            :             }
     601                 :          2 :             jl_options.image_file = free_path;
     602                 :            :         }
     603         [ +  - ]:         14 :         if (jl_options.image_file)
     604                 :         14 :             jl_options.image_file = abspath(jl_options.image_file, 0);
     605         [ +  + ]:         14 :         if (free_path) {
     606                 :          2 :             free(free_path);
     607                 :          2 :             free_path = NULL;
     608                 :            :         }
     609                 :            :     }
     610         [ +  + ]:         15 :     if (jl_options.outputo)
     611                 :          2 :         jl_options.outputo = abspath(jl_options.outputo, 0);
     612         [ +  + ]:         15 :     if (jl_options.outputji)
     613                 :          7 :         jl_options.outputji = abspath(jl_options.outputji, 0);
     614         [ -  + ]:         15 :     if (jl_options.outputbc)
     615                 :          0 :         jl_options.outputbc = abspath(jl_options.outputbc, 0);
     616         [ -  + ]:         15 :     if (jl_options.outputasm)
     617                 :          0 :         jl_options.outputasm = abspath(jl_options.outputasm, 0);
     618         [ -  + ]:         15 :     if (jl_options.machine_file)
     619                 :          0 :         jl_options.machine_file = abspath(jl_options.machine_file, 0);
     620         [ -  + ]:         15 :     if (jl_options.output_code_coverage)
     621                 :          0 :         jl_options.output_code_coverage = absformat(jl_options.output_code_coverage);
     622         [ -  + ]:         15 :     if (jl_options.tracked_path)
     623                 :          0 :         jl_options.tracked_path = absformat(jl_options.tracked_path);
     624                 :            : 
     625                 :         15 :     const char **cmdp = jl_options.cmds;
     626         [ +  + ]:         15 :     if (cmdp) {
     627         [ +  + ]:          8 :         for (; *cmdp; cmdp++) {
     628                 :          4 :             const char *cmd = *cmdp;
     629         [ -  + ]:          4 :             if (cmd[0] == 'L') {
     630                 :          0 :                 *cmdp = abspath(cmd, 1);
     631                 :            :             }
     632                 :            :         }
     633                 :            :     }
     634                 :         15 : }
     635                 :            : 
     636                 :          0 : JL_DLLEXPORT int jl_is_file_tracked(jl_sym_t *path)
     637                 :            : {
     638                 :          0 :     const char* path_ = jl_symbol_name(path);
     639                 :          0 :     int tpath_len = strlen(jl_options.tracked_path);
     640   [ #  #  #  # ]:          0 :     return (strlen(path_) >= tpath_len) && (strncmp(path_, jl_options.tracked_path, tpath_len) == 0);
     641                 :            : }
     642                 :            : 
     643                 :       9134 : static void jl_set_io_wait(int v)
     644                 :            : {
     645                 :       9134 :     jl_task_t *ct = jl_current_task;
     646                 :       9134 :     ct->ptls->io_wait = v;
     647                 :       9134 : }
     648                 :            : 
     649                 :            : extern jl_mutex_t jl_modules_mutex;
     650                 :            : 
     651                 :         15 : static void restore_fp_env(void)
     652                 :            : {
     653   [ +  -  -  + ]:         15 :     if (jl_set_zero_subnormals(0) || jl_set_default_nans(0)) {
     654                 :          0 :         jl_error("Failed to configure floating point environment");
     655                 :            :     }
     656                 :         15 : }
     657                 :            : 
     658                 :            : static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_task_t *ct);
     659                 :            : 
     660                 :            : JL_DLLEXPORT int jl_default_debug_info_kind;
     661                 :            : 
     662                 :         15 : JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel)
     663                 :            : {
     664                 :         15 :     jl_default_debug_info_kind = 0;
     665                 :            : 
     666                 :         15 :     jl_init_timing();
     667                 :            :     // Make sure we finalize the tls callback before starting any threads.
     668                 :         15 :     (void)jl_get_pgcstack();
     669                 :         15 :     jl_safepoint_init();
     670                 :         15 :     libsupport_init();
     671                 :         15 :     htable_new(&jl_current_modules, 0);
     672                 :         15 :     JL_MUTEX_INIT(&jl_modules_mutex);
     673                 :         15 :     jl_precompile_toplevel_module = NULL;
     674                 :         15 :     ios_set_io_wait_func = jl_set_io_wait;
     675                 :         15 :     jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.),
     676                 :            :                                     // best to call this first, since it also initializes libuv
     677                 :         15 :     jl_init_uv();
     678                 :         15 :     init_stdio();
     679                 :         15 :     restore_fp_env();
     680                 :         15 :     restore_signals();
     681                 :         15 :     jl_init_intrinsic_properties();
     682                 :            : 
     683                 :         15 :     jl_page_size = jl_getpagesize();
     684                 :         15 :     jl_prep_sanitizers();
     685                 :            :     void *stack_lo, *stack_hi;
     686                 :         15 :     jl_init_stack_limits(1, &stack_lo, &stack_hi);
     687                 :            : 
     688                 :         15 :     jl_libjulia_internal_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT, 1);
     689                 :            : #ifdef _OS_WINDOWS_
     690                 :            :     jl_exe_handle = GetModuleHandleA(NULL);
     691                 :            :     jl_RTLD_DEFAULT_handle = jl_libjulia_internal_handle;
     692                 :            :     if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
     693                 :            :                             (LPCWSTR)&jl_any_type,
     694                 :            :                             (HMODULE*)&jl_libjulia_handle)) {
     695                 :            :         jl_error("could not load base module");
     696                 :            :     }
     697                 :            :     jl_ntdll_handle = jl_dlopen("ntdll.dll", 0); // bypass julia's pathchecking for system dlls
     698                 :            :     jl_kernel32_handle = jl_dlopen("kernel32.dll", 0);
     699                 :            :     jl_crtdll_handle = jl_dlopen(jl_crtdll_name, 0);
     700                 :            :     jl_winsock_handle = jl_dlopen("ws2_32.dll", 0);
     701                 :            :     uv_mutex_init(&jl_in_stackwalk);
     702                 :            :     SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_IGNORE_CVREC);
     703                 :            :     if (!SymInitialize(GetCurrentProcess(), "", 1)) {
     704                 :            :         jl_printf(JL_STDERR, "WARNING: failed to initialize stack walk info\n");
     705                 :            :     }
     706                 :            :     needsSymRefreshModuleList = 0;
     707                 :            :     HMODULE jl_dbghelp = (HMODULE) jl_dlopen("dbghelp.dll", 0);
     708                 :            :     if (jl_dbghelp)
     709                 :            :         jl_dlsym(jl_dbghelp, "SymRefreshModuleList", (void **)&hSymRefreshModuleList, 1);
     710                 :            : #else
     711                 :         15 :     jl_exe_handle = jl_dlopen(NULL, JL_RTLD_NOW);
     712                 :            : #ifdef RTLD_DEFAULT
     713                 :            :     jl_RTLD_DEFAULT_handle = RTLD_DEFAULT;
     714                 :            : #else
     715                 :         15 :     jl_RTLD_DEFAULT_handle = jl_exe_handle;
     716                 :            : #endif
     717                 :            : #endif
     718                 :            : 
     719   [ +  +  +  -  :         15 :     if ((jl_options.outputo || jl_options.outputbc || jl_options.outputasm) &&
                   -  + ]
     720   [ +  -  -  + ]:          2 :         (jl_options.code_coverage || jl_options.malloc_log)) {
     721                 :          0 :         jl_error("cannot generate code-coverage or track allocation information while generating a .o, .bc, or .s output file");
     722                 :            :     }
     723                 :            : 
     724                 :         15 :     jl_init_rand();
     725                 :         15 :     jl_init_profile_lock();
     726                 :         15 :     jl_init_runtime_ccall();
     727                 :         15 :     jl_init_tasks();
     728                 :         15 :     jl_init_threading();
     729                 :         15 :     jl_init_threadinginfra();
     730         [ +  - ]:         15 :     if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON)
     731                 :         15 :         jl_install_default_signal_handlers();
     732                 :            : 
     733                 :         15 :     jl_gc_init();
     734                 :         15 :     jl_ptls_t ptls = jl_init_threadtls(0);
     735                 :            : #pragma GCC diagnostic push
     736                 :            : #if defined(_COMPILER_GCC_) && __GNUC__ >= 12
     737                 :            : #pragma GCC diagnostic ignored "-Wdangling-pointer"
     738                 :            : #endif
     739                 :            :     // warning: this changes `jl_current_task`, so be careful not to call that from this function
     740                 :         15 :     jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi);
     741                 :            : #pragma GCC diagnostic pop
     742                 :            :     JL_GC_PROMISE_ROOTED(ct);
     743                 :         15 :     _finish_julia_init(rel, ptls, ct);
     744                 :         15 : }
     745                 :            : 
     746                 :         15 : static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_task_t *ct)
     747                 :            : {
     748                 :         15 :     jl_resolve_sysimg_location(rel);
     749                 :            :     // loads sysimg if available, and conditionally sets jl_options.cpu_target
     750         [ +  + ]:         15 :     if (jl_options.image_file)
     751                 :         14 :         jl_preload_sysimg_so(jl_options.image_file);
     752         [ -  + ]:         15 :     if (jl_options.cpu_target == NULL)
     753                 :          0 :         jl_options.cpu_target = "native";
     754                 :            : 
     755         [ +  + ]:         15 :     if (jl_options.image_file) {
     756                 :         14 :         jl_restore_system_image(jl_options.image_file);
     757                 :            :     } else {
     758                 :          1 :         jl_init_types();
     759                 :          1 :         jl_init_codegen();
     760                 :            :     }
     761                 :            : 
     762                 :         15 :     jl_init_common_symbols();
     763                 :         15 :     jl_init_flisp();
     764                 :         15 :     jl_init_serializer();
     765                 :            : 
     766         [ +  + ]:         15 :     if (!jl_options.image_file) {
     767                 :          1 :         jl_core_module = jl_new_module(jl_symbol("Core"));
     768                 :          1 :         jl_core_module->parent = jl_core_module;
     769                 :          1 :         jl_type_typename->mt->module = jl_core_module;
     770                 :          1 :         jl_top_module = jl_core_module;
     771                 :          1 :         jl_init_intrinsic_functions();
     772                 :          1 :         jl_init_primitives();
     773                 :          1 :         jl_init_main_module();
     774                 :          1 :         jl_load(jl_core_module, "boot.jl");
     775                 :          1 :         post_boot_hooks();
     776                 :            :     }
     777                 :            : 
     778         [ +  + ]:         15 :     if (jl_base_module == NULL) {
     779                 :            :         // nthreads > 1 requires code in Base
     780                 :          3 :         jl_n_threads = 1;
     781                 :            :     }
     782                 :         15 :     jl_start_threads();
     783                 :            : 
     784                 :         15 :     jl_gc_enable(1);
     785                 :            : 
     786   [ +  +  +  +  :         15 :     if (jl_options.image_file && (!jl_generating_output() || jl_options.incremental) && jl_module_init_order) {
             +  +  +  - ]
     787                 :         10 :         jl_array_t *init_order = jl_module_init_order;
     788                 :         10 :         JL_GC_PUSH1(&init_order);
     789                 :         10 :         jl_module_init_order = NULL;
     790                 :         10 :         int i, l = jl_array_len(init_order);
     791         [ +  + ]:        250 :         for (i = 0; i < l; i++) {
     792                 :        240 :             jl_value_t *mod = jl_array_ptr_ref(init_order, i);
     793                 :        240 :             jl_module_run_initializer((jl_module_t*)mod);
     794                 :            :         }
     795                 :         10 :         JL_GC_POP();
     796                 :            :     }
     797                 :            : 
     798         [ +  - ]:         15 :     if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON)
     799                 :         15 :         jl_install_sigint_handler();
     800                 :         15 : }
     801                 :            : 
     802                 :         29 : static jl_value_t *core(const char *name)
     803                 :            : {
     804                 :         29 :     return jl_get_global(jl_core_module, jl_symbol(name));
     805                 :            : }
     806                 :            : 
     807                 :            : // fetch references to things defined in boot.jl
     808                 :          1 : static void post_boot_hooks(void)
     809                 :            : {
     810                 :          1 :     jl_char_type    = (jl_datatype_t*)core("Char");
     811                 :          1 :     jl_int8_type    = (jl_datatype_t*)core("Int8");
     812                 :          1 :     jl_int16_type   = (jl_datatype_t*)core("Int16");
     813                 :          1 :     jl_float16_type = (jl_datatype_t*)core("Float16");
     814                 :          1 :     jl_float32_type = (jl_datatype_t*)core("Float32");
     815                 :          1 :     jl_float64_type = (jl_datatype_t*)core("Float64");
     816                 :          1 :     jl_floatingpoint_type = (jl_datatype_t*)core("AbstractFloat");
     817                 :          1 :     jl_number_type  = (jl_datatype_t*)core("Number");
     818                 :          1 :     jl_signed_type  = (jl_datatype_t*)core("Signed");
     819                 :          1 :     jl_datatype_t *jl_unsigned_type = (jl_datatype_t*)core("Unsigned");
     820                 :          1 :     jl_datatype_t *jl_integer_type = (jl_datatype_t*)core("Integer");
     821                 :            : 
     822                 :          1 :     jl_bool_type->super = jl_integer_type;
     823                 :          1 :     jl_uint8_type->super = jl_unsigned_type;
     824                 :          1 :     jl_uint16_type->super = jl_unsigned_type;
     825                 :          1 :     jl_uint32_type->super = jl_unsigned_type;
     826                 :          1 :     jl_uint64_type->super = jl_unsigned_type;
     827                 :          1 :     jl_int32_type->super = jl_signed_type;
     828                 :          1 :     jl_int64_type->super = jl_signed_type;
     829                 :            : 
     830                 :          1 :     jl_errorexception_type = (jl_datatype_t*)core("ErrorException");
     831                 :          1 :     jl_stackovf_exception  = jl_new_struct_uninit((jl_datatype_t*)core("StackOverflowError"));
     832                 :          1 :     jl_diverror_exception  = jl_new_struct_uninit((jl_datatype_t*)core("DivideError"));
     833                 :          1 :     jl_undefref_exception  = jl_new_struct_uninit((jl_datatype_t*)core("UndefRefError"));
     834                 :          1 :     jl_undefvarerror_type  = (jl_datatype_t*)core("UndefVarError");
     835                 :          1 :     jl_atomicerror_type    = (jl_datatype_t*)core("ConcurrencyViolationError");
     836                 :          1 :     jl_interrupt_exception = jl_new_struct_uninit((jl_datatype_t*)core("InterruptException"));
     837                 :          1 :     jl_boundserror_type    = (jl_datatype_t*)core("BoundsError");
     838                 :          1 :     jl_memory_exception    = jl_new_struct_uninit((jl_datatype_t*)core("OutOfMemoryError"));
     839                 :          1 :     jl_readonlymemory_exception = jl_new_struct_uninit((jl_datatype_t*)core("ReadOnlyMemoryError"));
     840                 :          1 :     jl_typeerror_type      = (jl_datatype_t*)core("TypeError");
     841                 :            : #ifdef SEGV_EXCEPTION
     842                 :            :     jl_segv_exception      = jl_new_struct_uninit((jl_datatype_t*)core("SegmentationFault"));
     843                 :            : #endif
     844                 :          1 :     jl_argumenterror_type  = (jl_datatype_t*)core("ArgumentError");
     845                 :          1 :     jl_methoderror_type    = (jl_datatype_t*)core("MethodError");
     846                 :          1 :     jl_loaderror_type      = (jl_datatype_t*)core("LoadError");
     847                 :          1 :     jl_initerror_type      = (jl_datatype_t*)core("InitError");
     848                 :          1 :     jl_pair_type           = core("Pair");
     849                 :            : 
     850                 :          1 :     jl_weakref_type = (jl_datatype_t*)core("WeakRef");
     851                 :          1 :     jl_vecelement_typename = ((jl_datatype_t*)jl_unwrap_unionall(core("VecElement")))->name;
     852                 :            : 
     853                 :          1 :     jl_init_box_caches();
     854                 :            : 
     855                 :            :     // set module field of primitive types
     856                 :            :     int i;
     857                 :          1 :     void **table = jl_core_module->bindings.table;
     858         [ +  + ]:       1025 :     for (i = 1; i < jl_core_module->bindings.size; i += 2) {
     859         [ +  + ]:       1024 :         if (table[i] != HT_NOTFOUND) {
     860                 :        325 :             jl_binding_t *b = (jl_binding_t*)table[i];
     861                 :        325 :             jl_value_t *v = jl_atomic_load_relaxed(&b->value);
     862         [ +  + ]:        325 :             if (v) {
     863         [ +  + ]:        314 :                 if (jl_is_unionall(v))
     864                 :         12 :                     v = jl_unwrap_unionall(v);
     865         [ +  + ]:        314 :                 if (jl_is_datatype(v)) {
     866                 :        208 :                     jl_datatype_t *tt = (jl_datatype_t*)v;
     867                 :        208 :                     tt->name->module = jl_core_module;
     868         [ +  + ]:        208 :                     if (tt->name->mt)
     869                 :        205 :                         tt->name->mt->module = jl_core_module;
     870                 :            :                 }
     871                 :            :             }
     872                 :            :         }
     873                 :            :     }
     874                 :          1 : }
     875                 :            : 
     876                 :            : #ifdef __cplusplus
     877                 :            : }
     878                 :            : #endif

Generated by: LCOV version 1.14