Fixed some edge case stuff with varargs, and added incremental GC.
This commit is contained in:
parent
2630b3ad1d
commit
bd5ed55ebd
31
limmutable.c
31
limmutable.c
@ -38,16 +38,21 @@ static int SHARED_CLASS_METATABLE;
|
|||||||
|
|
||||||
static int Lcreate_instance(lua_State *L)
|
static int Lcreate_instance(lua_State *L)
|
||||||
{
|
{
|
||||||
|
size_t n_args = lua_gettop(L)-1;
|
||||||
// arg 1: class table, ...
|
// arg 1: class table, ...
|
||||||
lua_getfield(L, 1, "__fields");
|
lua_getfield(L, 1, "__fields");
|
||||||
size_t n = lua_objlen(L, -1);
|
size_t n = lua_objlen(L, -1);
|
||||||
|
if (n_args > n) {
|
||||||
|
luaL_error(L, "Too many args: expected %d, but got %d", n, n_args);
|
||||||
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// Compute the hash:
|
// Compute the hash:
|
||||||
lua_Integer hash = (lua_Integer)lua_topointer(L, 1); // Hash depends on the metatable used in creation
|
lua_Integer hash = (lua_Integer)lua_topointer(L, 1); // Hash depends on the metatable used in creation
|
||||||
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
|
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
|
||||||
lua_Integer item_hash;
|
lua_Integer item_hash;
|
||||||
switch (lua_type(L, 1+i)) {
|
int type = n > n_args ? LUA_TNIL : lua_type(L, 1+i);
|
||||||
|
switch (type) {
|
||||||
case LUA_TNIL: case LUA_TNONE:
|
case LUA_TNIL: case LUA_TNONE:
|
||||||
// Arbitrarily chosen value
|
// Arbitrarily chosen value
|
||||||
item_hash = 0x97167da9;
|
item_hash = 0x97167da9;
|
||||||
@ -55,8 +60,8 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
case LUA_TNUMBER:
|
case LUA_TNUMBER:
|
||||||
{
|
{
|
||||||
// Cast float bits to integer
|
// Cast float bits to integer
|
||||||
lua_Number n = lua_tonumber(L, 1+i);
|
lua_Number num = lua_tonumber(L, 1+i);
|
||||||
item_hash = *((lua_Integer*)&n);
|
item_hash = *((lua_Integer*)&num);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TBOOLEAN:
|
case LUA_TBOOLEAN:
|
||||||
@ -98,7 +103,7 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
// Stack: [buckets, nil]
|
// Stack: [buckets, nil]
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
// Stack: [buckets]
|
// Stack: [buckets]
|
||||||
lua_createtable(L, 1, 0);
|
lua_createtable(L, 0, 1);
|
||||||
// Stack: [buckets, bucket]
|
// Stack: [buckets, bucket]
|
||||||
lua_pushlightuserdata(L, (void*)&SHARED_BUCKET_METATABLE);
|
lua_pushlightuserdata(L, (void*)&SHARED_BUCKET_METATABLE);
|
||||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||||
@ -116,7 +121,7 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
while (lua_next(L, -2) != 0) { // for hash_collider_inst, hash_collider in pairs(bucket) do
|
while (lua_next(L, -2) != 0) { // for hash_collider_inst, hash_collider in pairs(bucket) do
|
||||||
// Stack: [buckets, bucket, hash_collider_inst, hash_collider]
|
// Stack: [buckets, bucket, hash_collider_inst, hash_collider]
|
||||||
int bucket_item_matches = 1;
|
int bucket_item_matches = 1;
|
||||||
// Perform a full equality check
|
// Shallow equality check:
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
while (lua_next(L, -2) != 0) { // for i, collider_value in pairs(hash_collider) do
|
while (lua_next(L, -2) != 0) { // for i, collider_value in pairs(hash_collider) do
|
||||||
// Stack: [buckets, bucket, hash_collider_inst, hash_collider, i, value]
|
// Stack: [buckets, bucket, hash_collider_inst, hash_collider, i, value]
|
||||||
@ -135,7 +140,7 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
if (bucket_item_matches) {
|
if (bucket_item_matches) {
|
||||||
// Stack: [buckets, bucket, hash_collider_inst, hash_collider]
|
// Stack: [buckets, bucket, hash_collider_inst, hash_collider]
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
// Found matching singleton
|
// Found matching pre-existing instance
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,14 +159,21 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
// Stack [buckets, bucket, inst_userdata, inst_userdata]
|
// Stack [buckets, bucket, inst_userdata, inst_userdata]
|
||||||
lua_createtable(L, n, 0); // Create the table to store the instance's data
|
lua_createtable(L, n, 0); // Create the table to store the instance's data
|
||||||
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table]
|
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table]
|
||||||
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
|
lua_Integer i;
|
||||||
|
for (i=1; i <= (lua_Integer)n_args; i++) {
|
||||||
lua_pushvalue(L, i+1);
|
lua_pushvalue(L, i+1);
|
||||||
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table, arg #1+i]
|
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table, arg #1+i]
|
||||||
lua_rawseti(L, -2, i);
|
lua_rawseti(L, -2, i);
|
||||||
}
|
}
|
||||||
|
for (; i <= (lua_Integer)n; i++) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table, nil]
|
||||||
|
lua_rawseti(L, -2, i);
|
||||||
|
}
|
||||||
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table]
|
// Stack [buckets, bucket, inst_userdata, inst_userdata, inst_table]
|
||||||
lua_settable(L, -4); // buckets[inst_userdata] = inst_table
|
lua_settable(L, -4); // buckets[inst_userdata] = inst_table
|
||||||
// Stack [buckets, bucket, inst_userdata]
|
// Stack [buckets, bucket, inst_userdata]
|
||||||
|
lua_gc(L, LUA_GCSTEP, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,8 +511,7 @@ static const luaL_Reg Rinstance_metamethods[] =
|
|||||||
static int Lmake_class(lua_State *L)
|
static int Lmake_class(lua_State *L)
|
||||||
{
|
{
|
||||||
// immutable([fields], [methods/metamethods])
|
// immutable([fields], [methods/metamethods])
|
||||||
|
lua_createtable(L, 0, 16); // Rough guess, 16 fields from Rinstance_metamethods + __fields, etc.
|
||||||
lua_newtable(L);
|
|
||||||
// Stack: [CLS]
|
// Stack: [CLS]
|
||||||
// Populate CLS.__len, CLS.__index, CLS.__pairs, etc.
|
// Populate CLS.__len, CLS.__index, CLS.__pairs, etc.
|
||||||
luaL_register(L,NULL,Rinstance_metamethods);
|
luaL_register(L,NULL,Rinstance_metamethods);
|
||||||
@ -525,7 +536,7 @@ static int Lmake_class(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stack: [CLS]
|
// Stack: [CLS]
|
||||||
lua_newtable(L);
|
lua_createtable(L, 0, 32); // Rough guess: at least 32 instances concurrently
|
||||||
// Stack: [CLS, CLS.buckets]
|
// Stack: [CLS, CLS.buckets]
|
||||||
lua_setfield(L, -2, "__instances");
|
lua_setfield(L, -2, "__instances");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user