[master] 949edaa Salvage more bits from experimental tree:

Poul-Henning Kamp phk at varnish-cache.org
Thu Oct 18 23:58:22 CEST 2012


commit 949edaa89c0fb2a3c984517f2384b1d499702ee6
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Oct 18 21:57:29 2012 +0000

    Salvage more bits from experimental tree:
    
    Be more aggressive about tracking const values and merge more const
    strings at compile time.

diff --git a/lib/libvcl/vcc_expr.c b/lib/libvcl/vcc_expr.c
index c3fbef4..f32208d 100644
--- a/lib/libvcl/vcc_expr.c
+++ b/lib/libvcl/vcc_expr.c
@@ -233,9 +233,19 @@ struct expr {
 	enum var_type	fmt;
 	struct vsb	*vsb;
 	uint8_t		constant;
+#define EXPR_VAR	(1<<0)
+#define EXPR_CONST	(1<<1)
+#define EXPR_STR_CONST	(1<<2)
 	struct token	*t1, *t2;
 };
 
+static inline int
+vcc_isconst(const struct expr *e)
+{
+	AN(e->constant);
+	return (e->constant & EXPR_CONST);
+}
+
 static void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt);
 
 static struct expr *
@@ -329,10 +339,13 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1,
 		case '-': VSB_cat(e->vsb, "\v-"); break;
 		case '1':
 		case '2':
-			if (*p == '1')
+			if (*p == '1') {
+				AN(e1);
+				AN(e1->constant);
 				VSB_cat(e->vsb, VSB_data(e1->vsb));
-			else {
+			} else {
 				AN(e2);
+				AN(e2->constant);
 				VSB_cat(e->vsb, VSB_data(e2->vsb));
 			}
 			break;
@@ -350,8 +363,10 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1,
 		e->t2 = e2->t1;
 	else if (e1 != NULL)
 		e->t1 = e1->t1;
-	if ((e1 == NULL || e1->constant) && (e2 == NULL || e2->constant))
-		e->constant = 1;
+	if ((e1 == NULL || vcc_isconst(e1)) && (e2 == NULL || vcc_isconst(e2)))
+		e->constant = EXPR_CONST;
+	else
+		e->constant = EXPR_VAR;
 	vcc_delete_expr(e1);
 	vcc_delete_expr(e2);
 	e->fmt = fmt;
@@ -417,6 +432,7 @@ static void
 vcc_expr_tostring(struct expr **e, enum var_type fmt)
 {
 	const char *p;
+	uint8_t	constant = EXPR_VAR;
 
 	CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
 	AN(fmt == STRING || fmt == STRING_LIST);
@@ -427,7 +443,14 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt)
 	case BOOL:	p = "VRT_BOOL_string(req, \v1)"; break;
 	case DURATION:	p = "VRT_REAL_string(req, \v1)"; break;
 			 /* XXX: should DURATION insist on "s" suffix ? */
-	case INT:	p = "VRT_INT_string(req, \v1)"; break;
+	case INT:
+		if (vcc_isconst(*e)) {
+			p = "\"\v1\"";
+			constant = EXPR_CONST;
+		} else {
+			p = "VRT_INT_string(req, \v1)";
+		}
+		break;
 	case IP:	p = "VRT_IP_string(req, \v1)"; break;
 	case BYTES:	p = "VRT_REAL_string(req, \v1)"; break; /* XXX */
 	case REAL:	p = "VRT_REAL_string(req, \v1)"; break;
@@ -436,7 +459,7 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt)
 	}
 	if (p != NULL) {
 		*e = vcc_expr_edit(fmt, p, *e, NULL);
-		(*e)->constant = 0;
+		(*e)->constant = constant;
 	}
 }
 
@@ -488,7 +511,7 @@ vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym)
 
 	vcc_NextToken(tl);
 	*e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0);
-	(*e)->constant = 1;
+	(*e)->constant = EXPR_CONST;
 }
 
 /*--------------------------------------------------------------------
@@ -503,6 +526,7 @@ vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym)
 	vcc_ExpectCid(tl);
 	vcc_AddRef(tl, tl->t, SYM_BACKEND);
 	*e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t));
+	(*e)->constant = EXPR_VAR;	/* XXX ? */
 	vcc_NextToken(tl);
 }
 
@@ -519,6 +543,7 @@ vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym)
 	ERRCHK(tl);
 	assert(vp != NULL);
 	*e = vcc_mk_expr(vp->fmt, "%s", vp->rname);
+	(*e)->constant = EXPR_VAR;
 	vcc_NextToken(tl);
 }
 
@@ -541,6 +566,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
 	SkipToken(tl, '(');
 	p = sym->args;
 	e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(req\v+", sym->cfunc);
+	e2->constant = EXPR_VAR;
 	while (*p != '\0') {
 		e1 = NULL;
 		fmt = vcc_arg_type(&p);
@@ -549,11 +575,13 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
 			AN(r);
 			e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s",
 			    (int) (r - sym->name), sym->name);
+			e1->constant = EXPR_VAR;
 			p += strlen(p) + 1;
 		} else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) {
 			bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++);
 			Fh(tl, 0, "struct vmod_priv %s;\n", buf);
 			e1 = vcc_mk_expr(VOID, "&%s", buf);
+			e1->constant = EXPR_VAR;
 			p += strlen(p) + 1;
 		} else if (fmt == ENUM) {
 			ExpectErr(tl, ID);
@@ -575,6 +603,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
 				return;
 			}
 			e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
+			e1->constant = EXPR_VAR;
 			while (*p != '\0')
 				p += strlen(p) + 1;
 			p++;
