]> git.ipfire.org Git - thirdparty/bird.git/blobdiff - filter/filter.c
Revert "Reducing filter stack size to allow for lesser thread stack size"
[thirdparty/bird.git] / filter / filter.c
index 7004b96d63beb9f24307db2c364be9de144f7429..20a380dc0a29f48ada71bdc8db4b989a364a43f4 100644 (file)
@@ -50,28 +50,30 @@ enum f_exception {
   FE_RETURN = 0x1,
 };
 
-struct filter_exec_stack {
-  const struct f_line *line;           /* The line that is being executed */
-  uint pos;                            /* Instruction index in the line */
-  uint ventry;                         /* Value stack depth on entry */
-  uint vbase;                          /* Where to index variable positions from */
-  enum f_exception emask;              /* Exception mask */
+
+struct filter_stack {
+  /* Value stack for execution */
+#define F_VAL_STACK_MAX        4096
+  uint vcnt;                           /* Current value stack size; 0 for empty */
+  uint ecnt;                           /* Current execute stack size; 0 for empty */
+
+  struct f_val vstk[F_VAL_STACK_MAX];  /* The stack itself */
+
+  /* Instruction stack for execution */
+#define F_EXEC_STACK_MAX 4096
+  struct {
+    const struct f_line *line;         /* The line that is being executed */
+    uint pos;                          /* Instruction index in the line */
+    uint ventry;                       /* Value stack depth on entry */
+    uint vbase;                                /* Where to index variable positions from */
+    enum f_exception emask;            /* Exception mask */
+  } estk[F_EXEC_STACK_MAX];
 };
 
 /* Internal filter state, to be allocated on stack when executing filters */
 struct filter_state {
   /* Stacks needed for execution */
-  struct filter_stack {
-    /* Current filter stack depth */
-
-    /* Value stack */
-    uint vcnt, vlen;
-    struct f_val *vstk;
-
-    /* Instruction stack for execution */
-    uint ecnt, elen;
-    struct filter_exec_stack *estk;
-  } stack;
+  struct filter_stack *stack;
 
   /* The route we are processing. This may be NULL to indicate no route available. */
   struct rte **rte;
@@ -93,13 +95,10 @@ struct filter_state {
 };
 
 _Thread_local static struct filter_state filter_state;
+_Thread_local static struct filter_stack filter_stack;
 
 void (*bt_assert_hook)(int result, const struct f_line_item *assert);
 
-#define _f_stack_init(fs, px, def) ((fs).stack.px##stk = alloca(sizeof(*(fs).stack.px##stk) * ((fs).stack.px##len = (config && config->filter_##px##stk) ? config->filter_##px##stk : (def))))
-
-#define f_stack_init(fs) ( _f_stack_init(fs, v, 128), _f_stack_init(fs, e, 128) )
-
 static inline void f_cache_eattrs(struct filter_state *fs)
 {
   fs->eattrs = &((*fs->rte)->attrs->eattrs);
@@ -164,17 +163,15 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
   ASSERT(line->args == 0);
 
   /* Initialize the filter stack */
-  struct filter_stack *fstk = &fs->stack;
+  struct filter_stack *fstk = fs->stack;
 
   fstk->vcnt = line->vars;
   memset(fstk->vstk, 0, sizeof(struct f_val) * line->vars);
 
   /* The same as with the value stack. Not resetting the stack for performance reasons. */
   fstk->ecnt = 1;
-  fstk->estk[0] = (struct filter_exec_stack) {
-    .line = line,
-    .pos = 0,
-  };
+  fstk->estk[0].line = line;
+  fstk->estk[0].pos = 0;
 
 #define curline fstk->estk[fstk->ecnt-1]
 
@@ -194,8 +191,6 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
 #define v2 vv(1)
 #define v3 vv(2)
 
-#define f_vcnt_check_overflow(n) do { if (fstk->vcnt + n >= fstk->vlen) runtime("Filter execution stack overflow"); } while (0)
-
 #define runtime(fmt, ...) do { \
   if (!(fs->flags & FF_SILENT)) \
     log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
@@ -220,8 +215,7 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
     }
 
     /* End of current line. Drop local variables before exiting. */
-    fstk->vcnt -= curline.line->vars;
-    fstk->vcnt -= curline.line->args;
+    fstk->vcnt = curline.ventry + curline.line->results;
     fstk->ecnt--;
   }
 
@@ -281,13 +275,12 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
 
   /* Initialize the filter state */
   filter_state = (struct filter_state) {
+    .stack = &filter_stack,
     .rte = rte,
     .pool = tmp_pool,
     .flags = flags,
   };
 
-  f_stack_init(filter_state);
-
   LOG_BUFFER_INIT(filter_state.buf);
 
   /* Run the interpreter itself */
@@ -346,12 +339,11 @@ enum filter_return
 f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool)
 {
   filter_state = (struct filter_state) {
+    .stack = &filter_stack,
     .rte = rte,
     .pool = tmp_pool,
   };
 
-  f_stack_init(filter_state);
-
   LOG_BUFFER_INIT(filter_state.buf);
 
   ASSERT(!((*rte)->flags & REF_COW));
@@ -370,11 +362,10 @@ enum filter_return
 f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres)
 {
   filter_state = (struct filter_state) {
+    .stack = &filter_stack,
     .pool = tmp_pool,
   };
 
-  f_stack_init(filter_state);
-
   LOG_BUFFER_INIT(filter_state.buf);
 
   enum filter_return fret = interpret(&filter_state, expr, pres);
@@ -391,11 +382,10 @@ f_eval_int(const struct f_line *expr)
 {
   /* Called independently in parse-time to eval expressions */
   filter_state = (struct filter_state) {
+    .stack = &filter_stack,
     .pool = cfg_mem,
   };
 
-  f_stack_init(filter_state);
-
   struct f_val val;
 
   LOG_BUFFER_INIT(filter_state.buf);