Skip to content

Commit b83ce34

Browse files
author
Sean
committed
#21 more robust OP_CAT code generation
1 parent f5e167e commit b83ce34

File tree

5 files changed

+124
-26
lines changed

5 files changed

+124
-26
lines changed

perf/cat.sink

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
var res
3+
for var i: range 10000
4+
res ~=
5+
"i+0: ${i + 0}, i+1: ${i + 1}, i+2: ${i + 2}, i+3: ${i + 3}" ~
6+
"i+4: ${i + 4}, i+5: ${i + 5}, i+6: ${i + 6}, i+7: ${i + 7}" ~
7+
"i+8: ${i + 8}, i+9: ${i + 9}, i+8: ${i + 8}, i+7: ${i + 7}"
8+
end
9+
say res

src/sink.c

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5307,6 +5307,15 @@ static inline void symtbl_clearTemp(symtbl sym, varloc_st vlc){
53075307
sym->fr->vars->vals[vlc.index] = FVR_TEMP_AVAIL;
53085308
}
53095309

5310+
static inline int symtbl_tempAvail(symtbl sym){
5311+
int cnt = 256 - sym->fr->vars->size;
5312+
for (int i = 0; i < sym->fr->vars->size; i++){
5313+
if (sym->fr->vars->vals[i] == FVR_TEMP_AVAIL)
5314+
cnt++;
5315+
}
5316+
return cnt;
5317+
}
5318+
53105319
static sta_st symtbl_addVar(symtbl sym, list_ptr names, int slot){
53115320
// set `slot` to negative to add variable at next available location
53125321
sfn_st nsr = symtbl_findNamespace(sym, names, names->size - 1);
@@ -6752,26 +6761,48 @@ static per_st program_eval(program prg, symtbl sym, pem_enum mode, varloc_st int
67526761
break;
67536762

67546763
case EXPR_CAT: {
6755-
if (ex->u.cat->size > 256)
6756-
return per_error(ex->flp, sink_format("Concatenation too large"));
67576764
if (mode == PEM_EMPTY || mode == PEM_CREATE){
67586765
sta_st ts = symtbl_addTemp(sym);
67596766
if (ts.type == STA_ERROR)
67606767
return per_error(ex->flp, ts.u.msg);
67616768
intoVlc = ts.u.vlc;
67626769
}
6763-
varloc_st p[256];
6764-
for (int i = 0; i < ex->u.cat->size; i++){
6765-
per_st pe = program_eval(prg, sym, PEM_CREATE, VARLOC_NULL, ex->u.cat->ptrs[i]);
6766-
if (pe.type == PER_ERROR)
6767-
return pe;
6768-
p[i] = pe.u.vlc;
6770+
varloc_st t = VARLOC_NULL;
6771+
int tmax = symtbl_tempAvail(sym) - 128;
6772+
if (tmax < 16)
6773+
tmax = 16;
6774+
if (ex->u.cat->size > tmax){
6775+
tmax--;
6776+
sta_st ts = symtbl_addTemp(sym);
6777+
if (ts.type == STA_ERROR)
6778+
return per_error(ex->flp, ts.u.msg);
6779+
t = ts.u.vlc;
67696780
}
6770-
op_cat(prg->ops, intoVlc, ex->u.cat->size);
6771-
for (int i = 0; i < ex->u.cat->size; i++){
6772-
symtbl_clearTemp(sym, p[i]);
6773-
op_arg(prg->ops, p[i]);
6781+
varloc_st p[256];
6782+
for (int ci = 0; ci < ex->u.cat->size; ci += tmax){
6783+
int len = ex->u.cat->size - ci;
6784+
if (len > tmax)
6785+
len = tmax;
6786+
for (int i = 0; i < len; i++){
6787+
per_st pe = program_eval(prg, sym, PEM_CREATE, VARLOC_NULL,
6788+
ex->u.cat->ptrs[ci + i]);
6789+
if (pe.type == PER_ERROR)
6790+
return pe;
6791+
p[i] = pe.u.vlc;
6792+
}
6793+
op_cat(prg->ops, ci > 0 ? t : intoVlc, len);
6794+
for (int i = 0; i < len; i++){
6795+
symtbl_clearTemp(sym, p[i]);
6796+
op_arg(prg->ops, p[i]);
6797+
}
6798+
if (ci > 0){
6799+
op_cat(prg->ops, intoVlc, 2);
6800+
op_arg(prg->ops, intoVlc);
6801+
op_arg(prg->ops, t);
6802+
}
67746803
}
6804+
if (!varloc_isnull(t))
6805+
symtbl_clearTemp(sym, t);
67756806
if (mode == PEM_EMPTY){
67766807
symtbl_clearTemp(sym, intoVlc);
67776808
return per_ok(VARLOC_NULL);

src/sink.js

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,6 +3308,15 @@ function symtbl_clearTemp(sym, vlc){
33083308
sym.fr.vars[vlc.index] = FVR_TEMP_AVAIL;
33093309
}
33103310

3311+
function symtbl_tempAvail(sym){
3312+
var cnt = 256 - sym.fr.vars.length;
3313+
for (var i = 0; i < sym.fr.vars.length; i++){
3314+
if (sym.fr.vars[i] == FVR_TEMP_AVAIL)
3315+
cnt++;
3316+
}
3317+
return cnt;
3318+
}
3319+
33113320
function symtbl_addVar(sym, names, slot){
33123321
// set `slot` to negative to add variable at next available location
33133322
var nsr = symtbl_findNamespace(sym, names, names.length - 1);
@@ -4552,26 +4561,43 @@ function program_eval(prg, sym, mode, intoVlc, ex){
45524561
break;
45534562

45544563
case EXPR_CAT: {
4555-
if (ex.cat.length > 256)
4556-
return per_error(ex.flp, 'Concatenation too large');
45574564
if (mode == PEM_EMPTY || mode == PEM_CREATE){
45584565
var ts = symtbl_addTemp(sym);
45594566
if (ts.type == STA_ERROR)
45604567
return per_error(ex.flp, ts.msg);
45614568
intoVlc = ts.vlc;
45624569
}
4563-
var p = new Array(ex.cat.length);
4564-
for (var i = 0; i < ex.cat.length; i++){
4565-
var pe = program_eval(prg, sym, PEM_CREATE, null, ex.cat[i]);
4566-
if (pe.type == PER_ERROR)
4567-
return pe;
4568-
p[i] = pe.vlc;
4570+
var t = null;
4571+
var tmax = Math.max(16, symtbl_tempAvail(sym) - 128);
4572+
if (ex.cat.length > tmax){
4573+
tmax--;
4574+
var ts = symtbl_addTemp(sym);
4575+
if (ts.type == STA_ERROR)
4576+
return per_error(ex.flp, ts.msg);
4577+
t = ts.vlc;
45694578
}
4570-
op_cat(prg.ops, intoVlc, ex.cat.length);
4571-
for (var i = 0; i < ex.cat.length; i++){
4572-
symtbl_clearTemp(sym, p[i]);
4573-
op_arg(prg.ops, p[i]);
4579+
for (var ci = 0; ci < ex.cat.length; ci += tmax){
4580+
var len = Math.min(tmax, ex.cat.length - ci);
4581+
var p = new Array(len);
4582+
for (var i = 0; i < len; i++){
4583+
var pe = program_eval(prg, sym, PEM_CREATE, null, ex.cat[ci + i]);
4584+
if (pe.type == PER_ERROR)
4585+
return pe;
4586+
p[i] = pe.vlc;
4587+
}
4588+
op_cat(prg.ops, ci > 0 ? t : intoVlc, len);
4589+
for (var i = 0; i < len; i++){
4590+
symtbl_clearTemp(sym, p[i]);
4591+
op_arg(prg.ops, p[i]);
4592+
}
4593+
if (ci > 0){
4594+
op_cat(prg.ops, intoVlc, 2);
4595+
op_arg(prg.ops, intoVlc);
4596+
op_arg(prg.ops, t);
4597+
}
45744598
}
4599+
if (t != null)
4600+
symtbl_clearTemp(sym, t);
45754601
if (mode == PEM_EMPTY){
45764602
symtbl_clearTemp(sym, intoVlc);
45774603
return per_ok(null);
@@ -7659,9 +7685,10 @@ function context_run(ctx){
76597685
if (listcat)
76607686
var_set(ctx, A, B, Array.prototype.concat.apply([], p));
76617687
else{
7688+
var out = '';
76627689
for (var i = 0; i < p.length; i++)
7663-
p[i] = sink_tostr(p[i]);
7664-
var_set(ctx, A, B, p.join(''));
7690+
out += sink_tostr(p[i]);
7691+
var_set(ctx, A, B, out);
76657692
}
76667693
} break;
76677694

tests/59.large-cat/large-cat.sink

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var i = 0
2+
say "${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
3+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
4+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
5+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
6+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
7+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
8+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
9+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
10+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
11+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
12+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
13+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
14+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
15+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}\n" ~
16+
"${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1} ${i+1}"

tests/59.large-cat/pass.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
1 1 1 1 1 1 1 1
2+
1 1 1 1 1 1 1 1
3+
1 1 1 1 1 1 1 1
4+
1 1 1 1 1 1 1 1
5+
1 1 1 1 1 1 1 1
6+
1 1 1 1 1 1 1 1
7+
1 1 1 1 1 1 1 1
8+
1 1 1 1 1 1 1 1
9+
1 1 1 1 1 1 1 1
10+
1 1 1 1 1 1 1 1
11+
1 1 1 1 1 1 1 1
12+
1 1 1 1 1 1 1 1
13+
1 1 1 1 1 1 1 1
14+
1 1 1 1 1 1 1 1
15+
1 1 1 1 1 1 1 1

0 commit comments

Comments
 (0)