// mark closure static inline void _gc_mark_closure(struct a2_gc* gc_p, struct a2_gcobj* gcobj, enum gc_mark m){ assert(gcobj->type == A2_TCLOSURE); if(mask(gcobj->mark) == mask(m)) return; gcobj->mark = m; size_t i; struct a2_closure* cls = a2_gcobj2closure(gcobj); // mark upvalue for(i=0; i<cls->uv_size; i++){ if(cls->uv_chain[i].type == uv_gc){ cls->uv_chain[i].v.uv_obj->mark = m; assert(cls->uv_chain[i].v.uv_obj->type == _A2_TUPVALUE); a2_gc_markit(gc_p, cls->uv_chain[i].v.uv_obj->value.uv, m); } } // mark const varable for(i=0; i<cls->xcls_p->c_stack.top; i++){ if(obj_t(&(cls->xcls_p->c_stack.stk_p[i])) == A2_TSTRING){ obj_vX(&(cls->xcls_p->c_stack.stk_p[i]), obj)->mark = m; } } }
// mark and clear gc void a2_vm_gc(struct a2_vm* vm_p){ if(curr_ci==NULL) goto STACK_FRAME_END; struct vm_callinfo* cip = curr_ci; while(!ci_iscls(cip)){ cip = cip->next; if(cip==NULL) goto STACK_FRAME_END; } size_t i, end; struct a2_obj* obj = NULL; switch(ci_op(cip)){ case NEWLIST: case NEWMAP: case CAT: case CLOSURE: end = ir_ga(ci_ir(cip))+cip->reg_stack.sf_idx; break; case RETURN: end = ir_ga(ci_ir(cip)) + ir_gbx(ci_ir(cip)) + cip->reg_stack.sf_idx; break; default: assert(cip->pc>0); ir per_ir = a2_closure_ir(cip->cls, cip->pc-1); assert(ir_gop(per_ir) == CALL); end = ir_ga(per_ir)+ir_gb(per_ir)+cip->reg_stack.sf_idx + 1; break; } assert(end <= vm_p->stack_frame.cap); // mark the stack frame for(i=0; i<end; i++){ obj = &(vm_p->stack_frame.sf_p[i]); a2_gc_markit(a2_envgc(vm_p->env_p), obj, mark_black); } STACK_FRAME_END: #ifdef _DEBUG_ printf("\n---gc mark----\n"); dump_gc(a2_envgc(vm_p->env_p)); #endif // clear a2_gc_clear(a2_envgc(vm_p->env_p)); #ifdef _DEBUG_ printf("----gc clear-----\n"); dump_gc(a2_envgc(vm_p->env_p)); #endif }
// mark array static inline void _gc_mark_array(struct a2_gc* gc_p, struct a2_gcobj* gcobj, enum gc_mark m){ assert(gcobj->type == A2_TARRAY); if(mask(gcobj->mark) == mask(m)) return; gcobj->mark = m; struct a2_obj k = a2_nil2obj(); struct a2_obj* vp = NULL; struct a2_array* array_p = a2_gcobj2array(gcobj); while(NULL != (vp=a2_array_next(array_p, &k))){ a2_gc_markit(gc_p, vp, m); } }
// mark map static inline void _gc_mark_map(struct a2_gc* gc_p, struct a2_gcobj* gcobj, enum gc_mark m){ assert(gcobj->type == A2_TMAP); if(mask(gcobj->mark) == mask(m)) return; gcobj->mark = m; struct a2_obj k = a2_nil2obj(); struct a2_obj* vp = NULL; struct a2_map* map_p = a2_gcobj2map(gcobj); while(NULL != (vp = a2_map_next(map_p, &k))){ if(obj_t(&k)==A2_TSTRING){ gcobj->mark = m; } a2_gc_markit(gc_p, vp, m); } }