Jelajahi Sumber

Comparisoin operators (and CALL)

Hugo Musso Gualandi 3 tahun lalu
induk
melakukan
27c419ce4f
2 mengubah file dengan 180 tambahan dan 36 penghapusan
  1. 143 0
      src/functions_header.c
  2. 37 36
      src/luaot_functions.c

+ 143 - 0
src/functions_header.c

@@ -122,6 +122,41 @@ typedef struct {
   (f)(L, ctx, pc, ra, v1, v2); \
 }
 
+/*
+** Comparison
+*/
+ 
+#undef  op_order
+#define op_order(L,opi,opn,other) {  \
+  int cond;  \
+  if (ttisinteger(s2v(ra)) && ttisinteger(rb)) {  \
+    lua_Integer ia = ivalue(s2v(ra));  \
+    lua_Integer ib = ivalue(rb);  \
+    cond = opi(ia, ib);  \
+  }  \
+  else if (ttisnumber(s2v(ra)) && ttisnumber(rb))  \
+    cond = opn(s2v(ra), rb);  \
+  else  \
+    Protect(cond = other(L, s2v(ra), rb));  \
+  return cond; \
+}
+
+#undef  op_orderI
+#define op_orderI(L,opi,opf,inv,tm) {  \
+        int cond;  \
+        if (ttisinteger(s2v(ra)))  \
+          cond = opi(ivalue(s2v(ra)), im);  \
+        else if (ttisfloat(s2v(ra))) {  \
+          lua_Number fa = fltvalue(s2v(ra));  \
+          lua_Number fim = cast_num(im);  \
+          cond = opf(fa, fim);  \
+        }  \
+        else {  \
+          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm));  \
+        }  \
+        return cond; \
+}
+
 /*
 ** some macros for common tasks in 'luaV_execute'
 */
