static void segv_handler(int sig, siginfo_t *info, void *context) { sigset_t sset; assert(sig == SIGSEGV); if (in_jl_ || is_addr_on_stack(info->si_addr)) { // stack overflow, or restarting jl_ sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_stackovf_exception); } else if (info->si_code == SEGV_ACCERR) { // writing to read-only memory (e.g., mmap) sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_readonlymemory_exception); } else { #ifdef SEGV_EXCEPTION sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_segv_exception); #else sigdie_handler(sig, info, context); #endif } }
static void segv_handler(int sig, siginfo_t *info, void *context) { assert(sig == SIGSEGV || sig == SIGBUS); #ifdef JULIA_ENABLE_THREADING if (info->si_addr == jl_gc_signal_page) { jl_unblock_signal(sig); jl_gc_signal_wait(); return; } #endif if (jl_safe_restore || is_addr_on_stack(jl_get_ptls_states(), info->si_addr)) { // stack overflow, or restarting jl_ jl_unblock_signal(sig); jl_throw(jl_stackovf_exception); } else if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { // writing to read-only memory (e.g., mmap) jl_unblock_signal(sig); jl_throw(jl_readonlymemory_exception); } else { #ifdef SEGV_EXCEPTION jl_unblock_signal(sig); jl_throw(jl_segv_exception); #else sigdie_handler(sig, info, context); #endif } }
void jl_compute_field_offsets(jl_datatype_t *st) { size_t sz = 0, alignm = 1; int ptrfree = 1; assert(0 <= st->fielddesc_type && st->fielddesc_type <= 2); uint64_t max_offset = (((uint64_t)1) << (1 << (3 + st->fielddesc_type))) - 1; uint64_t max_size = max_offset >> 1; for(size_t i=0; i < jl_datatype_nfields(st); i++) { jl_value_t *ty = jl_field_type(st, i); size_t fsz, al; if (jl_isbits(ty) && jl_is_leaf_type(ty)) { fsz = jl_datatype_size(ty); // Should never happen if (__unlikely(fsz > max_size)) jl_throw(jl_overflow_exception); al = ((jl_datatype_t*)ty)->alignment; jl_field_setisptr(st, i, 0); if (((jl_datatype_t*)ty)->haspadding) st->haspadding = 1; } else { fsz = sizeof(void*); if (fsz > MAX_ALIGN) fsz = MAX_ALIGN; al = fsz; jl_field_setisptr(st, i, 1); ptrfree = 0; } if (al != 0) { size_t alsz = LLT_ALIGN(sz, al); if (sz & (al - 1)) st->haspadding = 1; sz = alsz; if (al > alignm) alignm = al; } jl_field_setoffset(st, i, sz); jl_field_setsize(st, i, fsz); if (__unlikely(max_offset - sz < fsz)) jl_throw(jl_overflow_exception); sz += fsz; } st->alignment = alignm; st->size = LLT_ALIGN(sz, alignm); if (st->size > sz) st->haspadding = 1; st->pointerfree = ptrfree && !st->abstract; }
jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i) { jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v); if (i >= jl_tuple_len(st->names)) jl_throw(jl_bounds_exception); size_t offs = jl_field_offset(st,i) + sizeof(void*); if (st->fields[i].isptr) { jl_value_t *fval = *(jl_value_t**)((char*)v + offs); if (fval == NULL) jl_throw(jl_undefref_exception); return fval; } return jl_new_bits(jl_tupleref(st->types,i), (char*)v + offs); }
JL_DLLEXPORT void JL_NORETURN jl_eof_error(void) { jl_datatype_t *eof_error = (jl_datatype_t*)jl_get_global(jl_base_module, jl_symbol("EOFError")); assert(eof_error != NULL); jl_throw(jl_new_struct(eof_error)); }
void usr2_handler(int sig, siginfo_t *info, void *ctx) { sigset_t sset; ucontext_t *context = (ucontext_t*)ctx; if ((remote_sig > 0 && waiting_for < 0) || waiting_for == ti_tid) { int realsig = remote_sig; #ifdef __APPLE__ signal_context = (unw_context_t*)&context->uc_mcontext->__ss; #else signal_context = (unw_context_t*)context; #endif pthread_mutex_lock(&in_signal_lock); wait_barrier(); pthread_cond_wait(&exit_signal_cond, &in_signal_lock); wait_barrier(); pthread_mutex_unlock(&in_signal_lock); if (ti_tid == 0 && realsig == SIGINT) { if (jl_defer_signal) { jl_signal_pending = realsig; } else { jl_signal_pending = 0; sigemptyset(&sset); sigaddset(&sset, sig); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_interrupt_exception); } } } }
JL_DLLEXPORT void JL_NORETURN jl_bounds_error_int(jl_value_t *v, size_t i) { jl_value_t *t = NULL; JL_GC_PUSH2(&v, &t); // root arguments so the caller doesn't need to t = jl_box_long(i); jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t)); }
static void add_page(pool_t *p) { #ifdef USE_MMAP gcpage_t *pg = (gcpage_t*)mmap(NULL, sizeof(gcpage_t), PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); #else gcpage_t *pg = (gcpage_t*)malloc_a16(sizeof(gcpage_t)); #endif if (pg == NULL) jl_throw(jl_memory_exception); gcval_t *v = (gcval_t*)&pg->data[0]; char *lim = (char*)v + GC_PAGE_SZ - p->osize; gcval_t *fl; gcval_t **pfl = &fl; while ((char*)v <= lim) { *pfl = v; pfl = &v->next; v = (gcval_t*)((char*)v + p->osize); } // these statements are ordered so that interrupting after any of them // leaves the system in a valid state *pfl = p->freelist; pg->next = p->pages; p->pages = pg; p->freelist = fl; }
void *jl_gc_managed_realloc(void *d, size_t sz, size_t oldsz, int isaligned) { if (allocd_bytes > collect_interval) jl_gc_collect(); sz = (sz+15) & -16; void *b; #ifdef _P64 b = realloc(d, sz); #elif defined(_OS_WINDOWS_) if (isaligned) b = _aligned_realloc(d, sz, 16); else b = realloc(d, sz); #elif defined(__APPLE__) b = realloc(d, sz); #else // TODO better aligned realloc here b = malloc_a16(sz); if (b != NULL) { memcpy(b, d, oldsz); if (isaligned) free_a16(d); else free(d); } #endif if (b == NULL) jl_throw(jl_memory_exception); allocd_bytes += sz; return b; }
void segv_handler(int sig, siginfo_t *info, void *context) { sigset_t sset; if ( #ifdef COPY_STACKS (char*)info->si_addr > (char*)jl_stack_lo-3000000 && (char*)info->si_addr < (char*)jl_stack_hi #else (char*)info->si_addr > (char*)jl_current_task->stack-8192 && (char*)info->si_addr < (char*)jl_current_task->stack+jl_current_task->ssize #endif ) { sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_stackovf_exception); } else { uv_tty_reset_mode(); sigfillset(&sset); sigprocmask(SIG_UNBLOCK, &sset, NULL); signal(sig, SIG_DFL); if (sig != SIGSEGV && sig != SIGBUS && sig != SIGILL) raise(sig); } }
void fpe_handler(int arg) #endif { (void)arg; #ifndef __WIN32__ sigset_t sset; sigemptyset(&sset); sigaddset(&sset, SIGFPE); sigprocmask(SIG_UNBLOCK, &sset, NULL); #else fpreset(); signal(SIGFPE, (void (__cdecl *)(int))fpe_handler); switch(num) { case _FPE_INVALID: case _FPE_OVERFLOW: case _FPE_UNDERFLOW: default: jl_errorf("Unexpected FPE Error 0x%X", num); break; case _FPE_ZERODIVIDE: #endif jl_throw(jl_diverror_exception); #ifdef __WIN32__ break; } #endif }
void __cdecl crt_sig_handler(int sig, int num) { jl_ptls_t ptls = jl_get_ptls_states(); CONTEXT Context; switch (sig) { case SIGFPE: fpreset(); signal(SIGFPE, (void (__cdecl *)(int))crt_sig_handler); switch(num) { case _FPE_INVALID: case _FPE_OVERFLOW: case _FPE_UNDERFLOW: default: jl_errorf("Unexpected FPE Error 0x%X", num); break; case _FPE_ZERODIVIDE: jl_throw(jl_diverror_exception); break; } break; case SIGINT: signal(SIGINT, (void (__cdecl *)(int))crt_sig_handler); if (exit_on_sigint) jl_exit(130); // 128 + SIGINT jl_try_throw_sigint(); break; default: // SIGSEGV, (SSIGTERM, IGILL) memset(&Context, 0, sizeof(Context)); RtlCaptureContext(&Context); jl_critical_error(sig, &Context, ptls->bt_data, &ptls->bt_size); raise(sig); } }
JL_DLLEXPORT void JL_NORETURN jl_errorf(const char *fmt, ...) { va_list args; va_start(args, fmt); jl_value_t *e = jl_vexceptionf(jl_errorexception_type, fmt, args); va_end(args); jl_throw(e); }
JL_DLLEXPORT void JL_NORETURN jl_bounds_error_v(jl_value_t *v, jl_value_t **idxs, size_t nidxs) { jl_value_t *t = NULL; // items in idxs are assumed to already be rooted JL_GC_PUSH2(&v, &t); // root v so the caller doesn't need to t = jl_f_tuple(NULL, idxs, nidxs); jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t)); }
void jl_arrayunset(jl_array_t *a, size_t i) { if (i >= jl_array_len(a)) jl_throw(jl_bounds_exception); char *ptail = (char*)a->data + i*a->elsize; if (a->ptrarray) memset(ptail, 0, a->elsize); }
JL_DLLEXPORT jl_value_t *jl_check_top_bit(jl_value_t *a) { jl_value_t *ty = jl_typeof(a); if (!jl_is_bitstype(ty)) jl_error("check_top_bit: value is not a bitstype"); if (signbitbyte(jl_data_ptr(a), jl_datatype_size(ty))) jl_throw(jl_inexact_exception); return a; }
// with function name / location description, plus extra context JL_DLLEXPORT void JL_NORETURN jl_type_error_rt(const char *fname, const char *context, jl_value_t *expected, jl_value_t *got) { jl_value_t *ctxt=NULL; JL_GC_PUSH2(&ctxt, &got); ctxt = jl_pchar_to_string((char*)context, strlen(context)); jl_value_t *ex = jl_new_struct(jl_typeerror_type, jl_symbol(fname), ctxt, expected, got); jl_throw(ex); }
JL_DLLEXPORT void JL_NORETURN jl_error(const char *str) { if (jl_errorexception_type == NULL) { jl_printf(JL_STDERR, "ERROR: %s\n", str); jl_exit(1); } jl_value_t *msg = jl_pchar_to_string((char*)str, strlen(str)); JL_GC_PUSH1(&msg); jl_throw(jl_new_struct(jl_errorexception_type, msg)); }
void sigint_handler(int sig, siginfo_t *info, void *context) { if (jl_defer_signal) { jl_signal_pending = sig; } else { jl_signal_pending = 0; jl_throw(jl_interrupt_exception); } }
void jl_type_error_rt(const char *fname, const char *context, jl_value_t *ty, jl_value_t *got) { jl_value_t *ctxt=NULL; JL_GC_PUSH2(&ctxt, &got); ctxt = jl_pchar_to_string((char*)context, strlen(context)); jl_value_t *ex = jl_new_struct(jl_typeerror_type, jl_symbol(fname), ctxt, ty, got); jl_throw(ex); }
void jl_error(const char *str) { if (jl_errorexception_type == NULL) { JL_PRINTF(JL_STDERR, "%s", str); jl_exit(1); } jl_value_t *msg = jl_pchar_to_string((char*)str, strlen(str)); JL_GC_PUSH1(&msg); jl_throw(jl_new_struct(jl_errorexception_type, msg)); }
DLLEXPORT void *jl_gc_counted_realloc(void *p, size_t sz) { if (allocd_bytes > collect_interval) jl_gc_collect(); allocd_bytes += ((sz+1)/2); // NOTE: wild guess at growth amount void *b = realloc(p, sz); if (b == NULL) jl_throw(jl_memory_exception); return b; }
DLLEXPORT void *jl_gc_counted_malloc(size_t sz) { if (allocd_bytes > collect_interval) jl_gc_collect(); allocd_bytes += sz; void *b = malloc(sz); if (b == NULL) jl_throw(jl_memory_exception); return b; }
JL_DLLEXPORT void JL_NORETURN jl_bounds_error_unboxed_int(void *data, jl_value_t *vt, size_t i) { jl_value_t *t = NULL, *v = NULL; // data is expected to be gc-safe (either gc-rooted, or alloca) // vt is expected to be gc-rooted (in a linfo-root probably) JL_GC_PUSH2(&v, &t); v = jl_new_bits(vt, data); t = jl_box_long(i); jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t)); }
void jl_compute_field_offsets(jl_datatype_t *st) { size_t sz = 0, alignm = 1; int ptrfree = 1; for(size_t i=0; i < jl_datatype_nfields(st); i++) { jl_value_t *ty = jl_field_type(st, i); size_t fsz, al; if (jl_isbits(ty) && jl_is_leaf_type(ty)) { fsz = jl_datatype_size(ty); if (__unlikely(fsz > JL_FIELD_MAX_SIZE)) jl_throw(jl_overflow_exception); al = ((jl_datatype_t*)ty)->alignment; st->fields[i].isptr = 0; if (((jl_datatype_t*)ty)->haspadding) st->haspadding = 1; } else { fsz = sizeof(void*); if (fsz > MAX_ALIGN) fsz = MAX_ALIGN; al = fsz; st->fields[i].isptr = 1; ptrfree = 0; } if (al != 0) { size_t alsz = LLT_ALIGN(sz, al); if (alsz > sz) st->haspadding = 1; sz = alsz; if (al > alignm) alignm = al; } if (__unlikely(sz > JL_FIELD_MAX_OFFSET)) jl_throw(jl_overflow_exception); st->fields[i].offset = sz; st->fields[i].size = fsz; sz += fsz; } st->alignment = alignm; st->size = LLT_ALIGN(sz, alignm); st->pointerfree = ptrfree && !st->abstract; }
void jl_undefined_var_error(jl_sym_t *var) { if (var->name[0] == '#') { // convention for renamed variables: #...#original_name char *nxt = strchr(var->name+1, '#'); if (nxt) var = jl_symbol(nxt+1); } jl_throw(jl_new_struct(jl_undefvarerror_type, var)); }
static void *alloc_big(size_t sz) { if (allocd_bytes > collect_interval) { jl_gc_collect(); } size_t offs = BVOFFS*sizeof(void*); if (sz+offs+15 < offs+15) // overflow in adding offs, size was "negative" jl_throw(jl_memory_exception); size_t allocsz = (sz+offs+15) & -16; bigval_t *v = (bigval_t*)malloc_a16(allocsz); allocd_bytes += allocsz; if (v == NULL) jl_throw(jl_memory_exception); v->sz = sz; v->flags = 0; v->next = big_objects; big_objects = v; return &v->_data[0]; }
void fpe_handler(int arg) { (void)arg; sigset_t sset; sigemptyset(&sset); sigaddset(&sset, SIGFPE); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_diverror_exception); }
void segv_handler(int sig, siginfo_t *info, void *context) { sigset_t sset; if (sig == SIGSEGV && (in_jl_ || is_addr_on_stack(info->si_addr))) { // stack overflow sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_stackovf_exception); } else if (info->si_code == SEGV_ACCERR) { // writing to read-only memory (e.g., mmap) sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_memory_exception); } else { sigdie_handler(sig, info, context); } }
void *jl_gc_managed_malloc(size_t sz) { if (allocd_bytes > collect_interval) jl_gc_collect(); sz = (sz+15) & -16; void *b = malloc_a16(sz); if (b == NULL) jl_throw(jl_memory_exception); allocd_bytes += sz; return b; }