Implement dispatch-table based interpretor
[lttng-ust.git] / liblttng-ust / lttng-filter.c
index 8a62c518e9a7e9d0427fefcb4dec7c78e5d98227..60879e1fc73f437e134130b55adce25a3ab08cb2 100644 (file)
@@ -264,10 +264,12 @@ int lttng_filter_false(void *filter_data,
        return 0;
 }
 
-#define INTERPRETER_USE_SWITCH
-
 #ifdef INTERPRETER_USE_SWITCH
 
+/*
+ * Fallback for compilers that do not support taking address of labels.
+ */
+
 #define START_OP       \
        start_pc = &bytecode->data[0]; \
        for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
@@ -286,7 +288,25 @@ int lttng_filter_false(void *filter_data,
 
 #else
 
-#define OP(name)       
+/*
+ * Dispatch-table based interpreter.
+ */
+
+#define START_OP                                       \
+       start_pc = &bytecode->data[0];                  \
+       pc = next_pc = start_pc;                        \
+       if (unlikely(pc - start_pc >= bytecode->len))   \
+               goto end;                               \
+       goto *dispatch[*(filter_opcode_t *) pc];
+
+#define OP(name)                                       \
+LABEL_##name
+
+#define PO                                             \
+               pc = next_pc;                           \
+               goto *dispatch[*(filter_opcode_t *) pc];
+
+#define END_OP
 
 #endif
 
@@ -301,7 +321,7 @@ int lttng_filter_interpret_bytecode(void *filter_data,
        struct reg reg[NR_REG];
 #ifndef INTERPRETER_USE_SWITCH
        static void *dispatch[NR_FILTER_OPS] = {
-               [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN = 0,
+               [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
 
                [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
 
@@ -576,59 +596,53 @@ int lttng_filter_interpret_bytecode(void *filter_data,
 
                /* unary */
                OP(FILTER_OP_UNARY_PLUS):
+               OP(FILTER_OP_UNARY_MINUS):
+               OP(FILTER_OP_UNARY_NOT):
+                       ERR("unsupported non-specialized bytecode op %u\n",
+                               (unsigned int) *(filter_opcode_t *) pc);
+                       ret = -EINVAL;
+                       goto end;
+
+
+               OP(FILTER_OP_UNARY_PLUS_S64):
+               OP(FILTER_OP_UNARY_PLUS_DOUBLE):
                {
                        next_pc += sizeof(struct unary_op);
                        PO;
                }
-               OP(FILTER_OP_UNARY_MINUS):
+               OP(FILTER_OP_UNARY_MINUS_S64):
                {
                        struct unary_op *insn = (struct unary_op *) pc;
 
-                       switch (reg[insn->reg].type) {
-                       default:
-                               ERR("unknown register type\n");
-                               ret = -EINVAL;
-                               goto end;
-
-                       case REG_STRING:
-                               ERR("Unary minus can only be applied to numeric or floating point registers\n");
-                               ret = -EINVAL;
-                               goto end;
-                       case REG_S64:
-                               reg[insn->reg].v = -reg[insn->reg].v;
-                               break;
-                       case REG_DOUBLE:
-                               reg[insn->reg].d = -reg[insn->reg].d;
-                               break;
-                       }
+                       reg[insn->reg].v = -reg[insn->reg].v;
                        next_pc += sizeof(struct unary_op);
                        PO;
                }
-               OP(FILTER_OP_UNARY_NOT):
+               OP(FILTER_OP_UNARY_MINUS_DOUBLE):
                {
                        struct unary_op *insn = (struct unary_op *) pc;
 
-                       switch (reg[insn->reg].type) {
-                       default:
-                               ERR("unknown register type\n");
-                               ret = -EINVAL;
-                               goto end;
+                       reg[insn->reg].d = -reg[insn->reg].d;
+                       next_pc += sizeof(struct unary_op);
+                       PO;
+               }
+               OP(FILTER_OP_UNARY_NOT_S64):
+               {
+                       struct unary_op *insn = (struct unary_op *) pc;
 
-                       case REG_STRING:
-                               ERR("Unary not can only be applied to numeric or floating point registers\n");
-                               ret = -EINVAL;
-                               goto end;
-                       case REG_S64:
-                               reg[insn->reg].v = !reg[insn->reg].v;
-                               break;
-                       case REG_DOUBLE:
-                               reg[insn->reg].d = !reg[insn->reg].d;
-                               break;
-                       }
                        reg[insn->reg].v = !reg[insn->reg].v;
                        next_pc += sizeof(struct unary_op);
                        PO;
                }
+               OP(FILTER_OP_UNARY_NOT_DOUBLE):
+               {
+                       struct unary_op *insn = (struct unary_op *) pc;
+
+                       reg[insn->reg].d = !reg[insn->reg].d;
+                       next_pc += sizeof(struct unary_op);
+                       PO;
+               }
+
                /* logical */
                OP(FILTER_OP_AND):
                {
@@ -780,6 +794,11 @@ end:
        return retval;
 }
 
+#undef START_OP
+#undef OP
+#undef PO
+#undef END_OP
+
 static
 int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
 {
@@ -1438,7 +1457,6 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
 
-
                /* unary */
                case FILTER_OP_UNARY_PLUS:
                {
This page took 0.024813 seconds and 4 git commands to generate.