diff options
author | Jo-Philipp Wich <jo@mein.io> | 2024-10-18 15:27:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-18 15:27:33 +0200 |
commit | 4b18a9b7897efbe5cee0b1c5eb3ba2c327ef3579 (patch) | |
tree | 04e1270662f04680f0584713aeff8b04d882e3a4 | |
parent | aa189522c26ba7d7bc34aca07351f7f359e89423 (diff) | |
parent | e5fe6b1b822bddeac7e6a6657e6c4885aef2f2d0 (diff) |
Merge pull request #213 from jow-/improve-vector-macros
utils: improve vector macros
-rw-r--r-- | chunk.c | 45 | ||||
-rw-r--r-- | compiler.c | 86 | ||||
-rw-r--r-- | include/ucode/util.h | 198 | ||||
-rw-r--r-- | lexer.c | 6 | ||||
-rw-r--r-- | lib/ubus.c | 4 | ||||
-rw-r--r-- | source.c | 10 | ||||
-rw-r--r-- | types.c | 36 | ||||
-rw-r--r-- | vm.c | 53 |
8 files changed, 230 insertions, 208 deletions
@@ -67,9 +67,7 @@ uc_chunk_add(uc_chunk_t *chunk, uint8_t byte, size_t offset) uc_offsetinfo_t *offsets = &chunk->debuginfo.offsets; size_t i; - uc_vector_grow(chunk); - - chunk->entries[chunk->count] = byte; + uc_vector_push(chunk, byte); /* offset info is encoded in bytes, for each byte, the first three bits * specify the number of source text bytes to advance since the last entry @@ -81,13 +79,11 @@ uc_chunk_add(uc_chunk_t *chunk, uint8_t byte, size_t offset) * instructions each */ for (i = offset; i > OFFSETINFO_MAX_BYTES; i -= OFFSETINFO_MAX_BYTES) { /* advance by 7 bytes */ - uc_vector_grow(offsets); - offsets->entries[offsets->count++] = OFFSETINFO_ENCODE(OFFSETINFO_MAX_BYTES, 0); + uc_vector_push(offsets, OFFSETINFO_ENCODE(OFFSETINFO_MAX_BYTES, 0)); } /* advance by `i` bytes, count one instruction */ - uc_vector_grow(offsets); - offsets->entries[offsets->count++] = OFFSETINFO_ENCODE(i, 1); + uc_vector_push(offsets, OFFSETINFO_ENCODE(i, 1)); } /* update instruction count at current offset entry */ @@ -97,18 +93,18 @@ uc_chunk_add(uc_chunk_t *chunk, uint8_t byte, size_t offset) * emit another offset entry with the initial three bits set to zero */ if (OFFSETINFO_NUM_INSNS(offsets->entries[offsets->count - 1]) >= OFFSETINFO_MAX_INSNS) { /* advance by 0 bytes, count one instruction */ - uc_vector_grow(offsets); - offsets->entries[offsets->count++] = OFFSETINFO_ENCODE(0, 1); + uc_vector_push(offsets, OFFSETINFO_ENCODE(0, 1)); } else { - offsets->entries[offsets->count - 1] = OFFSETINFO_ENCODE( - OFFSETINFO_NUM_BYTES(offsets->entries[offsets->count - 1]), - OFFSETINFO_NUM_INSNS(offsets->entries[offsets->count - 1]) + 1 - ); + uint8_t *prev = uc_vector_last(offsets); + + *prev = OFFSETINFO_ENCODE( + OFFSETINFO_NUM_BYTES(*prev), + OFFSETINFO_NUM_INSNS(*prev) + 1); } } - return chunk->count++; + return chunk->count - 1; } void @@ -124,10 +120,9 @@ uc_chunk_pop(uc_chunk_t *chunk) n_insns = OFFSETINFO_NUM_INSNS(offsets->entries[offsets->count - 1]); if (n_insns > 0) { - offsets->entries[offsets->count - 1] = OFFSETINFO_ENCODE( - OFFSETINFO_NUM_BYTES(offsets->entries[offsets->count - 1]), - n_insns - 1 - ); + uint8_t *prev = uc_vector_last(offsets); + + *prev = OFFSETINFO_ENCODE(OFFSETINFO_NUM_BYTES(*prev), n_insns - 1); } else { offsets->count--; @@ -162,14 +157,12 @@ uc_chunk_debug_add_variable(uc_chunk_t *chunk, size_t from, size_t to, size_t sl if (upval) slot += (size_t)-1 / 2; - uc_vector_grow(variables); - - variables->entries[variables->count].nameidx = uc_vallist_add(varnames, name); - variables->entries[variables->count].slot = slot; - variables->entries[variables->count].from = from; - variables->entries[variables->count].to = to; - - variables->count++; + uc_vector_push(variables, { + .nameidx = uc_vallist_add(varnames, name), + .slot = slot, + .from = from, + .to = to + }); } uc_value_t * @@ -823,14 +823,13 @@ uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool consta } } - uc_vector_grow(locals); - - locals->entries[locals->count].name = ucv_get(name); - locals->entries[locals->count].depth = -1; - locals->entries[locals->count].captured = false; - locals->entries[locals->count].from = chunk->count; - locals->entries[locals->count].constant = constant; - locals->count++; + uc_vector_push(locals, { + .name = ucv_get(name), + .depth = -1, + .captured = false, + .from = chunk->count, + .constant = constant + }); return -1; } @@ -896,16 +895,16 @@ uc_compiler_add_upval(uc_compiler_t *compiler, size_t idx, bool local, uc_value_ return -1; } - uc_vector_grow(upvals); - - upvals->entries[upvals->count].local = local; - upvals->entries[upvals->count].index = idx; - upvals->entries[upvals->count].name = ucv_get(name); - upvals->entries[upvals->count].constant = constant; + uc_vector_push(upvals, { + .local = local, + .index = idx, + .name = ucv_get(name), + .constant = constant + }); function->nupvals++; - return upvals->count++; + return upvals->count - 1; } static ssize_t @@ -1618,10 +1617,8 @@ uc_compiler_compile_call(uc_compiler_t *compiler) if (!uc_compiler_parse_check(compiler, TK_RPAREN)) { do { /* if this is a spread arg, remember the argument index */ - if (uc_compiler_parse_match(compiler, TK_ELLIP)) { - uc_vector_grow(&spreads); - spreads.entries[spreads.count++] = nargs; - } + if (uc_compiler_parse_match(compiler, TK_ELLIP)) + uc_vector_push(&spreads, nargs); /* compile argument expression */ uc_compiler_parse_precedence(compiler, P_ASSIGN); @@ -2175,14 +2172,14 @@ uc_compiler_declare_internal(uc_compiler_t *compiler, size_t srcpos, const char uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); uc_locals_t *locals = &compiler->locals; - uc_vector_grow(locals); + uc_vector_push(locals, { + .name = ucv_string_new(name), + .depth = compiler->scope_depth, + .captured = false, + .from = chunk->count + }); - locals->entries[locals->count].name = ucv_string_new(name); - locals->entries[locals->count].depth = compiler->scope_depth; - locals->entries[locals->count].captured = false; - locals->entries[locals->count].from = chunk->count; - - return locals->count++; + return locals->count - 1; } static void @@ -2292,8 +2289,7 @@ uc_compiler_compile_if(uc_compiler_t *compiler) /* we just compiled an elsif block */ if (!expect_endif && type == TK_ELIF) { /* emit jump to skip to the end */ - uc_vector_grow(&elifs); - elifs.entries[elifs.count++] = uc_compiler_emit_jmp(compiler, 0); + uc_vector_push(&elifs, uc_compiler_emit_jmp(compiler, 0)); /* point previous conditional jump to beginning of branch */ uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); @@ -2310,8 +2306,7 @@ uc_compiler_compile_if(uc_compiler_t *compiler) } else if (!expect_endif && type == TK_ELSE) { /* emit jump to skip to the end */ - uc_vector_grow(&elifs); - elifs.entries[elifs.count++] = uc_compiler_emit_jmp(compiler, 0); + uc_vector_push(&elifs, uc_compiler_emit_jmp(compiler, 0)); /* point previous conditional jump to beginning of branch */ uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); @@ -2746,13 +2741,9 @@ uc_compiler_compile_switch(uc_compiler_t *compiler) * For the `default` case, beginning and end offsets of the * condition expression are equal. */ - uc_vector_grow(&cases); + uc_vector_extend(&cases, 3); cases.entries[cases.count++] = (locals->count - 1) - value_slot; - - uc_vector_grow(&cases); cases.entries[cases.count++] = chunk->count; - - uc_vector_grow(&cases); cases.entries[cases.count++] = chunk->count; } @@ -2770,13 +2761,9 @@ uc_compiler_compile_switch(uc_compiler_t *compiler) * 2) beginning of condition expression * 3) end of condition expression */ - uc_vector_grow(&cases); + uc_vector_extend(&cases, 3); cases.entries[cases.count++] = (locals->count - 1) - value_slot; - - uc_vector_grow(&cases); cases.entries[cases.count++] = skip_jmp + 5; - - uc_vector_grow(&cases); cases.entries[cases.count++] = uc_compiler_emit_jmp(compiler, 0); /* patch jump skipping over the case value */ @@ -2911,13 +2898,12 @@ uc_compiler_compile_try(uc_compiler_t *compiler) /* Catch block ---------------------------------------------------------- */ if (try_to > try_from) { - uc_vector_grow(ranges); - - ranges->entries[ranges->count].from = try_from; - ranges->entries[ranges->count].to = try_to; - ranges->entries[ranges->count].target = chunk->count; - ranges->entries[ranges->count].slot = ehvar_slot; - ranges->count++; + uc_vector_push(ranges, { + .from = try_from, + .to = try_to, + .target = chunk->count, + .slot = ehvar_slot + }); } uc_compiler_enter_scope(compiler); @@ -2983,10 +2969,8 @@ uc_compiler_compile_control(uc_compiler_t *compiler) uc_compiler_emit_insn(compiler, 0, locals->entries[i - 1].captured ? I_CUPV : I_POP); - uc_vector_grow(p); - - p->entries[p->count++] = - uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type); + uc_vector_push(p, + uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type)); uc_compiler_parse_consume(compiler, TK_SCOL); } diff --git a/include/ucode/util.h b/include/ucode/util.h index a3692d5..cc92e33 100644 --- a/include/ucode/util.h +++ b/include/ucode/util.h @@ -30,6 +30,14 @@ #define __hidden __attribute__((visibility("hidden"))) #endif +#ifndef localfunc +# if defined(__GNUC__) || defined(__clang__) +# define localfunc static __attribute__((noinline,unused)) +# else +# define localfunc static inline +# endif +#endif + /* alignment & array size */ @@ -42,69 +50,6 @@ #endif -/* vector macros */ - -#define UC_VECTOR_CHUNK_SIZE 8 - -#define uc_declare_vector(name, type) \ - typedef struct { \ - size_t count; \ - type *entries; \ - } name - -#define uc_vector_grow(vec) \ - do { \ - if (((vec)->count % UC_VECTOR_CHUNK_SIZE) == 0) { \ - (vec)->entries = xrealloc((vec)->entries, sizeof((vec)->entries[0]) * ((vec)->count + UC_VECTOR_CHUNK_SIZE)); \ - memset(&(vec)->entries[(vec)->count], 0, sizeof((vec)->entries[0]) * UC_VECTOR_CHUNK_SIZE); \ - } \ - } while(0) - -#define uc_vector_clear(vec) \ - do { \ - free((vec)->entries); \ - (vec)->entries = NULL; \ - (vec)->count = 0; \ - } while(0) - -#define uc_vector_first(vec) \ - (&((vec)->entries[0])) - -#define uc_vector_last(vec) \ - (&((vec)->entries[(vec)->count - 1])) - -#define uc_vector_push(vec, val) do { \ - uc_vector_grow(vec); \ - (vec)->entries[(vec)->count++] = (val); \ -} while(0) - - -/* linked lists */ - -typedef struct uc_list { - struct uc_list *prev; - struct uc_list *next; -} uc_list_t; - -static inline void uc_list_insert(uc_list_t *list, uc_list_t *item) -{ - list->next->prev = item; - item->next = list->next; - item->prev = list; - list->next = item; -} - -static inline void uc_list_remove(uc_list_t *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; - item->prev = item->next = item; -} - -#define uc_list_foreach(item, list) \ - for (uc_list_t *item = (list)->next; item != (list); item = item->next) - - /* "failsafe" utility functions */ static inline void *xcalloc(size_t size, size_t nmemb) { @@ -195,4 +140,131 @@ static inline struct printbuf *xprintbuf_new(void) { return pb; } + +/* linked lists */ + +typedef struct uc_list { + struct uc_list *prev; + struct uc_list *next; +} uc_list_t; + +static inline void uc_list_insert(uc_list_t *list, uc_list_t *item) +{ + list->next->prev = item; + item->next = list->next; + item->prev = list; + list->next = item; +} + +static inline void uc_list_remove(uc_list_t *item) +{ + item->next->prev = item->prev; + item->prev->next = item->next; + item->prev = item->next = item; +} + +#define uc_list_foreach(item, list) \ + for (uc_list_t *item = (list)->next; item != (list); item = item->next) + + +/* vector macros */ + +#define UC_VECTOR_INIT_SIZE 8 + +#define uc_declare_vector(name, type) \ + typedef struct { \ + size_t count; \ + type *entries; \ + } name + +localfunc size_t +uc_vector_capacity(size_t init, size_t count) +{ + if (count == 0) + return init; + + size_t capacity = init; + + while (capacity <= count) + capacity += (capacity >> 1); + + return capacity; +} + +localfunc void +uc_vector_reduce_(char **base, size_t itemsize, size_t count, size_t remove) +{ + if (*base == NULL) + return; + + if (remove > count) + remove = count; + + size_t next_capacity = uc_vector_capacity(UC_VECTOR_INIT_SIZE, count - remove); + + if (uc_vector_capacity(next_capacity, count) != next_capacity) + *base = (__typeof__(*base))xrealloc(*base, itemsize * next_capacity); +} + +localfunc void * +uc_vector_extend_(char **base, size_t itemsize, size_t count, size_t add) +{ + size_t curr_capacity = uc_vector_capacity(UC_VECTOR_INIT_SIZE, count); + + if (*base == NULL || count + add >= curr_capacity) { + size_t next_capacity = uc_vector_capacity(curr_capacity, count + add); + + *base = (__typeof__(*base))xrealloc(*base, itemsize * next_capacity); + + memset(*base + itemsize * count, 0, + itemsize * (next_capacity - count)); + } + + return *base + itemsize * count; +} + +#define uc_vector_reduce(vec, remove) \ + uc_vector_reduce_((char **)&(vec)->entries, sizeof((vec)->entries[0]), (vec)->count, (remove)) + +#define uc_vector_extend(vec, add) \ + (__typeof__((vec)->entries + 0)) uc_vector_extend_( \ + (char **)&(vec)->entries, \ + sizeof((vec)->entries[0]), \ + (vec)->count, (add)) + +#define uc_vector_grow(vec) \ + uc_vector_extend_((char **)&(vec)->entries, sizeof((vec)->entries[0]), (vec)->count, 1) + +#define uc_vector_clear(vec) \ + do { \ + free((vec)->entries); \ + (vec)->entries = NULL; \ + (vec)->count = 0; \ + } while(0) + +#define uc_vector_first(vec) \ + (&((vec)->entries[0])) + +#define uc_vector_last(vec) \ + ((vec)->count ? &((vec)->entries[(vec)->count - 1]) : NULL) + +#define uc_vector_push(vec, ...) ({ \ + *uc_vector_extend((vec), 1) = ((__typeof__((vec)->entries[0]))__VA_ARGS__); \ + &(vec)->entries[(vec)->count++]; \ +}) + +#define uc_vector_pop(vec) \ + ((vec)->count ? &(vec)->entries[--(vec)->count] : NULL) + +#define uc_vector_foreach(vec, iter) \ + for (__typeof__((vec)->entries + 0) iter = (vec)->entries; \ + iter < (vec)->entries + (vec)->count; \ + iter++) + +#define uc_vector_foreach_reverse(vec, iter) \ + for (__typeof__((vec)->entries + 0) iter = (vec)->count \ + ? (vec)->entries + (vec)->count - 1 : NULL; \ + iter != NULL && iter >= (vec)->entries; \ + iter--) + #endif /* UCODE_UTIL_H */ @@ -153,11 +153,13 @@ emit_op(uc_lexer_t *lex, ssize_t pos, int type, uc_value_t *uv) static uc_token_t * emit_buffer(uc_lexer_t *lex, ssize_t pos, int type, const char *strip_trailing_chars) { uc_token_t *rv = NULL; + char *p; if (lex->buffer.count) { if (strip_trailing_chars) - while (lex->buffer.count > 0 && strchr(strip_trailing_chars, *uc_vector_last(&lex->buffer))) - lex->buffer.count--; + for (p = uc_vector_last(&lex->buffer); + p && strchr(strip_trailing_chars, *p); + lex->buffer.count--, p = uc_vector_last(&lex->buffer)); rv = emit_op(lex, pos, type, ucv_string_new_length(uc_vector_first(&lex->buffer), lex->buffer.count)); @@ -724,6 +724,7 @@ uc_ubus_defer(uc_vm_t *vm, size_t nargs) uc_ubus_deferred_t *defer; uc_ubus_connection_t *c; enum ubus_msg_status rv; + uc_callframe_t *frame; uint32_t id; conn_get(vm, &c); @@ -762,7 +763,8 @@ uc_ubus_defer(uc_vm_t *vm, size_t nargs) uloop_timeout_set(&defer->timeout, c->timeout * 1000); res = uc_resource_new(defer_type, defer); - conn = uc_vector_last(&vm->callframes)->ctx; + frame = uc_vector_last(&vm->callframes); + conn = frame ? frame->ctx : NULL; defer->registry_index = request_reg_add(vm, ucv_get(res), ucv_get(replycb), ucv_get(conn)); @@ -157,10 +157,7 @@ uc_source_type_test(uc_source_t *source) void uc_source_line_next(uc_source_t *source) { - uc_lineinfo_t *lines = &source->lineinfo; - - uc_vector_grow(lines); - lines->entries[lines->count++] = 0x80; + uc_vector_push(&source->lineinfo, 0x80); } void @@ -183,11 +180,8 @@ uc_source_line_update(uc_source_t *source, size_t off) while (off > 0) { n = (off > 0x7f) ? 0x7f : off; - uc_vector_grow(lines); - entry = uc_vector_last(lines); - entry[1] = n; + uc_vector_push(lines, n); off -= n; - lines->count++; } } } @@ -705,17 +705,13 @@ ucv_array_new_length(uc_vm_t *vm, size_t length) { uc_array_t *array; - /* XXX */ - length = 0; - - array = xalloc(sizeof(*array) + length * sizeof(array->entries[0])); + array = xalloc(sizeof(*array)); array->header.type = UC_ARRAY; array->header.refcount = 1; - if (length > 0) - array->count = length; - - uc_vector_grow(array); + /* preallocate memory */ + if (length) + uc_vector_extend(array, length); if (vm) { ucv_ref(&vm->values, &array->ref); @@ -779,10 +775,9 @@ ucv_array_unshift(uc_value_t *uv, uc_value_t *item) if (ucv_type(uv) != UC_ARRAY) return NULL; - array->count++; - uc_vector_grow(array); + uc_vector_extend(array, 1); - for (i = array->count; i > 1; i--) + for (i = ++array->count; i > 1; i--) array->entries[i - 1] = array->entries[i - 2]; array->entries[0] = item; @@ -826,10 +821,9 @@ ucv_array_delete(uc_value_t *uv, size_t offset, size_t count) &array->entries[offset + count], (array->count - (offset + count)) * sizeof(array->entries[0])); + uc_vector_reduce(array, count); array->count -= count; - uc_vector_grow(array); - return true; } @@ -837,24 +831,13 @@ bool ucv_array_set(uc_value_t *uv, size_t index, uc_value_t *item) { uc_array_t *array = (uc_array_t *)uv; - size_t old_count, new_count; if (ucv_type(uv) != UC_ARRAY) return false; if (index >= array->count) { - old_count = array->count; - new_count = (index + 1) & ~(UC_VECTOR_CHUNK_SIZE - 1); - - if (new_count > old_count) { - array->count = new_count; - uc_vector_grow(array); - } - + uc_vector_extend(array, index + 1 - array->count); array->count = index + 1; - - while (old_count < array->count) - array->entries[old_count++] = NULL; } else { ucv_put(array->entries[index]); @@ -1151,8 +1134,7 @@ ucv_resource_type_add(uc_vm_t *vm, const char *name, uc_value_t *proto, void (*f type->proto = proto; type->free = freefn; - uc_vector_grow(&vm->restypes); - vm->restypes.entries[vm->restypes.count++] = type; + uc_vector_push(&vm->restypes, type); return type; } @@ -431,11 +431,7 @@ uc_vm_resolve_upval(uc_vm_t *vm, uc_value_t *value) void uc_vm_stack_push(uc_vm_t *vm, uc_value_t *value) { - uc_vector_grow(&vm->stack); - - ucv_put(vm->stack.entries[vm->stack.count]); - vm->stack.entries[vm->stack.count] = uc_vm_resolve_upval(vm, value); - vm->stack.count++; + uc_vector_push(&vm->stack, value); if (vm->trace) { fprintf(stderr, " [+%zd] %s\n", @@ -488,14 +484,13 @@ uc_vm_call_native(uc_vm_t *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall uc_callframe_t *frame; /* add new callframe */ - uc_vector_grow(&vm->callframes); - - frame = &vm->callframes.entries[vm->callframes.count++]; - frame->stackframe = vm->stack.count - nargs - 1; - frame->cfunction = fptr; - frame->closure = NULL; - frame->ctx = ctx; - frame->mcall = mcall; + frame = uc_vector_push(&vm->callframes, { + .stackframe = vm->stack.count - nargs - 1, + .cfunction = fptr, + .closure = NULL, + .ctx = ctx, + .mcall = mcall + }); if (vm->trace) uc_vm_frame_dump(vm, frame); @@ -641,16 +636,15 @@ uc_vm_call_function(uc_vm_t *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, s } } - uc_vector_grow(&vm->callframes); - - frame = &vm->callframes.entries[vm->callframes.count++]; - frame->stackframe = stackoff; - frame->cfunction = NULL; - frame->closure = closure; - frame->ctx = ctx; - frame->ip = function->chunk.entries; - frame->mcall = mcall; - frame->strict = function->strict; + frame = uc_vector_push(&vm->callframes, { + .stackframe = stackoff, + .cfunction = NULL, + .closure = closure, + .ctx = ctx, + .ip = function->chunk.entries, + .mcall = mcall, + .strict = function->strict + }); if (vm->trace) uc_vm_frame_dump(vm, frame); @@ -3033,13 +3027,12 @@ uc_vm_execute(uc_vm_t *vm, uc_program_t *program, uc_value_t **retval) uc_stringbuf_t *buf; uc_value_t *val; - uc_vector_grow(&vm->callframes); - - frame = &vm->callframes.entries[vm->callframes.count++]; - frame->closure = closure; - frame->stackframe = 0; - frame->ip = uc_vm_frame_chunk(frame)->entries; - frame->strict = fn->strict; + frame = uc_vector_push(&vm->callframes, { + .closure = closure, + .stackframe = 0, + .ip = closure->function->chunk.entries, + .strict = fn->strict + }); if (vm->trace) { buf = xprintbuf_new(); |