Skip to content

Commit

Permalink
* Fast refs. This code is quite a bit faster than the Lua 5.2 refs.
Browse files Browse the repository at this point in the history
Supported through #define LUA_FASTREF_SUPPORT 1.

Available through the new APIs lua_fastref(), lua_fastrefindex(), lua_fastunref(), and lua_getfastref().

Fastrefs are treated exactly as a stack entry within all APIs.
  • Loading branch information
jjensen committed Jan 14, 2011
1 parent b0e54d7 commit 6d308e7
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 2 deletions.
114 changes: 114 additions & 0 deletions src/lapi.c
Expand Up @@ -39,6 +39,28 @@ const char lua_ident[] =
"invalid index")


#if LUA_FASTREF_SUPPORT

static const TValue *luaH_getinthelper (Table *t, int key) {
/* (1 <= key && key <= t->sizearray) */
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
return &t->array[key-1];
else
return luaH_getint(t, key);
}


static TValue *luaH_setinthelper (lua_State *L, Table *t, int key) {
/* (1 <= key && key <= t->sizearray) */
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
return &t->array[key-1];
else
return luaH_setint(L, t, key);
}

#endif /* LUA_FASTREF_SUPPORT */


static TValue *index2addr (lua_State *L, int idx) {
CallInfo *ci = L->ci;
if (idx > 0) {
Expand All @@ -51,6 +73,14 @@ static TValue *index2addr (lua_State *L, int idx) {
api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
return L->top + idx;
}
#if LUA_FASTREF_SUPPORT
else if (idx <= LUA_FASTREFNIL) {
if (idx == LUA_FASTREFNIL)
return &G(L)->fastrefNilValue;
idx = -idx + LUA_FASTREFNIL - 1;
return (TValue*)luaH_getinthelper(hvalue(&G(L)->l_refs), idx);
}
#endif /* LUA_FASTREF_SUPPORT */
else if (idx == LUA_REGISTRYINDEX)
return &G(L)->l_registry;
else { /* upvalues */
Expand Down Expand Up @@ -1214,3 +1244,87 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
luaC_objbarrier(L, f1, *up2);
}



#if LUA_FASTREF_SUPPORT

/*
** {======================================================
** Reference system
** =======================================================
*/

LUA_API int lua_fastrefindex (lua_State *L, int idx) {
const TValue* firstfree;
TValue* value;
TValue* newKey;
int ref;
StkId to = &G(L)->l_refs;

lua_lock(L);

value = index2addr(L, idx);
if (ttype(value) == LUA_TNIL) {
lua_unlock(L);
return LUA_FASTREFNIL;
}

/* get first free element */
firstfree = luaH_getinthelper(hvalue(to), LUA_RIDX_FASTREF_FREELIST);
lua_number2integer(ref, nvalue(firstfree));

if (ref != 0) { /* any free element? */
/* remove it from list */
const TValue* refValue = luaH_getinthelper(hvalue(to), ref);
setobj2t(L, (TValue*)firstfree, refValue);
}
else /* no free elements */
ref = (int)luaH_getn(hvalue(to)) + 1; /* get a new reference */

newKey = luaH_setinthelper(L, hvalue(to), ref);
value = index2addr(L, idx);
setobj2t(L, newKey, value);

luaC_barrierback(L, gcvalue(to), value);

lua_unlock(L);
return LUA_FASTREFNIL - 1 - ref;
}


LUA_API int lua_fastref (lua_State *L) {
int ref;
lua_lock(L);
ref = lua_fastrefindex(L, -1);
L->top--;
lua_unlock(L);
return ref;
}


LUA_API void lua_fastunref (lua_State *L, int ref) {
ref = -ref + LUA_FASTREFNIL - 1;
if (ref >= 0) {
TValue refObj;
StkId to = &G(L)->l_refs;
const TValue *firstfree = luaH_getinthelper(hvalue(to), LUA_RIDX_FASTREF_FREELIST);
setobj2t(L, luaH_setinthelper(L, hvalue(to), ref), firstfree);
setnvalue(&refObj, cast_num(ref));
setobj2t(L, (TValue*)firstfree, &refObj);
}
}


LUA_API void lua_getfastref (lua_State *L, int ref) {
StkId o = &G(L)->l_refs;
ref = -ref + LUA_FASTREFNIL - 1;
lua_lock(L);
setobj2s(L, L->top, luaH_getinthelper(hvalue(o), ref));
api_incr_top(L);
lua_unlock(L);
}


/* }====================================================== */

#endif /* LUA_FASTREF_SUPPORT */
6 changes: 6 additions & 0 deletions src/lgc.c
Expand Up @@ -326,6 +326,9 @@ static void markroot (lua_State *L) {
markobject(g, g->mainthread);
markvalue(g, &g->l_registry);
markmt(g);
#if LUA_FASTREF_SUPPORT
markvalue(g, &g->l_refs);
#endif /* LUA_FASTREF_SUPPORT */
markbeingfnz(g); /* mark any finalizing object left from previous cycle */
}

Expand Down Expand Up @@ -854,6 +857,9 @@ static void atomic (lua_State *L) {
/* registry and global metatables may be changed by API */
markvalue(g, &g->l_registry);
markmt(g); /* mark basic metatables */
#if LUA_FASTREF_SUPPORT
markvalue(g, &g->l_refs);
#endif /* LUA_FASTREF_SUPPORT */
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
/* traverse objects caught by write barrier and by 'remarkupvals' */
Expand Down
11 changes: 11 additions & 0 deletions src/lstate.c
Expand Up @@ -137,6 +137,17 @@ static void init_registry (lua_State *L, global_State *g) {
/* registry[LUA_RIDX_GLOBALS] = table of globals */
sethvalue(L, &mt, luaH_new(L));
setobj2t(L, luaH_setint(L, registry, LUA_RIDX_GLOBALS), &mt);
#if LUA_FASTREF_SUPPORT
{
TValue n;

sethvalue(L, &G(L)->l_refs, luaH_new(L)); /* refs */
setnvalue(&n, 0);
setobj2t(L, luaH_setint(L, hvalue(&G(L)->l_refs), LUA_RIDX_FASTREF_FREELIST), &n);

setnilvalue(&g->fastrefNilValue);
}
#endif /* LUA_FASTREF */
}


Expand Down
4 changes: 4 additions & 0 deletions src/lstate.h
Expand Up @@ -144,6 +144,10 @@ typedef struct global_State {
TString *memerrmsg; /* memory-error message */
TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
#if LUA_FASTREF_SUPPORT
TValue l_refs;
TValue fastrefNilValue;
#endif /* LUA_FASTREF_SUPPORT */
} global_State;


Expand Down
17 changes: 15 additions & 2 deletions src/lua.h
Expand Up @@ -94,10 +94,13 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);


/* predefined values in the registry */
#define LUA_RIDX_MAINTHREAD 1
#define LUA_RIDX_GLOBALS 2
#define LUA_RIDX_MAINTHREAD 1
#define LUA_RIDX_GLOBALS 2
#define LUA_RIDX_LAST LUA_RIDX_GLOBALS

#if LUA_FASTREF_SUPPORT
#define LUA_RIDX_FASTREF_FREELIST 1
#endif /* LUA_FASTREF_SUPPORT */

/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
Expand Down Expand Up @@ -413,6 +416,16 @@ struct lua_Debug {

/* }====================================================================== */

#if LUA_FASTREF_SUPPORT

#define LUA_FASTREFNIL (-1999999)

LUA_API int lua_fastref (lua_State *L);
LUA_API int lua_fastrefindex (lua_State *L, int idx);
LUA_API void lua_fastunref (lua_State *L, int ref);
LUA_API void lua_getfastref (lua_State *L, int ref);

#endif /* LUA_FASTREF_SUPPORT */

/******************************************************************************
* Copyright (C) 1994-2010 Lua.org, PUC-Rio. All rights reserved.
Expand Down
4 changes: 4 additions & 0 deletions src/luaconf.h
Expand Up @@ -11,6 +11,10 @@
#include <limits.h>
#include <stddef.h>

#ifndef LUA_FASTREF_SUPPORT
#define LUA_FASTREF_SUPPORT 1
#endif /* LUA_FASTREF_SUPPORT */


/*
** ==================================================================
Expand Down

0 comments on commit 6d308e7

Please sign in to comment.