/*! @file src/Object/ObjectBase.hpp @brief 值表示定义 (NaN Boxing) uint64 @author PuqiAR (im@puqiar.top) @date 2026-02-19 */ #pragma once #include #include #include namespace Fig { struct Object; // 前置声明 /* 正常来说直接 Value = std::uint64_t会更快 但是这样会带来隐式转换的问题 因此我们封装成一个类,这样速度不会损失很多。 (release模式编译器会直接优化, 速度和uint64_t直接表示一样快) */ class Value { private: std::uint64_t v_; // 唯一的物理成员 sizeof(Value) 永远是 8 字节。 // --- 私有掩码常量 --- static constexpr std::uint64_t QNAN_MASK = 0x7ffc000000000000; static constexpr std::uint64_t SIGN_BIT = 0x8000000000000000; // 专门给 Int32 预留的高位 Tag static constexpr std::uint32_t INT_TAG_HIGH = 0x7FFD0000; // 基础原语 Tag static constexpr std::uint64_t TAG_NULL = 1; static constexpr std::uint64_t TAG_FALSE = 2; static constexpr std::uint64_t TAG_TRUE = 3; // 私有底层构造:仅供内部组装使用 constexpr explicit Value(uint64_t raw) : v_(raw) {} public: // 默认构造为 Null,保证未初始化变量也是安全的 constexpr Value() { *this = GetNullInstance(); } [[nodiscard]] static constexpr Value FromDouble(double d) { uint64_t raw = std::bit_cast(d); // 清洗非法的 NaN if ((raw & QNAN_MASK) == QNAN_MASK) return Value(QNAN_MASK); return Value(raw); } [[nodiscard]] static constexpr Value FromInt(std::int32_t i) { // 移位构造,彻底阻断符号扩展漏洞 return Value((static_cast(INT_TAG_HIGH) << 32) | static_cast(i)); } [[nodiscard]] static constexpr Value &GetTrueInstance() { static Value trueInstance(QNAN_MASK | TAG_TRUE); return trueInstance; } [[nodiscard]] static constexpr Value &GetFalseInstance() { static Value falseInstance(QNAN_MASK | TAG_FALSE); return falseInstance; } [[nodiscard]] static constexpr Value &FromBool(bool b) { return (b ? GetTrueInstance() : GetFalseInstance()); } [[nodiscard]] static constexpr Value &GetNullInstance() { static Value nullInstance(QNAN_MASK | TAG_NULL); return nullInstance; } [[nodiscard]] static Value FromObject(Object *ptr) { return Value(reinterpret_cast(ptr) | SIGN_BIT | QNAN_MASK); } // 类型检查 (Is) [[nodiscard]] constexpr bool IsDouble() const { return (v_ & QNAN_MASK) != QNAN_MASK; } [[nodiscard]] constexpr bool IsInt() const { // 安全的高 32 位移位判定 return static_cast(v_ >> 32) == INT_TAG_HIGH; } [[nodiscard]] constexpr bool IsNumber() const { return IsDouble() || IsInt(); } [[nodiscard]] constexpr bool IsNull() const { return v_ == (QNAN_MASK | TAG_NULL); } [[nodiscard]] constexpr bool IsBool() const { return (v_ | 1) == (QNAN_MASK | TAG_TRUE); } [[nodiscard]] constexpr bool IsObject() const { return (v_ & (SIGN_BIT | QNAN_MASK)) == (SIGN_BIT | QNAN_MASK); } // 提取数据 (Unbox / As) [[nodiscard]] constexpr double AsDouble() const { return std::bit_cast(v_); } [[nodiscard]] constexpr int32_t AsInt() const { return static_cast(v_); } // 核心辅助:泛型数字提取。算术指令可以直接用这个,免去手写 if 分支 // 若不是 int/double 会导致非常恐怖的问题 [[nodiscard]] constexpr double CastToDouble() const { return IsInt() ? static_cast(AsInt()) : AsDouble(); } [[nodiscard]] constexpr bool AsBool() const { return v_ == (QNAN_MASK | TAG_TRUE); } [[nodiscard]] struct Object *AsObject() const { return reinterpret_cast(v_ & ~(SIGN_BIT | QNAN_MASK)); } // 重载 // 暴露原生值用于硬核位运算或 Hash 计算 [[nodiscard]] constexpr uint64_t Raw() const { return v_; } // 让 VM 的 OP_EQ 指令极简:`if (RA == RB)` [[nodiscard]] constexpr bool operator==(const Value &other) const { // IEEE 754 规定浮点数有 +0.0 == -0.0 的特殊规则,所以不直接比对raw bits而是转换成 double进行C++比对 if (IsDouble() && other.IsDouble()) { return AsDouble() == other.AsDouble(); } // 直接比较 64 位整数内存,所以堆对象比较为地址(运算符重载由Compiler处理) return v_ == other.v_; } [[nodiscard]] constexpr bool operator!=(const Value &other) const { return !(*this == other); } // 类函数 [[nodiscard]] String ToString() const; }; /* C风格继承 + 手动分发 禁止任何 virtual 达到最高效率 */ enum class ObjectType : uint8_t { String, Function, Struct, Instance, }; struct StructObject /* : public Object */; // 结构体基类的定义,前向声明 // Total 24 bytes size struct Object { Object *next; // 8 bytes: gc链表 StructObject *klass; // 8 bytes: 一切皆对象,父类指针 ObjectType type; // 1 byte : 类型 bool isMarked = false; // 1 byte : gc标记 // + 6 bytes padding constexpr bool isString() const { return type == ObjectType::String; } constexpr bool isFunction() const { return type == ObjectType::Function; } constexpr bool isStruct() const { return type == ObjectType::Struct; } constexpr bool isInstance() const { return type == ObjectType::Instance; } }; } // namespace Fig