From b436aeaf5fa8d5f01d543b8a6a907acba1a93dbe Mon Sep 17 00:00:00 2001 From: Bill Meier Date: Wed, 28 Nov 2007 22:44:37 +0000 Subject: [PATCH] From Didier Gautheron: Bug #2042: Move constants initialisation at compile time. svn path=/trunk/; revision=23659 --- epan/dfilter/dfilter-int.h | 5 +++ epan/dfilter/dfilter.c | 34 ++++++++++++++++++--- epan/dfilter/dfvm.c | 62 +++++++++++++++++++++++++++++++++++--- epan/dfilter/dfvm.h | 2 ++ epan/dfilter/gencode.c | 48 +++++++++++++++++++++++++++-- 5 files changed, 140 insertions(+), 11 deletions(-) diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h index 059a6b75af..f66e7c8a4c 100644 --- a/epan/dfilter/dfilter-int.h +++ b/epan/dfilter/dfilter-int.h @@ -32,7 +32,9 @@ /* Passed back to user */ struct _dfilter_t { GPtrArray *insns; + GPtrArray *consts; int num_registers; + int max_registers; GList **registers; gboolean *attempted_load; int *interesting_fields; @@ -44,10 +46,13 @@ typedef struct { stnode_t *st_root; gboolean syntax_error; GPtrArray *insns; + GPtrArray *consts; GHashTable *loaded_fields; GHashTable *interesting_fields; int next_insn_id; + int next_const_id; int next_register; + int first_constant; /* first register used as a constant */ } dfwork_t; /* Constructor/Destructor prototypes for Lemon Parser */ diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index d6cf5679a0..c6d0a2b3d7 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -137,13 +137,28 @@ free_insns(GPtrArray *insns) void dfilter_free(dfilter_t *df) { + int i; + + if (!df) + return; + if (df->insns) { free_insns(df->insns); } + if (df->consts) { + free_insns(df->consts); + } if (df->interesting_fields) { g_free(df->interesting_fields); } + + /* clear registers */ + for (i = 0; i < df->max_registers; i++) { + if (df->registers[i]) { + g_list_free(df->registers[i]); + } + } g_free(df->registers); g_free(df->attempted_load); @@ -161,10 +176,12 @@ dfwork_new(void) dfw->st_root = NULL; dfw->syntax_error = FALSE; dfw->insns = NULL; + dfw->consts = NULL; dfw->loaded_fields = NULL; dfw->interesting_fields = NULL; dfw->next_insn_id = 0; dfw->next_register = 0; + dfw->first_constant = -1; return dfw; } @@ -187,11 +204,14 @@ dfwork_free(dfwork_t *dfw) if (dfw->insns) { free_insns(dfw->insns); } + + if (dfw->consts) { + free_insns(dfw->consts); + } g_free(dfw); } - gboolean dfilter_compile(const gchar *text, dfilter_t **dfp) { @@ -279,14 +299,20 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) /* Tuck away the bytecode in the dfilter_t */ dfilter = dfilter_new(); dfilter->insns = dfw->insns; + dfilter->consts = dfw->consts; dfw->insns = NULL; + dfw->consts = NULL; dfilter->interesting_fields = dfw_interesting_fields(dfw, &dfilter->num_interesting_fields); /* Initialize run-time space */ - dfilter->num_registers = dfw->next_register; - dfilter->registers = g_new0(GList*, dfilter->num_registers); - dfilter->attempted_load = g_new0(gboolean, dfilter->num_registers); + dfilter->num_registers = dfw->first_constant; + dfilter->max_registers = dfw->next_register; + dfilter->registers = g_new0(GList*, dfilter->max_registers); + dfilter->attempted_load = g_new0(gboolean, dfilter->max_registers); + + /* Initialize constants */ + dfvm_init_const(dfilter); /* And give it to the user. */ *dfp = dfilter; diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c index 17d627e906..1d5899074a 100644 --- a/epan/dfilter/dfvm.c +++ b/epan/dfilter/dfvm.c @@ -36,6 +36,7 @@ dfvm_insn_new(dfvm_opcode_t op) insn->arg1 = NULL; insn->arg2 = NULL; insn->arg3 = NULL; + insn->arg4 = NULL; return insn; } @@ -68,6 +69,9 @@ dfvm_insn_free(dfvm_insn_t *insn) if (insn->arg3) { dfvm_value_free(insn->arg3); } + if (insn->arg4) { + dfvm_value_free(insn->arg4); + } g_free(insn); } @@ -439,11 +443,6 @@ dfvm_apply(dfilter_t *df, proto_tree *tree) &df->registers[arg2->value.numeric]); break; - case PUT_FVALUE: - accum = put_fvalue(df, - arg1->value.fvalue, arg2->value.numeric); - break; - case MK_RANGE: arg3 = insn->arg3; mk_range(df, @@ -518,6 +517,12 @@ dfvm_apply(dfilter_t *df, proto_tree *tree) } break; + case PUT_FVALUE: +#if 0 + accum = put_fvalue(df, + arg1->value.fvalue, arg2->value.numeric); + break; +#endif default: g_assert_not_reached(); @@ -528,3 +533,50 @@ dfvm_apply(dfilter_t *df, proto_tree *tree) g_assert_not_reached(); return FALSE; /* to appease the compiler */ } + +void +dfvm_init_const(dfilter_t *df) +{ + int id, length; + dfvm_insn_t *insn; + dfvm_value_t *arg1; + dfvm_value_t *arg2; + + length = df->consts->len; + + for (id = 0; id < length; id++) { + + insn = g_ptr_array_index(df->consts, id); + arg1 = insn->arg1; + arg2 = insn->arg2; + + switch (insn->op) { + case PUT_FVALUE: + put_fvalue(df, + arg1->value.fvalue, arg2->value.numeric); + break; + case CHECK_EXISTS: + case READ_TREE: + case CALL_FUNCTION: + case MK_RANGE: + case ANY_EQ: + case ANY_NE: + case ANY_GT: + case ANY_GE: + case ANY_LT: + case ANY_LE: + case ANY_BITWISE_AND: + case ANY_CONTAINS: + case ANY_MATCHES: + case NOT: + case RETURN: + case IF_TRUE_GOTO: + case IF_FALSE_GOTO: + default: + g_assert_not_reached(); + break; + } + } + + return; +} diff --git a/epan/dfilter/dfvm.h b/epan/dfilter/dfvm.h index cdc8f96453..ffe1b61de6 100644 --- a/epan/dfilter/dfvm.h +++ b/epan/dfilter/dfvm.h @@ -102,5 +102,7 @@ dfvm_dump(FILE *f, GPtrArray *insns); gboolean dfvm_apply(dfilter_t *df, proto_tree *tree); +void +dfvm_init_const(dfilter_t *df); #endif diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c index 78e57a7853..e6ff76ac70 100644 --- a/epan/dfilter/gencode.c +++ b/epan/dfilter/gencode.c @@ -47,6 +47,14 @@ dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn) g_ptr_array_add(dfw->insns, insn); } +static void +dfw_append_const(dfwork_t *dfw, dfvm_insn_t *insn) +{ + insn->id = dfw->next_const_id; + dfw->next_const_id++; + g_ptr_array_add(dfw->consts, insn); +} + /* returns register number */ static int dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo) @@ -116,11 +124,11 @@ dfw_append_put_fvalue(dfwork_t *dfw, fvalue_t *fv) val1 = dfvm_value_new(FVALUE); val1->value.fvalue = fv; val2 = dfvm_value_new(REGISTER); - reg = dfw->next_register++; + reg = dfw->first_constant--; val2->value.numeric = reg; insn->arg1 = val1; insn->arg2 = val2; - dfw_append_insn(dfw, insn); + dfw_append_const(dfw, insn); return reg; } @@ -444,6 +452,7 @@ dfw_gencode(dfwork_t *dfw) dfvm_value_t *arg1; dfw->insns = g_ptr_array_new(); + dfw->consts = g_ptr_array_new(); dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal); dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal); gencode(dfw, dfw->st_root); @@ -485,6 +494,41 @@ dfw_gencode(dfwork_t *dfw) } } + /* move constants after registers*/ + if (dfw->first_constant == -1) { + /* NONE */ + dfw->first_constant = 0; + return; + } + + id = -dfw->first_constant -1; + dfw->first_constant = dfw->next_register; + dfw->next_register += id; + + length = dfw->consts->len; + for (id = 0; id < length; id++) { + insn = g_ptr_array_index(dfw->consts, id); + if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 ) + insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1; + } + + length = dfw->insns->len; + for (id = 0; id < length; id++) { + insn = g_ptr_array_index(dfw->insns, id); + if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 ) + insn->arg1->value.numeric = dfw->first_constant - insn->arg1->value.numeric -1; + + if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 ) + insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1; + + if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 ) + insn->arg3->value.numeric = dfw->first_constant - insn->arg3->value.numeric -1; + + if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 ) + insn->arg4->value.numeric = dfw->first_constant - insn->arg4->value.numeric -1; + } + + }