Skip to content

Commit e843a4f

Browse files
muhmuhtennicowilliams
authored andcommitted
Make builtin binding fast again by binding only referenced symbols
Avoid doing the internal binding of top-level symbols in the parser, leaving that work to be done in a post-processing step. For builtins, this lets us do a reference-aware bind step (block_bind_incremental) *after* generating builtins/0. Libraries are a bit trickier since they may be bound multiple times, so instead of thinking through the implications I added (block_bind_self) to resolve all internal symbols immediately.
1 parent b2b0bd3 commit e843a4f

File tree

6 files changed

+54
-9
lines changed

6 files changed

+54
-9
lines changed

src/builtin.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,7 +1743,7 @@ static block bind_bytecoded_builtins(block b) {
17431743
BLOCK(gen_param("start"), gen_param("end")),
17441744
range));
17451745
}
1746-
return block_bind(builtins, b, OP_IS_CALL_PSEUDO);
1746+
return BLOCK(builtins, b);
17471747
}
17481748

17491749
static const char jq_builtins[] =
@@ -1793,7 +1793,7 @@ int builtins_bind(jq_state *jq, block* bb) {
17931793
builtins = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), builtins);
17941794
builtins = gen_builtin_list(builtins);
17951795

1796-
*bb = block_bind(builtins, *bb, OP_IS_CALL_PSEUDO);
1796+
*bb = block_bind_incremental(builtins, *bb, OP_IS_CALL_PSEUDO);
17971797
*bb = block_drop_unreferenced(*bb);
17981798
return nerrors;
17991799
}

src/compile.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,9 @@ block gen_op_unbound(opcode op, const char* name) {
222222

223223
block gen_op_var_fresh(opcode op, const char* name) {
224224
assert(opcode_describe(op)->flags & OP_HAS_VARIABLE);
225-
return block_bind(gen_op_unbound(op, name),
226-
gen_noop(), OP_HAS_VARIABLE);
225+
block b = gen_op_unbound(op, name);
226+
b.first->bound_by = b.first;
227+
return b;
227228
}
228229

229230
block gen_op_bound(opcode op, block binder) {
@@ -382,7 +383,7 @@ static int block_bind_each(block binder, block body, int bindflags) {
382383
return nrefs;
383384
}
384385

385-
block block_bind(block binder, block body, int bindflags) {
386+
static block block_bind(block binder, block body, int bindflags) {
386387
block_bind_each(binder, body, bindflags);
387388
return block_join(binder, body);
388389
}
@@ -434,6 +435,48 @@ block block_bind_referenced(block binder, block body, int bindflags) {
434435
return body;
435436
}
436437

438+
static inst* block_take_last(block* b) {
439+
inst* i = b->last;
440+
if (i == 0)
441+
return 0;
442+
if (i->prev) {
443+
i->prev->next = i->next;
444+
b->last = i->prev;
445+
i->prev = 0;
446+
} else {
447+
b->first = 0;
448+
b->last = 0;
449+
}
450+
return i;
451+
}
452+
453+
// Binds a sequence of binders, which *must not* alrady be bound to each other,
454+
// to body, throwing away unreferenced defs
455+
block block_bind_incremental(block binder, block body, int bindflags) {
456+
assert(block_has_only_binders(binder, bindflags));
457+
bindflags |= OP_HAS_BINDING;
458+
459+
inst* curr;
460+
while ((curr = block_take_last(&binder))) {
461+
body = block_bind_referenced(inst_block(curr), body, bindflags);
462+
}
463+
return body;
464+
}
465+
466+
block block_bind_self(block binder, int bindflags) {
467+
assert(block_has_only_binders(binder, bindflags));
468+
bindflags |= OP_HAS_BINDING;
469+
block body = gen_noop();
470+
471+
inst* curr;
472+
while ((curr = block_take_last(&binder))) {
473+
block b = inst_block(curr);
474+
block_bind_subblock(b, body, bindflags, 0);
475+
body = BLOCK(b, body);
476+
}
477+
return body;
478+
}
479+
437480
static void block_mark_referenced(block body) {
438481
int saw_top = 0;
439482
for (inst* i = body.last; i; i = i->prev) {
@@ -1074,7 +1117,7 @@ block gen_cbinding(const struct cfunction* cfunctions, int ncfunctions, block co
10741117
i->imm.cfunc = &cfunctions[cfunc];
10751118
i->symbol = strdup(i->imm.cfunc->name);
10761119
i->any_unbound = 0;
1077-
code = block_bind(inst_block(i), code, OP_IS_CALL_PSEUDO);
1120+
code = BLOCK(inst_block(i), code);
10781121
}
10791122
return code;
10801123
}

src/compile.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ int block_has_only_binders(block, int bindflags);
7272
int block_has_main(block);
7373
int block_is_funcdef(block b);
7474
int block_is_single(block b);
75-
block block_bind(block binder, block body, int bindflags);
7675
block block_bind_library(block binder, block body, int bindflags, const char* libname);
7776
block block_bind_referenced(block binder, block body, int bindflags);
77+
block block_bind_incremental(block binder, block body, int bindflags);
78+
block block_bind_self(block binder, int bindflags);
7879
block block_drop_unreferenced(block body);
7980

8081
jv block_take_imports(block* body);

src/linker.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ static int load_library(jq_state *jq, jv lib_path, int is_data, int raw, const c
336336
jv_string(dirname(lib_origin)),
337337
&program, lib_state);
338338
free(lib_origin);
339+
program = block_bind_self(program, OP_IS_CALL_PSEUDO);
339340
}
340341
}
341342
state_idx = lib_state->ct++;

src/parser.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2423,7 +2423,7 @@ YYLTYPE yylloc = yyloc_default;
24232423
case 9:
24242424
#line 333 "src/parser.y" /* yacc.c:1646 */
24252425
{
2426-
(yyval.blk) = block_bind((yyvsp[-1].blk), (yyvsp[0].blk), OP_IS_CALL_PSEUDO);
2426+
(yyval.blk) = block_join((yyvsp[-1].blk), (yyvsp[0].blk));
24272427
}
24282428
#line 2429 "src/parser.c" /* yacc.c:1646 */
24292429
break;

src/parser.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ FuncDefs:
331331
$$ = gen_noop();
332332
} |
333333
FuncDef FuncDefs {
334-
$$ = block_bind($1, $2, OP_IS_CALL_PSEUDO);
334+
$$ = block_join($1, $2);
335335
}
336336

337337
Exp:

0 commit comments

Comments
 (0)