Browse Source

[Feature] Allow to optimize lua -> C transition by flattening table args

tags/1.2.4
Vsevolod Stakhov 8 years ago
parent
commit
7c783a4d49
1 changed files with 103 additions and 41 deletions
  1. 103
    41
      src/lua/lua_common.c

+ 103
- 41
src/lua/lua_common.c View File

@@ -588,7 +588,7 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
{
const gchar *p, *key = NULL, *end, *cls;
va_list ap;
gboolean required = FALSE, failed = FALSE;
gboolean required = FALSE, failed = FALSE, is_table;
gchar classbuf[128];
enum {
read_key = 0,
@@ -598,14 +598,22 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
read_semicolon
} state = read_key;
gsize keylen = 0, *valuelen, clslen;
gint idx;

g_assert (extraction_pattern != NULL);

if (pos < 0) {
/* Get absolute pos */
pos = lua_gettop (L) + pos + 1;
}

g_assert (extraction_pattern != NULL);
g_assert (lua_type (L, pos) == LUA_TTABLE);
if (lua_type (L, pos) == LUA_TTABLE) {
is_table = TRUE;
}
else {
is_table = FALSE;
idx = pos;
}

p = extraction_pattern;
end = p + strlen (extraction_pattern);
@@ -636,15 +644,19 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
break;
case read_arg:
g_assert (keylen != 0);
lua_pushlstring (L, key, keylen);
lua_gettable (L, pos);

if (is_table) {
lua_pushlstring (L, key, keylen);
lua_gettable (L, pos);
idx = -1;
}

switch (g_ascii_toupper (*p)) {
case 'S':
if (lua_type (L, -1) == LUA_TSTRING) {
*(va_arg (ap, const gchar **)) = lua_tostring (L, -1);
if (lua_type (L, idx) == LUA_TSTRING) {
*(va_arg (ap, const gchar **)) = lua_tostring (L, idx);
}
else if (lua_type (L, -1) == LUA_TNIL) {
else if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
*(va_arg (ap, const gchar **)) = NULL;
}
@@ -661,14 +673,17 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,

return FALSE;
}
lua_pop (L, 1);

if (is_table) {
lua_pop (L, 1);
}
break;

case 'I':
if (lua_type (L, -1) == LUA_TNUMBER) {
*(va_arg (ap, gint64 *)) = lua_tonumber (L, -1);
if (lua_type (L, idx) == LUA_TNUMBER) {
*(va_arg (ap, gint64 *)) = lua_tonumber (L, idx);
}
else if (lua_type (L, -1) == LUA_TNIL) {
else if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
*(va_arg (ap, gint64 *)) = 0;
}
@@ -680,23 +695,31 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
" %.*s: '%s', '%s' is expected",
(gint) keylen,
key,
lua_typename (L, lua_type (L, -1)),
lua_typename (L, lua_type (L, idx)),
"int64");
va_end (ap);

return FALSE;
}
lua_pop (L, 1);
if (is_table) {
lua_pop (L, 1);
}
break;

case 'F':
if (lua_type (L, -1) == LUA_TFUNCTION) {
if (lua_type (L, idx) == LUA_TFUNCTION) {
if (!is_table) {
lua_pushvalue (L, idx);
}

*(va_arg (ap, gint *)) = luaL_ref (L, LUA_REGISTRYINDEX);
}
else if (lua_type (L, -1) == LUA_TNIL) {
else if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
*(va_arg (ap, gint *)) = -1;
lua_pop (L, 1);
if (is_table) {
lua_pop (L, 1);
}
}
else {
g_set_error (err,
@@ -706,10 +729,12 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
" %.*s: '%s', '%s' is expected",
(gint) keylen,
key,
lua_typename (L, lua_type (L, -1)),
lua_typename (L, lua_type (L, idx)),
"function");
va_end (ap);
lua_pop (L, 1);
if (is_table) {
lua_pop (L, 1);
}

return FALSE;
}
@@ -718,10 +743,10 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
break;

case 'B':
if (lua_type (L, -1) == LUA_TBOOLEAN) {
if (lua_type (L, idx) == LUA_TBOOLEAN) {
*(va_arg (ap, gboolean *)) = lua_toboolean (L, -1);
}
else if (lua_type (L, -1) == LUA_TNIL) {
else if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
*(va_arg (ap, gboolean *)) = 0;
}
@@ -733,20 +758,23 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
" %.*s: '%s', '%s' is expected",
(gint) keylen,
key,
lua_typename (L, lua_type (L, -1)),
lua_typename (L, lua_type (L, idx)),
"bool");
va_end (ap);

return FALSE;
}
lua_pop (L, 1);

if (is_table) {
lua_pop (L, 1);
}
break;

case 'N':
if (lua_type (L, -1) == LUA_TNUMBER) {
*(va_arg (ap, gdouble *)) = lua_tonumber (L, -1);
if (lua_type (L, idx) == LUA_TNUMBER) {
*(va_arg (ap, gdouble *)) = lua_tonumber (L, idx);
}
else if (lua_type (L, -1) == LUA_TNIL) {
else if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
*(va_arg (ap, gdouble *)) = 0;
}
@@ -758,22 +786,26 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
" %.*s: '%s', '%s' is expected",
(gint) keylen,
key,
lua_typename (L, lua_type (L, -1)),
lua_typename (L, lua_type (L, idx)),
"double");
va_end (ap);

return FALSE;
}
lua_pop (L, 1);