@@ -735,3 +770,111 @@ void luaot_LEN(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
 {
     Protect(luaV_objlen(L, ra, rb));
 }
+
+static
+void luaot_CONCAT(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+                  StkId ra, int n)
+{
+    L->top = ra + n;  /* mark the end of concat operands */
+    ProtectNT(luaV_concat(L, n));
+    checkGC(L, L->top); /* 'luaV_concat' ensures correct top */
+}
+
+static
+void luaot_CLOSE(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+                 StkId ra)
+{
+    Protect(luaF_close(L, ra, LUA_OK, 1));
+}
+
+static
+void luaot_TBC(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+               StkId ra)
+{
+    /* create new to-be-closed upvalue */
+    halfProtect(luaF_newtbcupval(L, ra));
+}
+
+static
+int luaot_EQ(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+              StkId ra, TValue *rb)
+{
+    int cond;
+    Protect(cond = luaV_equalobj(L, s2v(ra), rb));
+    return cond;
+}
+
+static
+int luaot_LT(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+             StkId ra, TValue *rb)
+{
+    op_order(L, l_lti, LTnum, lessthanothers);
+}
+
+static
+int luaot_LE(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+             StkId ra, TValue *rb)
+{
+    op_order(L, l_lei, LEnum, lessequalothers);
+}
+
+static
+int luaot_EQI(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+              StkId ra, int im, int isf)
+{
+    int cond;
+    if (ttisinteger(s2v(ra)))
+      cond = (ivalue(s2v(ra)) == im);
+    else if (ttisfloat(s2v(ra)))
+      cond = luai_numeq(fltvalue(s2v(ra)), cast_num(im));
+    else
+      cond = 0;  /* other types cannot be equal to a number */
+    return cond;
+}
+
+static
+int luaot_LTI(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+              StkId ra, int im, int isf)
+{
+    op_orderI(L, l_lti, luai_numlt, 0, TM_LT);
+}
+
+static
+int luaot_LEI(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+              StkId ra, int im, int isf)
+{
+    op_orderI(L, l_lei, luai_numle, 0, TM_LE);
+}
+
+static
+int luaot_GTI(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+              StkId ra, int im, int isf)
+{
+    op_orderI(L, l_gti, luai_numgt, 1, TM_LT);
+}
+
+static
+int luaot_GEI(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+              StkId ra, int im, int isf)
+{
+    op_orderI(L, l_gei, luai_numge, 1, TM_LE);
+}
+
+static
+CallInfo* luaot_CALL(lua_State *L, LuaotExecuteState *ctx, const Instruction *pc,
+               StkId ra, int b, int nresults)
+{
+    CallInfo *newci;
+    if (b != 0)  /* fixed number of arguments? */
+        L->top = ra + b;  /* top signals number of arguments */
+    /* else previous instruction set top */
+    savepc(L);  /* in case of errors */
+    if ((newci = luaD_precall(L, ra, nresults)) == NULL) {
+        updatetrap(ctx->ci);  /* C call; nothing else to be done */
+        return NULL;
+    } else {
+        ctx->ci = newci;
+        ctx->ci->callstatus = 0;  /* call re-uses 'luaV_execute' */
+        return ctx->ci;
+    }
+}

+ 37 - 36
src/luaot_functions.c

@@ -17,11 +17,11 @@ void println_goto_ret()
 {
     // This is the piece of code that is after the "ret" label.
     // It should be used in the places that do "goto ret;"
-    println("    if (ci->callstatus & CIST_FRESH)");
+    println("    if (ctx->ci->callstatus & CIST_FRESH)");
     println("        return NULL;  /* end this frame */");
     println("    else {");
-    println("        ci = ci->previous;");
-    println("        return ci;");
+    println("        ctx->ci = ctx->ci->previous;");
+    println("        return ctx->ci;");
     println("    }");
 }
 
@@ -370,41 +370,43 @@ void create_function(Proto *f)
             }
             case OP_CONCAT: {
                 println("    int n = GETARG_B(i);  /* number of elements to concatenate */");
-                println("    L->top = ra + n;  /* mark the end of concat operands */");
-                println("    ProtectNT(luaV_concat(L, n));");
-                println("    checkGC(L, L->top); /* 'luaV_concat' ensures correct top */");
+                println("    luaot_CONCAT(L, ctx, pc, ra, n);");
                 break;
             }
             case OP_CLOSE: {
-                println("Protect(luaF_close(L, ra, LUA_OK, 1));");
+                println("    luaot_CLOSE(L, ctx, pc, ra);");
                 break;
             }
             case OP_TBC: {
-                println("    /* create new to-be-closed upvalue */");
-                println("    halfProtect(luaF_newtbcupval(L, ra));");
+                println("    luaot_TBC(L, ctx, pc, ra);");
                 break;
             }
             case OP_JMP: {
+                // INLINED
                 println("    updatetrap(ctx->ci);");
                 println("    goto label_%02d;", jump_target(f, pc));//(!)
                 break;
             }
             case OP_EQ: {
-                println("    int cond;");
                 println("    TValue *rb = vRB(i);");
-                println("    Protect(cond = luaV_equalobj(L, s2v(ra), rb));");
+                println("    int cond = luaot_EQ(L, ctx, pc, ra, rb);");
                 println("    docondjump();");
                 break;
             }
             case OP_LT: {
-                println("    op_order(L, l_lti, LTnum, lessthanothers);");
+                println("    TValue *rb = vRB(i);");
+                println("    int cond = luaot_LT(L, ctx, pc, ra, rb);");
+                println("    docondjump();");
                 break;
             }
             case OP_LE: {
-                println("    op_order(L, l_lei, LEnum, lessequalothers);");
+                println("    TValue *rb = vRB(i);");
+                println("    int cond = luaot_LE(L, ctx, pc, ra, rb);");
+                println("    docondjump();");
                 break;
             }
             case OP_EQK: {
+                // This can be simply inlined
                 println("    TValue *rb = KB(i);");
                 println("    /* basic types do not use '__eq'; we can use raw equality */");
                 println("    int cond = luaV_equalobj(NULL, s2v(ra), rb);");
@@ -412,39 +414,48 @@ void create_function(Proto *f)
                 break;
             }
             case OP_EQI: {
-                println("    int cond;");
                 println("    int im = GETARG_sB(i);");
-                println("    if (ttisinteger(s2v(ra)))");
-                println("      cond = (ivalue(s2v(ra)) == im);");
-                println("    else if (ttisfloat(s2v(ra)))");
-                println("      cond = luai_numeq(fltvalue(s2v(ra)), cast_num(im));");
-                println("    else");
-                println("      cond = 0;  /* other types cannot be equal to a number */");
+                println("    int isf = GETARG_C(i);");
+                println("    int cond = luaot_EQI(L, ctx, pc, ra, im, isf);");
                 println("    docondjump();");
                 break;
             }
             case OP_LTI: {
-                println("    op_orderI(L, l_lti, luai_numlt, 0, TM_LT);");
+                println("    int im = GETARG_sB(i);");
+                println("    int isf = GETARG_C(i);");
+                println("    int cond = luaot_LTI(L, ctx, pc, ra, im, isf);");
+                println("    docondjump();");
                 break;
             }
             case OP_LEI: {
-                println("    op_orderI(L, l_lei, luai_numle, 0, TM_LE);");
+                println("    int im = GETARG_sB(i);");
+                println("    int isf = GETARG_C(i);");
+                println("    int cond = luaot_LEI(L, ctx, pc, ra, im, isf);");
+                println("    docondjump();");
                 break;
             }
             case OP_GTI: {
-                println("    op_orderI(L, l_gti, luai_numgt, 1, TM_LT);");
+                println("    int im = GETARG_sB(i);");
+                println("    int isf = GETARG_C(i);");
+                println("    int cond = luaot_GTI(L, ctx, pc, ra, im, isf);");
+                println("    docondjump();");
                 break;
             }
             case OP_GEI: {
-                println("    op_orderI(L, l_gei, luai_numge, 1, TM_LE);");
+                println("    int im = GETARG_sB(i);");
+                println("    int isf = GETARG_C(i);");
+                println("    int cond = luaot_GEI(L, ctx, pc, ra, im, isf);");
+                println("    docondjump();");
                 break;
             }
             case OP_TEST: {
+                // INLINED
                 println("    int cond = !l_isfalse(s2v(ra));");
                 println("    docondjump();");
                 break;
             }
             case OP_TESTSET: {
+                // INLINED
                 println("    TValue *rb = vRB(i);");
                 println("    if (l_isfalse(rb) == GETARG_k(i))");
                 println("      goto LUAOT_SKIP1;"); // (!)
@@ -455,20 +466,10 @@ void create_function(Proto *f)
                 break;
             }
             case OP_CALL: {
-                println("    CallInfo *newci;");
                 println("    int b = GETARG_B(i);");
                 println("    int nresults = GETARG_C(i) - 1;");
-                println("    if (b != 0)  /* fixed number of arguments? */");
-                println("        L->top = ra + b;  /* top signals number of arguments */");
-                println("    /* else previous instruction set top */");
-                println("    savepc(L);  /* in case of errors */");
-                println("    if ((newci = luaD_precall(L, ra, nresults)) == NULL)");
-                println("        updatetrap(ctx->ci);  /* C call; nothing else to be done */");
-                println("    else {");
-                println("        ctx->ci = newci;");
-                println("        ctx->ci->callstatus = 0;  /* call re-uses 'luaV_execute' */");
-                println("        return ctx->ci;");
-                println("    }");
+                println("    CallInfo *newci = luaot_CALL(L, ctx, pc, ra, b, nresults);");
+                println("    if (newci) return newci;");
                 break;
             }
             case OP_TAILCALL: {