-Subproject commit 003e72af4ededf99627521dd0f61547ce26edcdb
+Subproject commit de339e926479367591c6dd16f63d331a4aedc797
#define ARRAY(o) (*(M_Vector*) ((M_Object)o)->data)
#define IO_FILE(o) (*(FILE**) (((M_Object)o)->data + SZ_INT))
#define Except(s, c) { exception(s, c); return; }
+
static inline void _release(const restrict M_Object obj, const restrict VM_Shred shred) {
if(!--obj->ref)__release(obj, shred);
}
struct ShredTick_ *list;
struct ShredTick_ *curr;
struct Vector_ shreds;
+ MUTEX_TYPE mutex;
size_t shred_ids;
m_bool loop;
};
size_t xid;
size_t size;
size_t array_depth;
- ae_flag flag;
HAS_OBJ
+ ae_flag flag;
};
Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
}
ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type,
- const Array_Sub array, const uint is_ref) {
+ const Array_Sub arr, const uint is_ref) {
+ Array_Sub array = arr;
if(type->array_depth) {
- assert(array);
+ if(!array) { // from typeof xxx[]...
+ Exp base = new_exp_prim_int(emit->gwion->p, 0, 0), e = base;
+ for(m_uint i = 0; i < type->array_depth; ++i)
+ e = (e->next = new_exp_prim_int(emit->gwion->p, 0, 0));
+ array = new_array_sub(emit->gwion->p, base);
+ }
assert(array->exp);
ArrayInfo* info = emit_array_extend_inner(emit, type, array->exp);
CHECK_OB(info)
info->is_ref = !!is_ref;
+ if(array != arr)
+ free_array_sub(emit->gwion->p, array);
} else if(!is_ref) {
const Instr instr = emit_add_instr(emit, ObjectInstantiate);
instr->m_val2 = (m_uint)type;
assign->m_val = emit_var;
if(is_array && !emit->env->scope->depth)
ADD_REF(type)
- const Instr instr = emit_add_instr(emit, RegAddRef);
- instr->m_val = emit_var;
+ if(isa(type, t_fork) < 0) { // beware fork
+ const Instr instr = emit_add_instr(emit, RegAddRef);
+ instr->m_val = emit_var;
+ }
}
return GW_OK;
}
return GW_OK;
}
-ANN2(1,2) static void emit_exp_spork_finish(const Emitter emit, const VM_Code code,
- const m_uint depth) {
+ANN static void emit_exp_spork_finish(const Emitter emit, const m_uint depth) {
const Instr pop = emit_add_instr(emit, RegPop);
pop->m_val = depth;
const Instr spork = emit_add_instr(emit, SporkFunc);
ini->m_val = (m_uint)code;
ini->m_val2 = is_spork;
if(unary->code) {
+ if(!is_spork) {
+ const Instr push = emit_add_instr(emit, RegPush);
+ push->m_val = SZ_INT;
+ }
const Instr spork = emit_add_instr(emit, is_spork ? SporkExp : ForkEnd);
spork->m_val = emit->code->stack_depth;
} else {
const Func f = unary->exp->d.exp_call.m_func;
const m_uint size = f->def->stack_depth - (GET_FLAG(f, member) && !GET_FLAG(code, member) ? SZ_INT : 0);
- emit_exp_spork_finish(emit, code, size);
+ emit_exp_spork_finish(emit, size);
const Instr end = emit_add_instr(emit, is_spork ? SporkEnd : ForkEnd);
end->m_val2 = f->def->base->ret_type->size;
}
CHECK_BB(exp_func[exp->exp_type](emit, &exp->d))
if(exp->cast_to)
CHECK_BB(emit_implicit_cast(emit, exp->type, exp->cast_to))
- if(ref && isa(exp->type, t_object) > 0) {
+ if(ref && isa(exp->type, t_object) > 0 && isa(exp->type, t_fork) < 0 ) { // beware fork
const Instr instr = emit_add_instr(emit, RegAddRef);
instr->m_val = exp->emit_var;
}
if(stmt->val) {
OPTIMIZE_TCO
CHECK_BB(emit_exp(emit, stmt->val, 0))
- if(isa(stmt->val->type, t_object) > 0)
+ if(isa(stmt->val->type, t_object) > 0 && isa(stmt->val->type , t_fork) < 0) // beware fork
emit_add_instr(emit, RegAddRef);
}
vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
describe_path_and_dir(, s->info->name)
describe_path_and_dir(_code, s->code->name)
-static DTOR(shred_dtor) { free_vm_shred(*(VM_Shred*)o->data); }
+static DTOR(shred_dtor) {
+ VM *vm = ME(o)->info->vm;
+ free_vm_shred(*(VM_Shred*)o->data);
+ if(isa(o->type_ref, t_fork) > 0)
+ free_vm(vm);
+}
+
+static MFUN(shred_lock) {
+ MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
+}
+
+static MFUN(shred_unlock) {
+ MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+}
static DTOR(fork_dtor) {
-// pthread_detach(FORK_THREAD(o));
THREAD_JOIN(FORK_THREAD(o));
mp_free(shred->info->mp, Gwion, ME(o)->info->vm->gwion);
- free_vm(ME(o)->info->vm);
}
static MFUN(fork_join) {
- if(*(m_int*)(o->data + o_fork_done))
+ MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
+ MUTEX_LOCK(shred->tick->shreduler->mutex);
+ if(*(m_int*)(o->data + o_fork_done)) {
+ MUTEX_UNLOCK(shred->tick->shreduler->mutex);
+ MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
return;
+ }
+ MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+ MUTEX_UNLOCK(shred->tick->shreduler->mutex);
shreduler_remove(shred->tick->shreduler, shred, 0);
vector_add(EV_SHREDS(*(M_Object*)(o->data + o_fork_ev)), (vtype)shred);
}
-//static MFUN(shred_cancel) {
-// ++*(m_int*)(o->data + o_shred_cancel);
-//}
+static MFUN(shred_cancel) {
+MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
+ *(m_int*)(o->data + o_shred_cancel) = *(m_int*)MEM(SZ_INT);
+MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
+}
static MFUN(shred_test_cancel) {
+MUTEX_LOCK(ME(o)->tick->shreduler->mutex);
if(*(m_int*)(o->data + o_shred_cancel))
vm_shred_exit(ME(o));
+MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex);
}
void fork_retval(const M_Object o) {
++vm->bbq->pos;
} while(vm->bbq->is_running);
fork_retval(me);
+ MUTEX_LOCK(vm->shreduler->mutex);
*(m_int*)(me->data + o_fork_done) = 1;
broadcast(*(M_Object*)(me->data + o_fork_ev));
- _release(me, ME(me));
+ MUTEX_UNLOCK(vm->shreduler->mutex);
THREAD_RETURN(NULL);
}
CHECK_BB(gwi_item_end(gwi, ae_flag_member, NULL))
gwi_item_ini(gwi, "int", "cancel");
- CHECK_BB((o_shred_cancel = gwi_item_end(gwi, 0, NULL)))
+ CHECK_BB((o_shred_cancel = gwi_item_end(gwi, ae_flag_const, NULL)))
gwi_func_ini(gwi, "void", "exit", gw_shred_exit);
CHECK_BB(gwi_func_end(gwi, 0))
gwi_func_ini(gwi, "string", "code_dir", shred_code_dir);
CHECK_BB(gwi_func_end(gwi, 0))
-// gwi_func_ini(gwi, "void", "cancel", shred_cancel);
-// CHECK_BB(gwi_func_end(gwi, 0))
+ gwi_func_ini(gwi, "void", "set_cancel", shred_cancel);
+ gwi_func_arg(gwi, "int", "n");
+ CHECK_BB(gwi_func_end(gwi, 0))
gwi_func_ini(gwi, "void", "test_cancel", shred_test_cancel);
CHECK_BB(gwi_func_end(gwi, 0))
+ gwi_func_ini(gwi, "void", "lock", shred_lock);
+ CHECK_BB(gwi_func_end(gwi, 0))
+ gwi_func_ini(gwi, "void", "unlock", shred_unlock);
+ CHECK_BB(gwi_func_end(gwi, 0))
CHECK_BB(gwi_class_end(gwi))
gwi_item_ini(gwi, "Shred", "me");
ERR_O(exp_self(decl)->pos, "can't use private type %s", t->name)
if(GET_FLAG(t, protect) && (!env->class_def || isa(t, env->class_def) < 0))
ERR_O(exp_self(decl)->pos, "can't use protected type %s", t->name)
- if(GET_FLAG(decl->td, global) && env->class_def)
- ERR_O(exp_self(decl)->pos, "can't declare variable global inside class.")
+// if(GET_FLAG(decl->td, global) && env->class_def)
+// ERR_O(exp_self(decl)->pos, "can't declare variable global inside class.")
if(env->class_def) {
if(!env->scope->depth) {
if(!env->func && !GET_FLAG(decl->td, static))
}
const ID_List types = id_list_copy(env->gwion->p, base);
ID_List list, tmp = types;
- while((list = (ID_List)vector_pop(v)))
+ for(m_uint i = vector_size(v) + 1; --i;) {
+ list = (ID_List)vector_pop(v);
tmp = (tmp->next = id_list_copy(env->gwion->p, list));
+ }
tmp->next = t->def->tmpl->list.list;
free_vector(env->gwion->p, v);
return types;
Type_List call = tl;
nspc_push_type(env->gwion->p, env->curr);
do {
- const Type t = call ? known_type(env, call->td) : NULL;
+ if(!call)
+ break;
+ const Type t = known_type(env, call->td);
if(!t)
POP_RET(-1);
nspc_add_type(env->curr, base->xid, t);
Driver *bbq = s->bbq;
struct ShredTick_ *tk = s->list;
if(!tk) {
-//printf("here %p %lu\n", s, s->bbq->pos);
if(!vector_size(&s->shreds) && !s->loop)
bbq->is_running = 0;
return NULL;
ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase) {
struct ShredTick_ *tk = out->tick;
assert(tk);
+ MUTEX_LOCK(s->mutex);
if(tk == s->curr)
s->curr = NULL;
else if(tk == s->list)
shreduler_erase(s, tk);
_release(out->info->me, out);
}
+ MUTEX_UNLOCK(s->mutex);
}
ANN void shredule(const Shreduler s, const VM_Shred shred, const m_float wake_time) {
vm->bbq = new_driver(p);
vm->shreduler = (Shreduler)mp_alloc(p, Shreduler);
vector_init(&vm->shreduler->shreds);
+ MUTEX_SETUP(vm->shreduler->mutex);
vm->shreduler->bbq = vm->bbq;
gw_seed(vm->rand, (uint64_t)time(NULL));
return vm;
if(vm->bbq)
free_driver(vm->bbq, vm);
mp_free(vm->gwion->p, Shreduler, vm->shreduler);
+ MUTEX_CLEANUP(vm->shreduler->mutex);
mp_free(vm->gwion->p, VM, vm);
}
struct timespec exec_ini, exec_end, exec_ret;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &exec_ini);
#endif
+ MUTEX_LOCK(s->mutex);
do {
register Instr instr; DISPATCH();
regsetimm:
reg += SZ_FLOAT;
DISPATCH();
regpushmemother:
-// LOOP_OPTIM
- for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) {
- m_uint* m0 = __builtin_assume_aligned((m_bit*)mem+i, SZ_INT);
-//printf("%p\n", m0);
-// m_uint* m = __builtin_assume_aligned((m_bit*)mem+instr->m_val+i, SZ_INT);
- m_uint* r = __builtin_assume_aligned(reg+i, SZ_INT);
-// *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + instr->m_val) + i);
-// *(m_uint*)(r) = *(m_uint*)(m);
- *(m_uint*)(r) = *(m_uint*)(m0+instr->m_val);
- }
+ for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT)
+ *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + instr->m_val) + i);
reg += instr->m_val2;
DISPATCH();
-regpushmemaddr: {
-m_bit* r0 __attribute__((aligned(SZ_INT))) = __builtin_assume_aligned(reg, SZ_INT);
-m_bit* m0 __attribute__((aligned(SZ_INT))) = mem + instr->m_val;
-// m_uint* r __attribute__((aligned(SZ_INT))) = r0;//__builtin_assume_aligned(reg, SZ_INT);
-// *(m_bit**)reg = __builtin_assume_aligned(mem + instr->m_val, SZ_INT);
- *(void**)r0 = m0;
+regpushmemaddr:
+ *(m_bit**)reg = mem + instr->m_val;
reg += SZ_INT;
- }
DISPATCH()
pushnow:
*(m_float*)reg = vm->bbq->pos;
pc = shred->pc;
DISPATCH()
} while(s->curr);
-//printf("no more curr %p\n", vm->shreduler);
+ MUTEX_UNLOCK(s->mutex);
#ifdef VMBENCH
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &exec_end);
timespecsub(&exec_end, &exec_ini, &exec_ret);
}
if(vector_size(&vm->ugen))
vm_ugen_init(vm);
-}
-//#pragma GCC pop_options
\ No newline at end of file
+}
\ No newline at end of file
-Subproject commit c04fc5e07c3a53554221f7bc6b760fb63e9e2df1
+Subproject commit 00c8b5e8217c2eaa4f3157fbe76191221610b912