if (is_table) {
lua_pop (L, 1);
}
break;

case 'V':
valuelen = va_arg (ap, gsize *);
if (lua_type (L, -1) == LUA_TSTRING) {
*(va_arg (ap, const gchar **)) = lua_tolstring (L, -1,

if (lua_type (L, idx) == LUA_TSTRING) {
*(va_arg (ap, const gchar **)) = lua_tolstring (L, idx,
valuelen);
}
else if (lua_type (L, -1) == LUA_TNIL) {
else if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
*(va_arg (ap, const char **)) = NULL;
*valuelen = 0;
@@ -786,19 +818,22 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
" %.*s: '%s', '%s' is expected",
(gint) keylen,
key,
lua_typename (L, lua_type (L, -1)),
lua_typename (L, lua_type (L, idx)),
"string");
va_end (ap);

return FALSE;
}
lua_pop (L, 1);

if (is_table) {
lua_pop (L, 1);
}
break;
case 'U':
if (lua_type (L, -1) == LUA_TNIL) {
if (lua_type (L, idx) == LUA_TNIL) {
failed = TRUE;
}
else if (lua_type (L, -1) != LUA_TUSERDATA) {
else if (lua_type (L, idx) != LUA_TUSERDATA) {
g_set_error (err,
lua_error_quark (),
1,
@@ -831,6 +866,10 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
return FALSE;
}

if (!is_table) {
idx ++;
}

/* Reset read params */
state = read_semicolon;
failed = FALSE;
@@ -846,7 +885,10 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
state = read_class;
}
else {
lua_pop (L, 1);
if (is_table) {
lua_pop (L, 1);
}

g_set_error (err, lua_error_quark (), 2, "missing classname for "
"%.*s", (gint)keylen, key);
va_end (ap);
@@ -860,7 +902,10 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
if (*p == '}') {
clslen = p - cls;
if (clslen == 0) {
lua_pop (L, 1);
if (is_table) {
lua_pop (L, 1);
}

g_set_error (err,
lua_error_quark (),
2,
@@ -876,8 +921,20 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
rspamd_snprintf (classbuf, sizeof (classbuf), "rspamd{%*s}",
(gint) clslen, cls);

if (!failed && rspamd_lua_check_class (L, -1, classbuf)) {
*(va_arg (ap, void **)) = *(void **)lua_touserdata (L, -1);
/*
* Need to go to the previous index as we have increased it in
* the previous state
*/
if (!is_table) {
idx --;
}

/*
* We skip class check here for speed in non-table mode
*/
if (!failed && (!is_table ||
rspamd_lua_check_class (L, idx, classbuf))) {
*(va_arg (ap, void **)) = *(void **)lua_touserdata (L, idx);
}
else {
if (!failed) {
@@ -888,14 +945,19 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
(gint) keylen,
key,
classbuf,
lua_tostring (L, -1));
lua_tostring (L, idx));
va_end (ap);

return FALSE;
}
}

lua_pop (L, 1);
if (!is_table) {
lua_pop (L, 1);
}
else {
idx ++;
}

if (failed && required) {
g_set_error (err,

Loading…
Cancel
Save