Lots of cleanup. Got rid of instances.

This commit is contained in:
Bruce Hill 2018-02-09 15:57:34 -08:00
parent 9172b8ceae
commit 5c8d0fd69a
2 changed files with 78 additions and 76 deletions

View File

@ -6,22 +6,7 @@
#include "lua.h"
#include "lauxlib.h"
#if !__has_include("lstate.h")
// LUAJIT
#include "lj_tab.h"
#include "lj_obj.h"
#define Table GCtab
#define setobj2s(L,obj1,obj2) copyTV(L, obj1, obj2);
#define luaH_getnum(t,k) arrayslot(t, k)
#else
#include "lstate.h"
#include "ltable.h"
#endif
#define HASH_BUCKETS 1
#define MYNAME "immutable"
#define MYTYPE MYNAME
@ -48,17 +33,14 @@ static int Lcreate_instance(lua_State *L)
lua_pop(L,1);
// Stack: []
lua_getfield(L, 1, "__instances");
// Stack: [__instances]
lua_createtable(L, n, 0);
// Stack [__instances, inst]
// Stack [inst]
// Copy in all the values, and simultaneously compute the hash:
lua_Integer hash = 0;
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
lua_pushinteger(L, i);
lua_pushvalue(L, i+1);
// Stack [__instances, inst, i, args[i+1]]
// Stack [inst, args[i+1]]
lua_Integer item_hash;
switch (lua_type(L, -1)) {
case LUA_TNIL:
@ -91,68 +73,67 @@ static int Lcreate_instance(lua_State *L)
item_hash = 0;
}
hash = (1000003 * hash) ^ item_hash;
lua_settable(L, -3);
// Stack [__instances, inst]
lua_rawseti(L, -2, i);
// Stack [inst]
}
// Stack: [__instances, inst]
lua_rawgeti(L, 1, HASH_BUCKETS);
// Stack: [inst, buckets]
// Find bucket
lua_pushinteger(L, hash);
// Stack: [__instances, inst, hash]
lua_gettable(L, -3);
// Stack: [__instances, inst, bucket]
lua_rawgeti(L, -1, hash);
// Stack: [inst, buckets, bucket]
if (lua_isnil(L, -1)) {
// Make a new bucket
// Stack: [__instances, inst, nil]
// Stack: [inst, buckets, nil]
lua_pop(L, 1);
// Stack: [__instances, inst]
// Stack: [inst, buckets]
lua_createtable(L, 1, 0);
// Stack: [__instances, inst, bucket]
// Stack: [inst, buckets, bucket]
// TODO: share bucket metatables
lua_createtable(L, 0, 1);
// Stack: [__instances, inst, bucket, bucket_mt]
lua_pushstring(L, "__mode");
// Stack: [inst, buckets, bucket, bucket_mt]
lua_pushstring(L, "k");
// Stack: [__instances, inst, bucket, bucket_mt, '__mode', 'k']
lua_settable(L, -3);
// Stack: [__instances, inst, bucket, {'__mode'='k'}]
lua_setfield(L, -2, "__mode");
// Stack: [inst, buckets, bucket, {'__mode'='k'}]
lua_setmetatable(L, -2);
// Stack: [__instances, inst, bucket]
// Stack: [inst, buckets, bucket]
lua_pushinteger(L, hash);
// Stack: [__instances, inst, bucket, hash]
lua_pushvalue(L, -2);
// Stack: [__instances, inst, bucket, hash, bucket]
lua_settable(L, -5);
// Stack: [__instances, inst, bucket]
lua_pushvalue(L, -1);
// Stack: [inst, buckets, bucket, bucket]
lua_rawseti(L, -3, hash);
// Stack: [inst, buckets, bucket]
}
// Stack: [__instances, inst, bucket]
// Stack: [inst, buckets, bucket]
// scan bucket
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider]
while (lua_next(L, -2) != 0) { // for hash_collider_inst, hash_collider in pairs(bucket) do
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider]
int bucket_item_matches = 1;
// Perform a full equality check
lua_pushnil(L);
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, nil]
while (lua_next(L, -2) != 0) {
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key, collider_value]
while (lua_next(L, -2) != 0) { // for collider_key, collider_value in pairs(hash_collider) do
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value]
lua_pushvalue(L, -2);
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, collider_key]
lua_gettable(L, -7); // inst[collider_key]
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
if (!lua_equal(L, -1, -2)) {
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, collider_key]
lua_gettable(L, -8); // inst[collider_key]
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
if (!lua_rawequal(L, -1, -2)) {
// go to next item in the bucket
bucket_item_matches = 0;
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
lua_pop(L, 4);
// Stack: [inst, buckets, bucket, hash_collider_inst]
break;
// Stack: [__instances, inst, bucket, hash_collider_inst]
} else {
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key, collider_value, inst_value]
lua_pop(L, 2);
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider, collider_key]
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider, collider_key]
}
}
if (bucket_item_matches) {
// Stack: [__instances, inst, bucket, hash_collider_inst, hash_collider]
// Stack: [inst, buckets, bucket, hash_collider_inst, hash_collider]
lua_pop(L, 1);
// Found matching singleton
return 1;
@ -160,24 +141,23 @@ static int Lcreate_instance(lua_State *L)
}
// failed to find a singleton
// Stack: [__instances, inst, bucket]
// Stack: [inst, buckets, bucket]
const void *data = lua_topointer(L, -2);
void** userdata = (void**)lua_newuserdata(L, sizeof(void*));
*userdata = (void*)data;
lua_Integer* userdata = (lua_Integer*)lua_newuserdata(L, sizeof(lua_Integer));
*userdata = hash;
// Stack [__instances, inst, bucket, inst_userdata]
// Stack [inst, buckets, bucket, inst_userdata]
lua_pushvalue(L, 1);
// Stack [__instances, inst, bucket, inst_userdata, metatable]
// Stack [inst, buckets, bucket, inst_userdata, metatable]
lua_setmetatable(L, -2);
// Stack [__instances, inst, bucket, inst_userdata]
// Stack [inst, buckets, bucket, inst_userdata]
lua_pushvalue(L, -1);
// Stack [__instances, inst, bucket, inst_userdata, inst_userdata]
lua_pushvalue(L, -4);
// Stack [__instances, inst, bucket, inst_userdata, inst_userdata, inst]
lua_settable(L, -4);
// Stack [__instances, inst, bucket, inst_userdata]
// Stack [inst, buckets, bucket, inst_userdata, inst_userdata]
lua_pushvalue(L, -5);
// Stack [inst, buckets, bucket, inst_userdata, inst_userdata, inst]
lua_settable(L, -4); // buckets[inst_userdata] = inst
// Stack [inst, buckets, bucket, inst_userdata]
return 1;
}
@ -199,11 +179,21 @@ static int Lindex(lua_State *L)
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_equal(L, -1, 2)) {
Table **inst_table = (Table**)lua_touserdata(L, 1);
lua_Integer i = lua_tointeger(L, -2);
const TValue* value = luaH_getnum(*inst_table, i);
setobj2s(L, L->top - 1, value);
// Stack: [mt, fields, i, field]
if (lua_rawequal(L, -1, 2)) {
lua_pop(L, 1);
// All the slowness is concentrated here
// Stack: [mt, fields, i]
lua_rawgeti(L, -3, HASH_BUCKETS);
// Stack: [mt, fields, i, buckets]
lua_rawgeti(L, -1, *((lua_Integer*)lua_touserdata(L, 1)));
// Stack: [mt, fields, i, buckets, bucket]
lua_pushvalue(L, 1);
// Stack: [mt, fields, i, buckets, bucket, inst_udata]
lua_rawget(L, -2);
// Stack: [mt, fields, i, buckets, bucket, inst_table]
lua_rawgeti(L, -1, lua_tonumber(L, -4));
// Stack: [mt, fields, i, buckets, bucket, inst_table, result]
return 1;
}
lua_pop(L, 1);
@ -213,6 +203,7 @@ static int Lindex(lua_State *L)
lua_getfield(L, -1, "__methods");
// Stack: [mt, __methods]
lua_pushvalue(L, 2);
// Stack: [mt, __methods, key]
lua_gettable(L, -2);
return 1;
}
@ -249,10 +240,10 @@ static int Lmake_class(lua_State *L)
}
}
// CLS.__instances = {}
// CLS.buckets = {}
lua_newtable(L);
// Stack: [CLS, CLS.__instances]
lua_setfield(L, -2, "__instances");
// Stack: [CLS, CLS.buckets]
lua_rawseti(L, -2, HASH_BUCKETS);
// Stack: [CLS]
// CLS.__fields = arg1

View File

@ -5,6 +5,17 @@ local red = string.char(27).."[31m"
local green = string.char(27).."[32m"
local reset = string.char(27).."[0m"
print(bright..underscore.."\nTesting with ".._VERSION..":"..reset)
repr = function(t)
local buff = tostring(t)
if type(t) == 'table' then
buff = "{"..buff.." "
for k, v in pairs(t) do
buff = buff..("%s = %s, "):format(k,v)
end
buff = buff.."}"
end
return buff
end
local num_errors = 0
local test_number = 0