]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Rework] Lua core: Use lightuserdata to index classes
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 16 Sep 2019 12:10:42 +0000 (13:10 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 16 Sep 2019 12:10:42 +0000 (13:10 +0100)
14 files changed:
src/lua/lua_cdb.c
src/lua/lua_common.c
src/lua/lua_common.h
src/lua/lua_cryptobox.c
src/lua/lua_dns_resolver.c
src/lua/lua_expression.c
src/lua/lua_ip.c
src/lua/lua_mempool.c
src/lua/lua_redis.c
src/lua/lua_regexp.c
src/lua/lua_rsa.c
src/lua/lua_sqlite3.c
src/lua/lua_trie.c
src/lua/lua_upstream.c

index 5d4c499a715aef63cc01bdf53c00ccdad6056ad4..1f9b48260d23e36d0b672aeb76957686056a8618 100644 (file)
@@ -151,17 +151,7 @@ lua_load_cdb (lua_State *L)
 void
 luaopen_cdb (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{cdb}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{cdb}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,  cdblib_m);
-       lua_pop (L, 1);                      /* remove metatable from stack */
-
+       rspamd_lua_new_class (L, "rspamd{cdb}", cdblib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_cdb", lua_load_cdb);
 }
index 5de0fa9ce0e2a5b81158a35b4532c37a569e5507..0040847c12b22fc2ae9d4b90dbb8e37474c28d94 100644 (file)
@@ -45,6 +45,25 @@ lua_error_quark (void)
        return g_quark_from_static_string ("lua-routines");
 }
 
+/* idea from daurnimator */
+#if defined(WITH_LUAJIT) && (defined(_LP64) || defined(_LLP64) || defined(__arch64__) || defined (__arm64__) || defined (__aarch64__) || defined(_WIN64))
+#define RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK 1
+#else
+#define RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK 0
+#endif
+
+#if RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK
+#define RSPAMD_LIGHTUSERDATA_MASK(p) ((void *)((uintptr_t)(p) & ((1UL<<47)-1)))
+#else
+#define RSPAMD_LIGHTUSERDATA_MASK(p) ((void *)(p))
+#endif
+
+/*
+ * Used to map string to a pointer
+ */
+KHASH_INIT (lua_class_set, const gchar *, bool, 0, rspamd_str_hash, rspamd_str_equal);
+khash_t (lua_class_set) *lua_classes = NULL;
+
 /* Util functions */
 /**
  * Create new class and store metatable on top of the stack (must be popped if not needed)
@@ -57,33 +76,48 @@ rspamd_lua_new_class (lua_State * L,
        const gchar *classname,
        const struct luaL_reg *methods)
 {
-       luaL_newmetatable (L, classname);   /* mt */
+       void *class_ptr;
+       khiter_t k;
+       gint r, nmethods = 0;
+
+       if (lua_classes == NULL) {
+               lua_classes = kh_init (lua_class_set);
+       }
+
+       k = kh_put (lua_class_set, lua_classes, classname, &r);
+       class_ptr = RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k));
+
+       if (methods) {
+               for (;;) {
+                       if (methods[nmethods].name != NULL) {
+                               nmethods ++;
+                       }
+                       else {
+                               break;
+                       }
+               }
+       }
+
+       lua_createtable (L, 0, 3 + nmethods);
        lua_pushstring (L, "__index");
        lua_pushvalue (L, -2);      /* pushes the metatable */
        lua_settable (L, -3);       /* metatable.__index = metatable */
 
-       lua_pushstring (L, "class");    /* mt,"class" */
-       lua_pushstring (L, classname);  /* mt,"class",classname */
-       lua_rawset (L, -3);         /* mt */
+       lua_pushstring (L, "class");
+       lua_pushstring (L, classname);
+       lua_rawset (L, -3);
+
+       lua_pushstring (L, "class_ptr");
+       lua_pushlightuserdata (L, class_ptr);
+       lua_rawset (L, -3);
 
        if (methods) {
                luaL_register (L, NULL, methods); /* pushes all methods as MT fields */
        }
-       /* MT is left on stack ! */
-}
 
-/**
- * Create and register new class with static methods and store metatable on top of the stack
- */
-void
-rspamd_lua_new_class_full (lua_State *L,
-       const gchar *classname,
-       const gchar *static_name,
-       const struct luaL_reg *methods,
-       const struct luaL_reg *func)
-{
-       rspamd_lua_new_class (L, classname, methods);
-       luaL_register (L, static_name, func);
+       lua_pushvalue (L, -1); /* Preserves metatable */
+       lua_rawsetp (L, LUA_REGISTRYINDEX, class_ptr);
+       /* MT is left on stack ! */
 }
 
 static const gchar *
