diff --git a/VM/include/luaconf.h b/VM/include/luaconf.h index 8bb3d609..29c31f40 100644 --- a/VM/include/luaconf.h +++ b/VM/include/luaconf.h @@ -124,3 +124,11 @@ } #define LUA_FLOAT4_VECTORS + +#ifdef LUA_FLOAT4_VECTORS +#define LUA_VECTOR_SIZE 4 +#else +#define LUA_VECTOR_SIZE 3 +#endif + +#define LUA_EXTRA_VALUE_SIZE LUA_VECTOR_SIZE - 2 // note: this assumes vector size >= 2! \ No newline at end of file diff --git a/VM/src/lbuiltins.cpp b/VM/src/lbuiltins.cpp index 71182dd3..3067b14a 100644 --- a/VM/src/lbuiltins.cpp +++ b/VM/src/lbuiltins.cpp @@ -1016,9 +1016,9 @@ static int luauF_tunpack(lua_State* L, StkId res, TValue* arg0, int nresults, St return -1; } -#ifdef LUA_FLOAT4_VECTORS static int luauF_vector(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) { +#ifdef LUA_FLOAT4_VECTORS if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1) && ttisnumber(args + 2)) { double x = nvalue(arg0); @@ -1029,12 +1029,7 @@ static int luauF_vector(lua_State* L, StkId res, TValue* arg0, int nresults, Stk setvvalue(res, float(x), float(y), float(z), float(w)); return 1; } - - return -1; -} #else -static int luauF_vector(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1)) { double x = nvalue(arg0); @@ -1044,10 +1039,10 @@ static int luauF_vector(lua_State* L, StkId res, TValue* arg0, int nresults, Stk setvvalue(res, float(x), float(y), float(z)); return 1; } +#endif return -1; } -#endif static int luauF_countlz(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) { diff --git a/VM/src/lmem.cpp b/VM/src/lmem.cpp index 96659823..d4eed618 100644 --- a/VM/src/lmem.cpp +++ b/VM/src/lmem.cpp @@ -35,17 +35,15 @@ #ifdef LUA_FLOAT4_VECTORS static_assert(sizeof(TValue) == ABISWITCH(24, 24, 24), "size mismatch for value"); -static_assert(offsetof(TString, data) == ABISWITCH(24, 20, 20), "size mismatch for string header"); -static_assert(offsetof(Udata, data) == ABISWITCH(24, 16, 16), "size mismatch for userdata header"); -static_assert(sizeof(Table) == ABISWITCH(56, 36, 36), "size mismatch for table header"); static_assert(sizeof(LuaNode) == ABISWITCH(48, 48, 48), "size mismatch for table entry"); #else static_assert(sizeof(TValue) == ABISWITCH(16, 16, 16), "size mismatch for value"); +static_assert(sizeof(LuaNode) == ABISWITCH(32, 32, 32), "size mismatch for table entry"); +#endif + static_assert(offsetof(TString, data) == ABISWITCH(24, 20, 20), "size mismatch for string header"); static_assert(offsetof(Udata, data) == ABISWITCH(24, 16, 16), "size mismatch for userdata header"); static_assert(sizeof(Table) == ABISWITCH(56, 36, 36), "size mismatch for table header"); -static_assert(sizeof(LuaNode) == ABISWITCH(32, 32, 32), "size mismatch for table entry"); -#endif const size_t kSizeClasses = LUA_SIZECLASSES; const size_t kMaxSmallSize = 512; diff --git a/VM/src/lobject.h b/VM/src/lobject.h index eb205910..0dca7351 100644 --- a/VM/src/lobject.h +++ b/VM/src/lobject.h @@ -47,11 +47,7 @@ typedef union typedef struct lua_TValue { Value value; -#ifdef LUA_FLOAT4_VECTORS - int extra[2]; -#else - int extra; -#endif + int extra[LUA_EXTRA_VALUE_SIZE]; int tt; } TValue; @@ -381,11 +377,7 @@ typedef struct Closure typedef struct TKey { ::Value value; -#ifdef LUA_FLOAT4_VECTORS - int extra[2]; -#else - int extra; -#endif + int extra[LUA_EXTRA_VALUE_SIZE]; unsigned tt : 4; int next : 28; /* for chaining */ } TKey; @@ -396,15 +388,14 @@ typedef struct LuaNode TKey key; } LuaNode; -#ifdef LUA_FLOAT4_VECTORS /* copy a value into a key */ #define setnodekey(L, node, obj) \ { \ LuaNode* n_ = (node); \ const TValue* i_o = (obj); \ n_->key.value = i_o->value; \ - n_->key.extra[0] = i_o->extra[0]; \ - n_->key.extra[1] = i_o->extra[1]; \ + for (int i = 0; i < LUA_EXTRA_VALUE_SIZE; i++) \ + n_->key.extra[i] = i_o->extra[i]; \ n_->key.tt = i_o->tt; \ checkliveness(L->global, i_o); \ } @@ -415,34 +406,11 @@ typedef struct LuaNode TValue* i_o = (obj); \ const LuaNode* n_ = (node); \ i_o->value = n_->key.value; \ - i_o->extra[0] = n_->key.extra[0]; \ - i_o->extra[1] = n_->key.extra[1]; \ + for (int i = 0; i < LUA_EXTRA_VALUE_SIZE; i++) \ + i_o->extra[i] = n_->key.extra[i]; \ i_o->tt = n_->key.tt; \ checkliveness(L->global, i_o); \ } -#else -/* copy a value into a key */ -#define setnodekey(L, node, obj) \ - { \ - LuaNode* n_ = (node); \ - const TValue* i_o = (obj); \ - n_->key.value = i_o->value; \ - n_->key.extra = i_o->extra; \ - n_->key.tt = i_o->tt; \ - checkliveness(L->global, i_o); \ - } - -/* copy a value from a key */ -#define getnodekey(L, obj, node) \ - { \ - TValue* i_o = (obj); \ - const LuaNode* n_ = (node); \ - i_o->value = n_->key.value; \ - i_o->extra = n_->key.extra; \ - i_o->tt = n_->key.tt; \ - checkliveness(L->global, i_o); \ - } -#endif // clang-format off typedef struct Table diff --git a/VM/src/ltable.cpp b/VM/src/ltable.cpp index 60d8f0c9..6a01c149 100644 --- a/VM/src/ltable.cpp +++ b/VM/src/ltable.cpp @@ -32,17 +32,10 @@ LUAU_FASTFLAGVARIABLE(LuauArrayBoundary, false) static_assert(offsetof(LuaNode, val) == 0, "Unexpected Node memory layout, pointer cast in gval2slot is incorrect"); -#ifdef LUA_FLOAT4_VECTORS // TKey is bitpacked for memory efficiency so we need to validate bit counts for worst case -static_assert(TKey{{NULL}, {0, 0}, LUA_TDEADKEY, 0}.tt == LUA_TDEADKEY, "not enough bits for tt"); -static_assert(TKey{{NULL}, {0, 0}, LUA_TNIL, MAXSIZE - 1}.next == MAXSIZE - 1, "not enough bits for next"); -static_assert(TKey{{NULL}, {0, 0}, LUA_TNIL, -(MAXSIZE - 1)}.next == -(MAXSIZE - 1), "not enough bits for next"); -#else -// TKey is bitpacked for memory efficiency so we need to validate bit counts for worst case -static_assert(TKey{{NULL}, 0, LUA_TDEADKEY, 0}.tt == LUA_TDEADKEY, "not enough bits for tt"); -static_assert(TKey{{NULL}, 0, LUA_TNIL, MAXSIZE - 1}.next == MAXSIZE - 1, "not enough bits for next"); -static_assert(TKey{{NULL}, 0, LUA_TNIL, -(MAXSIZE - 1)}.next == -(MAXSIZE - 1), "not enough bits for next"); -#endif +static_assert(TKey{{NULL}, {0}, LUA_TDEADKEY, 0}.tt == LUA_TDEADKEY, "not enough bits for tt"); +static_assert(TKey{{NULL}, {0}, LUA_TNIL, MAXSIZE - 1}.next == MAXSIZE - 1, "not enough bits for next"); +static_assert(TKey{{NULL}, {0}, LUA_TNIL, -(MAXSIZE - 1)}.next == -(MAXSIZE - 1), "not enough bits for next"); // reset cache of absent metamethods, cache is updated in luaT_gettm #define invalidateTMcache(t) t->flags = 0 @@ -102,53 +95,31 @@ static LuaNode* hashnum(const Table* t, double n) return hashpow2(t, h2); } +static LuaNode* hashvec(const Table* t, const float* v) +{ + unsigned int i[LUA_VECTOR_SIZE]; + memcpy(i, v, sizeof(i)); + + for(int j = 0; j < LUA_VECTOR_SIZE; j++) + { + // convert -0 to 0 to make sure they hash to the same value + i[j] = (i[j] == 0x8000000) ? 0 : i[j]; + + // scramble bits to make sure that integer coordinates have entropy in lower bits + i[j] ^= i[j] >> 17; + } + + // Optimized Spatial Hashing for Collision Detection of Deformable Objects + static_assert(LUA_VECTOR_SIZE >= 3, "vector size must be 3 or 4 currently"); + unsigned int h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791); + #ifdef LUA_FLOAT4_VECTORS -static LuaNode* hashvec(const Table* t, const float* v) -{ - unsigned int i[4]; - memcpy(i, v, sizeof(i)); - - // convert -0 to 0 to make sure they hash to the same value - i[0] = (i[0] == 0x8000000) ? 0 : i[0]; - i[1] = (i[1] == 0x8000000) ? 0 : i[1]; - i[2] = (i[2] == 0x8000000) ? 0 : i[2]; - i[3] = (i[3] == 0x8000000) ? 0 : i[3]; - - // scramble bits to make sure that integer coordinates have entropy in lower bits - i[0] ^= i[0] >> 17; - i[1] ^= i[1] >> 17; - i[2] ^= i[2] >> 17; - i[3] ^= i[3] >> 17; - - // Optimized Spatial Hashing for Collision Detection of Deformable Objects - unsigned int h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791); h ^= i[3]; // TODO: proper hashing function for 4D vectors - - return hashpow2(t, h); -} -#else -static LuaNode* hashvec(const Table* t, const float* v) -{ - unsigned int i[3]; - memcpy(i, v, sizeof(i)); - - // convert -0 to 0 to make sure they hash to the same value - i[0] = (i[0] == 0x8000000) ? 0 : i[0]; - i[1] = (i[1] == 0x8000000) ? 0 : i[1]; - i[2] = (i[2] == 0x8000000) ? 0 : i[2]; - - // scramble bits to make sure that integer coordinates have entropy in lower bits - i[0] ^= i[0] >> 17; - i[1] ^= i[1] >> 17; - i[2] ^= i[2] >> 17; - - // Optimized Spatial Hashing for Collision Detection of Deformable Objects - unsigned int h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791); - - return hashpow2(t, h); -} #endif + return hashpow2(t, h); +} + /* ** returns the `main' position of an element in a table (that is, the index ** of its hash value) diff --git a/VM/src/lvmexecute.cpp b/VM/src/lvmexecute.cpp index 6c8669a1..3dd0d9cd 100644 --- a/VM/src/lvmexecute.cpp +++ b/VM/src/lvmexecute.cpp @@ -604,11 +604,9 @@ static void luau_execute(lua_State* L) #ifdef LUA_FLOAT4_VECTORS if(name[0] == 'w') ic = 3; - - if (unsigned(ic) < 4 && name[1] == '\0') -#else - if (unsigned(ic) < 3 && name[1] == '\0') #endif + + if (unsigned(ic) < LUA_VECTOR_SIZE && name[1] == '\0') { setnvalue(ra, rb->value.v[ic]); VM_NEXT(); @@ -1533,11 +1531,9 @@ static void luau_execute(lua_State* L) { const float* vb = rb->value.v; const float* vc = rc->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] + vc[0], vb[1] + vc[1], vb[2] + vc[2], vb[3] + vc[3]); -#else - setvvalue(ra, vb[0] + vc[0], vb[1] + vc[1], vb[2] + vc[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] + vc[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else @@ -1583,11 +1579,9 @@ static void luau_execute(lua_State* L) { const float* vb = rb->value.v; const float* vc = rc->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] - vc[0], vb[1] - vc[1], vb[2] - vc[2], vb[3] - vc[3]); -#else - setvvalue(ra, vb[0] - vc[0], vb[1] - vc[1], vb[2] - vc[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] - vc[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else @@ -1633,33 +1627,27 @@ static void luau_execute(lua_State* L) { const float* vb = rb->value.v; float vc = cast_to(float, nvalue(rc)); -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] * vc, vb[1] * vc, vb[2] * vc, vb[2] * vc); -#else - setvvalue(ra, vb[0] * vc, vb[1] * vc, vb[2] * vc); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] * vc; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else if (ttisvector(rb) && ttisvector(rc)) { const float* vb = rb->value.v; const float* vc = rc->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] * vc[0], vb[1] * vc[1], vb[2] * vc[2], vb[3] * vc[3]); -#else - setvvalue(ra, vb[0] * vc[0], vb[1] * vc[1], vb[2] * vc[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] * vc[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else if (ttisnumber(rb) && ttisvector(rc)) { float vb = cast_to(float, nvalue(rb)); const float* vc = rc->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb * vc[0], vb * vc[1], vb * vc[2], vb * vc[3]); -#else - setvvalue(ra, vb * vc[0], vb * vc[1], vb * vc[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb + vc[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else @@ -1706,33 +1694,27 @@ static void luau_execute(lua_State* L) { const float* vb = rb->value.v; float vc = cast_to(float, nvalue(rc)); -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] / vc, vb[1] / vc, vb[2] / vc, vb[3] / vc); -#else - setvvalue(ra, vb[0] / vc, vb[1] / vc, vb[2] / vc); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] / vc; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else if (ttisvector(rb) && ttisvector(rc)) { const float* vb = rb->value.v; const float* vc = rc->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] / vc[0], vb[1] / vc[1], vb[2] / vc[2], vb[3] / vc[3]); -#else - setvvalue(ra, vb[0] / vc[0], vb[1] / vc[1], vb[2] / vc[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] / vc[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else if (ttisnumber(rb) && ttisvector(rc)) { float vb = cast_to(float, nvalue(rb)); const float* vc = rc->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb / vc[0], vb / vc[1], vb / vc[2], vb / vc[3]); -#else - setvvalue(ra, vb / vc[0], vb / vc[1], vb / vc[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb / vc[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else @@ -1865,11 +1847,9 @@ static void luau_execute(lua_State* L) { const float* vb = rb->value.v; float vc = cast_to(float, nvalue(kv)); -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] * vc, vb[1] * vc, vb[2] * vc, vb[3] * vc); -#else - setvvalue(ra, vb[0] * vc, vb[1] * vc, vb[2] * vc); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] * vc; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else @@ -1915,11 +1895,9 @@ static void luau_execute(lua_State* L) { const float* vb = rb->value.v; float vc = cast_to(float, nvalue(kv)); -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, vb[0] / vc, vb[1] / vc, vb[2] / vc, vb[3] / vc); -#else - setvvalue(ra, vb[0] / vc, vb[1] / vc, vb[2] / vc); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] / vc; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else @@ -2084,11 +2062,9 @@ static void luau_execute(lua_State* L) else if (ttisvector(rb)) { const float* vb = rb->value.v; -#ifdef LUA_FLOAT4_VECTORS - setvvalue(ra, -vb[0], -vb[1], -vb[2], -vb[3]); -#else - setvvalue(ra, -vb[0], -vb[1], -vb[2]); -#endif + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = -vb[i]; + setttype(ra, LUA_TVECTOR); VM_NEXT(); } else diff --git a/VM/src/lvmutils.cpp b/VM/src/lvmutils.cpp index acea5401..6e2bbb6d 100644 --- a/VM/src/lvmutils.cpp +++ b/VM/src/lvmutils.cpp @@ -398,49 +398,33 @@ void luaV_doarith(lua_State* L, StkId ra, const TValue* rb, const TValue* rc, TM if (vb && vc) { -#ifdef LUA_FLOAT4_VECTORS switch (op) { case TM_ADD: - setvvalue(ra, vb[0] + vc[0], vb[1] + vc[1], vb[2] + vc[2], vb[3] + vc[3]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] + vc[i]; return; case TM_SUB: - setvvalue(ra, vb[0] - vc[0], vb[1] - vc[1], vb[2] - vc[2], vb[2] - vc[2]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] - vc[i]; return; case TM_MUL: - setvvalue(ra, vb[0] * vc[0], vb[1] * vc[1], vb[2] * vc[2], vb[2] * vc[2]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] * vc[i]; return; case TM_DIV: - setvvalue(ra, vb[0] / vc[0], vb[1] / vc[1], vb[2] / vc[2], vb[2] / vc[2]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] / vc[i]; return; case TM_UNM: - setvvalue(ra, -vb[0], -vb[1], -vb[2], -vb[3]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = -vb[i]; return; default: break; } -#else - switch (op) - { - case TM_ADD: - setvvalue(ra, vb[0] + vc[0], vb[1] + vc[1], vb[2] + vc[2]); - return; - case TM_SUB: - setvvalue(ra, vb[0] - vc[0], vb[1] - vc[1], vb[2] - vc[2]); - return; - case TM_MUL: - setvvalue(ra, vb[0] * vc[0], vb[1] * vc[1], vb[2] * vc[2]); - return; - case TM_DIV: - setvvalue(ra, vb[0] / vc[0], vb[1] / vc[1], vb[2] / vc[2]); - return; - case TM_UNM: - setvvalue(ra, -vb[0], -vb[1], -vb[2]); - return; - default: - break; - } -#endif + + setttype(ra, LUA_TVECTOR); } else if (vb) { @@ -449,31 +433,20 @@ void luaV_doarith(lua_State* L, StkId ra, const TValue* rb, const TValue* rc, TM if (c) { float nc = cast_to(float, nvalue(c)); -#ifdef LUA_FLOAT4_VECTORS switch (op) { case TM_MUL: - setvvalue(ra, vb[0] * nc, vb[1] * nc, vb[2] * nc, vb[3] * nc); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] * nc; return; case TM_DIV: - setvvalue(ra, vb[0] / nc, vb[1] / nc, vb[2] / nc, vb[3] / nc); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = vb[i] / nc; return; default: break; } -#else - switch (op) - { - case TM_MUL: - setvvalue(ra, vb[0] * nc, vb[1] * nc, vb[2] * nc); - return; - case TM_DIV: - setvvalue(ra, vb[0] / nc, vb[1] / nc, vb[2] / nc); - return; - default: - break; - } -#endif + setttype(ra, LUA_TVECTOR); } } else if (vc) @@ -483,31 +456,20 @@ void luaV_doarith(lua_State* L, StkId ra, const TValue* rb, const TValue* rc, TM if (b) { float nb = cast_to(float, nvalue(b)); -#ifdef LUA_FLOAT4_VECTORS switch (op) { case TM_MUL: - setvvalue(ra, nb * vc[0], nb * vc[1], nb * vc[2], nb * vc[3]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = nb * vc[i]; return; case TM_DIV: - setvvalue(ra, nb / vc[0], nb / vc[1], nb / vc[2], nb / vc[2]); + for (int i = 0; i < LUA_VECTOR_SIZE; i++) + ra->value.v[i] = nb / vc[i]; return; default: break; } -#else - switch (op) - { - case TM_MUL: - setvvalue(ra, nb * vc[0], nb * vc[1], nb * vc[2]); - return; - case TM_DIV: - setvvalue(ra, nb / vc[0], nb / vc[1], nb / vc[2]); - return; - default: - break; - } -#endif + setttype(ra, LUA_TVECTOR); } }