SEVERITY ?= 10
GWION_TEST_DIR ?= /tmp
-
-src := $(wildcard src/*.c)
-src += $(wildcard src/*/*.c)
-
test_dir_all := $(wildcard tests/*)
test_ignore = tests/plug test/driver tests/module
test_dir := $(filter-out $(test_ignore), $(test_dir_all))
test_dir += examples
+src := $(wildcard src/*.c)
+src += $(wildcard src/*/*.c)
+
CFLAGS += -Iutil/include -Iast/include -Ilibcmdapp/src -D_GNU_SOURCE
CFLAGS += -Iast/libprettyerr/src -Ifmt/include
gcda := $(src:.c=.gcda)
gcno := $(src:.c=.gcno)
lib_obj := $(filter-out src/main.o, ${src_obj})
+almost_obj := $(filter-out src/vm/vm.o, ${src_obj})
CFLAGS += -Iinclude
LDFLAGS += -lrt
endif
-CFLAGS += -DGWION_BUILTIN
-
-_GWLIBS = util/libgwion_util.a ast/libgwion_ast.a libcmdapp/libcmdapp.a lib${PRG}.a util/libtermcolor/libtermcolor.a ast/libprettyerr/libprettyerr.a fmt/libgwion-fmt.a
-GWLIBS := lib${PRG}.a libcmdapp/libcmdapp.a ast/libgwion_ast.a
-GWLIBS += util/libgwion_util.a ast/libprettyerr/libprettyerr.a util/libtermcolor/libtermcolor.a
-GWLIBS += fmt/libgwion-fmt.a
-_LDFLAGS = ${GWLIBS} ${LDFLAGS}
+ALMOST_LIBS := libcmdapp/libcmdapp.a fmt/libgwion-fmt.a
+ALMOST_LIBS += ast/libgwion_ast.a ast/libprettyerr/libprettyerr.a
+ALMOST_LIBS += util/libgwion_util.a util/libtermcolor/libtermcolor.a
+GWLIBS := lib${PRG}.a ${ALMOST_LIBS}
+LDFLAGS := ${GWLIBS} ${LDFLAGS}
# we are not pedantic
CFLAGS += -Wno-pedantic
-all: options-show ${_GWLIBS} src/main.o
+CFLAGS += -DGWION_BUILTIN
+
+all: options-show ${GWLIBS} src/main.o
@$(info link ${PRG})
- @${CC} src/main.o -o ${PRG} ${_LDFLAGS} ${LIBS}
+ @${CC} src/main.o -o ${PRG} ${LDFLAGS} ${LIBS}
options-show:
@$(call _options)
@$(info libs: ${GWLIBS})
+almost_gwion: ${almost_obj} ${ALMOST_LIBS}
+
+lto:
+ @${MAKE} USE_LTO=1 almost_gwion
+ @${MAKE} USE_LTO=0
+
lib${PRG}.a: ${lib_obj}
@${AR} ${AR_OPT}
git submodule update --recursive --init
make
-.PHONY: .afl
-
clean: clean_core
$(info cleaning ...)
@rm -f src/*.o src/*/*.o gwion lib${PRG}.a ${gcno} ${gcda}
scan:
@rm -rf scan_output
- @scan-build -o ./scan_output make
+ @scan-build -o ./scan_output make USE_DEBUG=1
@scan-view ./scan_output/*
include $(wildcard .d/*.d)
-Subproject commit 6d965961163bf32e912acd09d6cda41b93e24ff7
+Subproject commit 5796cf89170539636d4f1405c59bc938e055acb0
-Subproject commit 14d746b2d31b99395d8035c8450353afc059eac5
+Subproject commit 260f256586cbd65f0e5c74484dbe71d26b6db62e
void func_def_cleaner(const Gwion, Func_Def);
#ifdef __CLEAN_IMPL
typedef struct {
- m_uint scope;
- Gwion gwion;
+ Gwion gwion;
+ uint16_t scope;
} Clean;
ANN static void clean_array_sub(Clean *a, Array_Sub b);
typedef struct Frame_ {
struct Vector_ stack;
- size_t curr_offset;
struct Map_ handlers;
struct Vector_ defer;
- m_uint try_top;
+ m_uint value_count;
+ uint16_t curr_offset;
+ uint16_t try_top;
} Frame;
+typedef struct VMValue_ {
+ Type t;
+ uint16_t offset;
+ uint16_t start;
+ uint16_t end;
+} VMValue;
+
typedef struct Code_ {
- Frame * frame;
- struct Vector_ instr;
- size_t stack_depth;
- struct Vector_ stack_cont;
- struct Vector_ stack_break;
- struct Vector_ stack_return;
- m_str name;
+ Frame * frame;
+ struct Vector_ instr;
+ struct Vector_ stack_cont;
+ struct Vector_ stack_break;
+ struct Vector_ stack_return;
+ struct M_Vector_ live_values;
+ m_str name;
+ uint16_t stack_depth;
} Code;
struct EmitterInfo_ {
struct Gwion_ * gwion;
struct EmitterInfo_ *info;
struct Vector_ stack;
- m_uint this_offset; // reset
- m_uint vararg_offset; // reset
+ uint16_t this_offset; // reset
+ uint16_t vararg_offset; // reset
};
ANEW ANN Emitter new_emitter(MemPool);
const Env env;
const envset_func func;
const void * data;
- const m_int scope;
const enum tflag flag;
Context _ctx;
m_str _filename;
+ const uint16_t scope;
bool run;
};
ANN void operator_suspend(const Nspc, struct Op_Import *);
ANN static inline void operator_resume(struct Op_Import *opi) {
+ assert(opi->ret);
*(uintptr_t *)opi->ret = opi->data;
}
struct Vector_ instr;
m_uint native_func;
};
- size_t stack_depth;
Type ret_type; // could be `struct Vector_ tmpl_types;`
union {
void * memoize;
Closure *closure;
};
- struct Map_ handlers;
m_str name;
+ struct Map_ handlers;
+ struct M_Vector_ live_values;
+ uint16_t stack_depth;
uint16_t ref;
- ae_flag flag;
bool builtin;
bool callback;
bool is_memoize;
struct ShredInfo_ *info;
};
REF_FUNC(VM_Code, vmcode)
-ANN2(1, 5)
-ANEW VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth,
- const int builtin, const m_str name);
+ANN2(1,4)
+ANEW VM_Code new_vmcode(MemPool p, const Vector instr, const M_Vector live_values, const m_str name,
+ const uint16_t stack_depth, const bool builtin);
ANN ANEW VM_Code vmcode_callback(MemPool p, const VM_Code code);
ANN VM_Shred shreduler_get(const Shreduler s) __attribute__((hot));
ANN void free_vm(VM *vm);
ANN void vm_ini_shred(const VM *vm, const VM_Shred shred) __attribute__((hot));
ANN void vm_add_shred(const VM *vm, const VM_Shred shred) __attribute__((hot));
-ANN void vm_remove(const VM *vm, const m_uint index) __attribute__((hot));
+ANN bool vm_remove(const VM *vm, const m_uint index) __attribute__((hot));
ANN m_str code_name_set(MemPool p, const m_str, const m_str);
ANN m_str code_name(const m_str, const bool);
ANN uint32_t gw_rand(uint32_t s[2]);
-Subproject commit a853cfd9bbaf47604202dda4ecd168a62091b13e
+Subproject commit 857e0e59f0bb00b6de35ad770814960c3e442d6a
const m_uint xid) {
struct Compiler c = {.base = filename, .type = COMPILE_NAME};
if (!compile(gwion, &c)) return 0;
+ assert(c.shred);
return c.shred->tick->xid = xid;
}
const m_str data, const m_uint xid) {
struct Compiler c = {.base = filename, .type = COMPILE_MSTR, .data = data};
if (!compile(gwion, &c)) return 0;
+ assert(c.shred);
return c.shred->tick->xid = xid;
}
FILE *file, const m_uint xid) {
struct Compiler c = {.base = filename, .type = COMPILE_FILE, .file = file};
if (!compile(gwion, &c)) return 0;
+ assert(c.shred);
return c.shred->tick->xid = xid;
}
Type type;
m_uint offset;
bool skip;
+ bool is_compound;
} Local;
static inline void emit_pop(const Emitter emit, const m_uint scope) {
return local;
}
-ANN static m_uint frame_local(MemPool p, Frame *frame, const Type t,
- const bool skip) {
- Local *local = new_local(p, t);
- local->offset = frame->curr_offset;
- local->skip = skip;
+ANN static Local *frame_local(MemPool p, Frame *frame, const Type t) {
+ Local *const l = new_local(p, t);
+ l->offset = frame->curr_offset;
frame->curr_offset += t->size;
- vector_add(&frame->stack, (vtype)local);
- return local->offset;
+ vector_add(&frame->stack, (vtype)l);
+ return l;
}
ANN static inline void frame_push(Frame *frame) {
DECL_OB(const Local *, l, = (Local *)vector_pop(&frame->stack));
frame->curr_offset -= l->type->size;
if (l->skip) return _frame_pop(emit);
- if (tflag(l->type, tflag_struct)) {
- struct_pop(emit, l->type, l->offset);
- return _frame_pop(emit);
- }
- return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset
- : _frame_pop(emit);
+ if (!l->is_compound) return _frame_pop(emit);
+ VMValue *vmval =
+ (VMValue *)m_vector_addr(&emit->code->live_values, --frame->value_count);
+ vmval->end = emit_code_size(emit);
+ if (!tflag(l->type, tflag_struct)) return (m_int)l->offset;
+ struct_pop(emit, l->type, l->offset);
+ return _frame_pop(emit);
}
ANN static m_int frame_pop(const Emitter emit) {
vector_init(&code->stack_break);
vector_init(&code->stack_cont);
vector_init(&code->stack_return);
+ m_vector_init(&code->live_values, sizeof(VMValue), 0);
code->frame = new_frame(emit->gwion->mp);
return code;
}
vector_release(&code->stack_break);
vector_release(&code->stack_cont);
vector_release(&code->stack_return);
+ if (code->live_values.ptr) m_vector_release(&code->live_values);
free_frame(p, code->frame);
free_mstr(p, code->name);
mp_free(p, Code, code);
}
ANN m_uint emit_local(const Emitter emit, const Type t) {
- return frame_local(emit->gwion->mp, emit->code->frame, t, false);
+ Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
+ if (isa(t, emit->gwion->type[et_compound]) > 0) {
+ l->is_compound = true;
+ VMValue vmval = {
+ .t = t, .offset = l->offset, .start = emit_code_size(emit)};
+ m_vector_add(&emit->code->live_values, &vmval);
+ ++emit->code->frame->value_count;
+ }
+ return l->offset;
}
ANN m_uint emit_localn(const Emitter emit, const Type t) {
- return frame_local(emit->gwion->mp, emit->code->frame, t, true);
+ Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
+ l->skip = true;
+ return l->offset;
}
ANN void emit_ext_ctor(const Emitter emit, const Type t);
}
ANN static void emit_pre_ctor(const Emitter emit, const Type type) {
- if (type->info->parent) emit_pre_ctor(emit, type->info->parent);
- if (tflag(type, tflag_typedef) && type->info->parent->array_depth)
- emit_array_extend(emit, type, type->info->cdef->base.ext->array->exp);
+ if (type->info->parent) {
+ emit_pre_ctor(emit, type->info->parent);
+ if (tflag(type, tflag_typedef) && type->info->parent->array_depth)
+ emit_array_extend(emit, type, type->info->cdef->base.ext->array->exp);
+ }
maybe_ctor(emit, type);
}
ANN static m_bool emit_prim_range(const Emitter emit, Range **data) {
Range *range = *data;
CHECK_BB(emit_range(emit, range));
- const Exp e = range->start ?: range->end;
- const Symbol sym = insert_symbol("@range");
+ const Exp e = range->start ?: range->end;
+ const Symbol sym = insert_symbol("@range");
+ assert(e);
struct Op_Import opi = {.op = sym,
.rhs = e->type,
.pos = e->pos,
ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice *range) {
CHECK_BB(emit_exp(emit, range->base));
CHECK_BB(emit_range(emit, range->range));
- const Symbol sym = insert_symbol("@slice");
- const Exp e = range->range->start ?: range->range->end;
+ const Symbol sym = insert_symbol("@slice");
+ const Exp e = range->range->start ?: range->range->end;
+ assert(e);
struct Op_Import opi = {.op = sym,
.lhs = e->type,
.rhs = range->base->type,
const Instr instr = (Instr)vector_back(&emit->code->instr);
if (instr->opcode == eDotTmplVal) {
size_t len = strlen(f->name);
- size_t sz = len - strlen(f->value_ref->from->owner_class->name);
+ assert(f->value_ref->from->owner_class);
+ size_t sz = len - strlen(f->value_ref->from->owner_class->name);
char c[sz + 1];
memcpy(c, f->name, sz);
c[sz] = '\0';
emit_add_instr(emit, RegPushImm);
push_spork_code(emit, sp->is_spork ? SPORK_CODE_PREFIX : FORK_CODE_PREFIX,
sp->code->pos);
+ if (emit->env->class_def) stack_alloc(emit);
if (emit->env->func && vflag(emit->env->func->value_ref, vflag_member))
stack_alloc(emit);
return scoped_stmt(emit, sp->code, 0);
}
ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
- if (!sp->code) CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call));
+ if (!sp->code) {
+ assert(sp->exp);
+ CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call));
+ }
if ((sp->code ? spork_prepare_code : spork_prepare_func)(emit, sp) > 0)
return finalyze(emit, EOC);
emit_pop_code(emit);
#include "escape.h"
static ANEW ANN VM_Code emit_code(const Emitter emit) {
- Code *const c = emit->code;
- const VM_Code code =
- new_vmcode(emit->gwion->mp, &c->instr, c->stack_depth, 0, c->name);
+ Code *const c = emit->code;
+ const bool has_values = m_vector_size(&c->live_values);
+ const VM_Code code = new_vmcode(emit->gwion->mp, &c->instr,
+ has_values ? &c->live_values : NULL, c->name,
+ c->stack_depth, false);
+ if (has_values) c->live_values.ptr = NULL;
return code;
}
ANN void builtin_func(const MemPool mp, const Func f, void *func_ptr) {
set_vflag(f->value_ref, vflag_builtin);
- f->code = new_vmcode(mp, NULL, f->def->stack_depth, 1, f->name);
+ f->code = new_vmcode(mp, NULL, NULL, f->name, f->def->stack_depth, true);
f->code->native_func = (m_uint)func_ptr;
}
}
ANN static void gwion_cleaner(const Gwion gwion) {
- const VM_Code code = new_vmcode(gwion->mp, NULL, 0, 1, "in code dtor");
+ const VM_Code code =
+ new_vmcode(gwion->mp, NULL, NULL, "in code dtor", 0, true);
gwion->vm->cleaner_shred = new_vm_shred(gwion->mp, code);
vm_ini_shred(gwion->vm, gwion->vm->cleaner_shred);
}
const enum tflag e) {
VM_Code *code = e == tflag_ctor ? &type->nspc->pre_ctor : &type->nspc->dtor;
const m_str name = type->name;
- *code = new_vmcode(p, NULL, SZ_INT, 1, name);
+ *code = new_vmcode(p, NULL, NULL, name, SZ_INT, true);
(*code)->native_func = (m_uint)d;
type->tflag |= e;
return GW_OK;
if (gwi->gwion->data->cdoc) {
lint_indent(gwi->lint);
gwi->lint->indent++;
+ assert(t->info->cdef);
lint_class_def(gwi->lint, t->info->cdef);
}
return t;
}
ANN static m_bool mk_gack(MemPool p, const Type type, const f_gack d) {
- const VM_Code code = new_vmcode(p, NULL, SZ_INT, 1, "@gack");
+ const VM_Code code = new_vmcode(p, NULL, NULL, "@gack", SZ_INT, true);
code->native_func = (m_uint)d;
type->info->gack = code;
return GW_OK;
builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 11),
vm_vector_foldr);
if (isa(base, env->gwion->type[et_compound]) > 0) {
- t->nspc->dtor =
- new_vmcode(env->gwion->mp, NULL, SZ_INT, 1, "array component dtor");
+ t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, NULL,
+ "array component dtor", SZ_INT, true);
set_tflag(t, tflag_dtor);
t->nspc->dtor->native_func = (m_uint)(
!tflag(base, tflag_struct) ? array_dtor_obj : array_dtor_struct);
gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n",
shred->tick->xid, shred->code->name);
vm_shred_exit(shred);
+ if (info->is_obj) free(aai.data);
return; // TODO make exception vararg
}
*(void **)(ref->data + SZ_INT) = aai.data;
env_pop(env, scope);
nspc_add_type_front(t->info->value->from->owner, info.name, t);
if (isa(base, env->gwion->type[et_compound]) > 0) {
- t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, SZ_INT, 1, "@PtrDtor");
+ t->nspc->dtor =
+ new_vmcode(env->gwion->mp, NULL, NULL, "@PtrDtor", SZ_INT, true);
if (!tflag(base, tflag_struct))
t->nspc->dtor->native_func = (m_uint)ptr_object_dtor;
else
}
char insert[strlen(STRING(arg)) + 1];
const m_uint len = strlen(str);
- memset(insert, 0, len + 1);
+ // memset(insert, 0, len + 1);
strcpy(insert, STRING(arg));
str[len] = '\0';
if (index > (m_int)len) index = len - 1;
Exp_Call *call = (Exp_Call *)data;
const Exp name = call->args;
if (!name || !name->next || name->next->next)
- ERR_N(name->pos, "Union constructor takes two arguments, "
- "'id' and 'value'");
+ ERR_N(call->func->pos, "Union constructor takes two arguments, "
+ "'id' and 'value'");
if (name->exp_type != ae_exp_primary || name->d.prim.prim_type != ae_prim_id)
return NULL;
const Exp val = name->next;
gwerr_basic(_("literal contains incompatible types"), fst, NULL, env->name,
loc, 0);
// suggested fix: rewrite int 2 as float 2.0"
- char sec[12 + strlen(e->type->name)];
+ char sec[16 + strlen(e->type->name)];
sprintf(sec, "got `{+/}%s{0}`", e->type->name);
gwerr_secondary(sec, env->name, e->pos);
ANN static Type check_prim_range(const Env env, Range **data) {
Range *range = *data;
CHECK_BO(check_range(env, range));
- const Exp e = range->start ?: range->end;
+ const Exp e = range->start ?: range->end;
+ assert(e);
const Symbol sym = insert_symbol("@range");
struct Op_Import opi = {.op = sym,
.rhs = e->type,
static ANN Type check_exp_slice(const Env env, const Exp_Slice *range) {
CHECK_OO(check_exp(env, range->base));
CHECK_BO(check_range(env, range->range));
- const Symbol sym = insert_symbol("@slice");
- const Exp e = range->range->start ?: range->range->end;
+ const Symbol sym = insert_symbol("@slice");
+ const Exp e = range->range->start ?: range->range->end;
+ assert(e);
struct Op_Import opi = {.op = sym,
.lhs = e->type,
.rhs = range->base->type,
free_scope(env->gwion->mp, env->curr->info->value);
env->curr->info->value = l->def->base->values;
if (env->class_def) set_vflag(l->def->base->func->value_ref, vflag_member);
+ exp->func->type = l->def->base->func->value_ref->type;
+ if (!l->def->base->ret_type)
+ l->def->base->ret_type = env->gwion->type[et_void];
}
- exp->func->type = l->def->base->func->value_ref->type;
- if (!l->def->base->ret_type)
- l->def->base->ret_type = env->gwion->type[et_void];
return ret > 0 ? l->def->base->ret_type : NULL;
}
if (ret > 0) {
set_fflag(fdef->base->func, fflag_valid);
if (env->class_def && fdef->base->effects.ptr &&
- !check_effect_overload(&fdef->base->effects, override->d.func_ref))
+ (override &&
+ !check_effect_overload(&fdef->base->effects, override->d.func_ref)))
ERR_B(fdef->base->pos, _("too much effects in override."),
s_name(fdef->base->xid))
}
UNSET_FLAG(list->td, late);
}
var->value = arg_value(env, list);
- nspc_add_value(env->curr, var->xid, var->value);
+ if (var->xid) nspc_add_value(env->curr, var->xid, var->value);
} while ((list = list->next));
return GW_OK;
}
ANN static Type scan1_noret(const Env env, const Func_Base *base) {
+ assert(base->td);
DECL_OO(const Type, t, = known_type(env, base->td));
if (!tflag(t, tflag_noret)) return t;
ERR_O(base->pos, _("Can't use type `{+G}%s{0}` for return"), t->name);
}
ANN static m_bool class_internal(const Env env, const Func_Base *base) {
+ assert(base->td);
if (!env->class_def)
ERR_B(base->td->pos, _("'%s' must be in class def!!"), s_name(base->xid))
if (base->args)
ANN static inline m_bool scan_internal_arg(const Env env,
const Func_Base *base) {
if (base->args && !base->args->next) return GW_OK;
+ assert(base->td);
ERR_B(base->td->pos, _("'%s' must have one (and only one) argument"),
s_name(base->xid))
}
ANN static inline m_bool scan_internal_int(const Env env,
const Func_Base *base) {
+ assert(base->td);
CHECK_BB(scan_internal_arg(env, base));
if (isa(base->ret_type, env->gwion->type[et_int]) > 0) return GW_OK;
ERR_B(base->td->pos, _("'%s' must return 'int'"), s_name(base->xid))
}
ANN static bool unwind(VM_Shred shred, const Symbol effect, const m_uint size) {
+ const VM_Code code = shred->code;
+ if (code->live_values.ptr) {
+ const uint16_t pc = shred->pc;
+ for (m_uint i = 0; i < m_vector_size(&code->live_values); i++) {
+ VMValue *vmval = (VMValue *)m_vector_addr(&code->live_values, i);
+ if (pc < vmval->start) break;
+ if (pc > vmval->end) continue;
+ m_bit *const data = &*(m_bit *)(shred->mem + vmval->offset);
+ compound_release(shred, vmval->t, data);
+ }
+ }
if (!size) return true;
- if (shred->code->handlers.ptr) {
+ if (code->handlers.ptr) {
const m_uint start = VKEY(&shred->info->frame, size - 1);
if (start > shred->pc) return true;
- const Map m = &shred->code->handlers;
+ const Map m = &code->handlers;
m_uint pc = 0;
for (m_uint i = 0; i < map_size(m); i++) {
if (start > shred->pc) break;
if (start < shred->pc && VKEY(m, i) > shred->pc) {
const m_uint next = VKEY(m, i);
- const Instr instr = (Instr)vector_at(&shred->code->instr, next + 1);
+ const Instr instr = (Instr)vector_at(&code->instr, next + 1);
if (!instr->m_val2 || (Symbol)instr->m_val2 == effect) {
pc = next + 1;
break;
vm_shred_exit(shred);
}
-void vm_remove(const VM *vm, const m_uint index) {
+ANN bool vm_remove(const VM *vm, const m_uint index) {
const Vector v = (Vector)&vm->shreduler->shreds;
LOOP_OPTIM
for (m_uint i = vector_size(v) + 1; --i;) {
const VM_Shred sh = (VM_Shred)vector_at(v, i - 1);
- if (sh && sh->tick->xid == index) handle(sh, "MsgRemove");
+ if (sh && sh->tick->xid == index) {
+ handle(sh, "MsgRemove");
+ return true;
+ }
}
+ return false;
}
ANN void free_vm(VM *vm) {
free_code_instr(&a->instr, gwion);
}
if (a->handlers.ptr) map_release(&a->handlers);
+ if (a->live_values.ptr) m_vector_release(&a->live_values);
vector_release(&a->instr);
}
free_mstr(gwion->mp, a->name);
return final;
}
-VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth,
- const int builtin, const m_str name) {
+VM_Code new_vmcode(MemPool p, const Vector instr, const M_Vector live_values,
+ const m_str name, const uint16_t stack_depth,
+ const bool builtin) {
VM_Code code = mp_calloc(p, VM_Code);
code->name = mstrdup(p, name);
if (instr) {
vector_copy2(instr, &code->instr);
code->bytecode = tobytecode(p, code);
}
+ if (live_values) code->live_values.ptr = live_values->ptr;
code->stack_depth = stack_depth;
code->builtin = builtin;
code->ref = 1;
VM_Code vmcode_callback(MemPool mp, VM_Code base) {
char name[strlen(base->name) + 11];
sprintf(name, "%s(callback)", base->name);
- const Instr instr = (Instr)vector_back(&base->instr);
- instr->opcode = eEOC;
- const VM_Code code =
- new_vmcode(mp, &base->instr, base->stack_depth, base->builtin, name);
- code->closure = base->closure;
- code->callback = 1;
- instr->opcode = eFuncReturn;
+ const Instr instr = (Instr)vector_back(&base->instr);
+ instr->opcode = eEOC;
+ const VM_Code code = new_vmcode(mp, &base->instr, &base->live_values, name,
+ base->stack_depth, base->builtin);
+ code->closure = base->closure;
+ code->callback = 1;
+ instr->opcode = eFuncReturn;
return code;
}
-Subproject commit 7364841ef46d456037eec97cdcb3ff3abb41289d
+Subproject commit f194f41413c7591d952e1abb399f60ca1da0715c