refactor: 引入 Arena 内存池并优化指令分发,为类型系统重构做准备
This commit is contained in:
@@ -21,6 +21,7 @@ namespace Fig
|
|||||||
enum class OpCode : std::uint8_t
|
enum class OpCode : std::uint8_t
|
||||||
{
|
{
|
||||||
Exit, // 结束运行
|
Exit, // 结束运行
|
||||||
|
|
||||||
LoadK, // iABx 模式: R[A] = Constants[Bx]
|
LoadK, // iABx 模式: R[A] = Constants[Bx]
|
||||||
LoadTrue, // iABC: R[A] = true
|
LoadTrue, // iABC: R[A] = true
|
||||||
LoadFalse, // iABC: R[A] = false
|
LoadFalse, // iABC: R[A] = false
|
||||||
@@ -35,7 +36,8 @@ namespace Fig
|
|||||||
Jmp, // iAsBx: ip += sBx 无条件跳转
|
Jmp, // iAsBx: ip += sBx 无条件跳转
|
||||||
JmpIfFalse, // iAsBx: 如果 R[A] 为假, ip += sBx
|
JmpIfFalse, // iAsBx: 如果 R[A] 为假, ip += sBx
|
||||||
|
|
||||||
Mov, // iABx: R[A] = R[Bx]
|
Mov, // iABx: R[A] = R[Bx]
|
||||||
|
|
||||||
Add, // iABC: R[A] = R[B] + R[C]
|
Add, // iABC: R[A] = R[B] + R[C]
|
||||||
Sub, // iABC: R[A] = R[B] - R[C]
|
Sub, // iABC: R[A] = R[B] - R[C]
|
||||||
Mul, // iABC: R[A] = R[B] * R[C]
|
Mul, // iABC: R[A] = R[B] * R[C]
|
||||||
@@ -43,6 +45,11 @@ namespace Fig
|
|||||||
Mod, // iABC: R[A] = R[B] % R[C]
|
Mod, // iABC: R[A] = R[B] % R[C]
|
||||||
BitXor, // iABC: R[A] = R[B] ^ R[C]
|
BitXor, // iABC: R[A] = R[B] ^ R[C]
|
||||||
|
|
||||||
|
IntFastAdd, // iABC: R[A] (Int) = R[B] (Int) + R[C] (Int)
|
||||||
|
IntFastSub, // iABC: R[A] (Int) = R[B] (Int) - R[C] (Int)
|
||||||
|
IntFastMul, // iABC: R[A] (Int) = R[B] (Int) * R[C] (Int)
|
||||||
|
IntFastDiv, // iABC: R[A] (Double) = R[B] (Int) / R[C] (Int)
|
||||||
|
|
||||||
Equal, // iABC: R[A] = R[B] == R[C]
|
Equal, // iABC: R[A] = R[B] == R[C]
|
||||||
NotEqual, // iABC: R[A] = R[B] != R[C]
|
NotEqual, // iABC: R[A] = R[B] != R[C]
|
||||||
Greater, // iABC: R[A] = R[B] > R[C]
|
Greater, // iABC: R[A] = R[B] > R[C]
|
||||||
|
|||||||
@@ -346,7 +346,13 @@ namespace Fig
|
|||||||
case OpCode::Sub:
|
case OpCode::Sub:
|
||||||
case OpCode::Mul:
|
case OpCode::Mul:
|
||||||
case OpCode::Div:
|
case OpCode::Div:
|
||||||
case OpCode::Mod: {
|
case OpCode::Mod:
|
||||||
|
|
||||||
|
case OpCode::IntFastAdd:
|
||||||
|
case OpCode::IntFastSub:
|
||||||
|
case OpCode::IntFastMul:
|
||||||
|
case OpCode::IntFastDiv:
|
||||||
|
{
|
||||||
// iABC 模式:解析 B (16~23 位) 和 C (24~31 位)
|
// iABC 模式:解析 B (16~23 位) 和 C (24~31 位)
|
||||||
std::uint8_t b = (inst >> 16) & 0xFF;
|
std::uint8_t b = (inst >> 16) & 0xFF;
|
||||||
std::uint8_t c = (inst >> 24) & 0xFF;
|
std::uint8_t c = (inst >> 24) & 0xFF;
|
||||||
|
|||||||
@@ -139,13 +139,16 @@ namespace Fig
|
|||||||
return compileAssignment(infix);
|
return compileAssignment(infix);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &_lhsReg = compileExpr(infix->left);
|
Expr *left = infix->left;
|
||||||
|
Expr *right = infix->right;
|
||||||
|
|
||||||
|
const auto &_lhsReg = compileExpr(left);
|
||||||
if (!_lhsReg)
|
if (!_lhsReg)
|
||||||
{
|
{
|
||||||
return _lhsReg;
|
return _lhsReg;
|
||||||
}
|
}
|
||||||
std::uint8_t lhsReg = *_lhsReg;
|
std::uint8_t lhsReg = *_lhsReg;
|
||||||
const auto &_rhsReg = compileExpr(infix->right);
|
const auto &_rhsReg = compileExpr(right);
|
||||||
if (!_rhsReg)
|
if (!_rhsReg)
|
||||||
{
|
{
|
||||||
return _rhsReg;
|
return _rhsReg;
|
||||||
@@ -156,25 +159,58 @@ namespace Fig
|
|||||||
FreeReg(lhsReg);
|
FreeReg(lhsReg);
|
||||||
|
|
||||||
std::uint8_t resultReg = AllocReg();
|
std::uint8_t resultReg = AllocReg();
|
||||||
|
|
||||||
switch (infix->op)
|
switch (infix->op)
|
||||||
{
|
{
|
||||||
case BinaryOperator::Add: {
|
case BinaryOperator::Add: {
|
||||||
Emit(Op::iABC(OpCode::Add, resultReg, lhsReg, rhsReg));
|
if (left->resolvedType == right->resolvedType && left->resolvedType->isInt())
|
||||||
|
{
|
||||||
|
// Int + Int
|
||||||
|
Emit(Op::iABC(OpCode::IntFastAdd, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Emit(Op::iABC(OpCode::Add, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BinaryOperator::Subtract: {
|
case BinaryOperator::Subtract: {
|
||||||
Emit(Op::iABC(OpCode::Sub, resultReg, lhsReg, rhsReg));
|
if (left->resolvedType == right->resolvedType && left->resolvedType->isInt())
|
||||||
|
{
|
||||||
|
// Int - Int
|
||||||
|
Emit(Op::iABC(OpCode::IntFastSub, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Emit(Op::iABC(OpCode::Sub, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BinaryOperator::Multiply: {
|
case BinaryOperator::Multiply: {
|
||||||
Emit(Op::iABC(OpCode::Mul, resultReg, lhsReg, rhsReg));
|
if (left->resolvedType == right->resolvedType && left->resolvedType->isInt())
|
||||||
|
{
|
||||||
|
// Int * Int
|
||||||
|
Emit(Op::iABC(OpCode::IntFastMul, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Emit(Op::iABC(OpCode::Mul, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BinaryOperator::Divide: {
|
case BinaryOperator::Divide: {
|
||||||
Emit(Op::iABC(OpCode::Div, resultReg, lhsReg, rhsReg));
|
if (left->resolvedType == right->resolvedType && left->resolvedType->isInt())
|
||||||
|
{
|
||||||
|
// Int / Int
|
||||||
|
Emit(Op::iABC(OpCode::IntFastDiv, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Emit(Op::iABC(OpCode::Div, resultReg, lhsReg, rhsReg));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,11 +299,11 @@ namespace Fig
|
|||||||
Emit(Op::iABx(OpCode::Mov, baseReg, *calleeRes));
|
Emit(Op::iABx(OpCode::Mov, baseReg, *calleeRes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < expr->args.size(); ++i)
|
for (size_t i = 0; i < expr->args.size(); ++i)
|
||||||
{
|
{
|
||||||
std::uint8_t argTarget = AllocReg();
|
std::uint8_t argTarget = AllocReg();
|
||||||
auto argRes = compileExpr(expr->args.args[i]);
|
auto argRes = compileExpr(expr->args.args[i]);
|
||||||
if (!argRes)
|
if (!argRes)
|
||||||
{
|
{
|
||||||
return argRes;
|
return argRes;
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ namespace Fig::CoreIO
|
|||||||
|
|
||||||
void InitConsoleIO()
|
void InitConsoleIO()
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
SetConsoleCP(CP_UTF8);
|
SetConsoleCP(CP_UTF8);
|
||||||
SetConsoleOutputCP(CP_UTF8);
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include <Object/ObjectBase.hpp>
|
#include <Object/ObjectBase.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
// 运行时闭包对象 (24字节 Base + 8字节 Proto指针 = 32 bytes)
|
// 运行时闭包对象 (24字节 Base + 8字节 Proto指针 = 32 bytes)
|
||||||
@@ -17,7 +16,9 @@ namespace Fig
|
|||||||
struct Proto;
|
struct Proto;
|
||||||
struct FunctionObject final : public Object
|
struct FunctionObject final : public Object
|
||||||
{
|
{
|
||||||
|
String name; // 调试使用
|
||||||
Proto *proto; // 指向编译器生成的只读字节码与常量池
|
Proto *proto; // 指向编译器生成的只读字节码与常量池
|
||||||
|
std::uint8_t paraCount;
|
||||||
|
|
||||||
// TODO: 实现闭包时 加一个 Upvalue 指针数组
|
// TODO: 实现闭包时 加一个 Upvalue 指针数组
|
||||||
// Value* upvalues;
|
// Value* upvalues;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Fig
|
|||||||
StateProtector p(this, {State::ParsingLiteralExpr});
|
StateProtector p(this, {State::ParsingLiteralExpr});
|
||||||
|
|
||||||
const Token &literal_token = consumeToken();
|
const Token &literal_token = consumeToken();
|
||||||
LiteralExpr *node = new LiteralExpr(literal_token, makeSourceLocation(literal_token));
|
LiteralExpr *node = arena.Allocate<LiteralExpr>(literal_token, makeSourceLocation(literal_token));
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
Result<IdentiExpr *, Error> Parser::parseIdentiExpr() // 当前token为Identifier调用
|
Result<IdentiExpr *, Error> Parser::parseIdentiExpr() // 当前token为Identifier调用
|
||||||
@@ -22,7 +22,7 @@ namespace Fig
|
|||||||
StateProtector p(this, {State::ParsingIdentiExpr});
|
StateProtector p(this, {State::ParsingIdentiExpr});
|
||||||
|
|
||||||
const Token &identifier = consumeToken();
|
const Token &identifier = consumeToken();
|
||||||
IdentiExpr *node = new IdentiExpr(
|
IdentiExpr *node = arena.Allocate<IdentiExpr>(
|
||||||
srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier));
|
srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier));
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
Expr *rhs = *rhs_result;
|
Expr *rhs = *rhs_result;
|
||||||
|
|
||||||
InfixExpr *node = new InfixExpr(lhs, op, rhs);
|
InfixExpr *node = arena.Allocate<InfixExpr>(lhs, op, rhs);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expr *rhs = *rhs_result;
|
Expr *rhs = *rhs_result;
|
||||||
PrefixExpr *node = new PrefixExpr(op, rhs);
|
PrefixExpr *node = arena.Allocate<PrefixExpr>(op, rhs);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
consumeToken(); // consume `]`
|
consumeToken(); // consume `]`
|
||||||
|
|
||||||
IndexExpr *indexExpr = new IndexExpr(base, *index_result);
|
IndexExpr *indexExpr = arena.Allocate<IndexExpr>(base, *index_result);
|
||||||
return indexExpr;
|
return indexExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ namespace Fig
|
|||||||
if (currentToken().type == TokenType::RightParen)
|
if (currentToken().type == TokenType::RightParen)
|
||||||
{
|
{
|
||||||
consumeToken(); // consume `)`
|
consumeToken(); // consume `)`
|
||||||
return new CallExpr(callee, callArgs);
|
return arena.Allocate<CallExpr>(callee, callArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
@@ -140,7 +140,7 @@ namespace Fig
|
|||||||
consumeToken(); // consume `,`
|
consumeToken(); // consume `,`
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CallExpr(callee, callArgs);
|
return arena.Allocate<CallExpr>(callee, callArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Expr *, Error> Parser::parseExpression(BindingPower rbp)
|
Result<Expr *, Error> Parser::parseExpression(BindingPower rbp)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
Result<Program *, Error> Parser::Parse()
|
Result<Program *, Error> Parser::Parse()
|
||||||
{
|
{
|
||||||
Program *program = new Program;
|
Program *program = arena.Allocate<Program>();
|
||||||
while (!isEOF)
|
while (!isEOF)
|
||||||
{
|
{
|
||||||
auto result = parseStatement();
|
auto result = parseStatement();
|
||||||
@@ -27,5 +27,6 @@ namespace Fig
|
|||||||
program->nodes.push_back(stmt);
|
program->nodes.push_back(stmt);
|
||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
|
|
||||||
}
|
}
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <Error/Error.hpp>
|
#include <Error/Error.hpp>
|
||||||
#include <Lexer/Lexer.hpp>
|
#include <Lexer/Lexer.hpp>
|
||||||
#include <Token/Token.hpp>
|
#include <Token/Token.hpp>
|
||||||
|
#include <Utils/Arena.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -24,6 +25,7 @@ namespace Fig
|
|||||||
class Parser
|
class Parser
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
Arena arena;
|
||||||
Lexer &lexer;
|
Lexer &lexer;
|
||||||
SourceManager &srcManager;
|
SourceManager &srcManager;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Fig
|
|||||||
Result<BlockStmt *, Error> Parser::parseBlockStmt() // 当前token为 {
|
Result<BlockStmt *, Error> Parser::parseBlockStmt() // 当前token为 {
|
||||||
{
|
{
|
||||||
SourceLocation location = makeSourceLocation(consumeToken()); // consume `{`
|
SourceLocation location = makeSourceLocation(consumeToken()); // consume `{`
|
||||||
BlockStmt *stmt = new BlockStmt();
|
BlockStmt *stmt = arena.Allocate<BlockStmt>();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (isEOF)
|
if (isEOF)
|
||||||
@@ -94,7 +94,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return std::unexpected(makeExpectSemicolonError());
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
}
|
}
|
||||||
VarDecl *varDecl = new VarDecl(isPublic, name, typeSpeicifer, isInfer, initExpr, location);
|
VarDecl *varDecl = arena.Allocate<VarDecl>(isPublic, name, typeSpeicifer, isInfer, initExpr, location);
|
||||||
return varDecl;
|
return varDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ namespace Fig
|
|||||||
return std::unexpected(result.error());
|
return std::unexpected(result.error());
|
||||||
}
|
}
|
||||||
BlockStmt *consequent = *result;
|
BlockStmt *consequent = *result;
|
||||||
ElseIfStmt *elif = new ElseIfStmt(cond, consequent, elseLocation);
|
ElseIfStmt *elif = arena.Allocate<ElseIfStmt>(cond, consequent, elseLocation);
|
||||||
elifs.push_back(elif);
|
elifs.push_back(elif);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -233,7 +233,7 @@ namespace Fig
|
|||||||
alternate = *result;
|
alternate = *result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IfStmt *ifStmt = new IfStmt(cond, consequent, elifs, alternate, location);
|
IfStmt *ifStmt = arena.Allocate<IfStmt>(cond, consequent, elifs, alternate, location);
|
||||||
return ifStmt;
|
return ifStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
BlockStmt *body = *result;
|
BlockStmt *body = *result;
|
||||||
|
|
||||||
WhileStmt *whileStmt = new WhileStmt(cond, body, location);
|
WhileStmt *whileStmt = arena.Allocate<WhileStmt>(cond, body, location);
|
||||||
return whileStmt;
|
return whileStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ namespace Fig
|
|||||||
defaultValue = *result;
|
defaultValue = *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PosParam *posParam = new PosParam(name, type, defaultValue, location);
|
PosParam *posParam = arena.Allocate<PosParam>(name, type, defaultValue, location);
|
||||||
params.push_back(posParam);
|
params.push_back(posParam);
|
||||||
|
|
||||||
if (match(TokenType::Comma))
|
if (match(TokenType::Comma))
|
||||||
@@ -423,7 +423,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
body = *bodyResult;
|
body = *bodyResult;
|
||||||
|
|
||||||
FnDefStmt *fnDef = new FnDefStmt(isPublic, name, params, returnType, body, location);
|
FnDefStmt *fnDef = arena.Allocate<FnDefStmt>(isPublic, name, params, returnType, body, location);
|
||||||
return fnDef;
|
return fnDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expr *value = *result;
|
Expr *value = *result;
|
||||||
ReturnStmt *returnStmt = new ReturnStmt(value, location);
|
ReturnStmt *returnStmt = arena.Allocate<ReturnStmt>(value, location);
|
||||||
|
|
||||||
if (!match(TokenType::Semicolon))
|
if (!match(TokenType::Semicolon))
|
||||||
{
|
{
|
||||||
@@ -507,7 +507,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return std::unexpected(makeExpectSemicolonError());
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
}
|
}
|
||||||
BreakStmt *breakStmt = new BreakStmt(location);
|
BreakStmt *breakStmt = arena.Allocate<BreakStmt>(location);
|
||||||
return breakStmt;
|
return breakStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +518,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return std::unexpected(makeExpectSemicolonError());
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
}
|
}
|
||||||
ContinueStmt *continueStmt = new ContinueStmt(location);
|
ContinueStmt *continueStmt = arena.Allocate<ContinueStmt>(location);
|
||||||
return continueStmt;
|
return continueStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,7 +532,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return std::unexpected(expr_result.error());
|
return std::unexpected(expr_result.error());
|
||||||
}
|
}
|
||||||
ExprStmt *exprStmt = new ExprStmt(*expr_result);
|
ExprStmt *exprStmt = arena.Allocate<ExprStmt>(*expr_result);
|
||||||
if (!match(TokenType::Semicolon))
|
if (!match(TokenType::Semicolon))
|
||||||
{
|
{
|
||||||
return std::unexpected(makeExpectSemicolonError());
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
@date 2026-02-25
|
@date 2026-02-25
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Parser/Parser.hpp>
|
#include <Parser/Parser.hpp>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
@@ -37,7 +35,7 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NamedTypeExpr *namedTypeExpr = new NamedTypeExpr(path, location);
|
NamedTypeExpr *namedTypeExpr = arena.Allocate<NamedTypeExpr>(path, location);
|
||||||
return namedTypeExpr;
|
return namedTypeExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,41 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return tag == TypeTag::Any;
|
return tag == TypeTag::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isNull() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInt() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Int;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDouble() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Double;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBool() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isString() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::String;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFunction() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStruct() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Struct;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 全局唯一类型驻留池
|
// 全局唯一类型驻留池
|
||||||
|
|||||||
115
src/Utils/Arena.hpp
Normal file
115
src/Utils/Arena.hpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*!
|
||||||
|
@file src/Utils/Arena.hpp
|
||||||
|
@brief 线性分配内存池,支持非平凡析构对象的自动清理
|
||||||
|
@author PuqiAR (im@puqiar.top)
|
||||||
|
@date 2026-03-08
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Fig
|
||||||
|
{
|
||||||
|
class Arena
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct DestructorNode
|
||||||
|
{
|
||||||
|
void (*destructor)(void *);
|
||||||
|
void *object;
|
||||||
|
DestructorNode *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::size_t CHUNK_SIZE = 64 * 1024; // 64KB 块大小
|
||||||
|
|
||||||
|
std::vector<char *> chunks;
|
||||||
|
char *currentPtr = nullptr;
|
||||||
|
std::size_t remaining = 0;
|
||||||
|
DestructorNode *destructorHead = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Arena() = default;
|
||||||
|
|
||||||
|
~Arena()
|
||||||
|
{
|
||||||
|
// 1. 逆序调用析构函数
|
||||||
|
DestructorNode *node = destructorHead;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
node->destructor(node->object);
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 释放所有分配的内存块
|
||||||
|
for (char *chunk : chunks)
|
||||||
|
{
|
||||||
|
delete[] chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁止拷贝和移动,防止内存所有权混乱
|
||||||
|
Arena(const Arena &) = delete;
|
||||||
|
Arena &operator=(const Arena &) = delete;
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
T *Allocate(Args &&...args)
|
||||||
|
{
|
||||||
|
std::size_t size = sizeof(T);
|
||||||
|
std::size_t alignment = alignof(T);
|
||||||
|
|
||||||
|
// 在当前块中尝试对齐并分配
|
||||||
|
void *ptr = allocateRaw(size, alignment);
|
||||||
|
|
||||||
|
// 在分配的内存上构造对象
|
||||||
|
T *obj = new (ptr) T(std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
// 如果 T 需要析构(如包含 String),注册到销毁链表
|
||||||
|
if constexpr (!std::is_trivially_destructible_v<T>)
|
||||||
|
{
|
||||||
|
// 注意: DestructorNode 本身是 POD,直接在 Arena 里分配,不需要注册析构
|
||||||
|
void *nodeRaw = allocateRaw(sizeof(DestructorNode), alignof(DestructorNode));
|
||||||
|
DestructorNode *node = new (nodeRaw) DestructorNode();
|
||||||
|
|
||||||
|
node->object = obj;
|
||||||
|
node->destructor = [](void *p) { static_cast<T *>(p)->~T(); };
|
||||||
|
node->next = destructorHead;
|
||||||
|
destructorHead = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *allocateRaw(std::size_t size, std::size_t alignment)
|
||||||
|
{
|
||||||
|
// 对齐计算
|
||||||
|
std::size_t adjustment = 0;
|
||||||
|
std::size_t currentAddr = reinterpret_cast<std::size_t>(currentPtr);
|
||||||
|
if (alignment > 0 && (currentAddr % alignment) != 0)
|
||||||
|
{
|
||||||
|
adjustment = alignment - (currentAddr % alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remaining < (size + adjustment))
|
||||||
|
{
|
||||||
|
// 当前块空间不足,分配新块
|
||||||
|
std::size_t nextChunkSize = (size > CHUNK_SIZE) ? size : CHUNK_SIZE;
|
||||||
|
currentPtr = new char[nextChunkSize];
|
||||||
|
chunks.push_back(currentPtr);
|
||||||
|
remaining = nextChunkSize;
|
||||||
|
adjustment = 0; // 新分配的块通常是最大对齐的
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPtr += adjustment;
|
||||||
|
void *res = currentPtr;
|
||||||
|
currentPtr += size;
|
||||||
|
remaining -= (size + adjustment);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace Fig
|
||||||
@@ -86,24 +86,37 @@ namespace Fig
|
|||||||
pushFrame(entry, registers);
|
pushFrame(entry, registers);
|
||||||
|
|
||||||
// 🔥 必须与 Bytecode.hpp 中的 OpCode 枚举严格一一对应!
|
// 🔥 必须与 Bytecode.hpp 中的 OpCode 枚举严格一一对应!
|
||||||
static const void *dispatchTable[] = {&&do_Exit,
|
static const void *dispatchTable[] = {
|
||||||
|
&&do_Exit,
|
||||||
|
|
||||||
&&do_LoadK,
|
&&do_LoadK,
|
||||||
&&do_LoadTrue,
|
&&do_LoadTrue,
|
||||||
&&do_LoadFalse,
|
&&do_LoadFalse,
|
||||||
&&do_LoadNull,
|
&&do_LoadNull,
|
||||||
|
|
||||||
&&do_FastCall,
|
&&do_FastCall,
|
||||||
&&do_Call,
|
&&do_Call,
|
||||||
&&do_Return,
|
&&do_Return,
|
||||||
|
|
||||||
&&do_LoadFn,
|
&&do_LoadFn,
|
||||||
|
|
||||||
&&do_Jmp,
|
&&do_Jmp,
|
||||||
&&do_JmpIfFalse,
|
&&do_JmpIfFalse,
|
||||||
|
|
||||||
&&do_Mov,
|
&&do_Mov,
|
||||||
|
|
||||||
&&do_Add,
|
&&do_Add,
|
||||||
&&do_Sub,
|
&&do_Sub,
|
||||||
&&do_Mul,
|
&&do_Mul,
|
||||||
&&do_Div,
|
&&do_Div,
|
||||||
&&do_Mod,
|
&&do_Mod,
|
||||||
&&do_BitXor,
|
&&do_BitXor,
|
||||||
|
|
||||||
|
&&do_IntFastAdd,
|
||||||
|
&&do_IntFastSub,
|
||||||
|
&&do_IntFastMul,
|
||||||
|
&&do_IntFastDiv,
|
||||||
|
|
||||||
&&do_Equal,
|
&&do_Equal,
|
||||||
&&do_NotEqual,
|
&&do_NotEqual,
|
||||||
&&do_Greater,
|
&&do_Greater,
|
||||||
@@ -114,7 +127,7 @@ namespace Fig
|
|||||||
|
|
||||||
Instruction inst;
|
Instruction inst;
|
||||||
|
|
||||||
// 🔥 核心分发引擎:取指 -> 直接查表并 Jump
|
// 取指 -> 直接查表并 Jump
|
||||||
#define DISPATCH() \
|
#define DISPATCH() \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
@@ -122,7 +135,7 @@ namespace Fig
|
|||||||
goto *dispatchTable[inst & 0xFF]; \
|
goto *dispatchTable[inst & 0xFF]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// 引擎点火!
|
// 引擎点火!! :3
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
|
||||||
do_Exit: {
|
do_Exit: {
|
||||||
@@ -215,6 +228,54 @@ namespace Fig
|
|||||||
assert(false && "VM: Mod and BitXor not fully implemented yet!");
|
assert(false && "VM: Mod and BitXor not fully implemented yet!");
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
|
||||||
|
do_IntFastAdd: {
|
||||||
|
std::uint8_t a = decodeA(inst);
|
||||||
|
std::uint8_t b = decodeB(inst);
|
||||||
|
std::uint8_t c = decodeC(inst);
|
||||||
|
|
||||||
|
Value l = currentFrame->registerBase[b];
|
||||||
|
Value r = currentFrame->registerBase[c];
|
||||||
|
|
||||||
|
currentFrame->registerBase[a] = Value::FromInt(l.AsInt() + r.AsInt());
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
|
do_IntFastSub: {
|
||||||
|
std::uint8_t a = decodeA(inst);
|
||||||
|
std::uint8_t b = decodeB(inst);
|
||||||
|
std::uint8_t c = decodeC(inst);
|
||||||
|
|
||||||
|
Value l = currentFrame->registerBase[b];
|
||||||
|
Value r = currentFrame->registerBase[c];
|
||||||
|
|
||||||
|
currentFrame->registerBase[a] = Value::FromInt(l.AsInt() - r.AsInt());
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
|
do_IntFastMul: {
|
||||||
|
std::uint8_t a = decodeA(inst);
|
||||||
|
std::uint8_t b = decodeB(inst);
|
||||||
|
std::uint8_t c = decodeC(inst);
|
||||||
|
|
||||||
|
Value l = currentFrame->registerBase[b];
|
||||||
|
Value r = currentFrame->registerBase[c];
|
||||||
|
|
||||||
|
currentFrame->registerBase[a] = Value::FromInt(l.AsInt() * r.AsInt());
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
|
do_IntFastDiv: {
|
||||||
|
std::uint8_t a = decodeA(inst);
|
||||||
|
std::uint8_t b = decodeB(inst);
|
||||||
|
std::uint8_t c = decodeC(inst);
|
||||||
|
|
||||||
|
Value l = currentFrame->registerBase[b];
|
||||||
|
Value r = currentFrame->registerBase[c];
|
||||||
|
|
||||||
|
currentFrame->registerBase[a] = Value::FromDouble(l.AsInt() + r.AsInt());
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
BINARY_COMPARE_OP(Equal, ==);
|
BINARY_COMPARE_OP(Equal, ==);
|
||||||
BINARY_COMPARE_OP(NotEqual, !=);
|
BINARY_COMPARE_OP(NotEqual, !=);
|
||||||
BINARY_COMPARE_OP(Greater, >);
|
BINARY_COMPARE_OP(Greater, >);
|
||||||
@@ -226,5 +287,6 @@ namespace Fig
|
|||||||
assert(false && "Hit Count sentinel!");
|
assert(false && "Hit Count sentinel!");
|
||||||
return Value::GetNullInstance();
|
return Value::GetNullInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
Reference in New Issue
Block a user