feat: 使用Computed Goto优化指令分发机制和算术运算处理
This commit is contained in:
251
src/VM/VM.cpp
251
src/VM/VM.cpp
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
@file src/VM/VM.hpp
|
||||
@file src/VM/VM.cpp
|
||||
@brief 虚拟机核心执行引擎实现
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-19
|
||||
@@ -7,8 +7,11 @@
|
||||
|
||||
#include <VM/VM.hpp>
|
||||
|
||||
#define BINARY_ARITHMETIC_OP(opCode, op) \
|
||||
case OpCode::opCode: { \
|
||||
// Computed GOTO!!!
|
||||
#define BINARY_ARITHMETIC_OP(opName, op) \
|
||||
do_##opName: \
|
||||
{ \
|
||||
std::uint8_t a = decodeA(inst); \
|
||||
std::uint8_t b = decodeB(inst); \
|
||||
std::uint8_t c = decodeC(inst); \
|
||||
Value lhs = currentFrame->registerBase[b]; \
|
||||
@@ -21,7 +24,6 @@
|
||||
{ \
|
||||
currentFrame->registerBase[a] = Value::FromDouble(lhs.AsDouble() op rhs.AsDouble()); \
|
||||
} \
|
||||
/* 隐式类型提升:Int 与 Double 混合运算 */ \
|
||||
else if (lhs.IsInt() && rhs.IsDouble()) [[likely]] \
|
||||
{ \
|
||||
currentFrame->registerBase[a] = Value::FromDouble(lhs.AsInt() op rhs.AsDouble()); \
|
||||
@@ -34,11 +36,13 @@
|
||||
{ \
|
||||
assert(false && "VM Runtime Error: Unsupported types for arithmetic operation"); \
|
||||
} \
|
||||
break; \
|
||||
DISPATCH(); \
|
||||
}
|
||||
|
||||
#define BINARY_COMPARE_OP(opCode, op) \
|
||||
case OpCode::opCode: { \
|
||||
#define BINARY_COMPARE_OP(opName, op) \
|
||||
do_##opName: \
|
||||
{ \
|
||||
std::uint8_t a = decodeA(inst); \
|
||||
std::uint8_t b = decodeB(inst); \
|
||||
std::uint8_t c = decodeC(inst); \
|
||||
Value lhs = currentFrame->registerBase[b]; \
|
||||
@@ -69,10 +73,9 @@
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* TODO: 非数字比较 */ \
|
||||
assert(false && "VM Runtime Error: Unsupported types for comparison"); \
|
||||
} \
|
||||
break; \
|
||||
DISPATCH(); \
|
||||
}
|
||||
|
||||
namespace Fig
|
||||
@@ -82,100 +85,146 @@ namespace Fig
|
||||
Proto *entry = compiledModule->protos[0];
|
||||
pushFrame(entry, registers);
|
||||
|
||||
while (true)
|
||||
// 🔥 必须与 Bytecode.hpp 中的 OpCode 枚举严格一一对应!
|
||||
static const void *dispatchTable[] = {&&do_Exit,
|
||||
&&do_LoadK,
|
||||
&&do_LoadTrue,
|
||||
&&do_LoadFalse,
|
||||
&&do_LoadNull,
|
||||
&&do_FastCall,
|
||||
&&do_Call,
|
||||
&&do_Return,
|
||||
&&do_LoadFn,
|
||||
&&do_Jmp,
|
||||
&&do_JmpIfFalse,
|
||||
&&do_Mov,
|
||||
&&do_Add,
|
||||
&&do_Sub,
|
||||
&&do_Mul,
|
||||
&&do_Div,
|
||||
&&do_Mod,
|
||||
&&do_BitXor,
|
||||
&&do_Equal,
|
||||
&&do_NotEqual,
|
||||
&&do_Greater,
|
||||
&&do_Less,
|
||||
&&do_GreaterEqual,
|
||||
&&do_LessEqual,
|
||||
&&do_Count};
|
||||
|
||||
Instruction inst;
|
||||
|
||||
// 🔥 核心分发引擎:取指 -> 直接查表并 Jump
|
||||
#define DISPATCH() \
|
||||
do \
|
||||
{ \
|
||||
inst = *(currentFrame->ip++); \
|
||||
goto *dispatchTable[inst & 0xFF]; \
|
||||
} while (0)
|
||||
|
||||
// 引擎点火!
|
||||
DISPATCH();
|
||||
|
||||
do_Exit: {
|
||||
[[unlikely]] return Value::GetNullInstance();
|
||||
}
|
||||
|
||||
do_LoadK: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
std::uint16_t bx = decodeBx(inst);
|
||||
currentFrame->registerBase[a] = currentFrame->getConstant(bx);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_LoadTrue: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
currentFrame->registerBase[a] = Value::GetTrueInstance();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_LoadFalse: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
currentFrame->registerBase[a] = Value::GetFalseInstance();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_LoadNull: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
currentFrame->registerBase[a] = Value::GetNullInstance();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_FastCall: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
Proto *proto = compiledModule->protos[a];
|
||||
std::uint8_t baseReg = decodeB(inst);
|
||||
pushFrame(proto, currentFrame->registerBase + baseReg);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_Call: {
|
||||
// TODO: FunctionObject 动态解包
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_Return: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
*currentFrame->registerBase = currentFrame->registerBase[a];
|
||||
popFrame();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_LoadFn: {
|
||||
// std::uint8_t a = decodeA(inst);
|
||||
// std::uint16_t bx = decodeBx(inst);
|
||||
// TODO: R[a] = new FunctionObject(compiledModule->protos[bx])
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_Jmp: {
|
||||
std::int16_t sbx = decodeSBx(inst);
|
||||
currentFrame->ip += sbx;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_JmpIfFalse: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
Value &v = currentFrame->registerBase[a];
|
||||
if (!v.AsBool())
|
||||
{
|
||||
// 取指并递增指针
|
||||
Instruction inst = *(currentFrame->ip++);
|
||||
|
||||
// 解码 OpCode 和 A 操作数
|
||||
OpCode op = decodeOpCode(inst);
|
||||
std::uint8_t a = decodeA(inst);
|
||||
switch (op)
|
||||
{
|
||||
case OpCode::Exit: { [[unlikely]]
|
||||
return Value::GetNullInstance();
|
||||
}
|
||||
|
||||
case OpCode::LoadK: {
|
||||
std::uint16_t bx = decodeBx(inst);
|
||||
currentFrame->registerBase[a] = currentFrame->getConstant(bx); // constants
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::LoadTrue: {
|
||||
currentFrame->registerBase[a] = Value::GetTrueInstance();
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::LoadFalse: {
|
||||
currentFrame->registerBase[a] = Value::GetFalseInstance();
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::LoadNull: {
|
||||
currentFrame->registerBase[a] = Value::GetNullInstance();
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::FastCall: {
|
||||
Proto *proto = compiledModule->protos[a];
|
||||
std::uint8_t baseReg = decodeB(inst);
|
||||
|
||||
pushFrame(proto, currentFrame->registerBase + baseReg);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::Call: {
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::Return: {
|
||||
*currentFrame->registerBase = currentFrame->registerBase[a];
|
||||
popFrame();
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::Jmp: {
|
||||
std::int16_t sbx = decodeSBx(inst);
|
||||
currentFrame->ip += sbx;
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::JmpIfFalse: {
|
||||
Value &v = currentFrame->registerBase[a];
|
||||
bool cond = v.AsBool(); // 条件类型 Compiler检查
|
||||
if (!cond)
|
||||
{
|
||||
std::int16_t sbx = decodeSBx(inst);
|
||||
currentFrame->ip += sbx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCode::Mov: {
|
||||
std::uint16_t bx = decodeBx(inst);
|
||||
currentFrame->registerBase[a] = currentFrame->registerBase[bx];
|
||||
break;
|
||||
}
|
||||
|
||||
BINARY_ARITHMETIC_OP(Add, +);
|
||||
BINARY_ARITHMETIC_OP(Sub, -);
|
||||
BINARY_ARITHMETIC_OP(Mul, *);
|
||||
BINARY_ARITHMETIC_OP(Div, /);
|
||||
|
||||
BINARY_COMPARE_OP(Equal, ==);
|
||||
BINARY_COMPARE_OP(NotEqual, !=);
|
||||
BINARY_COMPARE_OP(Greater, >);
|
||||
BINARY_COMPARE_OP(Less, <);
|
||||
BINARY_COMPARE_OP(GreaterEqual, >=);
|
||||
BINARY_COMPARE_OP(LessEqual, <=);
|
||||
|
||||
|
||||
// default: {
|
||||
// assert(false && "VM: Unknown OpCode encountered!");
|
||||
// }
|
||||
}
|
||||
std::int16_t sbx = decodeSBx(inst);
|
||||
currentFrame->ip += sbx;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
do_Mov: {
|
||||
std::uint8_t a = decodeA(inst);
|
||||
std::uint16_t bx = decodeBx(inst);
|
||||
currentFrame->registerBase[a] = currentFrame->registerBase[bx];
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
BINARY_ARITHMETIC_OP(Add, +);
|
||||
BINARY_ARITHMETIC_OP(Sub, -);
|
||||
BINARY_ARITHMETIC_OP(Mul, *);
|
||||
BINARY_ARITHMETIC_OP(Div, /);
|
||||
|
||||
do_Mod:
|
||||
do_BitXor:
|
||||
assert(false && "VM: Mod and BitXor not fully implemented yet!");
|
||||
DISPATCH();
|
||||
|
||||
BINARY_COMPARE_OP(Equal, ==);
|
||||
BINARY_COMPARE_OP(NotEqual, !=);
|
||||
BINARY_COMPARE_OP(Greater, >);
|
||||
BINARY_COMPARE_OP(Less, <);
|
||||
BINARY_COMPARE_OP(GreaterEqual, >=);
|
||||
BINARY_COMPARE_OP(LessEqual, <=);
|
||||
|
||||
do_Count: {
|
||||
assert(false && "Hit Count sentinel!");
|
||||
return Value::GetNullInstance();
|
||||
}
|
||||
}
|
||||
}; // namespace Fig
|
||||
Reference in New Issue
Block a user