Esempio n. 1
0
void interpreter::call(const variant & func, int retnum, int * retpos)
{
	fake * fk = m_fk;
	paramstack * ps = getps(m_fk);
	const funcunion * f = m_fk->fm.get_func(func);
	bool & err = m_isend;
	USE(err);
	if (UNLIKE(!f))
	{
		FKERR("fkrun no func %s fail", vartostring(&func).c_str());
		m_isend = true;
		seterror(m_fk, efk_run_no_func_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "fkrun no func %s fail", vartostring(&func).c_str());
		return;
	}

	// 常规函数
	if (LIKE(f->havefb))
	{
		const func_binary * fb = &f->fb;
		variant * v = 0;

		// 准备栈大小
		int needsize = m_sp + BP_SIZE + retnum + FUNC_BINARY_MAX_STACK(*fb);
		if (UNLIKE(needsize > (int)ARRAY_MAX_SIZE(m_stack)))
		{
			int newsize = needsize + needsize * m_fk->cfg.array_grow_speed / 100;
			ARRAY_GROW(m_stack, newsize, variant);
		}

		// 老的bp
		int oldbp = m_bp;
		m_bp = m_sp;

		// 记录返回位置
		for (int i = 0; i < retnum; i++)
		{
			v = &ARRAY_GET(m_stack, m_bp);
			v->type = variant::NIL;
			v->data.buf = retpos[i];
			m_bp++;
		}

		// 记录返回值数目
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = retnum;
		m_bp++;

		// 记录老的ip
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = m_ip;
		m_bp++;

		// 记录profile
		if (UNLIKE(m_fk->pf.isopen()))
		{
			v = &ARRAY_GET(m_stack, m_bp);
			v->data.buf = fkgetmstick();
		}
		v->type = variant::NIL;
		m_bp++;

		// 记录老的fb
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = (uint64_t)m_fb;
		m_bp++;

		// 记录老的bp
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = oldbp;
		m_bp++;

		// 设置sp
		m_sp = m_bp + FUNC_BINARY_MAX_STACK(*fb);
		
		if (UNLIKE((int)ps->m_variant_list_num != FUNC_BINARY_PARAMNUM(*fb)))
		{
			FKERR("call func %s param not match", vartostring(&func).c_str());
			m_isend = true;
			seterror(m_fk, efk_run_param_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "call func %s param not match", vartostring(&func).c_str());
			return;
		}

		assert(FUNC_BINARY_PARAMNUM(*fb) <= REAL_MAX_FAKE_PARAM_NUM);
		assert(m_bp + FUNC_BINARY_PARAMNUM(*fb) <= (int)ARRAY_MAX_SIZE(m_stack));

		// 分配入参
		memcpy(&ARRAY_GET(m_stack, m_bp), ps->m_variant_list, FUNC_BINARY_PARAMNUM(*fb) * sizeof(variant));
		PS_CLEAR(*ps);

		// 重置ret
		V_SET_NIL(&m_ret[0]);

		// 标记
		FUNC_BINARY_USE(*fb)++;

		// 新函数
		m_fb = fb;
		m_ip = 0;

		return;
	}

	// 记录profile
	uint32_t s = 0;
	if (UNLIKE(m_fk->pf.isopen()))
	{
		s = fkgetmstick();
	}

	// 绑定函数
	if (f->haveff)
	{
		BIND_FUNC_CALL(f, this);
		FKLOG("call C func %s", vartostring(&func).c_str());
	}
	// 内置函数
	else if (f->havebif)
	{
		BUILDIN_FUNC_CALL(f, this);
		FKLOG("call buildin func %s", vartostring(&func).c_str());
	}
	else
	{
		assert(0);
		FKERR("fkrun no inter func %s fail", vartostring(&func).c_str());
		m_isend = true;
		seterror(m_fk, efk_run_no_func_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "fkrun no inter func %s fail", vartostring(&func).c_str());
		return;
	}

	// 返回值
	// 这种情况是直接跳过脚本调用了C函数
	if (UNLIKE(BP_END(m_bp)))
	{
		variant * cret;
		PS_POP_AND_GET(*ps, cret);
		m_isend = true;
		// 直接塞返回值
		m_ret[0] = *cret;
	}
	// 否则塞到当前堆栈上
	else
	{
		// 检查返回值数目对不对
		if (UNLIKE((int)ps->m_variant_list_num != retnum))
		{
			FKERR("native func %s param not match, give %d need %d", vartostring(&func).c_str(), (int)ps->m_variant_list_num, retnum);
			m_isend = true;
			seterror(m_fk, efk_run_param_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "native func %s param not match, give %d need %d", vartostring(&func).c_str(), (int)ps->m_variant_list_num, retnum);
			return;
		}
		
		// 塞返回值
		for (int i = 0; i < retnum; i++)
		{
			variant * ret;
			GET_VARIANT(*m_fb, m_bp, ret, retpos[i]);
			
			variant * cret;
			PS_GET(*ps, cret, i);
			
			*ret = *cret;
		}
	}
	
	if (UNLIKE(m_fk->pf.isopen()))
	{
		const char * name = 0;
		V_GET_STRING(&func, name);
		m_fk->pf.add_func_sample(name, fkgetmstick() - s);
	}

	return;
}
Esempio n. 2
0
const char * interpreter::get_running_call_stack() const
{
	if (!m_fb)
	{
		return "";
	}
	
	m_fk->rn.cur_runinginfo.clear();
	int deps = 0;

	int ip = m_ip;
	int bp = m_bp;
	const func_binary * fb = m_fb;

	while (!BP_END(bp))
	{
		m_fk->rn.cur_runinginfo += "#";
		m_fk->rn.cur_runinginfo += fkitoa(deps);
		m_fk->rn.cur_runinginfo += "	";
		m_fk->rn.cur_runinginfo += fb ? FUNC_BINARY_NAME(*fb) : "";
		m_fk->rn.cur_runinginfo += " at ";
		m_fk->rn.cur_runinginfo += fb ? FUNC_BINARY_FILENAME(*fb) : "";
		m_fk->rn.cur_runinginfo += ":";
		m_fk->rn.cur_runinginfo += fb ? fkitoa(GET_CMD_LINENO(*fb, ip)) : 0;
		m_fk->rn.cur_runinginfo += "\n";
		for (int j = 0; fb && j < FUNC_BINARY_MAX_STACK(*fb); j++)
		{
			m_fk->rn.cur_runinginfo += "		";
			
			String variant_name;
			for (int i = 0; i < fb->m_debug_stack_variant_info_num; i++)
			{
				const stack_variant_info & info = fb->m_debug_stack_variant_info[i];
				if (info.pos == j)
				{
					variant_name += info.name;
					variant_name += "(line:";
					variant_name += fkitoa(info.line);
					variant_name += ") ";
				}
			}
			if (variant_name.empty())
			{
				variant_name = "(anonymous)";
			}
			
			m_fk->rn.cur_runinginfo += variant_name;
			m_fk->rn.cur_runinginfo += "\t[";
			m_fk->rn.cur_runinginfo += fkitoa(j);
			m_fk->rn.cur_runinginfo += "]\t";
			variant * v = 0;
			GET_STACK(bp, v, j);
			m_fk->rn.cur_runinginfo += vartostring(v);
			m_fk->rn.cur_runinginfo += "\n";
		}

		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;
		}
		
		deps++;
	}
	
	return m_fk->rn.cur_runinginfo.c_str();
}
Esempio n. 3
0
void interpreter::call(const variant & func)
{
    fake * fk = m_fk;
	const funcunion * f = m_fk->fm.get_func(func);
	if (UNLIKE(!f))
	{
		FKERR("fkrun no func %s fail", vartostring(&func).c_str());
		seterror(m_fk, efk_run_no_func_error, "fkrun no func %s fail", vartostring(&func).c_str());
		m_isend = true;
		return;
	}

	// 常规函数
	if (f->havefb)
	{
		const func_binary * fb = &f->fb;

		// 空函数处理
		if (UNLIKE(!FUNC_BINARY_CMDSIZE(*fb)))
		{
			// 所有都完
			if (ARRAY_EMPTY(m_stack_list))
			{
				FKLOG("call stack empty end");
				m_isend = true;
			}
			return;
		}

		// 压栈
		if (UNLIKE(ARRAY_SIZE(m_stack_list) >= ARRAY_MAX_SIZE(m_stack_list)))
		{
			int newsize = ARRAY_MAX_SIZE(m_stack_list) + 1 + ARRAY_MAX_SIZE(m_stack_list) * m_fk->cfg.array_grow_speed / 100;
			ARRAY_GROW(m_stack_list, newsize, stack);
		}
		ARRAY_PUSH_BACK(m_stack_list);
		stack & s = ARRAY_BACK(m_stack_list);
		m_cur_stack = &s;
		STACK_INI(s, m_fk, fb);
		if (UNLIKE(FUNC_BINARY_MAX_STACK(*fb) > (int)ARRAY_MAX_SIZE(s.m_stack_variant_list)))
		{
			ARRAY_GROW(s.m_stack_variant_list, FUNC_BINARY_MAX_STACK(*fb), variant);
		}

		// 记录profile
		beginfuncprofile();
		
		paramstack * ps = getps(m_fk);

		if (UNLIKE((int)ps->m_variant_list_num != FUNC_BINARY_PARAMNUM(*fb)))
		{
			FKERR("call func %s param not match", vartostring(&func).c_str());
			seterror(m_fk, efk_run_param_error, "call func %s param not match", vartostring(&func).c_str());
			m_isend = true;
			return;
		}

		assert(FUNC_BINARY_PARAMNUM(*fb) <= (int)ARRAY_MAX_SIZE(s.m_stack_variant_list));

		// 分配栈空间
		for (int i = 0; i < (int)FUNC_BINARY_PARAMNUM(*fb); i++)
		{
			SET_STACK(&(ps->m_variant_list[i]), s, i);
			FKLOG("call set %s to pos %d", (vartostring(&(ps->m_variant_list[i]))).c_str(), i);
		}
		
		ps->clear();

		// 重置ret
		V_SET_NIL(&m_ret[0]);

		// 标记
		FUNC_BINARY_USE(*fb)++;

		return;
	}

	// 记录profile
	uint32_t s = 0;
	if (m_fk->pf.isopen())
	{
		s = fkgetmstick();
	}

	// 绑定函数
	if (f->haveff)
	{
		BIND_FUNC_CALL(f, this);
		FKLOG("call C func %s", vartostring(&func).c_str());
	}
	// 内置函数
	else if (f->havebif)
	{
		BUILDIN_FUNC_CALL(f, this);
		FKLOG("call buildin func %s", vartostring(&func).c_str());
	}
	else
	{
		assert(0);
		FKERR("fkrun no inter func %s fail", vartostring(&func).c_str());
		seterror(m_fk, efk_run_no_func_error, "fkrun no inter func %s fail", vartostring(&func).c_str());
		m_isend = true;
		return;
	}

	// 返回值
	paramstack * theps = getps(m_fk);
    bool err = false;
	USE(err);

	// 这种情况是直接跳过脚本调用了C函数
	if (UNLIKE(ARRAY_EMPTY(m_stack_list)))
	{
    	variant * cret;
    	PS_POP_AND_GET(*theps, cret);
		m_isend = true;
		// 直接塞返回值
		m_ret[0] = *cret;
	}
	// 否则塞到当前堆栈上
	else
	{
		// 塞返回值
		m_cur_stack = &ARRAY_BACK(m_stack_list);
		const func_binary & fb = *m_cur_stack->m_fb;
		for (int i = 0; i < m_cur_stack->m_retnum; i++)
		{
			variant * ret;
			GET_VARIANT(*m_cur_stack, fb, ret, m_cur_stack->m_retvpos[i]);
			
        	variant * cret;
        	PS_GET(*theps, cret, i);
        	
			*ret = *cret;
		}
	}
    if (UNLIKE(err))
    {
        m_isend = true;
    }
    
	if (m_fk->pf.isopen())
	{
	    bool err = false;
		const char * name = 0;
		V_GET_STRING(&func, name);
		m_fk->pf.add_func_sample(name, fkgetmstick() - s);
	}

	return;
}