From 20307eecd5a8ccbf334aaa97129e2405cd1f2b22 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 21 Jun 2024 09:21:37 +0200 Subject: utils: improve vector utilities This commits introduces a number of new helper macros to deal with vectors and refactors the existing code for better resource utilization. The allocation strategy is changed from multiple of 8 to exponential growth by factor 1.5 in order to minimize the number of reallocations and potentially needed memory copies. The newly introduced macros are: - uc_vector_capacity(init_capacity, add_items) Derive the resulting vector capacity from the given item count and initial capacity. - uc_vector_extend(vector, add_items) Increase vector capacity by given amount of items, zero-initialize added capacity and return pointer to first new item past the current length. - uc_vector_reduce(vector, remove_items) Reduce vector capacity by given amount of items. - uc_vector_pop(vector) Return pointer to last element and decrement count, or NULL if the vector is empty. - uc_vector_foreach(vector, itervar) A for() loop wrapper to iterate vectors, providing an iter variable to the loop body. - uc_vector_foreach_reverse(vector, itervar) A for() loop wrapper to iterate vectors backwards, providing an iter variable to the loop body. The uc_vector_push() macro has been changed into a variadic macro which internally prefixes the argument list with a cast to the vector element type, allowing user to pass compound expressions like struct initializers in order to simplify adding elements: uc_vector_push(&my_collection, { .foo = 1, .bar = "qrx" }); Like uc_vector_pop(), the uc_vector_last() macro has been made safe to use on empty vectors, it'll now return NULL in this case. Finally the vector realloc logic was moved into static functions within the header file, allowing all vector using code of a compilation unit to share the reallocation, shrinking the size of libucode.so by 1-2KB as a side effect. Signed-off-by: Jo-Philipp Wich --- include/ucode/util.h | 198 +++++++++++++++++++++++++++++++++++---------------- types.c | 36 +++------- 2 files changed, 144 insertions(+), 90 deletions(-) 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 */ diff --git a/types.c b/types.c index 84a7b17..382e49a 100644 --- a/types.c +++ b/types.c @@ -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]); @@ -1116,8 +1099,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; } -- cgit v1.2.3 From e5fe6b1b822bddeac7e6a6657e6c4885aef2f2d0 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 17 Oct 2024 12:27:37 +0200 Subject: treewide: refactor vector usage code Utilize uc_vector_push() and uc_vector_foreach() where applicable. Signed-off-by: Jo-Philipp Wich --- chunk.c | 45 ++++++++++++++------------------ compiler.c | 86 +++++++++++++++++++++++++------------------------------------- lexer.c | 6 +++-- lib/ubus.c | 4 ++- source.c | 10 ++------ vm.c | 53 +++++++++++++++++--------------------- 6 files changed, 86 insertions(+), 118 deletions(-) diff --git a/chunk.c b/chunk.c index 5dbd1a1..63a7064 100644 --- a/chunk.c +++ b/chunk.c @@ -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 * diff --git a/compiler.c b/compiler.c index b64537a..6e417d2 100644 --- a/compiler.c +++ b/compiler.c @@ -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/lexer.c b/lexer.c index 52945dc..875e5dd 100644 --- a/lexer.c +++ b/lexer.c @@ -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)); diff --git a/lib/ubus.c b/lib/ubus.c index 36a5674..40711d1 100644 --- a/lib/ubus.c +++ b/lib/ubus.c @@ -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)); diff --git a/source.c b/source.c index 39295f6..e23c24d 100644 --- a/source.c +++ b/source.c @@ -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++; } } } diff --git a/vm.c b/vm.c index bb6dc2f..e4fe45d 100644 --- a/vm.c +++ b/vm.c @@ -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); @@ -3032,13 +3026,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(); -- cgit v1.2.3