Commit 949edaa8 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Salvage more bits from experimental tree:

Be more aggressive about tracking const values and merge more const
strings at compile time.
parent 8b0b76f6
...@@ -233,9 +233,19 @@ struct expr { ...@@ -233,9 +233,19 @@ struct expr {
enum var_type fmt; enum var_type fmt;
struct vsb *vsb; struct vsb *vsb;
uint8_t constant; uint8_t constant;
#define EXPR_VAR (1<<0)
#define EXPR_CONST (1<<1)
#define EXPR_STR_CONST (1<<2)
struct token *t1, *t2; 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 void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt);
static struct expr * static struct expr *
...@@ -329,10 +339,13 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, ...@@ -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 '-': VSB_cat(e->vsb, "\v-"); break;
case '1': case '1':
case '2': case '2':
if (*p == '1') if (*p == '1') {
AN(e1);
AN(e1->constant);
VSB_cat(e->vsb, VSB_data(e1->vsb)); VSB_cat(e->vsb, VSB_data(e1->vsb));
else { } else {
AN(e2); AN(e2);
AN(e2->constant);
VSB_cat(e->vsb, VSB_data(e2->vsb)); VSB_cat(e->vsb, VSB_data(e2->vsb));
} }
break; break;
...@@ -350,8 +363,10 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, ...@@ -350,8 +363,10 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1,
e->t2 = e2->t1; e->t2 = e2->t1;
else if (e1 != NULL) else if (e1 != NULL)
e->t1 = e1->t1; e->t1 = e1->t1;
if ((e1 == NULL || e1->constant) && (e2 == NULL || e2->constant)) if ((e1 == NULL || vcc_isconst(e1)) && (e2 == NULL || vcc_isconst(e2)))
e->constant = 1; e->constant = EXPR_CONST;
else
e->constant = EXPR_VAR;
vcc_delete_expr(e1); vcc_delete_expr(e1);
vcc_delete_expr(e2); vcc_delete_expr(e2);
e->fmt = fmt; e->fmt = fmt;
...@@ -417,6 +432,7 @@ static void ...@@ -417,6 +432,7 @@ static void
vcc_expr_tostring(struct expr **e, enum var_type fmt) vcc_expr_tostring(struct expr **e, enum var_type fmt)
{ {
const char *p; const char *p;
uint8_t constant = EXPR_VAR;
CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC); CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
AN(fmt == STRING || fmt == STRING_LIST); AN(fmt == STRING || fmt == STRING_LIST);
...@@ -427,7 +443,14 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt) ...@@ -427,7 +443,14 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt)
case BOOL: p = "VRT_BOOL_string(req, \v1)"; break; case BOOL: p = "VRT_BOOL_string(req, \v1)"; break;
case DURATION: p = "VRT_REAL_string(req, \v1)"; break; case DURATION: p = "VRT_REAL_string(req, \v1)"; break;
/* XXX: should DURATION insist on "s" suffix ? */ /* 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 IP: p = "VRT_IP_string(req, \v1)"; break;
case BYTES: p = "VRT_REAL_string(req, \v1)"; break; /* XXX */ case BYTES: p = "VRT_REAL_string(req, \v1)"; break; /* XXX */
case REAL: p = "VRT_REAL_string(req, \v1)"; break; case REAL: p = "VRT_REAL_string(req, \v1)"; break;
...@@ -436,7 +459,7 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt) ...@@ -436,7 +459,7 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt)
} }
if (p != NULL) { if (p != NULL) {
*e = vcc_expr_edit(fmt, p, *e, 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) ...@@ -488,7 +511,7 @@ vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym)
vcc_NextToken(tl); vcc_NextToken(tl);
*e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0); *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) ...@@ -503,6 +526,7 @@ vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym)
vcc_ExpectCid(tl); vcc_ExpectCid(tl);
vcc_AddRef(tl, tl->t, SYM_BACKEND); vcc_AddRef(tl, tl->t, SYM_BACKEND);
*e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t)); *e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t));
(*e)->constant = EXPR_VAR; /* XXX ? */
vcc_NextToken(tl); vcc_NextToken(tl);
} }
...@@ -519,6 +543,7 @@ vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -519,6 +543,7 @@ vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym)
ERRCHK(tl); ERRCHK(tl);
assert(vp != NULL); assert(vp != NULL);
*e = vcc_mk_expr(vp->fmt, "%s", vp->rname); *e = vcc_mk_expr(vp->fmt, "%s", vp->rname);
(*e)->constant = EXPR_VAR;
vcc_NextToken(tl); vcc_NextToken(tl);
} }
...@@ -541,6 +566,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -541,6 +566,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
SkipToken(tl, '('); SkipToken(tl, '(');
p = sym->args; p = sym->args;
e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(req\v+", sym->cfunc); e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(req\v+", sym->cfunc);
e2->constant = EXPR_VAR;
while (*p != '\0') { while (*p != '\0') {
e1 = NULL; e1 = NULL;
fmt = vcc_arg_type(&p); fmt = vcc_arg_type(&p);
...@@ -549,11 +575,13 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -549,11 +575,13 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
AN(r); AN(r);
e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s", e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s",
(int) (r - sym->name), sym->name); (int) (r - sym->name), sym->name);
e1->constant = EXPR_VAR;
p += strlen(p) + 1; p += strlen(p) + 1;
} else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) { } else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) {
bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++); bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++);
Fh(tl, 0, "struct vmod_priv %s;\n", buf); Fh(tl, 0, "struct vmod_priv %s;\n", buf);
e1 = vcc_mk_expr(VOID, "&%s", buf); e1 = vcc_mk_expr(VOID, "&%s", buf);
e1->constant = EXPR_VAR;
p += strlen(p) + 1; p += strlen(p) + 1;
} else if (fmt == ENUM) { } else if (fmt == ENUM) {
ExpectErr(tl, ID); ExpectErr(tl, ID);
...@@ -575,6 +603,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -575,6 +603,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
return; return;
} }
e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t)); e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
e1->constant = EXPR_VAR;
while (*p != '\0') while (*p != '\0')
p += strlen(p) + 1; p += strlen(p) + 1;
p++; p++;
...@@ -607,6 +636,7 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -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\")", e1 = vcc_mk_expr(VOID, "VRT_MkGethdr(req, %s, \"%s\")",
v->http, v->hdr); v->http, v->hdr);
e1->constant = EXPR_VAR;
if (*p != '\0') if (*p != '\0')
SkipToken(tl, ','); SkipToken(tl, ',');
} else { } else {
...@@ -631,10 +661,12 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -631,10 +661,12 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
SkipToken(tl, ','); SkipToken(tl, ',');
} }
e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1); e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1);
e2->constant = EXPR_VAR;
} }
SkipToken(tl, ')'); SkipToken(tl, ')');
e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL); e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL);
*e = e2; *e = e2;
(*e)->constant = EXPR_VAR;
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -699,7 +731,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -699,7 +731,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
EncToken(e1->vsb, tl->t); EncToken(e1->vsb, tl->t);
e1->fmt = STRING; e1->fmt = STRING;
e1->t1 = tl->t; e1->t1 = tl->t;
e1->constant = 1; e1->constant = EXPR_CONST;
vcc_NextToken(tl); vcc_NextToken(tl);
AZ(VSB_finish(e1->vsb)); AZ(VSB_finish(e1->vsb));
*e = e1; *e = e1;
...@@ -726,7 +758,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -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)); e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t));
vcc_NextToken(tl); vcc_NextToken(tl);
} }
e1->constant = 1; e1->constant = EXPR_CONST;
*e = e1; *e = e1;
break; break;
default: default:
...@@ -786,51 +818,83 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -786,51 +818,83 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt)
* SYNTAX: * SYNTAX:
* ExprAdd: * ExprAdd:
* ExprMul { {'+'|'-'} ExprMul } * * 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 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; struct expr *e2;
enum var_type f2; enum var_type f2;
struct token *tk;
*e = NULL; AN((*e)->constant);
vcc_expr_mul(tl, e, fmt);
ERRCHK(tl);
f2 = (*e)->fmt; f2 = (*e)->fmt;
if ((f2 == STRING_LIST || f2 == STRING) && tl->t->tok == '+') { while (tl->t->tok == '+') {
while (tl->t->tok == '+') { vcc_NextToken(tl);
vcc_NextToken(tl); vcc_expr_mul(tl, &e2, STRING);
vcc_expr_mul(tl, &e2, STRING); ERRCHK(tl);
ERRCHK(tl); if (e2->fmt != STRING && e2->fmt != STRING_LIST)
if (e2->fmt != STRING && e2->fmt != STRING_LIST) vcc_expr_tostring(&e2, f2);
vcc_expr_tostring(&e2, f2); ERRCHK(tl);
ERRCHK(tl); assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
if ((*e)->constant && e2->constant) { AN((*e)->constant);
assert((*e)->fmt == STRING); AN(e2->constant);
assert(e2->fmt == STRING);
*e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2); if (vcc_isconst(*e) && vcc_isconst(e2)) {
} else { assert((*e)->fmt == STRING);
*e = vcc_expr_edit(STRING_LIST, assert(e2->fmt == STRING);
"\v1,\n\v2", *e, e2); *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, *e = vcc_expr_edit(STRING,
"\v+VRT_ReqString(req,\n\v1,\nvrt_magic_string_end)", "\v+VRT_ReqString(req,\n\v1,\nvrt_magic_string_end)",
*e, NULL); *e, NULL);
if (fmt == STRING_LIST && (*e)->fmt == STRING) (*e)->constant = EXPR_VAR;
} if (fmt == STRING_LIST && (*e)->fmt == STRING) {
(*e)->fmt = STRING_LIST; (*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) { switch(f2) {
case INT: break; case STRING: break;
case TIME: break; case STRING_LIST: break;
case DURATION: break; case INT: break;
case BYTES: break; case TIME: break;
case DURATION: break;
case BYTES: break;
default: default:
if (tl->t->tok != '+' && tl->t->tok != '-') if (tl->t->tok != '+' && tl->t->tok != '-')
return; return;
...@@ -840,6 +904,11 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -840,6 +904,11 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
return; return;
} }
if (f2 == STRING || f2 == STRING_LIST) {
vcc_expr_string_add(tl, e, fmt);
return;
}
while (tl->t->tok == '+' || tl->t->tok == '-') { while (tl->t->tok == '+' || tl->t->tok == '-') {
if (f2 == TIME) if (f2 == TIME)
f2 = DURATION; f2 = DURATION;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment