|
8 | 8 | #define lfunc_h |
9 | 9 |
|
10 | 10 |
|
11 | | -#include "lobject.h" |
| 11 | +#include "lobject_core.h" /* GCBase, GCObject, TValue */ |
| 12 | +#include "lproto.h" /* Proto */ |
| 13 | + |
| 14 | +/* Forward declarations */ |
| 15 | +class lua_State; |
| 16 | +class TString; |
| 17 | +typedef union StackValue *StkId; |
| 18 | + |
| 19 | + |
| 20 | +/* |
| 21 | +** {================================================================== |
| 22 | +** Functions |
| 23 | +** =================================================================== |
| 24 | +*/ |
| 25 | + |
| 26 | +inline constexpr int LUA_VUPVAL = makevariant(LUA_TUPVAL, 0); |
| 27 | + |
| 28 | + |
| 29 | +/* Variant tags for functions */ |
| 30 | +inline constexpr int LUA_VLCL = makevariant(LUA_TFUNCTION, 0); /* Lua closure */ |
| 31 | +inline constexpr int LUA_VLCF = makevariant(LUA_TFUNCTION, 1); /* light C function */ |
| 32 | +inline constexpr int LUA_VCCL = makevariant(LUA_TFUNCTION, 2); /* C closure */ |
| 33 | + |
| 34 | +constexpr bool ttisfunction(const TValue* o) noexcept { return checktype(o, LUA_TFUNCTION); } |
| 35 | +constexpr bool ttisLclosure(const TValue* o) noexcept { return checktag(o, ctb(LUA_VLCL)); } |
| 36 | +constexpr bool ttislcf(const TValue* o) noexcept { return checktag(o, LUA_VLCF); } |
| 37 | +constexpr bool ttisCclosure(const TValue* o) noexcept { return checktag(o, ctb(LUA_VCCL)); } |
| 38 | +constexpr bool ttisclosure(const TValue* o) noexcept { return ttisLclosure(o) || ttisCclosure(o); } |
| 39 | + |
| 40 | +constexpr bool TValue::isFunction() const noexcept { return checktype(this, LUA_TFUNCTION); } |
| 41 | +constexpr bool TValue::isLClosure() const noexcept { return checktag(this, ctb(LUA_VLCL)); } |
| 42 | +constexpr bool TValue::isLightCFunction() const noexcept { return checktag(this, LUA_VLCF); } |
| 43 | +constexpr bool TValue::isCClosure() const noexcept { return checktag(this, ctb(LUA_VCCL)); } |
| 44 | +constexpr bool TValue::isClosure() const noexcept { return isLClosure() || isCClosure(); } |
| 45 | + |
| 46 | +inline constexpr bool isLfunction(const TValue* o) noexcept { |
| 47 | + return ttisLclosure(o); |
| 48 | +} |
| 49 | + |
| 50 | +constexpr bool TValue::isLuaFunction() const noexcept { return isLClosure(); } |
| 51 | + |
| 52 | +inline Closure* clvalue(const TValue* o) noexcept { return o->closureValue(); } |
| 53 | +inline LClosure* clLvalue(const TValue* o) noexcept { return o->lClosureValue(); } |
| 54 | +inline CClosure* clCvalue(const TValue* o) noexcept { return o->cClosureValue(); } |
| 55 | + |
| 56 | +inline lua_CFunction fvalue(const TValue* o) noexcept { return o->functionValue(); } |
| 57 | + |
| 58 | +constexpr lua_CFunction fvalueraw(const Value& v) noexcept { return v.f; } |
| 59 | + |
| 60 | + |
| 61 | +/* setfvalue now defined as inline function below */ |
| 62 | + |
| 63 | +/* setclCvalue now defined as inline function below */ |
| 64 | + |
| 65 | + |
| 66 | +/* |
| 67 | +** Upvalues for Lua closures |
| 68 | +*/ |
| 69 | +// UpVal inherits from GCBase (CRTP) |
| 70 | +class UpVal : public GCBase<UpVal> { |
| 71 | +private: |
| 72 | + union { |
| 73 | + TValue *p; /* points to stack or to its own value */ |
| 74 | + ptrdiff_t offset; /* used while the stack is being reallocated */ |
| 75 | + } v; |
| 76 | + union { |
| 77 | + struct { /* (when open) */ |
| 78 | + UpVal *next; /* linked list */ |
| 79 | + UpVal **previous; |
| 80 | + } open; |
| 81 | + TValue value; /* the value (when closed) */ |
| 82 | + } u; |
| 83 | + |
| 84 | +public: |
| 85 | + // Phase 50: Constructor - initializes all fields to safe defaults |
| 86 | + UpVal() noexcept { |
| 87 | + v.p = nullptr; // Initialize v union (pointer variant) |
| 88 | + // Initialize u union as closed upvalue with nil |
| 89 | + u.value.valueField().n = 0; // Zero-initialize Value union |
| 90 | + u.value.setType(LUA_TNIL); |
| 91 | + } |
| 92 | + |
| 93 | + // Phase 50: Destructor - trivial (GC handles deallocation) |
| 94 | + ~UpVal() noexcept = default; |
| 95 | + |
| 96 | + // Phase 50: Placement new operator - integrates with Lua's GC (implemented in lgc.h) |
| 97 | + static void* operator new(size_t size, lua_State* L, lu_byte tt); |
| 98 | + |
| 99 | + // Disable regular new/delete (must use placement new with GC) |
| 100 | + static void* operator new(size_t) = delete; |
| 101 | + static void operator delete(void*) = delete; |
| 102 | + |
| 103 | + // Inline accessors for v union |
| 104 | + TValue* getVP() noexcept { return v.p; } |
| 105 | + const TValue* getVP() const noexcept { return v.p; } |
| 106 | + void setVP(TValue* ptr) noexcept { v.p = ptr; } |
| 107 | + |
| 108 | + ptrdiff_t getOffset() const noexcept { return v.offset; } |
| 109 | + void setOffset(ptrdiff_t off) noexcept { v.offset = off; } |
| 110 | + |
| 111 | + // Inline accessors for u union (open upvalues) |
| 112 | + UpVal* getOpenNext() const noexcept { return u.open.next; } |
| 113 | + void setOpenNext(UpVal* next_uv) noexcept { u.open.next = next_uv; } |
| 114 | + UpVal** getOpenNextPtr() noexcept { return &u.open.next; } |
| 115 | + |
| 116 | + UpVal** getOpenPrevious() const noexcept { return u.open.previous; } |
| 117 | + void setOpenPrevious(UpVal** prev) noexcept { u.open.previous = prev; } |
| 118 | + |
| 119 | + // Accessor for u.value (closed upvalues) |
| 120 | + TValue* getValueSlot() noexcept { return &u.value; } |
| 121 | + const TValue* getValueSlot() const noexcept { return &u.value; } |
| 122 | + |
| 123 | + // Status check |
| 124 | + bool isOpen() const noexcept { return v.p != &u.value; } |
| 125 | + |
| 126 | + // Level accessor for open upvalues (Phase 44.3) |
| 127 | + StkId getLevel() const noexcept { |
| 128 | + lua_assert(isOpen()); |
| 129 | + return reinterpret_cast<StkId>(v.p); |
| 130 | + } |
| 131 | + |
| 132 | + // Backward compatibility (getValue returns current value pointer) |
| 133 | + TValue* getValue() noexcept { return v.p; } |
| 134 | + const TValue* getValue() const noexcept { return v.p; } |
| 135 | + |
| 136 | + // Methods (implemented in lfunc.cpp) |
| 137 | + void unlink(); |
| 138 | +}; |
| 139 | + |
| 140 | + |
| 141 | + |
| 142 | +// Closures inherit from GCBase (CRTP) |
| 143 | +// ClosureHeader fields: nupvalues, gclist (GC fields inherited from GCBase) |
| 144 | + |
| 145 | +class CClosure : public GCBase<CClosure> { |
| 146 | +private: |
| 147 | + lu_byte nupvalues; |
| 148 | + GCObject *gclist; |
| 149 | + lua_CFunction f; |
| 150 | + TValue upvalue[1]; /* list of upvalues */ |
| 151 | + |
| 152 | +public: |
| 153 | + // Member placement new operator for GC allocation (defined in lgc.h) |
| 154 | + static void* operator new(size_t size, lua_State* L, lu_byte tt, size_t extra = 0); |
| 155 | + |
| 156 | + // Constructor |
| 157 | + CClosure(int nupvals); |
| 158 | + |
| 159 | + // Factory method |
| 160 | + static CClosure* create(lua_State* L, int nupvals); |
| 161 | + |
| 162 | + // Inline accessors |
| 163 | + lua_CFunction getFunction() const noexcept { return f; } |
| 164 | + void setFunction(lua_CFunction func) noexcept { f = func; } |
| 165 | + |
| 166 | + lu_byte getNumUpvalues() const noexcept { return nupvalues; } |
| 167 | + void setNumUpvalues(lu_byte n) noexcept { nupvalues = n; } |
| 168 | + |
| 169 | + TValue* getUpvalue(int idx) noexcept { return &upvalue[idx]; } |
| 170 | + const TValue* getUpvalue(int idx) const noexcept { return &upvalue[idx]; } |
| 171 | + |
| 172 | + GCObject* getGclist() noexcept { return gclist; } |
| 173 | + void setGclist(GCObject* gc) noexcept { gclist = gc; } |
| 174 | + // For GC gray list traversal - allows efficient list manipulation |
| 175 | + GCObject** getGclistPtr() noexcept { return &gclist; } |
| 176 | + |
| 177 | + // Static helper for size calculation (can access private upvalue field) |
| 178 | + static constexpr size_t sizeForUpvalues(int n) noexcept { |
| 179 | + return offsetof(CClosure, upvalue) + sizeof(TValue) * cast_uint(n); |
| 180 | + } |
| 181 | +}; |
| 182 | + |
| 183 | +class LClosure : public GCBase<LClosure> { |
| 184 | +private: |
| 185 | + lu_byte nupvalues; |
| 186 | + GCObject *gclist; |
| 187 | + Proto *p; |
| 188 | + UpVal *upvals[1]; /* list of upvalues */ |
| 189 | + |
| 190 | +public: |
| 191 | + // Member placement new operator for GC allocation (defined in lgc.h) |
| 192 | + static void* operator new(size_t size, lua_State* L, lu_byte tt, size_t extra = 0); |
| 193 | + |
| 194 | + // Constructor |
| 195 | + LClosure(int nupvals); |
| 196 | + |
| 197 | + // Factory method |
| 198 | + static LClosure* create(lua_State* L, int nupvals); |
| 199 | + |
| 200 | + // Inline accessors |
| 201 | + Proto* getProto() const noexcept { return p; } |
| 202 | + void setProto(Proto* proto) noexcept { p = proto; } |
| 203 | + |
| 204 | + lu_byte getNumUpvalues() const noexcept { return nupvalues; } |
| 205 | + void setNumUpvalues(lu_byte n) noexcept { nupvalues = n; } |
| 206 | + |
| 207 | + UpVal* getUpval(int idx) const noexcept { return upvals[idx]; } |
| 208 | + void setUpval(int idx, UpVal* uv) noexcept { upvals[idx] = uv; } |
| 209 | + UpVal** getUpvalPtr(int idx) noexcept { return &upvals[idx]; } |
| 210 | + |
| 211 | + GCObject* getGclist() noexcept { return gclist; } |
| 212 | + void setGclist(GCObject* gc) noexcept { gclist = gc; } |
| 213 | + // For GC gray list traversal - allows efficient list manipulation |
| 214 | + GCObject** getGclistPtr() noexcept { return &gclist; } |
| 215 | + |
| 216 | + // Static helper for size calculation (can access private upvals field) |
| 217 | + static constexpr size_t sizeForUpvalues(int n) noexcept { |
| 218 | + return offsetof(LClosure, upvals) + sizeof(UpVal *) * cast_uint(n); |
| 219 | + } |
| 220 | + |
| 221 | + // Methods (implemented in lfunc.cpp) |
| 222 | + void initUpvals(lua_State* L); |
| 223 | +}; |
| 224 | + |
| 225 | + |
| 226 | +typedef union Closure { |
| 227 | + CClosure c; |
| 228 | + LClosure l; |
| 229 | +} Closure; |
| 230 | + |
| 231 | +inline Proto* getproto(const TValue* o) noexcept { |
| 232 | + return clLvalue(o)->getProto(); |
| 233 | +} |
| 234 | + |
| 235 | +/* }================================================================== */ |
12 | 236 |
|
13 | 237 |
|
14 | 238 | // Phase 88: Convert sizeCclosure and sizeLclosure macros to inline constexpr functions |
|
0 commit comments