@@ -607,6 +636,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
 			}
 			e1 = vcc_mk_expr(VOID, "VRT_MkGethdr(req, %s, \"%s\")",
 			    v->http, v->hdr);
+			e1->constant = EXPR_VAR;
 			if (*p != '\0')
 				SkipToken(tl, ',');
 		} else {
@@ -631,10 +661,12 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
 				SkipToken(tl, ',');
 		}
 		e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1);
+		e2->constant = EXPR_VAR;
 	}
 	SkipToken(tl, ')');
 	e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL);
 	*e = e2;
+	(*e)->constant = EXPR_VAR;
 }
 
 /*--------------------------------------------------------------------
@@ -699,7 +731,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
 		EncToken(e1->vsb, tl->t);
 		e1->fmt = STRING;
 		e1->t1 = tl->t;
-		e1->constant = 1;
+		e1->constant = EXPR_CONST;
 		vcc_NextToken(tl);
 		AZ(VSB_finish(e1->vsb));
 		*e = e1;
@@ -726,7 +758,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
 			e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t));
 			vcc_NextToken(tl);
 		}
-		e1->constant = 1;
+		e1->constant = EXPR_CONST;
 		*e = e1;
 		break;
 	default:
@@ -786,51 +818,83 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt)
  * SYNTAX:
  *    ExprAdd:
  *      ExprMul { {'+'|'-'} ExprMul } *
+ *
+ * For reasons of memory allocation/copying and general performance,
+ * STRINGs in VCL are quite special.   Addition/concatenation is split
+ * into it's own subfunction to encapsulate this.
  */
 
 static void
-vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
+vcc_expr_string_add(struct vcc *tl, struct expr **e, enum var_type fmt)
 {
 	struct expr  *e2;
 	enum var_type f2;
-	struct token *tk;
 
-	*e = NULL;
-	vcc_expr_mul(tl, e, fmt);
-	ERRCHK(tl);
+	AN((*e)->constant);
 	f2 = (*e)->fmt;
 
-	if ((f2 == STRING_LIST || f2 == STRING) && tl->t->tok == '+') {
-		while (tl->t->tok == '+') {
-			vcc_NextToken(tl);
-			vcc_expr_mul(tl, &e2, STRING);
-			ERRCHK(tl);
-			if (e2->fmt != STRING && e2->fmt != STRING_LIST)
-				vcc_expr_tostring(&e2, f2);
-			ERRCHK(tl);
-			assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
-			if ((*e)->constant &&  e2->constant) {
-				assert((*e)->fmt == STRING);
-				assert(e2->fmt == STRING);
-				*e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2);
-			} else {
-				*e = vcc_expr_edit(STRING_LIST,
-				    "\v1,\n\v2", *e, e2);
-			}
+	while (tl->t->tok == '+') {
+		vcc_NextToken(tl);
+		vcc_expr_mul(tl, &e2, STRING);
+		ERRCHK(tl);
+		if (e2->fmt != STRING && e2->fmt != STRING_LIST)
+			vcc_expr_tostring(&e2, f2);
+		ERRCHK(tl);
+		assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
+
+		AN((*e)->constant);
+		AN(e2->constant);
+
+		if (vcc_isconst(*e) && vcc_isconst(e2)) {
+			assert((*e)->fmt == STRING);
+			assert(e2->fmt == STRING);
+			*e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2);
+			(*e)->constant = EXPR_CONST;
+		} else if (((*e)->constant & EXPR_STR_CONST) &&
+		    vcc_isconst(e2)) {
+			assert((*e)->fmt == STRING_LIST);
+			assert(e2->fmt == STRING);
+			*e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2);
+			(*e)->constant |= EXPR_STR_CONST;
+		} else if (e2->fmt == STRING && vcc_isconst(e2)) {
+			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
+			(*e)->constant = EXPR_VAR | EXPR_STR_CONST;
+		} else {
+			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
+			(*e)->constant = EXPR_VAR;
 		}
 	}
-	if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST)
+	AN((*e)->constant);
+	if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST) {
 		*e = vcc_expr_edit(STRING,
 		    "\v+VRT_ReqString(req,\n\v1,\nvrt_magic_string_end)",
 		    *e, NULL);
-	if (fmt == STRING_LIST && (*e)->fmt == STRING)
+		(*e)->constant = EXPR_VAR;
+	} if (fmt == STRING_LIST && (*e)->fmt == STRING) {
 		(*e)->fmt = STRING_LIST;
+	}
+	AN((*e)->constant);
+}
+
+static void
+vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr  *e2;
+	enum var_type f2;
+	struct token *tk;
+
+	*e = NULL;
+	vcc_expr_mul(tl, e, fmt);
+	ERRCHK(tl);
+	f2 = (*e)->fmt;
 
 	switch(f2) {
-	case INT:	break;
-	case TIME:	break;
-	case DURATION:	break;
-	case BYTES:	break;
+	case STRING:		break;
+	case STRING_LIST:	break;
+	case INT:		break;
+	case TIME:		break;
+	case DURATION:		break;
+	case BYTES:		break;
 	default:
 		if (tl->t->tok != '+' && tl->t->tok != '-')
 			return;
@@ -840,6 +904,11 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
 		return;
 	}
 
+	if (f2 == STRING || f2 == STRING_LIST) {
+		vcc_expr_string_add(tl, e, fmt);
+		return;
+	}
+
 	while (tl->t->tok == '+' || tl->t->tok == '-') {
 		if (f2 == TIME)
 			f2 = DURATION;



More information about the varnish-commit mailing list