FAKE_API void fkresumeps(fake * fk, bool & isend) { FKLOG("fkresumeps %p", fk); isend = false; // 上次的processor pool<processor>::node * n = 0; GET_CUR_PROCESSOR(n, fk->rn); if (UNLIKE(!n)) { variant * ret = 0; bool err = false; PS_PUSH_AND_GET(fk->ps, ret); *ret = NILV; FKLOG("fkresumeps %p no processor", fk); CHECK_ERR(err); return; } // 先pop防止重入 POP_CUR_PROCESSOR(fk->rn); processor & pro = n->t; pro.run(); if (LIKE(!PROCESS_END(pro))) { // 重新塞入 PUSH_CUR_PROCESSOR(n, fk->rn); variant * ret = 0; bool err = false; PS_PUSH_AND_GET(fk->ps, ret); *ret = NILV; FKLOG("fkresumeps %p not end", fk); CHECK_ERR(err); return; } // 结束了 variant * ret = 0; bool err = false; PS_PUSH_AND_GET(fk->ps, ret); *ret = ROUTINE_GETRET(*pro.m_entryroutine); CHECK_ERR(err); POOL_PUSH(fk->pp, n); fk->rn.rundeps--; isend = true; FKLOG("fkresumeps %p OK", fk); }
// 调用函数 FAKE_API void fkrunps(fake * fk, const char * func) { FKLOG("fkrunps %p %s", fk, func); fk->rn.rundeps++; // 清空运行环境 fk->clearerr(); // 分配个 pool<processor>::node * n = 0; if (UNLIKE(POOL_EMPTY(fk->pp))) { POOL_GROW(fk->pp, pool<processor>::node, n); PROCESS_INI(n->t, fk); } POOL_POP(fk->pp, n); assert(ARRAY_EMPTY(n->t.m_pl.l)); assert(n->t.m_routine_num == 0); processor & pro = n->t; PROCESS_CLEAR(pro); variant funcv; V_SET_STRING(&funcv, func); routine * r = pro.start_routine(funcv, 0, 0); PUSH_CUR_PROCESSOR(n, fk->rn); // 单独执行,下次再跑run if (UNLIKE(fk->rn.stepmod)) { variant * ret = 0; bool err = false; PS_PUSH_AND_GET(fk->ps, ret); *ret = NILV; FKLOG("fkrunps %p %s yield", fk, func); CHECK_ERR(err); return; } pro.run(); POP_CUR_PROCESSOR(fk->rn); variant * ret = 0; bool err = false; PS_PUSH_AND_GET(fk->ps, ret); *ret = ROUTINE_GETRET(*r); CHECK_ERR(err); POOL_PUSH(fk->pp, n); fk->rn.rundeps--; FKLOG("fkrunps %p %s OK", fk, func); }
FAKE_API void fkpspushuint64(fake * fk, uint64_t ret) { bool err = false; variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); V_SET_UUID(v, ret); CHECK_ERR(err); }
FAKE_API void fkpspushbool(fake * fk, bool ret) { bool err = false; variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); V_SET_REAL(v, ret); CHECK_ERR(err); }
FAKE_API void fkpspushccharptr(fake * fk, const char * ret) { bool err = false; variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); V_SET_STRING(v, ret); CHECK_ERR(err); }
// map void buildin_map(fake * fk, interpreter * inter) { bool err = false; variant_map * m = fk->con.newmap(); variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); V_SET_MAP(v, m); }
// array void buildin_array(fake * fk, interpreter * inter) { bool err = false; variant_array * a = fk->con.newarray(); variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); V_SET_ARRAY(v, a); }
FAKE_API void fkpspushpointer(fake * fk, void * p, const char * type) { bool err = false; variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); if (UNLIKE(p == 0)) { V_SET_NIL(v); } else { V_SET_POINTER(v, p, type); } CHECK_ERR(err); }
// getconst void buildin_getconst(fake * fk, interpreter * inter) { bool err = false; const char * str = fkpspopcstrptr(fk); variant * v = 0; PS_PUSH_AND_GET(fk->ps, v); variant * gcv = fk->pa.get_const_define(str); if (gcv) { *v = *gcv; } else { *v = NILV; } }
int interpreter::run(int cmdnum) { fake * fk = m_fk; bool & err = m_isend; int i = 0; // 栈溢出检查 if (UNLIKE((int)ARRAY_MAX_SIZE(m_stack) > m_fk->cfg.stack_max)) { m_isend = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "stack too big %d", ARRAY_MAX_SIZE(m_stack)); return 0; } // 切换检查 if (UNLIKE(m_sleeping)) { if (LIKE(m_yieldtime)) { m_yieldtime--; return 0; } else if (LIKE(fkgetmstick() < m_wakeuptime)) { return 0; } else { m_wakeuptime = 0; } } if (UNLIKE(m_isend)) { return 0; } while (1) { // 当前函数走完 if (UNLIKE(m_ip >= (int)FUNC_BINARY_CMDSIZE(*m_fb))) { FKLOG("pop stack %s", FUNC_BINARY_NAME(*m_fb)); // 记录profile if (UNLIKE(m_fk->pf.isopen())) { uint32_t calltime = 0; BP_GET_CALLTIME(m_bp, calltime); m_fk->pf.add_func_sample(FUNC_BINARY_NAME(*m_fb), fkgetmstick() - calltime); } // 标记 FUNC_BINARY_USE(*m_fb)--; // 更新 if (UNLIKE(!FUNC_BINARY_USE(*m_fb) && FUNC_BINARY_BACKUP(*m_fb))) { FUNC_BINARY_BACKUP_MOVE(*m_fb); } // 出栈 int oldretnum = 0; BP_GET_RETNUM(m_bp, oldretnum); int callbp = 0; BP_GET_BP(m_bp, callbp); BP_GET_FB(m_bp, m_fb); BP_GET_IP(m_bp, m_ip); int oldbp = m_bp; m_sp = m_bp - BP_SIZE - oldretnum; m_bp = callbp; // 所有都完 if (UNLIKE(BP_END(m_bp))) { FKLOG("stack empty end"); m_isend = true; break; } // 塞返回值 else { for (int i = 0; i < oldretnum; i++) { int oldretpos = 0; BP_GET_RETPOS(oldbp, oldretnum, oldretpos, i); variant * ret; GET_VARIANT(*m_fb, m_bp, ret, oldretpos); *ret = m_ret[i]; } } continue; } int code = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); FKLOG("next %d %d %s", COMMAND_TYPE(GET_CMD(*m_fb, m_ip)), code, OpCodeStr(code)); assert (COMMAND_TYPE(GET_CMD(*m_fb, m_ip)) == COMMAND_OPCODE); m_ip++; if (UNLIKE(m_fk->pf.isopen())) { m_fk->pf.add_code_sample(code); } // 执行对应命令,放一起switch效率更高,cpu有缓存 switch (code) { case OPCODE_ASSIGN: { // 赋值dest,必须为栈上或容器内 if (UNLIKE(!(CHECK_STACK_POS(*m_fb, m_ip) || CHECK_CONTAINER_POS(*m_fb, m_ip)))) { err = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter assign error, dest is not stack or container, type %s", POS_TYPE_NAME(*m_fb, m_ip)); break; } variant * varv = 0; LOG_VARIANT(*m_fb, m_ip, "var"); GET_VARIANT(*m_fb, m_bp, varv, m_ip); m_ip++; // 赋值来源 const variant * valuev = 0; LOG_VARIANT(*m_fb, m_ip, "value"); GET_VARIANT(*m_fb, m_bp, valuev, m_ip); m_ip++; // 赋值 *varv = *valuev; FKLOG("assign %s to %s", (vartostring(valuev)).c_str(), (vartostring(varv)).c_str()); } break; case OPCODE_PLUS: { MATH_OPER(*m_fb, m_bp, m_ip, PLUS); } break; case OPCODE_MINUS: { MATH_OPER(*m_fb, m_bp, m_ip, MINUS); } break; case OPCODE_MULTIPLY: { MATH_OPER(*m_fb, m_bp, m_ip, MULTIPLY); } break; case OPCODE_DIVIDE: { MATH_OPER(*m_fb, m_bp, m_ip, DIVIDE); } break; case OPCODE_DIVIDE_MOD: { MATH_OPER(*m_fb, m_bp, m_ip, DIVIDE_MOD); } break; case OPCODE_AND: { MATH_OPER(*m_fb, m_bp, m_ip, AND); } break; case OPCODE_OR: { MATH_OPER(*m_fb, m_bp, m_ip, OR); } break; case OPCODE_LESS: { MATH_OPER(*m_fb, m_bp, m_ip, LESS); } break; case OPCODE_MORE: { MATH_OPER(*m_fb, m_bp, m_ip, MORE); } break; case OPCODE_EQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, EQUAL); } break; case OPCODE_MOREEQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, MOREEQUAL); } break; case OPCODE_LESSEQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, LESSEQUAL); } break; case OPCODE_NOTEQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, NOTEQUAL); } break; case OPCODE_NOT: { MATH_SINGLE_OPER(*m_fb, m_bp, m_ip, NOT); } break; case OPCODE_AND_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, AND_JNE); } break; case OPCODE_OR_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, OR_JNE); } break; case OPCODE_LESS_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, LESS_JNE); } break; case OPCODE_MORE_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, MORE_JNE); } break; case OPCODE_EQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, EQUAL_JNE); } break; case OPCODE_MOREEQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, MOREEQUAL_JNE); } break; case OPCODE_LESSEQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, LESSEQUAL_JNE); } break; case OPCODE_NOTEQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, NOTEQUAL_JNE); } break; case OPCODE_NOT_JNE: { MATH_SINGLE_OPER_JNE(*m_fb, m_bp, m_ip, NOT_JNE); } break; case OPCODE_JNE: { const variant * cmp = 0; LOG_VARIANT(*m_fb, m_ip, "cmp"); GET_VARIANT(*m_fb, m_bp, cmp, m_ip); m_ip++; int ip = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; if (!(V_ISBOOL(cmp))) { FKLOG("jne %d", ip); m_ip = ip; } else { FKLOG("not jne %d", ip); } } break; case OPCODE_JMP: { int ip = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; FKLOG("jmp %d", ip); m_ip = ip; } break; case OPCODE_PLUS_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, PLUS); } break; case OPCODE_MINUS_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, MINUS); } break; case OPCODE_MULTIPLY_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, MULTIPLY); } break; case OPCODE_DIVIDE_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, DIVIDE); } break; case OPCODE_DIVIDE_MOD_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, DIVIDE_MOD); } break; case OPCODE_CALL: { int calltype = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; const variant * callpos = 0; LOG_VARIANT(*m_fb, m_ip, "callpos"); GET_VARIANT(*m_fb, m_bp, callpos, m_ip); m_ip++; int retnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; int retpos[MAX_FAKE_RETURN_NUM]; for (int i = 0; i < retnum; i++) { assert(CHECK_STACK_POS(*m_fb, m_ip)); retpos[i] = m_ip; m_ip++; } int argnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; paramstack & ps = *getps(m_fk); PS_CLEAR(ps); for (int i = 0; i < argnum; i++) { variant * arg = 0; LOG_VARIANT(*m_fb, m_ip, "arg"); GET_VARIANT(*m_fb, m_bp, arg, m_ip); m_ip++; variant * argdest = 0; PS_PUSH_AND_GET(ps, argdest); *argdest = *arg; } if (LIKE(calltype == CALL_NORMAL)) { call(*callpos, retnum, retpos); } else { m_processor->start_routine(*callpos, retnum, retpos); } } break; case OPCODE_RETURN: { int returnnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); if (UNLIKE(!returnnum)) { FKLOG("return empty"); m_ip = (*m_fb).m_size; break; } m_ip++; // 塞给ret for (int i = 0; i < returnnum; i++) { const variant * ret = 0; LOG_VARIANT(*m_fb, m_ip, "ret"); GET_VARIANT(*m_fb, m_bp, ret, m_ip); m_ip++; m_ret[i] = *ret; FKLOG("return %s", (vartostring(&m_ret[i])).c_str()); } m_ip = (*m_fb).m_size; } break; case OPCODE_FORBEGIN: { // 赋值dest,必须为栈上或容器内 if (UNLIKE(!(CHECK_STACK_POS(*m_fb, m_ip) || CHECK_CONTAINER_POS(*m_fb, m_ip)))) { err = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter assign error, dest is not stack or container, type %s", POS_TYPE_NAME(*m_fb, m_ip)); break; } // var variant * varv = 0; LOG_VARIANT(*m_fb, m_ip, "var"); GET_VARIANT(*m_fb, m_bp, varv, m_ip); m_ip++; // begin const variant * beginv = 0; LOG_VARIANT(*m_fb, m_ip, "begin"); GET_VARIANT(*m_fb, m_bp, beginv, m_ip); m_ip++; // end const variant * endv = 0; LOG_VARIANT(*m_fb, m_ip, "endv"); GET_VARIANT(*m_fb, m_bp, endv, m_ip); m_ip++; // add const variant * addv = 0; LOG_VARIANT(*m_fb, m_ip, "addv"); GET_VARIANT(*m_fb, m_bp, addv, m_ip); m_ip++; int jneip = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; // 赋值 *varv = *beginv; // 增长 if (LIKE(addv->data.real > 0)) { // 判断是否超出 if (UNLIKE(varv->data.real >= endv->data.real)) { m_ip = jneip; } } else { // 判断是否小 if (UNLIKE(varv->data.real <= endv->data.real)) { m_ip = jneip; } } } break; case OPCODE_FORLOOP: { // var variant * varv = 0; LOG_VARIANT(*m_fb, m_ip, "var"); GET_VARIANT(*m_fb, m_bp, varv, m_ip); m_ip++; // end const variant * endv = 0; LOG_VARIANT(*m_fb, m_ip, "endv"); GET_VARIANT(*m_fb, m_bp, endv, m_ip); m_ip++; // add const variant * addv = 0; LOG_VARIANT(*m_fb, m_ip, "addv"); GET_VARIANT(*m_fb, m_bp, addv, m_ip); m_ip++; int continueip = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; // 赋值 V_PLUS(varv, varv, addv); // 增长 if (LIKE(addv->data.real > 0)) { // 判断是否超出 if (UNLIKE(varv->data.real < endv->data.real)) { m_ip = continueip; } } else { // 判断是否小 if (UNLIKE(varv->data.real > endv->data.real)) { m_ip = continueip; } } } break; case OPCODE_SLEEP: { const variant * time = 0; LOG_VARIANT(*m_fb, m_ip, "time"); GET_VARIANT(*m_fb, m_bp, time, m_ip); m_ip++; uint32_t sleeptime = 0; V_GET_REAL(time, sleeptime); m_wakeuptime = fkgetmstick() + sleeptime; m_sleeping = true; return i + 1; } break; case OPCODE_YIELD: { const variant * time = 0; LOG_VARIANT(*m_fb, m_ip, "time"); GET_VARIANT(*m_fb, m_bp, time, m_ip); m_ip++; V_GET_REAL(time, m_yieldtime); m_sleeping = true; return i + 1; } break; default: assert(0); FKERR("next err code %d %s", code, OpCodeStr(code)); break; } if (UNLIKE(err)) { // 发生错误 m_isend = true; } if (UNLIKE(m_isend)) { break; } i++; if (UNLIKE(i >= cmdnum)) { break; } } return i; }
// range void buildin_range(fake * fk, interpreter * inter) { BIF_CHECK_ARG_NUM(2); // pos int pos = fkpspop<int>(fk); // container bool err = false; variant * v = 0; PS_POP_AND_GET(fk->ps, v); if (v->type == variant::STRING) { if (pos >= 0 && pos < (int)v->data.str->sz) { char data[2]; data[0] = v->data.str->s[pos]; data[1] = 0; fkpspush<const char *>(fk, data); } else { fkpspush<const char *>(fk, ""); } } else if (v->type == variant::ARRAY) { if (pos >= 0 && pos < (int)ARRAY_SIZE(v->data.va->va) && ARRAY_GET(v->data.va->va, pos)) { variant * ret = 0; PS_PUSH_AND_GET(fk->ps, ret); if (ARRAY_GET(v->data.va->va, pos)) { *ret = *(ARRAY_GET(v->data.va->va, pos)); } else { *ret = NILV; } } else { fkpspush<bool>(fk, false); } } else if (v->type == variant::MAP) { if (pos >= 0 && pos < (int)v->data.vm->vm.size()) { variant * key = 0; PS_PUSH_AND_GET(fk->ps, key); variant * value = 0; PS_PUSH_AND_GET(fk->ps, value); const fkhashmap<variant, variant *>::ele * e = v->data.vm->vm.at(pos); *key = e->k; *value = *(*e->t); } else { fkpspush<bool>(fk, false); fkpspush<bool>(fk, false); } } else { fkpspush<bool>(fk, false); } }
int interpreter::run(int cmdnum) { fake * fk = m_fk; bool & err = m_isend; int i = 0; // 栈溢出检查 if (UNLIKE((int)ARRAY_MAX_SIZE(m_stack) > m_fk->cfg.stack_max)) { m_isend = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "stack too big %d", ARRAY_MAX_SIZE(m_stack)); return 0; } // 切换检查 if (UNLIKE(m_sleeping)) { if (LIKE(m_yieldtime)) { m_yieldtime--; return 0; } else if (LIKE(fkgetmstick() < m_wakeuptime)) { return 0; } else { m_wakeuptime = 0; } } if (UNLIKE(m_isend)) { return 0; } while (1) { // 当前函数走完 if (UNLIKE(m_ip >= (int)FUNC_BINARY_CMDSIZE(*m_fb))) { FKLOG("pop stack %s", FUNC_BINARY_NAME(*m_fb)); // 记录profile if (UNLIKE(m_fk->pf.isopen())) { uint32_t calltime = 0; BP_GET_CALLTIME(m_bp, calltime); m_fk->pf.add_func_sample(FUNC_BINARY_NAME(*m_fb), fkgetmstick() - calltime); } // 标记 FUNC_BINARY_USE(*m_fb)--; // 更新 if (UNLIKE(!FUNC_BINARY_USE(*m_fb) && FUNC_BINARY_BACKUP(*m_fb))) { FUNC_BINARY_BACKUP_MOVE(*m_fb); } // 出栈 int oldretnum = 0; BP_GET_RETNUM(m_bp, oldretnum); int callbp = 0; BP_GET_BP(m_bp, callbp); BP_GET_FB(m_bp, m_fb); BP_GET_IP(m_bp, m_ip); int oldbp = m_bp; m_sp = m_bp - BP_SIZE - oldretnum; m_bp = callbp; // 所有都完 if (UNLIKE(BP_END(m_bp))) { FKLOG("stack empty end"); m_isend = true; break; } // 塞返回值 else { for (int i = 0; i < oldretnum; i++) { int oldretpos = 0; BP_GET_RETPOS(oldbp, oldretnum, oldretpos, i); variant * ret; GET_VARIANT(*m_fb, m_bp, ret, oldretpos); *ret = m_ret[i]; } } continue; } int code = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); FKLOG("next %d %d %s", COMMAND_TYPE(GET_CMD(*m_fb, m_ip)), code, OpCodeStr(code)); assert (COMMAND_TYPE(GET_CMD(*m_fb, m_ip)) == COMMAND_OPCODE); m_ip++; if (UNLIKE(m_fk->pf.isopen())) { m_fk->pf.add_code_sample(code); } // 执行对应命令,放一起switch效率更高,cpu有缓存 switch (code) { case OPCODE_ASSIGN: { // 赋值dest,必须为栈上或容器内 if (UNLIKE(!(CHECK_STACK_POS(*m_fb, m_ip) || CHECK_CONTAINER_POS(*m_fb, m_ip)))) { err = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter assign error, dest is not stack or container, type %s", POS_TYPE_NAME(*m_fb, m_ip)); break; } variant * varv = 0; LOG_VARIANT(*m_fb, m_ip, "var"); GET_VARIANT(*m_fb, m_bp, varv, m_ip); if (UNLIKE(CHECK_CONST_MAP_POS(varv) || CHECK_CONST_ARRAY_POS(varv))) { err = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter assign error, dest is const container"); break; } m_ip++; // 赋值来源 const variant * valuev = 0; LOG_VARIANT(*m_fb, m_ip, "value"); GET_VARIANT(*m_fb, m_bp, valuev, m_ip); m_ip++; // 赋值 *varv = *valuev; FKLOG("assign %s to %s", (vartostring(valuev)).c_str(), (vartostring(varv)).c_str()); } break; case OPCODE_PLUS: { MATH_OPER(*m_fb, m_bp, m_ip, PLUS); } break; case OPCODE_MINUS: { MATH_OPER(*m_fb, m_bp, m_ip, MINUS); } break; case OPCODE_MULTIPLY: { MATH_OPER(*m_fb, m_bp, m_ip, MULTIPLY); } break; case OPCODE_DIVIDE: { MATH_OPER(*m_fb, m_bp, m_ip, DIVIDE); } break; case OPCODE_DIVIDE_MOD: { MATH_OPER(*m_fb, m_bp, m_ip, DIVIDE_MOD); } break; case OPCODE_STRING_CAT: { MATH_OPER(*m_fb, m_bp, m_ip, STRING_CAT); } break; case OPCODE_AND: { MATH_OPER(*m_fb, m_bp, m_ip, AND); } break; case OPCODE_OR: { MATH_OPER(*m_fb, m_bp, m_ip, OR); } break; case OPCODE_LESS: { MATH_OPER(*m_fb, m_bp, m_ip, LESS); } break; case OPCODE_MORE: { MATH_OPER(*m_fb, m_bp, m_ip, MORE); } break; case OPCODE_EQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, EQUAL); } break; case OPCODE_MOREEQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, MOREEQUAL); } break; case OPCODE_LESSEQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, LESSEQUAL); } break; case OPCODE_NOTEQUAL: { MATH_OPER(*m_fb, m_bp, m_ip, NOTEQUAL); } break; case OPCODE_NOT: { MATH_SINGLE_OPER(*m_fb, m_bp, m_ip, NOT); } break; case OPCODE_AND_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, AND_JNE); } break; case OPCODE_OR_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, OR_JNE); } break; case OPCODE_LESS_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, LESS_JNE); } break; case OPCODE_MORE_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, MORE_JNE); } break; case OPCODE_EQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, EQUAL_JNE); } break; case OPCODE_MOREEQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, MOREEQUAL_JNE); } break; case OPCODE_LESSEQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, LESSEQUAL_JNE); } break; case OPCODE_NOTEQUAL_JNE: { MATH_OPER_JNE(*m_fb, m_bp, m_ip, NOTEQUAL_JNE); } break; case OPCODE_NOT_JNE: { MATH_SINGLE_OPER_JNE(*m_fb, m_bp, m_ip, NOT_JNE); } break; case OPCODE_JNE: { const variant * cmp = 0; LOG_VARIANT(*m_fb, m_ip, "cmp"); GET_VARIANT(*m_fb, m_bp, cmp, m_ip); m_ip++; int ip = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; if (!(V_ISBOOL(cmp))) { FKLOG("jne %d", ip); m_ip = ip; } else { FKLOG("not jne %d", ip); } } break; case OPCODE_JMP: { int ip = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; FKLOG("jmp %d", ip); m_ip = ip; } break; case OPCODE_PLUS_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, PLUS); } break; case OPCODE_MINUS_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, MINUS); } break; case OPCODE_MULTIPLY_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, MULTIPLY); } break; case OPCODE_DIVIDE_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, DIVIDE); } break; case OPCODE_DIVIDE_MOD_ASSIGN: { MATH_ASSIGN_OPER(*m_fb, m_bp, m_ip, DIVIDE_MOD); } break; case OPCODE_CALL: { int calltype = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; const variant * callpos = 0; LOG_VARIANT(*m_fb, m_ip, "callpos"); GET_VARIANT(*m_fb, m_bp, callpos, m_ip); m_ip++; int retnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; int retpos[MAX_FAKE_RETURN_NUM]; for (int i = 0; i < retnum; i++) { assert(CHECK_STACK_POS(*m_fb, m_ip) || CHECK_CONTAINER_POS(*m_fb, m_ip)); retpos[i] = m_ip; m_ip++; } int argnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); m_ip++; paramstack & ps = *getps(m_fk); PS_CLEAR(ps); for (int i = 0; i < argnum; i++) { variant * arg = 0; LOG_VARIANT(*m_fb, m_ip, "arg"); GET_VARIANT(*m_fb, m_bp, arg, m_ip); m_ip++; variant * argdest = 0; PS_PUSH_AND_GET(ps, argdest); *argdest = *arg; } if (LIKE(calltype == CALL_NORMAL)) { call(*callpos, retnum, retpos); } else if (LIKE(calltype == CALL_CLASSMEM)) { void * classptr = 0; const char * classprefix = 0; // prefix variant * classvar; PS_GET(ps, classvar, PS_SIZE(ps) - 1); V_GET_POINTER(classvar, classptr, classprefix); if (UNLIKE(err)) { break; } // mem func name const char * funcname = 0; V_GET_STRING(callpos, funcname); if (UNLIKE(err)) { break; } if (UNLIKE(!classptr)) { err = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter class mem call error, the class ptr is null, type %s", classprefix); break; } // whole name char wholename[MAX_FAKE_REG_FUNC_NAME_LEN]; if (UNLIKE(classvar->data.ponter->typesz + callpos->data.str->sz >= MAX_FAKE_REG_FUNC_NAME_LEN)) { err = true; seterror(fk, efk_run_inter_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "interpreter class mem call error, the name is too long, func %s %s", classprefix, funcname); break; } memcpy(wholename, classprefix, classvar->data.ponter->typesz); memcpy(wholename + classvar->data.ponter->typesz, funcname, callpos->data.str->sz); wholename[classvar->data.ponter->typesz + callpos->data.str->sz] = 0; // call it variant tmp; V_SET_STRING(&tmp, wholename); call(tmp, retnum, retpos); } else { m_processor->start_routine(*callpos, retnum, retpos); } } break; case OPCODE_RETURN: { int returnnum = COMMAND_CODE(GET_CMD(*m_fb, m_ip)); if (UNLIKE(!returnnum)) { FKLOG("return empty"); m_ip = (*m_fb).m_size; break; } m_ip++; // 塞给ret for (int i = 0; i < returnnum; i++) { const variant * ret = 0; LOG_VARIANT(*m_fb, m_ip, "ret"); GET_VARIANT(*m_fb, m_bp, ret, m_ip); m_ip++; m_ret[i] = *ret; FKLOG("return %s", (vartostring(&m_ret[i])).c_str()); } m_ip = (*m_fb).m_size; } break; case OPCODE_SLEEP: { const variant * time = 0; LOG_VARIANT(*m_fb, m_ip, "time"); GET_VARIANT(*m_fb, m_bp, time, m_ip); m_ip++; uint32_t sleeptime = 0; V_GET_REAL(time, sleeptime); m_wakeuptime = fkgetmstick() + sleeptime; m_sleeping = true; return i + 1; } break; case OPCODE_YIELD: { const variant * time = 0; LOG_VARIANT(*m_fb, m_ip, "time"); GET_VARIANT(*m_fb, m_bp, time, m_ip); m_ip++; V_GET_REAL(time, m_yieldtime); m_sleeping = true; return i + 1; } break; default: assert(0); FKERR("next err code %d %s", code, OpCodeStr(code)); break; } if (UNLIKE(err)) { // 发生错误 m_isend = true; // 清除当前栈上函数的使用标记 { int ip = m_ip; int bp = m_bp; const func_binary * fb = m_fb; while (!BP_END(bp)) { // 标记 FUNC_BINARY_USE(*fb)--; // 更新 if (UNLIKE(!FUNC_BINARY_USE(*fb) && FUNC_BINARY_BACKUP(*fb))) { FUNC_BINARY_BACKUP_MOVE(*fb); } BP_GET_FB(bp, fb); BP_GET_IP(bp, ip); int callbp = 0; BP_GET_BP(bp, callbp); bp = callbp; if (BP_END(bp)) { break; } } } } if (UNLIKE(m_isend)) { break; } i++; if (UNLIKE(i >= cmdnum)) { break; } } return i; }
void debuging::debug() { fake * fk = m_fk; bool isend = false; int range = 0; int command = debug_next; std::vector<String> paramvec; const char * lastfunc = 0; breakpoint_list blist; int bindex = 0; int frame = 0; int lastrid = fkgetcurroutineid(fk); int rid = lastrid; std::vector<String> watchvec; bool firsttime = true; while (1) { show_watch_variant(fk, rid, frame, watchvec); check_show_func_header(fk, rid, frame, lastrid, lastfunc); show_debug_code(fk, rid, frame, range); FAKEINPUT: get_debug_command(fk, command, paramvec); switch (command) { case debug_next: { frame = 0; rid = fkgetcurroutineid(fk); if (firsttime) { if (check_trigger_breakpoint(fk, blist)) { firsttime = false; break; } } firsttime = false; const char * lastfile = fkgetcurfile(fk); int lastline = fkgetcurline(fk); int laststacklength = fkgetcurcallstacklength(fk); int lastrid = rid; const char * curfile = fkgetcurfile(fk); int curline = fkgetcurline(fk); int curstacklength = fkgetcurcallstacklength(fk); int currid = rid; while (currid == lastrid && (curstacklength > laststacklength || (strcmp(lastfile, curfile) == 0 && lastline == curline))) { resume(isend); if (isend) { break; } curfile = fkgetcurfile(fk); curline = fkgetcurline(fk); curstacklength = fkgetcurcallstacklength(fk); currid = fkgetcurroutineid(fk); if (check_trigger_breakpoint(fk, blist)) { break; } } rid = fkgetcurroutineid(fk); } break; case debug_step: { frame = 0; rid = fkgetcurroutineid(fk); if (firsttime) { if (check_trigger_breakpoint(fk, blist)) { firsttime = false; break; } } firsttime = false; const char * lastfile = fkgetcurfile(fk); int lastline = fkgetcurline(fk); int lastrid = rid; const char * curfile = fkgetcurfile(fk); int curline = fkgetcurline(fk); int currid = rid; while (currid == lastrid && (strcmp(lastfile, curfile) == 0 && lastline == curline)) { resume(isend); if (isend) { break; } curfile = fkgetcurfile(fk); curline = fkgetcurline(fk); currid = fkgetcurroutineid(fk); if (check_trigger_breakpoint(fk, blist)) { break; } } rid = fkgetcurroutineid(fk); } break; case debug_next_instruction: { frame = 0; rid = fkgetcurroutineid(fk); if (firsttime) { if (check_trigger_breakpoint(fk, blist)) { firsttime = false; break; } } firsttime = false; int laststacklength = fkgetcurcallstacklength(fk); int lastrid = rid; int curstacklength = fkgetcurcallstacklength(fk); int currid = rid; do { resume(isend); if (isend) { break; } curstacklength = fkgetcurcallstacklength(fk); currid = fkgetcurroutineid(fk); if (check_trigger_breakpoint(fk, blist)) { break; } } while (currid == lastrid && curstacklength > laststacklength); rid = fkgetcurroutineid(fk); } break; case debug_step_instruction: { frame = 0; rid = fkgetcurroutineid(fk); if (firsttime) { if (check_trigger_breakpoint(fk, blist)) { firsttime = false; break; } } firsttime = false; resume(isend); rid = fkgetcurroutineid(fk); if (check_trigger_breakpoint(fk, blist)) { break; } } break; case debug_continue: { frame = 0; rid = fkgetcurroutineid(fk); if (firsttime) { if (check_trigger_breakpoint(fk, blist)) { firsttime = false; break; } } firsttime = false; while (1) { resume(isend); rid = fkgetcurroutineid(fk); if (check_trigger_breakpoint(fk, blist)) { break; } if (isend) { break; } } } break; case debug_breakpoint: { breakpoint tmp; if (paramvec.empty()) { tmp.file = fkgetcurfilebyroutinebyframe(fk, rid, frame); tmp.line = fkgetcurlinebyroutinebyframe(fk, rid, frame); } else { String str = paramvec[0]; int subpos = str.find(':'); if (subpos != -1) { String filestr = str.substr(0, subpos); String linestr = str.substr(subpos + 1); tmp.file = filestr; tmp.line = fkatoi(&linestr); } else { bool isnumber = true; for (int i = 0; i < (int)str.size(); i++) { if (!isdigit(str[i])) { isnumber = false; break; } } if (isnumber) { tmp.file = fkgetcurfilebyroutinebyframe(fk, rid, frame); tmp.line = fkatoi(&str); } else { if (!fkisfunc(fk, str.c_str())) { printf("%s is not func\n", str.c_str()); continue; } tmp.file = fkgetfuncfile(fk, str.c_str()); tmp.line = fkgetfuncstartline(fk, str.c_str()); } } } tmp.enable = true; tmp.id = bindex; if ((int)tmp.file.find_last_of('/') != -1) { tmp.file = tmp.file.substr(tmp.file.find_last_of('/') + 1); } blist.push_back(tmp); bindex++; printf("Breakpoint %d at file %s, line %d total %d\n", tmp.id, tmp.file.c_str(), tmp.line, (int)blist.size()); } break; case debug_enable: { if (paramvec.empty()) { for (int i = 0; i < (int)blist.size(); i++) { breakpoint & tmp = blist[i]; tmp.enable = true; } } else { int id = atoi(paramvec[0].c_str()); for (int i = 0; i < (int)blist.size(); i++) { breakpoint & tmp = blist[i]; if (tmp.id == id) { tmp.enable = true; } } } } break; case debug_disable: { if (paramvec.empty()) { for (int i = 0; i < (int)blist.size(); i++) { breakpoint & tmp = blist[i]; tmp.enable = false; } } else { int id = fkatoi(¶mvec[0]); for (int i = 0; i < (int)blist.size(); i++) { breakpoint & tmp = blist[i]; if (tmp.id == id) { tmp.enable = false; } } } } break; case debug_delete: { if (paramvec.empty()) { blist.clear(); watchvec.clear(); continue; } else { int id = fkatoi(¶mvec[0]); for (int i = 0; i < (int)blist.size(); i++) { breakpoint & tmp = blist[i]; if (tmp.id == id) { blist.erase(blist.begin() + i); } } } } break; case debug_info: { if (paramvec.empty()) { printf("need arg, useage: i b, i r\n"); continue; } if (paramvec[0] == "b") { printf("Id\tEnb\twhere\n"); for (int i = 0; i < (int)blist.size(); i++) { breakpoint & tmp = blist[i]; printf("%d\t%s\tfile %s, line %d\n", tmp.id, tmp.enable ? "y" : "n", tmp.file.c_str(), tmp.line); } } else if (paramvec[0] == "r") { for (int i = 0; i < (int)fkgetcurroutinenum(fk); i++) { printf("%s%s%s\n", fkgetroutineidbyindex(fk, i) == rid ? "*" : "", fkgetroutineidbyindex(fk, i) == fkgetcurroutineid(fk) ? "->" : "", fkgetcurroutinebyindex(fk, i)); } } printf("\n"); } break; case debug_finish: { frame = 0; rid = fkgetcurroutineid(fk); int laststacklength = fkgetcurcallstacklength(fk); int curstacklength = fkgetcurcallstacklength(fk); do { resume(isend); if (isend) { break; } curstacklength = fkgetcurcallstacklength(fk); } while (curstacklength >= laststacklength); } break; case debug_list: { int listrange = 3; if (!paramvec.empty()) { listrange = fkatoi(¶mvec[0]); } show_debug_code(fk, rid, frame, listrange); goto FAKEINPUT; } break; case debug_print: { if (paramvec.empty()) { printf("need arg, useage: p variant\n"); continue; } String name = paramvec[0]; printf("%s\n", fkgetcurvaiantbyroutinebyframe(fk, rid, frame, name.c_str())); } break; case debug_set: { if (paramvec.size() < 2) { printf("need arg, useage: set variant value\n"); continue; } String name = paramvec[0]; String value = paramvec[1]; fksetcurvaiantbyroutinebyframe(fk, rid, frame, name.c_str(), value.c_str()); printf("%s\n", fkgetcurvaiantbyroutinebyframe(fk, rid, frame, name.c_str())); } break; case debug_watch: { if (paramvec.empty()) { printf("need arg, useage: wa variant\n"); continue; } String name = paramvec[0]; watchvec.push_back(name); } break; case debug_backtrace: { int length = fkgetcurcallstacklengthbyroutine(fk, rid); for (int i = 0; i < length; i++) { printf("%s%s\n", i == frame ? "*" : " ", fkgetcurcallstackbyroutinebyframe(fk, rid, i)); } goto FAKEINPUT; } break; case debug_frame: { if (paramvec.empty()) { frame = 0; } else { int theframe = fkatoi(¶mvec[0]); if (theframe < 0 || theframe >= fkgetcurcallstacklengthbyroutine(fk, rid)) { printf("%d is invalid\n", theframe); } frame = theframe; } } break; case debug_disa: { int pos = fkgetcurbytecodeposbyroutine(fk, rid); const char * func = fkgetcurfuncbyroutinebyframe(fk, rid, frame); printf("%s\n", fkdumpfunc(fk, func, pos)); } break; case debug_routine: { if (paramvec.empty()) { printf("need arg, useage: r rid\n"); continue; } int id = fkatoi(¶mvec[0]); if (!fkishaveroutine(fk, id)) { printf("no routine %d\n", id); continue; } rid = id; } break; default: continue; } if (isend) { break; } } printf("end\n"); // ret { fkpsclear(fk); variant * ret = 0; bool err = false; PS_PUSH_AND_GET(fk->ps, ret); *ret = m_ret; CHECK_ERR(err); } }