@@ -150,7 +184,14 @@ rspamd_lua_class_tostring (lua_State * L)
 void
 rspamd_lua_setclass (lua_State * L, const gchar *classname, gint objidx)
 {
-       luaL_getmetatable (L, classname);
+       khiter_t k;
+
+       k = kh_get (lua_class_set, lua_classes, classname);
+
+       g_assert (k != kh_end (lua_classes));
+       lua_rawgetp (L, LUA_REGISTRYINDEX,
+                       RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
+
        if (objidx < 0) {
                objidx--;
        }
@@ -161,7 +202,6 @@ rspamd_lua_setclass (lua_State * L, const gchar *classname, gint objidx)
 void
 rspamd_lua_table_set (lua_State * L, const gchar *index, const gchar *value)
 {
-
        lua_pushstring (L, index);
        if (value) {
                lua_pushstring (L, value);
@@ -929,16 +969,10 @@ rspamd_lua_init (bool wipe_mem)
        lua_settop (L, 0);
 #endif
 
-       luaL_newmetatable (L, "rspamd{ev_base}");
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{ev_base}");
-       lua_rawset (L, -3);
+       rspamd_lua_new_class (L, "rspamd{ev_base}", NULL);
        lua_pop (L, 1);
 
-       luaL_newmetatable (L, "rspamd{session}");
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{session}");
-       lua_rawset (L, -3);
+       rspamd_lua_new_class (L, "rspamd{session}", NULL);
        lua_pop (L, 1);
 
        rspamd_lua_add_preload (L, "lpeg", luaopen_lpeg);
@@ -1206,12 +1240,23 @@ gpointer
 rspamd_lua_check_class (lua_State *L, gint index, const gchar *name)
 {
        gpointer p;
+       khiter_t k;
 
        if (lua_type (L, index) == LUA_TUSERDATA) {
                p = lua_touserdata (L, index);
                if (p) {
                        if (lua_getmetatable (L, index)) {
-                               lua_getfield (L, LUA_REGISTRYINDEX, name);  /* get correct metatable */
+                               k = kh_get (lua_class_set, lua_classes, name);
+
+                               if (k == kh_end (lua_classes)) {
+                                       lua_pop (L, 1);
+
+                                       return NULL;
+                               }
+
+                               lua_rawgetp (L, LUA_REGISTRYINDEX,
+                                               RSPAMD_LIGHTUSERDATA_MASK (kh_value (lua_classes, k)));
+
                                if (lua_rawequal (L, -1, -2)) {  /* does it have the correct mt? */
                                        lua_pop (L, 2);  /* remove both metatables */
                                        return p;
@@ -1824,6 +1869,7 @@ rspamd_lua_check_udata_common (lua_State *L, gint pos, const gchar *classname,
 {
        void *p = lua_touserdata (L, pos);
        guint i, top = lua_gettop (L);
+       khiter_t k;
 
        if (p == NULL) {
                goto err;
@@ -1831,7 +1877,14 @@ rspamd_lua_check_udata_common (lua_State *L, gint pos, const gchar *classname,
        else {
                /* Match class */
                if (lua_getmetatable (L, pos)) {
-                       luaL_getmetatable (L, classname);
+                       k = kh_get (lua_class_set, lua_classes, (gchar *)classname);
+
+                       if (k == kh_end (lua_classes)) {
+                               goto err;
+                       }
+
+                       lua_rawgetp (L, LUA_REGISTRYINDEX,
+                                       RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
 
                        if (!lua_rawequal (L, -1, -2)) {
                                goto err;
index 265775835be5824c81de223e35e539deeef6d344..9878cc5212b361e835afb9d31f9a9f783efb92a9 100644 (file)
@@ -154,15 +154,6 @@ void rspamd_lua_new_class (lua_State *L,
                                                   const gchar *classname,
                                                   const struct luaL_reg *methods);
 
-/**
- * Create and register new class with static methods
- */
-void rspamd_lua_new_class_full (lua_State *L,
-                                                               const gchar *classname,
-                                                               const gchar *static_name,
-                                                               const struct luaL_reg *methods,
-                                                               const struct luaL_reg *func);
-
 /**
  * Set class name for object at @param objidx position
  */
index 35faa00376f0e3e9edf4274bed32f11d2cf04f44..645b2495fc90dced44d3c6c0ea7880e9c6b19fb2 100644 (file)
@@ -2437,54 +2437,20 @@ lua_load_cryptobox (lua_State * L)
 void
 luaopen_cryptobox (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{cryptobox_pubkey}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{cryptobox_pubkey}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, cryptoboxpubkeylib_m);
+       rspamd_lua_new_class (L, "rspamd{cryptobox_pubkey}", cryptoboxpubkeylib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_cryptobox_pubkey", lua_load_pubkey);
 
-       luaL_newmetatable (L, "rspamd{cryptobox_keypair}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{cryptobox_keypair}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, cryptoboxkeypairlib_m);
+       rspamd_lua_new_class (L, "rspamd{cryptobox_keypair}", cryptoboxkeypairlib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_cryptobox_keypair", lua_load_keypair);
 
-       luaL_newmetatable (L, "rspamd{cryptobox_signature}");
-
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{cryptobox_signature}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, cryptoboxsignlib_m);
+       rspamd_lua_new_class (L, "rspamd{cryptobox_signature}", cryptoboxsignlib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_cryptobox_signature", lua_load_signature);
 
-       luaL_newmetatable (L, "rspamd{cryptobox_hash}");
-
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{cryptobox_hash}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, cryptoboxhashlib_m);
+       rspamd_lua_new_class (L, "rspamd{cryptobox_hash}", cryptoboxhashlib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_cryptobox_hash", lua_load_hash);
 
        rspamd_lua_add_preload (L, "rspamd_cryptobox", lua_load_cryptobox);
index a4e3b4b03a9a8d3ff01efabe2117b5974470ab3a..5478ab65ab0809ed6d910b8d2f2aebd7aef2346c 100644 (file)
@@ -693,15 +693,7 @@ void
 luaopen_dns_resolver (lua_State * L)
 {
 
-       luaL_newmetatable (L, "rspamd{resolver}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{resolver}");
-       lua_rawset (L, -3);
-
+       rspamd_lua_new_class (L, "rspamd{resolver}", dns_resolverlib_m);
        {
                LUA_ENUM (L, DNS_A,      RDNS_REQUEST_A);
                LUA_ENUM (L, DNS_PTR, RDNS_REQUEST_PTR);
@@ -713,8 +705,7 @@ luaopen_dns_resolver (lua_State * L)
                LUA_ENUM (L, DNS_SOA, RDNS_REQUEST_SOA);
        }
 
-       luaL_register (L, NULL, dns_resolverlib_m);
-       rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
+       lua_pop (L, 1);
 
-       lua_pop (L, 1);                      /* remove metatable from stack */
+       rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
 }
index c0e75fe84e2fd5348ef16f3146237894ce30c623..60ee8fdf7c57273ff85fa8c6bb0ee5bb416c9e19 100644 (file)
@@ -511,17 +511,7 @@ lua_load_expression (lua_State * L)
 void
 luaopen_expression (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{expr}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{expr}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,            exprlib_m);
+       rspamd_lua_new_class (L, "rspamd{expr}", exprlib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_expression", lua_load_expression);
-
-       lua_pop (L, 1);                      /* remove metatable from stack */
 }
index 3c3ef2d512754eb10801134a9e2982824967eb2d..1d44af2bfe01d25553692e050f71f0f842b79606 100644 (file)
@@ -584,17 +584,7 @@ lua_load_ip (lua_State * L)
 void
 luaopen_ip (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{ip}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{ip}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,            iplib_m);
-       rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
-
+       rspamd_lua_new_class (L, "rspamd{ip}", iplib_m);
        lua_pop (L, 1);
+       rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
 }
index 62d2941113d96cff6cfa375a94b480b079d23480..06dcd2d5c0bc94890d58809b431f731bb7d3f2ef 100644 (file)
@@ -582,17 +582,7 @@ lua_load_mempool (lua_State * L)
 void
 luaopen_mempool (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{mempool}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{mempool}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,                         mempoollib_m);
+       rspamd_lua_new_class (L, "rspamd{mempool}", mempoollib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_mempool", lua_load_mempool);
-
-       lua_pop (L, 1);                      /* remove metatable from stack */
 }
index ac1a8c297ffd7337fda037b215492ebe0097df52..279f84ffae4a9321efddb281fbc3e43936847d68 100644 (file)
@@ -1603,17 +1603,7 @@ lua_load_redis (lua_State * L)
 void
 luaopen_redis (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{redis}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{redis}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, redislib_m);
+       rspamd_lua_new_class (L, "rspamd{redis}", redislib_m);
        lua_pop (L, 1);
-
        rspamd_lua_add_preload (L, "rspamd_redis", lua_load_redis);
 }
index 4033722a3128fed537443a14fcfdfe608abbd7b3..95f40f8f0ab434d61408463890207ddb1a983b88 100644 (file)
@@ -880,22 +880,12 @@ lua_load_regexp (lua_State * L)
 void
 luaopen_regexp (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{regexp}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{regexp}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, regexplib_m);
+       rspamd_lua_new_class (L, "rspamd{regexp}", regexplib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_regexp", lua_load_regexp);
 
        if (regexp_static_pool == NULL) {
                regexp_static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
                                "regexp_lua_pool");
        }
-
-       lua_settop (L, 0);
 }
index 58607f92c5a8eaab1b6b920a49835c08425a5bf7..4b2caa2bf0f753a92809927857feefed14069144 100644 (file)
@@ -719,40 +719,16 @@ lua_load_rsa (lua_State * L)
 void
 luaopen_rsa (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{rsa_pubkey}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{rsa_pubkey}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, rsapubkeylib_m);
+       rspamd_lua_new_class (L, "rspamd{rsa_pubkey}", rsapubkeylib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_rsa_pubkey", lua_load_pubkey);
 
-       luaL_newmetatable (L, "rspamd{rsa_privkey}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{rsa_privkey}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, rsaprivkeylib_m);
+       rspamd_lua_new_class (L, "rspamd{rsa_privkey}", rsaprivkeylib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_rsa_privkey", lua_load_privkey);
 
-       luaL_newmetatable (L, "rspamd{rsa_signature}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{rsa_signature}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, rsasignlib_m);
+       rspamd_lua_new_class (L, "rspamd{rsa_signature}", rsasignlib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_rsa_signature", lua_load_signature);
 
        rspamd_lua_add_preload (L, "rspamd_rsa", lua_load_rsa);
index 87d798666836773a5039cd61ae6e3141262443fe..95104d1b0d9088071da26877da8e082d33d335c5 100644 (file)
@@ -373,28 +373,10 @@ lua_load_sqlite3 (lua_State * L)
 void
 luaopen_sqlite3 (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{sqlite3}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{sqlite3}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, sqlitelib_m);
+       rspamd_lua_new_class (L, "rspamd{sqlite3}", sqlitelib_m);
        lua_pop (L, 1);
 
-       luaL_newmetatable (L, "rspamd{sqlite3_stmt}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{sqlite3_stmt}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL, sqlitestmtlib_m);
+       rspamd_lua_new_class (L, "rspamd{sqlite3_stmt}", sqlitestmtlib_m);
        lua_pop (L, 1);
 
        rspamd_lua_add_preload (L, "rspamd_sqlite3", lua_load_sqlite3);
index 82d11c50c65fe3919f36a52ea042e4dec7f7c210..58a6698325621654b2805bc3f529db99a09054ab 100644 (file)
@@ -441,17 +441,7 @@ lua_load_trie (lua_State *L)
 void
 luaopen_trie (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{trie}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{trie}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,                  trielib_m);
+       rspamd_lua_new_class (L, "rspamd{trie}", trielib_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_trie", lua_load_trie);
-
-       lua_pop (L, 1);                      /* remove metatable from stack */
 }
index 3c4f3f4c32ef06d94e28890cbf1ebcffc7aba53a..7ba77839ffc15d2400d0c862db8e5e0964b70f9c 100644 (file)
@@ -569,30 +569,10 @@ lua_load_upstream_list (lua_State * L)
 void
 luaopen_upstream (lua_State * L)
 {
-       luaL_newmetatable (L, "rspamd{upstream_list}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{upstream_list}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,                    upstream_list_m);
+       rspamd_lua_new_class (L, "rspamd{upstream_list}", upstream_list_m);
+       lua_pop (L, 1);
        rspamd_lua_add_preload (L, "rspamd_upstream_list", lua_load_upstream_list);
 
-       lua_pop (L, 1);                      /* remove metatable from stack */
-
-       luaL_newmetatable (L, "rspamd{upstream}");
-       lua_pushstring (L, "__index");
-       lua_pushvalue (L, -2);
-       lua_settable (L, -3);
-
-       lua_pushstring (L, "class");
-       lua_pushstring (L, "rspamd{upstream}");
-       lua_rawset (L, -3);
-
-       luaL_register (L, NULL,           upstream_m);
-
-       lua_pop (L, 1);                      /* remove metatable from stack */
+       rspamd_lua_new_class (L, "rspamd{upstream}", upstream_m);
+       lua_pop (L, 1);
 }