diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-07-20 15:24:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-07-20 15:24:50 -0300 |
commit | e247c3ada3ff47a1352927e797263137f4e02e0e (patch) | |
tree | 4d2563f59472bdee4c4f58dd87cb1d8eeaf2c1b3 | |
parent | b5dc2f9b0c57fef5f72152973938ff5265366dcd (diff) | |
download | lua-e247c3ada3ff47a1352927e797263137f4e02e0e.tar.gz lua-e247c3ada3ff47a1352927e797263137f4e02e0e.tar.bz2 lua-e247c3ada3ff47a1352927e797263137f4e02e0e.zip |
implementation of fast track for gettable operations
-rw-r--r-- | lapi.c | 48 | ||||
-rw-r--r-- | lvm.c | 32 | ||||
-rw-r--r-- | lvm.h | 28 |
3 files changed, 70 insertions, 38 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.249 2015/04/06 12:23:48 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.250 2015/06/18 14:19:52 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -579,16 +579,27 @@ LUA_API int lua_pushthread (lua_State *L) { | |||
579 | */ | 579 | */ |
580 | 580 | ||
581 | 581 | ||
582 | static int auxgetstr (lua_State *L, const TValue *t, const char *k) { | ||
583 | const TValue *aux; | ||
584 | TString *str = luaS_new(L, k); | ||
585 | if (luaV_fastget(L, t, str, aux, luaH_getstr)) { | ||
586 | setobj2s(L, L->top, aux); | ||
587 | api_incr_top(L); | ||
588 | } | ||
589 | else { | ||
590 | setsvalue2s(L, L->top, str); | ||
591 | api_incr_top(L); | ||
592 | luaV_finishget(L, t, L->top - 1, L->top - 1, aux); | ||
593 | } | ||
594 | lua_unlock(L); | ||
595 | return ttnov(L->top - 1); | ||
596 | } | ||
597 | |||
598 | |||
582 | LUA_API int lua_getglobal (lua_State *L, const char *name) { | 599 | LUA_API int lua_getglobal (lua_State *L, const char *name) { |
583 | Table *reg = hvalue(&G(L)->l_registry); | 600 | Table *reg = hvalue(&G(L)->l_registry); |
584 | const TValue *gt; /* global table */ | ||
585 | lua_lock(L); | 601 | lua_lock(L); |
586 | gt = luaH_getint(reg, LUA_RIDX_GLOBALS); | 602 | return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); |
587 | setsvalue2s(L, L->top, luaS_new(L, name)); | ||
588 | api_incr_top(L); | ||
589 | luaV_gettable(L, gt, L->top - 1, L->top - 1); | ||
590 | lua_unlock(L); | ||
591 | return ttnov(L->top - 1); | ||
592 | } | 603 | } |
593 | 604 | ||
594 | 605 | ||
@@ -603,24 +614,25 @@ LUA_API int lua_gettable (lua_State *L, int idx) { | |||
603 | 614 | ||
604 | 615 | ||
605 | LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { | 616 | LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { |
606 | StkId t; | ||
607 | lua_lock(L); | 617 | lua_lock(L); |
608 | t = index2addr(L, idx); | 618 | return auxgetstr(L, index2addr(L, idx), k); |
609 | setsvalue2s(L, L->top, luaS_new(L, k)); | ||
610 | api_incr_top(L); | ||
611 | luaV_gettable(L, t, L->top - 1, L->top - 1); | ||
612 | lua_unlock(L); | ||
613 | return ttnov(L->top - 1); | ||
614 | } | 619 | } |
615 | 620 | ||
616 | 621 | ||
617 | LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { | 622 | LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { |
618 | StkId t; | 623 | StkId t; |
624 | const TValue *aux; | ||
619 | lua_lock(L); | 625 | lua_lock(L); |
620 | t = index2addr(L, idx); | 626 | t = index2addr(L, idx); |
621 | setivalue(L->top, n); | 627 | if (luaV_fastget(L, t, n, aux, luaH_getint)) { |
622 | api_incr_top(L); | 628 | setobj2s(L, L->top, aux); |
623 | luaV_gettable(L, t, L->top - 1, L->top - 1); | 629 | api_incr_top(L); |
630 | } | ||
631 | else { | ||
632 | setivalue(L->top, n); | ||
633 | api_incr_top(L); | ||
634 | luaV_finishget(L, t, L->top - 1, L->top - 1, aux); | ||
635 | } | ||
624 | lua_unlock(L); | 636 | lua_unlock(L); |
625 | return ttnov(L->top - 1); | 637 | return ttnov(L->top - 1); |
626 | } | 638 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.246 2015/06/25 14:00:01 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.247 2015/07/04 16:31:03 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -153,30 +153,28 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, | |||
153 | 153 | ||
154 | 154 | ||
155 | /* | 155 | /* |
156 | ** Main function for table access (invoking metamethods if needed). | 156 | ** Complete a table access: if 't' is a table, 'tm' has its metamethod; |
157 | ** Compute 'val = t[key]' | 157 | ** otherwise, 'tm' is NULL. |
158 | */ | 158 | */ |
159 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 159 | void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, |
160 | const TValue *tm) { | ||
160 | int loop; /* counter to avoid infinite loops */ | 161 | int loop; /* counter to avoid infinite loops */ |
162 | lua_assert(tm != NULL || !ttistable(t)); | ||
161 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 163 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
162 | const TValue *tm; | 164 | if (tm == NULL) { /* no metamethod (from a table)? */ |
163 | if (ttistable(t)) { /* 't' is a table? */ | 165 | if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) |
164 | Table *h = hvalue(t); | 166 | luaG_typeerror(L, t, "index"); /* no metamethod */ |
165 | const TValue *res = luaH_get(h, key); /* do a primitive get */ | ||
166 | if (!ttisnil(res) || /* result is not nil? */ | ||
167 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ | ||
168 | setobj2s(L, val, res); /* result is the raw get */ | ||
169 | return; | ||
170 | } | ||
171 | /* else will try metamethod */ | ||
172 | } | 167 | } |
173 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) | ||
174 | luaG_typeerror(L, t, "index"); /* no metamethod */ | ||
175 | if (ttisfunction(tm)) { /* metamethod is a function */ | 168 | if (ttisfunction(tm)) { /* metamethod is a function */ |
176 | luaT_callTM(L, tm, t, key, val, 1); | 169 | luaT_callTM(L, tm, t, key, val, 1); /* call it */ |
177 | return; | 170 | return; |
178 | } | 171 | } |
179 | t = tm; /* else repeat access over 'tm' */ | 172 | t = tm; /* else repeat access over 'tm' */ |
173 | if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ | ||
174 | setobj2s(L, val, tm); /* done */ | ||
175 | return; | ||
176 | } | ||
177 | /* else repeat */ | ||
180 | } | 178 | } |
181 | luaG_runerror(L, "gettable chain too long; possible loop"); | 179 | luaG_runerror(L, "gettable chain too long; possible loop"); |
182 | } | 180 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -48,13 +48,35 @@ | |||
48 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) | 48 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) |
49 | 49 | ||
50 | 50 | ||
51 | /* | ||
52 | ** fast track for 'gettable': 1 means 'aux' points to resulted value; | ||
53 | ** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is | ||
54 | ** the raw get function to use. | ||
55 | */ | ||
56 | #define luaV_fastget(L,t,k,aux,f) \ | ||
57 | (!ttistable(t) \ | ||
58 | ? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ | ||
59 | : (aux = f(hvalue(t), k), /* else, do raw access */ \ | ||
60 | !ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ | ||
61 | : (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\ | ||
62 | aux != NULL ? 0 /* has metamethod? must call it */ \ | ||
63 | : (aux = luaO_nilobject, 1)))) /* else, final result is nil */ | ||
64 | |||
65 | /* | ||
66 | ** standard implementation for 'gettable' | ||
67 | */ | ||
68 | #define luaV_gettable(L,t,k,v) { const TValue *aux; \ | ||
69 | if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ | ||
70 | else luaV_finishget(L,t,k,v,aux); } | ||
71 | |||
72 | |||
51 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); | 73 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); |
52 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); | 74 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); |
53 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); | 75 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); |
54 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); | 76 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); |
55 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); | 77 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); |
56 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, | 78 | LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, |
57 | StkId val); | 79 | StkId val, const TValue *tm); |
58 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, | 80 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, |
59 | StkId val); | 81 | StkId val); |
60 | LUAI_FUNC void luaV_finishOp (lua_State *L); | 82 | LUAI_FUNC void luaV_finishOp (lua_State *L); |