- optimizations for logical expressions
( exp(rval(v)) -> exp(v), exp_elem(x, rval(v)) -> exp_elem(x, v) )
- comp_rve() fix
... | ... |
@@ -93,6 +93,12 @@ struct route_list branch_rt; |
93 | 93 |
struct route_list onsend_rt; |
94 | 94 |
|
95 | 95 |
|
96 |
+/** script optimization level, useful for debugging. |
|
97 |
+ * 0 - no optimization |
|
98 |
+ * 1 - optimize rval expressions |
|
99 |
+ * 2 - optimize expr elems |
|
100 |
+ */ |
|
101 |
+int scr_opt_lev=9; |
|
96 | 102 |
|
97 | 103 |
inline static void destroy_rlist(struct route_list* rt) |
98 | 104 |
{ |
... | ... |
@@ -283,6 +289,205 @@ int route_lookup(struct route_list* rt, char* name) |
283 | 283 |
int fix_actions(struct action* a); /*fwd declaration*/ |
284 | 284 |
|
285 | 285 |
|
286 |
+/** optimize the left side of a struct expr. |
|
287 |
+ * @return 1 if optimized, 0 if not and -1 on error |
|
288 |
+ */ |
|
289 |
+static int exp_optimize_left(struct expr* exp) |
|
290 |
+{ |
|
291 |
+ struct rval_expr* rve; |
|
292 |
+ struct rvalue* rval; |
|
293 |
+ int old_type, old_op; |
|
294 |
+ int ret; |
|
295 |
+ |
|
296 |
+ ret=0; |
|
297 |
+ if (exp->type!=ELEM_T) |
|
298 |
+ return 0; |
|
299 |
+ old_type=exp->l_type; |
|
300 |
+ old_op=exp->op; |
|
301 |
+ if (exp->l_type==RVEXP_O){ |
|
302 |
+ rve=exp->l.param; |
|
303 |
+ /* rve should be previously fixed/optimized */ |
|
304 |
+ /* optimize exp (rval(val)) -> exp(val) */ |
|
305 |
+ if (rve->op==RVE_RVAL_OP){ |
|
306 |
+ rval=&rve->left.rval; |
|
307 |
+ switch(rval->type){ |
|
308 |
+ case RV_INT: |
|
309 |
+ if (exp->op==NO_OP){ |
|
310 |
+ exp->l_type=NUMBER_O; |
|
311 |
+ exp->l.param=0; |
|
312 |
+ exp->r_type=NUMBER_ST; |
|
313 |
+ exp->r.numval=rval->v.l; |
|
314 |
+ rval_destroy(rval); |
|
315 |
+ pkg_free(rve); |
|
316 |
+ ret=1; |
|
317 |
+ } |
|
318 |
+ break; |
|
319 |
+ case RV_STR: |
|
320 |
+ /* string evaluated in expression context - not |
|
321 |
+ supported */ |
|
322 |
+ break; |
|
323 |
+ case RV_BEXPR: |
|
324 |
+ if (exp->op==NO_OP){ |
|
325 |
+ /* replace the current expr. */ |
|
326 |
+ *exp=*(rval->v.bexpr); |
|
327 |
+ rval_destroy(rval); |
|
328 |
+ pkg_free(rve); |
|
329 |
+ ret=1; |
|
330 |
+ }; |
|
331 |
+ break; |
|
332 |
+ case RV_ACTION_ST: |
|
333 |
+ if (exp->op==NO_OP){ |
|
334 |
+ exp->l_type=ACTION_O; |
|
335 |
+ exp->l.param=0; |
|
336 |
+ exp->r_type=ACTION_ST; |
|
337 |
+ exp->r.param=rval->v.action; |
|
338 |
+ rval_destroy(rval); |
|
339 |
+ pkg_free(rve); |
|
340 |
+ ret=1; |
|
341 |
+ } |
|
342 |
+ break; |
|
343 |
+ case RV_SEL: |
|
344 |
+ exp->l.select=pkg_malloc(sizeof(*exp->l.select)); |
|
345 |
+ if (exp->l.select){ |
|
346 |
+ exp->l_type=SELECT_O; |
|
347 |
+ *exp->l.select=rval->v.sel; |
|
348 |
+ rval_destroy(rval); |
|
349 |
+ pkg_free(rve); |
|
350 |
+ ret=1; |
|
351 |
+ }else |
|
352 |
+ ret=-1; |
|
353 |
+ break; |
|
354 |
+ case RV_AVP: |
|
355 |
+ exp->l.attr=pkg_malloc(sizeof(*exp->l.attr)); |
|
356 |
+ if (exp->l.attr){ |
|
357 |
+ exp->l_type=AVP_O; |
|
358 |
+ *exp->l.attr=rval->v.avps; |
|
359 |
+ rval_destroy(rval); |
|
360 |
+ pkg_free(rve); |
|
361 |
+ ret=1; |
|
362 |
+ }else |
|
363 |
+ ret=-1; |
|
364 |
+ break; |
|
365 |
+ case RV_PVAR: |
|
366 |
+ exp->l.param=pkg_malloc(sizeof(pv_spec_t)); |
|
367 |
+ if (exp->l.param){ |
|
368 |
+ exp->l_type=PVAR_O; |
|
369 |
+ *((pv_spec_t*)exp->l.param)=rval->v.pvs; |
|
370 |
+ rval_destroy(rval); |
|
371 |
+ pkg_free(rve); |
|
372 |
+ ret=1; |
|
373 |
+ }else |
|
374 |
+ ret=-1; |
|
375 |
+ break; |
|
376 |
+ case RV_NONE: |
|
377 |
+ break; |
|
378 |
+ } |
|
379 |
+ } |
|
380 |
+ } |
|
381 |
+ if (ret>0) |
|
382 |
+ DBG("left EXP optimized succesfully: %d op %d to %d op %d\n", |
|
383 |
+ old_type, old_op, exp->l_type, exp->op); |
|
384 |
+ return ret; |
|
385 |
+} |
|
386 |
+ |
|
387 |
+ |
|
388 |
+ |
|
389 |
+/** optimize the left side of a struct expr. |
|
390 |
+ * @return 1 if optimized, 0 if not and -1 on error |
|
391 |
+ */ |
|
392 |
+static int exp_optimize_right(struct expr* exp) |
|
393 |
+{ |
|
394 |
+ struct rval_expr* rve; |
|
395 |
+ struct rvalue* rval; |
|
396 |
+ int old_type, old_op; |
|
397 |
+ int ret; |
|
398 |
+ |
|
399 |
+ ret=0; |
|
400 |
+ if ((exp->type!=ELEM_T) ||(exp->op==NO_OP)) |
|
401 |
+ return 0; |
|
402 |
+ old_type=exp->r_type; |
|
403 |
+ old_op=exp->op; |
|
404 |
+ if (exp->r_type==RVE_ST){ |
|
405 |
+ rve=exp->r.param; |
|
406 |
+ /* rve should be previously fixed/optimized */ |
|
407 |
+ /* optimize exp (rval(val)) -> exp(val) */ |
|
408 |
+ if (rve->op==RVE_RVAL_OP){ |
|
409 |
+ rval=&rve->left.rval; |
|
410 |
+ switch(rval->type){ |
|
411 |
+ case RV_INT: |
|
412 |
+ exp->r_type=NUMBER_ST; |
|
413 |
+ exp->r.numval=rval->v.l; |
|
414 |
+ rval_destroy(rval); |
|
415 |
+ pkg_free(rve); |
|
416 |
+ ret=1; |
|
417 |
+ break; |
|
418 |
+ case RV_STR: |
|
419 |
+ exp->r.str.s=pkg_malloc(rval->v.s.len+1); |
|
420 |
+ if (exp->r.str.s){ |
|
421 |
+ exp->r.str.len=rval->v.s.len; |
|
422 |
+ memcpy(exp->r.str.s, rval->v.s.s, rval->v.s.len); |
|
423 |
+ exp->r_type=STRING_ST; |
|
424 |
+ rval_destroy(rval); |
|
425 |
+ pkg_free(rve); |
|
426 |
+ ret=1; |
|
427 |
+ }else |
|
428 |
+ ret=-1; |
|
429 |
+ break; |
|
430 |
+ case RV_BEXPR: |
|
431 |
+ /* cannot be optimized further, is an exp_elem |
|
432 |
+ which is not constant */ |
|
433 |
+ break; |
|
434 |
+ case RV_ACTION_ST: |
|
435 |
+ /* cannot be optimized further, is not constant and |
|
436 |
+ eval_elem() does not support ACTION_ST for op!=NO_OP*/ |
|
437 |
+ break; |
|
438 |
+ case RV_SEL: |
|
439 |
+ exp->r.select=pkg_malloc(sizeof(*exp->l.select)); |
|
440 |
+ if (exp->r.select){ |
|
441 |
+ exp->r_type=SELECT_ST; |
|
442 |
+ *exp->r.select=rval->v.sel; |
|
443 |
+ rval_destroy(rval); |
|
444 |
+ pkg_free(rve); |
|
445 |
+ ret=1; |
|
446 |
+ }else |
|
447 |
+ ret=-1; |
|
448 |
+ break; |
|
449 |
+ case RV_AVP: |
|
450 |
+ exp->r.attr=pkg_malloc(sizeof(*exp->l.attr)); |
|
451 |
+ if (exp->r.attr){ |
|
452 |
+ exp->r_type=AVP_ST; |
|
453 |
+ *exp->r.attr=rval->v.avps; |
|
454 |
+ rval_destroy(rval); |
|
455 |
+ pkg_free(rve); |
|
456 |
+ ret=1; |
|
457 |
+ }else |
|
458 |
+ ret=-1; |
|
459 |
+ break; |
|
460 |
+ case RV_PVAR: |
|
461 |
+ exp->r.param=pkg_malloc(sizeof(pv_spec_t)); |
|
462 |
+ if (exp->r.param){ |
|
463 |
+ exp->r_type=PVAR_ST; |
|
464 |
+ *((pv_spec_t*)exp->r.param)=rval->v.pvs; |
|
465 |
+ rval_destroy(rval); |
|
466 |
+ pkg_free(rve); |
|
467 |
+ ret=1; |
|
468 |
+ }else |
|
469 |
+ ret=-1; |
|
470 |
+ break; |
|
471 |
+ case RV_NONE: |
|
472 |
+ ret=-1; |
|
473 |
+ break; |
|
474 |
+ } |
|
475 |
+ } |
|
476 |
+ } |
|
477 |
+ if (ret>0) |
|
478 |
+ DBG("right EXP optimized succesfully: %d op %d to %d op %d\n", |
|
479 |
+ old_type, old_op, exp->r_type, exp->op); |
|
480 |
+ return ret; |
|
481 |
+} |
|
482 |
+ |
|
483 |
+ |
|
484 |
+ |
|
286 | 485 |
/* traverses an expr tree and compiles the REs where necessary) |
287 | 486 |
* returns: 0 for ok, <0 if errors */ |
288 | 487 |
int fix_expr(struct expr* exp) |
... | ... |
@@ -382,12 +587,16 @@ int fix_expr(struct expr* exp) |
382 | 382 |
ERR("Unable to fix left rval expression\n"); |
383 | 383 |
return ret; |
384 | 384 |
} |
385 |
+ if (scr_opt_lev>=2) |
|
386 |
+ exp_optimize_left(exp); |
|
385 | 387 |
} |
386 | 388 |
if (exp->r_type==RVE_ST){ |
387 | 389 |
if ((ret=fix_rval_expr(&exp->r.param))<0){ |
388 | 390 |
ERR("Unable to fix right rval expression\n"); |
389 | 391 |
return ret; |
390 | 392 |
} |
393 |
+ if (scr_opt_lev>=2) |
|
394 |
+ exp_optimize_right(exp); |
|
391 | 395 |
} |
392 | 396 |
/* PVAR don't need fixing */ |
393 | 397 |
ret=0; |
... | ... |
@@ -934,11 +1143,28 @@ inline static int comp_rve(int op, struct rval_expr* rve, int rtype, |
934 | 934 |
struct run_act_ctx* h) |
935 | 935 |
{ |
936 | 936 |
int i; |
937 |
+ struct rvalue* rv; |
|
938 |
+ struct rvalue* rv1; |
|
939 |
+ struct rval_cache c1; |
|
937 | 940 |
|
938 |
- if (unlikely(rval_expr_eval_int(h, msg, &i, rve)<0)){ |
|
941 |
+ rval_cache_init(&c1); |
|
942 |
+ if (unlikely(rval_expr_eval_rvint(h, msg, &rv, &i, rve, &c1)<0)){ |
|
939 | 943 |
ERR("failure evaluating expression: bad type\n"); |
940 | 944 |
i=0; /* false */ |
945 |
+ goto int_expr; |
|
946 |
+ } |
|
947 |
+ if (unlikely(rv)){ |
|
948 |
+ /* no int => str */ |
|
949 |
+ rv1=rval_convert(h, msg, RV_STR, rv, &c1); |
|
950 |
+ i=comp_str(op, &rv1->v.s, rtype, r, msg, h); |
|
951 |
+ rval_destroy(rv1); |
|
952 |
+ rval_destroy(rv); |
|
953 |
+ rval_cache_clean(&c1); |
|
954 |
+ return i; |
|
941 | 955 |
} |
956 |
+ /* expr evaluated to int */ |
|
957 |
+int_expr: |
|
958 |
+ rval_cache_clean(&c1); |
|
942 | 959 |
if (op==NO_OP) |
943 | 960 |
return !(!i); /* transform it into { 0, 1 } */ |
944 | 961 |
return comp_num(op, i, rtype, r, msg, h); |