Revision e976e63cc791411b1e7d88b7ca705e87e10d8574 authored by Sacha Verweij on 23 March 2017, 21:22:17 UTC, committed by Stefan Karpinski on 23 March 2017, 21:22:17 UTC
* Resolve ambiguity between cat (git-cat-file and other) methods. * Reenable the Core+Base ambiguity detection test.
1 parent 52f04d2
init.c
// This file is a part of Julia. License is MIT: http://julialang.org/license
/*
init.c
system initialization and global state
*/
#include "platform.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#if !defined(_OS_WINDOWS_) || defined(_COMPILER_MINGW_)
#include <getopt.h>
#endif
#include "julia.h"
#include "julia_internal.h"
#define DEFINE_BUILTIN_GLOBALS
#include "builtin_proto.h"
#undef DEFINE_BUILTIN_GLOBALS
#include "threading.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
JL_DLLEXPORT char *dirname(char *);
#else
#include <libgen.h>
#endif
#ifdef _OS_WINDOWS_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h>
extern int needsSymRefreshModuleList;
extern BOOL (WINAPI *hSymRefreshModuleList)(HANDLE);
#else
#include <sys/resource.h>
#include <unistd.h>
#endif
#ifdef JL_ASAN_ENABLED
JL_DLLEXPORT const char* __asan_default_options() {
return "allow_user_segv_handler=1:detect_leaks=0";
// FIXME: enable LSAN after fixing leaks & defining __lsan_default_suppressions(),
// or defining __lsan_default_options = exitcode=0 once publicly available
// (here and in flisp/flmain.c)
}
#endif
int jl_boot_file_loaded = 0;
size_t jl_page_size;
void jl_init_stack_limits(int ismaster)
{
jl_ptls_t ptls = jl_get_ptls_states();
#ifdef _OS_WINDOWS_
(void)ismaster;
# ifdef _COMPILER_MICROSOFT_
# ifdef _P64
void **tib = (void**)__readgsqword(0x30);
# else
void **tib = (void**)__readfsdword(0x18);
# endif
# else
void **tib;
# ifdef _P64
__asm__("movq %%gs:0x30, %0" : "=r" (tib) : : );
# else
__asm__("movl %%fs:0x18, %0" : "=r" (tib) : : );
# endif
# endif
// https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
ptls->stack_hi = (char*)tib[1]; // Stack Base / Bottom of stack (high address)
ptls->stack_lo = (char*)tib[2]; // Stack Limit / Ceiling of stack (low address)
#else
# ifdef JULIA_ENABLE_THREADING
// Only use pthread_*_np functions to get stack address for non-master
// threads since it seems to return bogus values for master thread on Linux
// and possibly OSX.
if (!ismaster) {
# if defined(_OS_LINUX_)
pthread_attr_t attr;
pthread_getattr_np(pthread_self(), &attr);
void *stackaddr;
size_t stacksize;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
ptls->stack_lo = (char*)stackaddr;
ptls->stack_hi = (char*)stackaddr + stacksize;
return;
# elif defined(_OS_DARWIN_)
extern void *pthread_get_stackaddr_np(pthread_t thread);
extern size_t pthread_get_stacksize_np(pthread_t thread);
pthread_t thread = pthread_self();
void *stackaddr = pthread_get_stackaddr_np(thread);
size_t stacksize = pthread_get_stacksize_np(thread);
ptls->stack_lo = (char*)stackaddr;
ptls->stack_hi = (char*)stackaddr + stacksize;
return;
# elif defined(_OS_FREEBSD_)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_get_np(pthread_self(), &attr);
void *stackaddr;
size_t stacksize;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
ptls->stack_lo = (char*)stackaddr;
ptls->stack_hi = (char*)stackaddr + stacksize;
return;
# else
# warning "Getting stack size for thread is not supported."
# endif
}
# else
(void)ismaster;
# endif
struct rlimit rl;
getrlimit(RLIMIT_STACK, &rl);
size_t stack_size = rl.rlim_cur;
ptls->stack_hi = (char*)&stack_size;
ptls->stack_lo = ptls->stack_hi - stack_size;
#endif
}
static void jl_find_stack_bottom(void)
{
#if !defined(_OS_WINDOWS_)
#if defined(JL_ASAN_ENABLED) || defined(JL_MSAN_ENABLED)
struct rlimit rl;
// When using the sanitizers, increase stack size because they bloat
// stack usage
const rlim_t kStackSize = 64 * 1024 * 1024; // 64MiB stack
int result;
result = getrlimit(RLIMIT_STACK, &rl);
if (result == 0) {
if (rl.rlim_cur < kStackSize) {
rl.rlim_cur = kStackSize;
result = setrlimit(RLIMIT_STACK, &rl);
if (result != 0) {
fprintf(stderr, "setrlimit returned result = %d\n", result);
}
}
}
#endif
#endif
jl_init_stack_limits(1);
}
struct uv_shutdown_queue_item { uv_handle_t *h; struct uv_shutdown_queue_item *next; };
struct uv_shutdown_queue { struct uv_shutdown_queue_item *first; struct uv_shutdown_queue_item *last; };
static void jl_uv_exitcleanup_add(uv_handle_t *handle, struct uv_shutdown_queue *queue)
{
struct uv_shutdown_queue_item *item = (struct uv_shutdown_queue_item*)malloc(sizeof(struct uv_shutdown_queue_item));
item->h = handle;
item->next = NULL;
if (queue->last) queue->last->next = item;
if (!queue->first) queue->first = item;
queue->last = item;
}
static void jl_uv_exitcleanup_walk(uv_handle_t *handle, void *arg)
{
jl_uv_exitcleanup_add(handle, (struct uv_shutdown_queue*)arg);
}
void jl_write_coverage_data(void);
void jl_write_malloc_log(void);
static void julia_save(void);
static struct uv_shutdown_queue_item *next_shutdown_queue_item(struct uv_shutdown_queue_item *item)
{
struct uv_shutdown_queue_item *rv = item->next;
free(item);
return rv;
}
void jl_init_timing(void);
void jl_destroy_timing(void);
void jl_uv_call_close_callback(jl_value_t *val);
JL_DLLEXPORT void jl_atexit_hook(int exitcode)
{
jl_ptls_t ptls = jl_get_ptls_states();
if (exitcode == 0) julia_save();
jl_print_gc_stats(JL_STDERR);
if (jl_options.code_coverage)
jl_write_coverage_data();
if (jl_options.malloc_log)
jl_write_malloc_log();
if (jl_base_module) {
jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit"));
if (f != NULL) {
JL_TRY {
size_t last_age = jl_get_ptls_states()->world_age;
jl_get_ptls_states()->world_age = jl_get_world_counter();
jl_apply(&f, 1);
jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
jl_printf(JL_STDERR, "\natexit hook threw an error: ");
jl_static_show(JL_STDERR, ptls->exception_in_transit);
}
}
}
// replace standard output streams with something that we can still print to
// after the finalizers from base/stream.jl close the TTY
JL_STDOUT = (uv_stream_t*) STDOUT_FILENO;
JL_STDERR = (uv_stream_t*) STDERR_FILENO;
jl_gc_run_all_finalizers(ptls);
uv_loop_t *loop = jl_global_event_loop();
if (loop == NULL) {
return;
}
struct uv_shutdown_queue queue = {NULL, NULL};
uv_walk(loop, jl_uv_exitcleanup_walk, &queue);
struct uv_shutdown_queue_item *item = queue.first;
while (item) {
JL_TRY {
while (item) {
uv_handle_t *handle = item->h;
if (handle->type != UV_FILE && uv_is_closing(handle)) {
item = next_shutdown_queue_item(item);
continue;
}
switch(handle->type) {
case UV_PROCESS:
// cause Julia to forget about the Process object
if (handle->data)
jl_uv_call_close_callback((jl_value_t*)handle->data);
// and make libuv think it is already dead
((uv_process_t*)handle)->pid = 0;
// fall-through
case UV_TTY:
case UV_UDP:
case UV_TCP:
case UV_NAMED_PIPE:
case UV_POLL:
case UV_TIMER:
case UV_ASYNC:
case UV_FS_EVENT:
case UV_FS_POLL:
case UV_IDLE:
case UV_PREPARE:
case UV_CHECK:
case UV_SIGNAL:
case UV_FILE:
// These will be shutdown as appropriate by jl_close_uv
jl_close_uv(handle);
break;
case UV_HANDLE:
case UV_STREAM:
case UV_UNKNOWN_HANDLE:
case UV_HANDLE_TYPE_MAX:
case UV_RAW_FD:
case UV_RAW_HANDLE:
default:
assert(0);
}
item = next_shutdown_queue_item(item);
}
}
JL_CATCH {
//error handling -- continue cleanup, as much as possible
uv_unref(item->h);
jl_printf(JL_STDERR, "error during exit cleanup: close: ");
jl_static_show(JL_STDERR, ptls->exception_in_transit);
item = next_shutdown_queue_item(item);
}
}
// force libuv to spin until everything has finished closing
loop->stop_flag = 0;
while (uv_run(loop,UV_RUN_DEFAULT)) {}
jl_destroy_timing();
#ifdef ENABLE_TIMINGS
jl_print_timings();
#endif
}
void jl_get_builtin_hooks(void);
void jl_get_builtins(void);
JL_DLLEXPORT void *jl_dl_handle;
void *jl_RTLD_DEFAULT_handle;
#ifdef _OS_WINDOWS_
JL_DLLEXPORT void *jl_exe_handle;
void *jl_ntdll_handle;
void *jl_kernel32_handle;
void *jl_crtdll_handle;
void *jl_winsock_handle;
#endif
uv_loop_t *jl_io_loop;
static void *init_stdio_handle(uv_file fd,int readable)
{
void *handle;
uv_handle_type type = uv_guess_handle(fd);
jl_uv_file_t *file;
#ifndef _OS_WINDOWS_
// Duplicate the file descriptor so we can later dup it over if we want to redirect
// STDIO without having to worry about closing the associated libuv object.
// On windows however, libuv objects remember streams by their HANDLE, so this is
// unnecessary.
fd = dup(fd);
#endif
//jl_printf(JL_STDOUT, "%d: %d -- %d\n", fd, type, 0);
switch(type) {
case UV_TTY:
handle = malloc(sizeof(uv_tty_t));
if (uv_tty_init(jl_io_loop,(uv_tty_t*)handle,fd,readable)) {
jl_errorf("error initializing stdio in uv_tty_init (%d, %d)", fd, type);
}
((uv_tty_t*)handle)->data=0;
uv_tty_set_mode((uv_tty_t*)handle, UV_TTY_MODE_NORMAL); //cooked stdio
break;
case UV_UNKNOWN_HANDLE:
// dup the descriptor with a new one pointing at the bit bucket ...
#if defined(_OS_WINDOWS_)
_dup2(_open("NUL", O_RDWR | O_BINARY, _S_IREAD | _S_IWRITE), fd);
#else
dup2(open("/dev/null", O_RDWR, S_IRUSR | S_IWUSR /* 0600 */ | S_IRGRP | S_IROTH /* 0644 */), fd);
#endif
// ...and continue on as in the UV_FILE case
case UV_FILE:
file = (jl_uv_file_t*)malloc(sizeof(jl_uv_file_t));
file->loop = jl_io_loop;
file->type = UV_FILE;
file->file = fd;
file->data = 0;
handle = file;
break;
case UV_NAMED_PIPE:
handle = malloc(sizeof(uv_pipe_t));
if (uv_pipe_init(jl_io_loop, (uv_pipe_t*)handle, (readable?UV_PIPE_READABLE:UV_PIPE_WRITABLE))) {
jl_errorf("error initializing stdio in uv_pipe_init (%d, %d)", fd, type);
}
if (uv_pipe_open((uv_pipe_t*)handle,fd)) {
jl_errorf("error initializing stdio in uv_pipe_open (%d, %d)", fd, type);
}
((uv_pipe_t*)handle)->data=0;
break;
case UV_TCP:
handle = malloc(sizeof(uv_tcp_t));
if (uv_tcp_init(jl_io_loop, (uv_tcp_t*)handle)) {
jl_errorf("error initializing stdio in uv_tcp_init (%d, %d)", fd, type);
}
if (uv_tcp_open((uv_tcp_t*)handle,fd)) {
jl_errorf("error initializing stdio in uv_tcp_open (%d, %d)", fd, type);
}
((uv_tcp_t*)handle)->data=0;
break;
case UV_UDP:
default:
jl_errorf("this type of handle for stdio is not yet supported (%d, %d)", fd, type);
break;
}
return handle;
}
void init_stdio(void)
{ //order must be 2,1,0
JL_STDERR = (uv_stream_t*)init_stdio_handle(STDERR_FILENO,0);
JL_STDOUT = (uv_stream_t*)init_stdio_handle(STDOUT_FILENO,0);
JL_STDIN = (uv_stream_t*)init_stdio_handle(STDIN_FILENO,1);
jl_flush_cstdio();
}
#ifdef JL_USE_INTEL_JITEVENTS
char jl_using_intel_jitevents; // Non-zero if running under Intel VTune Amplifier
#endif
#ifdef JL_USE_OPROFILE_JITEVENTS
char jl_using_oprofile_jitevents = 0; // Non-zero if running under OProfile
#endif
int isabspath(const char *in)
{
#ifdef _OS_WINDOWS_
char c0 = in[0];
if (c0 == '/' || c0 == '\\') {
return 1; // absolute path relative to %CD% (current drive), or UNC
}
else if (c0 && in[1] == ':') {
char c2 = in[2];
return c2 == '/' || c2 == '\\'; // absolute path with drive name
}
#else
if (in[0] == '/') return 1; // absolute path
#endif
return 0; // relative path
}
static char *abspath(const char *in)
{ // compute an absolute path location, so that chdir doesn't change the file reference
#ifndef _OS_WINDOWS_
char *out = realpath(in, NULL);
if (!out) {
if (in[0] == PATHSEPSTRING[0]) {
out = strdup(in);
}
else {
size_t path_size = PATH_MAX;
size_t len = strlen(in);
char *path = (char*)malloc(PATH_MAX);
if (uv_cwd(path, &path_size)) {
jl_error("fatal error: unexpected error while retrieving current working directory");
}
if (path_size + len + 2 >= PATH_MAX) {
jl_error("fatal error: current working directory path too long");
}
path[path_size] = PATHSEPSTRING[0];
memcpy(path + path_size + 1, in, len+1);
out = strdup(path);
free(path);
}
}
#else
DWORD n = GetFullPathName(in, 0, NULL, NULL);
if (n <= 0) {
jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed");
}
char *out = (char*)malloc(n);
DWORD m = GetFullPathName(in, n, out, NULL);
if (n != m + 1) {
jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed");
}
#endif
return out;
}
static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel)
{ // this function resolves the paths in jl_options to absolute file locations as needed
// and it replaces the pointers to `julia_home`, `julia_bin`, `image_file`, and output file paths
// it may fail, print an error, and exit(1) if any of these paths are longer than PATH_MAX
//
// note: if you care about lost memory, you should call the appropriate `free()` function
// on the original pointer for each `char*` you've inserted into `jl_options`, after
// calling `julia_init()`
char *free_path = (char*)malloc(PATH_MAX);
size_t path_size = PATH_MAX;
if (uv_exepath(free_path, &path_size)) {
jl_error("fatal error: unexpected error while retrieving exepath");
}
if (path_size >= PATH_MAX) {
jl_error("fatal error: jl_options.julia_bin path too long");
}
jl_options.julia_bin = (char*)malloc(path_size+1);
memcpy((char*)jl_options.julia_bin, free_path, path_size);
((char*)jl_options.julia_bin)[path_size] = '\0';
if (!jl_options.julia_home) {
jl_options.julia_home = getenv("JULIA_HOME");
if (!jl_options.julia_home) {
jl_options.julia_home = dirname(free_path);
}
}
if (jl_options.julia_home)
jl_options.julia_home = abspath(jl_options.julia_home);
free(free_path);
free_path = NULL;
if (jl_options.image_file) {
if (rel == JL_IMAGE_JULIA_HOME && !isabspath(jl_options.image_file)) {
// build time path, relative to JULIA_HOME
free_path = (char*)malloc(PATH_MAX);
int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s",
jl_options.julia_home, jl_options.image_file);
if (n >= PATH_MAX || n < 0) {
jl_error("fatal error: jl_options.image_file path too long");
}
jl_options.image_file = free_path;
}
if (jl_options.image_file)
jl_options.image_file = abspath(jl_options.image_file);
if (free_path) {
free(free_path);
free_path = NULL;
}
}
if (jl_options.outputo)
jl_options.outputo = abspath(jl_options.outputo);
if (jl_options.outputji)
jl_options.outputji = abspath(jl_options.outputji);
if (jl_options.outputbc)
jl_options.outputbc = abspath(jl_options.outputbc);
if (jl_options.machinefile)
jl_options.machinefile = abspath(jl_options.machinefile);
if (jl_options.load)
jl_options.load = abspath(jl_options.load);
}
static void jl_set_io_wait(int v)
{
jl_ptls_t ptls = jl_get_ptls_states();
ptls->io_wait = v;
}
void _julia_init(JL_IMAGE_SEARCH rel)
{
jl_init_timing();
#ifdef JULIA_ENABLE_THREADING
// Make sure we finalize the tls callback before starting any threads.
jl_get_ptls_states_getter();
#endif
jl_ptls_t ptls = jl_get_ptls_states();
jl_safepoint_init();
libsupport_init();
ios_set_io_wait_func = jl_set_io_wait;
jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.),
// best to call this first, since it also initializes libuv
jl_init_signal_async();
restore_signals();
jl_resolve_sysimg_location(rel);
// loads sysimg if available, and conditionally sets jl_options.cpu_target
jl_preload_sysimg_so(jl_options.image_file);
if (jl_options.cpu_target == NULL)
jl_options.cpu_target = "native";
jl_page_size = jl_getpagesize();
uint64_t total_mem = uv_get_total_memory();
if (total_mem >= (size_t)-1) {
total_mem = (size_t)-1;
}
jl_arr_xtralloc_limit = total_mem / 100; // Extra allocation limited to 1% of total RAM
jl_find_stack_bottom();
jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT);
#ifdef RTLD_DEFAULT
jl_RTLD_DEFAULT_handle = RTLD_DEFAULT;
#else
jl_RTLD_DEFAULT_handle = jl_dl_handle;
#endif
#ifdef _OS_WINDOWS_
jl_ntdll_handle = jl_dlopen("ntdll.dll", 0); // bypass julia's pathchecking for system dlls
jl_kernel32_handle = jl_dlopen("kernel32.dll", 0);
#if defined(_MSC_VER) && _MSC_VER == 1800
jl_crtdll_handle = jl_dlopen("msvcr120.dll", 0);
#else
jl_crtdll_handle = jl_dlopen("msvcrt.dll", 0);
#endif
jl_winsock_handle = jl_dlopen("ws2_32.dll", 0);
jl_exe_handle = GetModuleHandleA(NULL);
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
if (!SymInitialize(GetCurrentProcess(), NULL, 1)) {
jl_printf(JL_STDERR, "WARNING: failed to initialize stack walk info\n");
}
needsSymRefreshModuleList = 0;
HMODULE jl_dbghelp = (HMODULE) jl_dlopen("dbghelp.dll", 0);
if (jl_dbghelp)
hSymRefreshModuleList = (BOOL (WINAPI*)(HANDLE)) jl_dlsym(jl_dbghelp, "SymRefreshModuleList");
#endif
#if defined(JL_USE_INTEL_JITEVENTS)
const char *jit_profiling = getenv("ENABLE_JITPROFILING");
if (jit_profiling && atoi(jit_profiling)) {
jl_using_intel_jitevents = 1;
}
#endif
#if defined(JL_USE_OPROFILE_JITEVENTS)
const char *jit_profiling = getenv("ENABLE_JITPROFILING");
if (jit_profiling && atoi(jit_profiling)) {
jl_using_oprofile_jitevents = 1;
}
#endif
#if defined(__linux__)
int ncores = jl_cpu_cores();
if (ncores > 1) {
cpu_set_t cpumask;
CPU_ZERO(&cpumask);
for(int i=0; i < ncores; i++) {
CPU_SET(i, &cpumask);
}
sched_setaffinity(0, sizeof(cpu_set_t), &cpumask);
}
#endif
jl_init_threading();
jl_gc_init();
jl_gc_enable(0);
jl_init_types();
jl_init_frontend();
jl_init_tasks();
jl_init_root_task(ptls->stack_lo, ptls->stack_hi-ptls->stack_lo);
#ifdef ENABLE_TIMINGS
jl_root_task->timing_stack = jl_root_timing;
#endif
init_stdio();
// libuv stdio cleanup depends on jl_init_tasks() because JL_TRY is used in jl_atexit_hook()
if ((jl_options.outputo || jl_options.outputbc) &&
(jl_options.code_coverage || jl_options.malloc_log)) {
jl_error("cannot generate code-coverage or track allocation information while generating a .o or .bc output file");
}
jl_init_codegen();
jl_start_threads();
jl_an_empty_vec_any = (jl_value_t*)jl_alloc_vec_any(0);
jl_init_serializer();
jl_init_intrinsic_properties();
if (!jl_options.image_file) {
jl_core_module = jl_new_module(jl_symbol("Core"));
jl_type_typename->mt->module = jl_core_module;
jl_top_module = jl_core_module;
ptls->current_module = jl_core_module;
jl_init_intrinsic_functions();
jl_init_primitives();
jl_get_builtins();
jl_new_main_module();
jl_internal_main_module = jl_main_module;
ptls->current_module = jl_core_module;
for (int t = 0;t < jl_n_threads;t++) {
jl_all_tls_states[t]->root_task->current_module = ptls->current_module;
}
jl_load("boot.jl");
jl_get_builtin_hooks();
jl_boot_file_loaded = 1;
jl_init_box_caches();
}
if (jl_options.image_file) {
JL_TRY {
jl_restore_system_image(jl_options.image_file);
}
JL_CATCH {
jl_printf(JL_STDERR, "error during init:\n");
jl_static_show(JL_STDERR, ptls->exception_in_transit);
jl_printf(JL_STDERR, "\n");
jl_exit(1);
}
}
// set module field of primitive types
int i;
void **table = jl_core_module->bindings.table;
for(i=1; i < jl_core_module->bindings.size; i+=2) {
if (table[i] != HT_NOTFOUND) {
jl_binding_t *b = (jl_binding_t*)table[i];
jl_value_t *v = b->value;
if (v) {
if (jl_is_unionall(v))
v = jl_unwrap_unionall(v);
if (jl_is_datatype(v)) {
jl_datatype_t *tt = (jl_datatype_t*)v;
tt->name->module = jl_core_module;
if (tt->name->mt)
tt->name->mt->module = jl_core_module;
}
}
}
}
// the Main module is the one which is always open, and set as the
// current module for bare (non-module-wrapped) toplevel expressions.
// it does "using Base" if Base is available.
if (jl_base_module != NULL) {
jl_add_standard_imports(jl_main_module);
}
ptls->current_module = jl_main_module;
for (int t = 0;t < jl_n_threads;t++) {
jl_all_tls_states[t]->root_task->current_module = ptls->current_module;
}
// This needs to be after jl_start_threads
if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON)
jl_install_default_signal_handlers();
jl_gc_enable(1);
if (jl_options.image_file && (!jl_generating_output() || jl_options.incremental) && jl_module_init_order) {
jl_array_t *init_order = jl_module_init_order;
JL_GC_PUSH1(&init_order);
jl_module_init_order = NULL;
int i, l = jl_array_len(init_order);
for (i = 0; i < l; i++) {
jl_value_t *mod = jl_array_ptr_ref(init_order, i);
jl_module_run_initializer((jl_module_t*)mod);
}
JL_GC_POP();
}
if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON)
jl_install_sigint_handler();
}
extern int asprintf(char **str, const char *fmt, ...);
JL_DLLEXPORT int jl_generating_output(void)
{
return jl_options.outputo || jl_options.outputbc || jl_options.outputji;
}
void jl_precompile(int all);
static void julia_save(void)
{
if (!jl_generating_output())
return;
if (!jl_options.incremental)
jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL);
if (!jl_module_init_order) {
jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n");
return;
}
jl_array_t *worklist = jl_module_init_order;
JL_GC_PUSH1(&worklist);
jl_module_init_order = jl_alloc_vec_any(0);
int i, l = jl_array_len(worklist);
for (i = 0; i < l; i++) {
jl_value_t *m = jl_arrayref(worklist, i);
if (jl_get_global((jl_module_t*)m, jl_symbol("__init__"))) {
jl_array_ptr_1d_push(jl_module_init_order, m);
}
}
if (jl_options.incremental) {
if (jl_options.outputji)
if (jl_save_incremental(jl_options.outputji, worklist))
jl_exit(1);
if (jl_options.outputbc)
jl_printf(JL_STDERR, "WARNING: incremental output to a .bc file is not implemented\n");
if (jl_options.outputo)
jl_printf(JL_STDERR, "WARNING: incremental output to a .o file is not implemented\n");
}
else {
ios_t *s = NULL;
if (jl_options.outputo || jl_options.outputbc)
s = jl_create_system_image();
if (jl_options.outputji) {
if (s == NULL) {
jl_save_system_image(jl_options.outputji);
}
else {
ios_t f;
if (ios_file(&f, jl_options.outputji, 1, 1, 1, 1) == NULL)
jl_errorf("cannot open system image file \"%s\" for writing", jl_options.outputji);
ios_write(&f, (const char*)s->buf, (size_t)s->size);
ios_close(&f);
}
}
if (jl_options.outputo || jl_options.outputbc)
jl_dump_native(jl_options.outputbc,
jl_options.outputo,
(const char*)s->buf, (size_t)s->size);
}
JL_GC_POP();
}
static jl_value_t *core(const char *name)
{
return jl_get_global(jl_core_module, jl_symbol(name));
}
static jl_value_t *basemod(const char *name)
{
return jl_get_global(jl_base_module, jl_symbol(name));
}
// fetch references to things defined in boot.jl
void jl_get_builtin_hooks(void)
{
int t;
for (t = 0; t < jl_n_threads; t++) {
jl_ptls_t ptls2 = jl_all_tls_states[t];
ptls2->root_task->tls = jl_nothing;
ptls2->root_task->consumers = jl_nothing;
ptls2->root_task->donenotify = jl_nothing;
ptls2->root_task->exception = jl_nothing;
ptls2->root_task->result = jl_nothing;
}
jl_char_type = (jl_datatype_t*)core("Char");
jl_int8_type = (jl_datatype_t*)core("Int8");
jl_int16_type = (jl_datatype_t*)core("Int16");
jl_uint16_type = (jl_datatype_t*)core("UInt16");
jl_uint32_type = (jl_datatype_t*)core("UInt32");
jl_uint64_type = (jl_datatype_t*)core("UInt64");
jl_float16_type = (jl_datatype_t*)core("Float16");
jl_float32_type = (jl_datatype_t*)core("Float32");
jl_float64_type = (jl_datatype_t*)core("Float64");
jl_floatingpoint_type = (jl_datatype_t*)core("AbstractFloat");
jl_number_type = (jl_datatype_t*)core("Number");
jl_signed_type = (jl_datatype_t*)core("Signed");
jl_errorexception_type = (jl_datatype_t*)core("ErrorException");
jl_stackovf_exception = jl_new_struct_uninit((jl_datatype_t*)core("StackOverflowError"));
jl_diverror_exception = jl_new_struct_uninit((jl_datatype_t*)core("DivideError"));
jl_domain_exception = jl_new_struct_uninit((jl_datatype_t*)core("DomainError"));
jl_overflow_exception = jl_new_struct_uninit((jl_datatype_t*)core("OverflowError"));
jl_inexact_exception = jl_new_struct_uninit((jl_datatype_t*)core("InexactError"));
jl_undefref_exception = jl_new_struct_uninit((jl_datatype_t*)core("UndefRefError"));
jl_undefvarerror_type = (jl_datatype_t*)core("UndefVarError");
jl_interrupt_exception = jl_new_struct_uninit((jl_datatype_t*)core("InterruptException"));
jl_boundserror_type = (jl_datatype_t*)core("BoundsError");
jl_memory_exception = jl_new_struct_uninit((jl_datatype_t*)core("OutOfMemoryError"));
jl_readonlymemory_exception = jl_new_struct_uninit((jl_datatype_t*)core("ReadOnlyMemoryError"));
jl_typeerror_type = (jl_datatype_t*)core("TypeError");
#ifdef SEGV_EXCEPTION
jl_segv_exception = jl_new_struct_uninit((jl_datatype_t*)core("SegmentationFault"));
#endif
jl_weakref_type = (jl_datatype_t*)core("WeakRef");
jl_vecelement_typename = ((jl_datatype_t*)jl_unwrap_unionall(core("VecElement")))->name;
}
JL_DLLEXPORT void jl_get_system_hooks(void)
{
if (jl_argumenterror_type) return; // only do this once
jl_argumenterror_type = (jl_datatype_t*)basemod("ArgumentError");
jl_methoderror_type = (jl_datatype_t*)basemod("MethodError");
jl_loaderror_type = (jl_datatype_t*)basemod("LoadError");
jl_initerror_type = (jl_datatype_t*)basemod("InitError");
jl_complex_type = (jl_unionall_t*)basemod("Complex");
}
void jl_get_builtins(void)
{
jl_builtin_throw = core("throw"); jl_builtin_is = core("===");
jl_builtin_typeof = core("typeof"); jl_builtin_sizeof = core("sizeof");
jl_builtin_issubtype = core("issubtype"); jl_builtin_isa = core("isa");
jl_builtin_typeassert = core("typeassert"); jl_builtin__apply = core("_apply");
jl_builtin_isdefined = core("isdefined"); jl_builtin_nfields = core("nfields");
jl_builtin_tuple = core("tuple"); jl_builtin_svec = core("svec");
jl_builtin_getfield = core("getfield"); jl_builtin_setfield = core("setfield!");
jl_builtin_fieldtype = core("fieldtype"); jl_builtin_arrayref = core("arrayref");
jl_builtin_arrayset = core("arrayset"); jl_builtin_arraysize = core("arraysize");
jl_builtin_apply_type = core("apply_type"); jl_builtin_applicable = core("applicable");
jl_builtin_invoke = core("invoke"); jl_builtin__expr = core("_expr");
}
#ifdef __cplusplus
}
#endif
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...