diff --git a/src/defs.h b/src/defs.h index 52db8d8..859ddce 100644 --- a/src/defs.h +++ b/src/defs.h @@ -25,7 +25,7 @@ #include #include -#define U6A_TOKEN_FN_CHAR ( 1 << 6 ) +#define U6A_TOKEN_FN_CHAR ( 1 << 4 ) #define U6A_TOKEN_FN_APP ( 1 << 5 ) enum u6a_token_fn { diff --git a/src/logging.c b/src/logging.c index 3f7b4d1..c249987 100644 --- a/src/logging.c +++ b/src/logging.c @@ -98,8 +98,8 @@ u6a_err_cannot_open_file(const char* stage, const char* filename) { } U6A_COLD void -u6a_err_stack_underflow(const char* stage, const char* description) { - fprintf(stderr, "%s: [%s] stack underflow error, %s.\n", prog_name, stage, description); +u6a_err_stack_underflow(const char* stage) { + fprintf(stderr, "%s: [%s] stack underflow.\n", prog_name, stage); } U6A_COLD void @@ -118,12 +118,17 @@ u6a_err_invalid_bc_file(const char* stage, const char* filename) { fprintf(stderr, "%s: [%s] %s is not a valid Unlambda bytecode file.\n", prog_name, stage, filename); } -void +U6A_COLD void u6a_err_bad_bc_ver(const char* stage, const char* filename, int ver_major, int ver_minor) { fprintf(stderr, "%s: [%s] bytecode file %s version %d.%d is not compatible.\n", prog_name, stage, filename, ver_major, ver_minor); } +U6A_COLD void +u6a_err_vm_pool_oom(const char* stage) { + fprintf(stderr, "%s: [%s] VM object pool memory exhausted.\n", stage, prog_name); +} + U6A_COLD void u6a_info_verbose_(const char* format, ...) { if (verbose) { diff --git a/src/logging.h b/src/logging.h index 1c161d4..35e26c6 100644 --- a/src/logging.h +++ b/src/logging.h @@ -63,7 +63,7 @@ void u6a_err_cannot_open_file(const char* stage, const char* filename); void -u6a_err_stack_underflow(const char* stage, const char* description); +u6a_err_stack_underflow(const char* stage); void u6a_err_invalid_uint(const char* stage, const char* str); @@ -77,6 +77,9 @@ u6a_err_invalid_bc_file(const char* stage, const char* filename); void u6a_err_bad_bc_ver(const char* stage, const char* filename, int ver_major, int ver_minor); +void +u6a_err_vm_pool_oom(const char* stage); + void u6a_info_verbose_(const char* format, ...); diff --git a/src/runtime.c b/src/runtime.c index 0d1f45d..c585de1 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -173,10 +173,10 @@ u6a_runtime_init(struct u6a_runtime_options* options) { if (UNLIKELY(rodata_len != fread(rodata, sizeof(char), rodata_len, options->istream))) { goto runtime_init_failed; } - if (UNLIKELY(!u6a_vm_stack_init(options->stack_segment_size))) { + if (UNLIKELY(!u6a_vm_stack_init(options->stack_segment_size, err_runtime))) { goto runtime_init_failed; } - if (UNLIKELY(!u6a_vm_pool_init(options->pool_size, text_len))) { + if (UNLIKELY(!u6a_vm_pool_init(options->pool_size, text_len, err_runtime))) { goto runtime_init_failed; } for (struct u6a_vm_ins* ins = text + text_subst_len; ins < text + text_len; ++ins) { diff --git a/src/vm_pool.c b/src/vm_pool.c index 42e3c2e..5c6bcce 100644 --- a/src/vm_pool.c +++ b/src/vm_pool.c @@ -19,6 +19,7 @@ #include "vm_pool.h" #include "vm_stack.h" +#include "logging.h" #include #include @@ -48,11 +49,14 @@ static struct vm_pool_elem** fstack; static uint32_t fstack_len; static uint32_t fstack_top; +const char* err_stage; + static inline struct vm_pool_elem* vm_pool_elem_alloc() { struct vm_pool_elem* new_elem; if (holes->pos == UINT32_MAX) { if (UNLIKELY(++active_pool->pos >= pool_len)) { + u6a_err_vm_pool_oom(err_stage); return NULL; } new_elem = active_pool->elems + active_pool->pos; @@ -89,21 +93,24 @@ free_stack_pop() { } bool -u6a_vm_pool_init(uint32_t pool_len_, uint32_t ins_len) { +u6a_vm_pool_init(uint32_t pool_len_, uint32_t ins_len, const char* err_stage_) { const uint32_t pool_size = sizeof(struct vm_pool) + pool_len_ * sizeof(struct vm_pool_elem); active_pool = malloc(pool_size); if (UNLIKELY(active_pool == NULL)) { + u6a_err_bad_alloc(err_stage_, pool_size); return false; } const uint32_t holes_size = sizeof(struct vm_pool_elem_ptrs) + pool_len_ * sizeof(struct vm_pool_elem*); holes = malloc(holes_size); if (UNLIKELY(holes == NULL)) { + u6a_err_bad_alloc(err_stage_, holes_size); free(holes); return false; } const uint32_t free_stack_size = ins_len * sizeof(struct vm_pool_elem*); fstack = malloc(free_stack_size); if (UNLIKELY(fstack == NULL)) { + u6a_err_bad_alloc(err_stage_, free_stack_size); free(active_pool); free(holes); return false; @@ -112,6 +119,7 @@ u6a_vm_pool_init(uint32_t pool_len_, uint32_t ins_len) { holes->pos = UINT32_MAX; pool_len = pool_len_; fstack_len = ins_len; + err_stage = err_stage_; return true; } diff --git a/src/vm_pool.h b/src/vm_pool.h index 701198b..a7d66db 100644 --- a/src/vm_pool.h +++ b/src/vm_pool.h @@ -27,7 +27,7 @@ #include bool -u6a_vm_pool_init(uint32_t pool_len, uint32_t ins_len); +u6a_vm_pool_init(uint32_t pool_len, uint32_t ins_len, const char* err_stage); uint32_t u6a_vm_pool_alloc1(struct u6a_vm_var_fn v1); diff --git a/src/vm_stack.c b/src/vm_stack.c index 3ff9e2b..78ecff1 100644 --- a/src/vm_stack.c +++ b/src/vm_stack.c @@ -19,6 +19,7 @@ #include "vm_stack.h" #include "vm_pool.h" +#include "logging.h" #include #include @@ -34,11 +35,14 @@ struct vm_stack { static struct vm_stack* active_stack; static uint32_t stack_seg_len; +const char* err_stage; + static inline struct vm_stack* vm_stack_create(struct vm_stack* prev, uint32_t top) { const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn); struct vm_stack* vs = malloc(size); if (UNLIKELY(vs == NULL)) { + u6a_err_bad_alloc(err_stage, size); return NULL; } vs->prev = prev; @@ -52,6 +56,7 @@ vm_stack_dup(struct vm_stack* vs) { const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn); struct vm_stack* dup_stack = malloc(size); if (UNLIKELY(dup_stack == NULL)) { + u6a_err_bad_alloc(err_stage, size); return NULL; } memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(struct u6a_vm_var_fn)); @@ -89,9 +94,10 @@ vm_stack_free(struct vm_stack* vs) { } bool -u6a_vm_stack_init(uint32_t stack_seg_len_) { +u6a_vm_stack_init(uint32_t stack_seg_len_, const char* err_stage_) { active_stack = vm_stack_create(NULL, UINT32_MAX); stack_seg_len = stack_seg_len_; + err_stage = err_stage_; return active_stack != NULL; } @@ -198,6 +204,7 @@ u6a_vm_stack_pop() { } active_stack = vs->prev; if (UNLIKELY(active_stack == NULL)) { + u6a_err_stack_underflow(err_stage); active_stack = vs; return false; } diff --git a/src/vm_stack.h b/src/vm_stack.h index 60ff66e..65bbd53 100644 --- a/src/vm_stack.h +++ b/src/vm_stack.h @@ -27,7 +27,7 @@ #include bool -u6a_vm_stack_init(uint32_t stack_seg_len); +u6a_vm_stack_init(uint32_t stack_seg_len, const char* err_stage); struct u6a_vm_var_fn u6a_vm_stack_top();