You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
5.4 KiB

  1. From 916c12fb593005771a6ce098f5a7da4dec0051d1 Mon Sep 17 00:00:00 2001
  2. From: Muh Muhten <muh.muhten@gmail.com>
  3. Date: Wed, 20 Feb 2019 01:48:56 -0500
  4. Subject: [PATCH 9/9] Make builtin binding fast again by binding only
  5. referenced symbols
  6. Avoid doing the internal binding of top-level symbols in the parser,
  7. leaving that work to be done in a post-processing step. For builtins,
  8. this lets us do a reference-aware bind step (block_bind_incremental)
  9. *after* generating builtins/0.
  10. Libraries are a bit trickier since they may be bound multiple times, so
  11. instead of thinking through the implications I added (block_bind_self)
  12. to resolve all internal symbols immediately.
  13. ---
  14. src/builtin.c | 4 ++--
  15. src/compile.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
  16. src/compile.h | 3 ++-
  17. src/linker.c | 1 +
  18. src/parser.c | 2 +-
  19. src/parser.y | 2 +-
  20. 6 files changed, 54 insertions(+), 9 deletions(-)
  21. --- a/src/builtin.c
  22. +++ b/src/builtin.c
  23. @@ -1703,7 +1703,7 @@ static block bind_bytecoded_builtins(blo
  24. BLOCK(gen_param("start"), gen_param("end")),
  25. range));
  26. }
  27. - return block_bind(builtins, b, OP_IS_CALL_PSEUDO);
  28. + return BLOCK(builtins, b);
  29. }
  30. static const char jq_builtins[] =
  31. @@ -1753,7 +1753,7 @@ int builtins_bind(jq_state *jq, block* b
  32. builtins = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), builtins);
  33. builtins = gen_builtin_list(builtins);
  34. - *bb = block_bind(builtins, *bb, OP_IS_CALL_PSEUDO);
  35. + *bb = block_bind_incremental(builtins, *bb, OP_IS_CALL_PSEUDO);
  36. *bb = block_drop_unreferenced(*bb);
  37. return nerrors;
  38. }
  39. --- a/src/compile.c
  40. +++ b/src/compile.c
  41. @@ -222,8 +222,9 @@ block gen_op_unbound(opcode op, const ch
  42. block gen_op_var_fresh(opcode op, const char* name) {
  43. assert(opcode_describe(op)->flags & OP_HAS_VARIABLE);
  44. - return block_bind(gen_op_unbound(op, name),
  45. - gen_noop(), OP_HAS_VARIABLE);
  46. + block b = gen_op_unbound(op, name);
  47. + b.first->bound_by = b.first;
  48. + return b;
  49. }
  50. block gen_op_bound(opcode op, block binder) {
  51. @@ -382,7 +383,7 @@ static int block_bind_each(block binder,
  52. return nrefs;
  53. }
  54. -block block_bind(block binder, block body, int bindflags) {
  55. +static block block_bind(block binder, block body, int bindflags) {
  56. block_bind_each(binder, body, bindflags);
  57. return block_join(binder, body);
  58. }
  59. @@ -434,6 +435,48 @@ block block_bind_referenced(block binder
  60. return body;
  61. }
  62. +static inst* block_take_last(block* b) {
  63. + inst* i = b->last;
  64. + if (i == 0)
  65. + return 0;
  66. + if (i->prev) {
  67. + i->prev->next = i->next;
  68. + b->last = i->prev;
  69. + i->prev = 0;
  70. + } else {
  71. + b->first = 0;
  72. + b->last = 0;
  73. + }
  74. + return i;
  75. +}
  76. +
  77. +// Binds a sequence of binders, which *must not* alrady be bound to each other,
  78. +// to body, throwing away unreferenced defs
  79. +block block_bind_incremental(block binder, block body, int bindflags) {
  80. + assert(block_has_only_binders(binder, bindflags));
  81. + bindflags |= OP_HAS_BINDING;
  82. +
  83. + inst* curr;
  84. + while ((curr = block_take_last(&binder))) {
  85. + body = block_bind_referenced(inst_block(curr), body, bindflags);
  86. + }
  87. + return body;
  88. +}
  89. +
  90. +block block_bind_self(block binder, int bindflags) {
  91. + assert(block_has_only_binders(binder, bindflags));
  92. + bindflags |= OP_HAS_BINDING;
  93. + block body = gen_noop();
  94. +
  95. + inst* curr;
  96. + while ((curr = block_take_last(&binder))) {
  97. + block b = inst_block(curr);
  98. + block_bind_subblock(b, body, bindflags, 0);
  99. + body = BLOCK(b, body);
  100. + }
  101. + return body;
  102. +}
  103. +
  104. static void block_mark_referenced(block body) {
  105. int saw_top = 0;
  106. for (inst* i = body.last; i; i = i->prev) {
  107. @@ -1074,7 +1117,7 @@ block gen_cbinding(const struct cfunctio
  108. i->imm.cfunc = &cfunctions[cfunc];
  109. i->symbol = strdup(i->imm.cfunc->name);
  110. i->any_unbound = 0;
  111. - code = block_bind(inst_block(i), code, OP_IS_CALL_PSEUDO);
  112. + code = BLOCK(inst_block(i), code);
  113. }
  114. return code;
  115. }
  116. --- a/src/compile.h
  117. +++ b/src/compile.h
  118. @@ -72,9 +72,10 @@ int block_has_only_binders(block, int bi
  119. int block_has_main(block);
  120. int block_is_funcdef(block b);
  121. int block_is_single(block b);
  122. -block block_bind(block binder, block body, int bindflags);
  123. block block_bind_library(block binder, block body, int bindflags, const char* libname);
  124. block block_bind_referenced(block binder, block body, int bindflags);
  125. +block block_bind_incremental(block binder, block body, int bindflags);
  126. +block block_bind_self(block binder, int bindflags);
  127. block block_drop_unreferenced(block body);
  128. jv block_take_imports(block* body);
  129. --- a/src/linker.c
  130. +++ b/src/linker.c
  131. @@ -336,6 +336,7 @@ static int load_library(jq_state *jq, jv
  132. jv_string(dirname(lib_origin)),
  133. &program, lib_state);
  134. free(lib_origin);
  135. + program = block_bind_self(program, OP_IS_CALL_PSEUDO);
  136. }
  137. }
  138. state_idx = lib_state->ct++;
  139. --- a/src/parser.c
  140. +++ b/src/parser.c
  141. @@ -2425,7 +2425,7 @@ yyreduce:
  142. case 9:
  143. #line 333 "src/parser.y" /* yacc.c:1646 */
  144. {
  145. - (yyval.blk) = block_bind((yyvsp[-1].blk), (yyvsp[0].blk), OP_IS_CALL_PSEUDO);
  146. + (yyval.blk) = block_join((yyvsp[-1].blk), (yyvsp[0].blk));
  147. }
  148. #line 2431 "src/parser.c" /* yacc.c:1646 */
  149. break;
  150. --- a/src/parser.y
  151. +++ b/src/parser.y
  152. @@ -331,7 +331,7 @@ FuncDefs:
  153. $$ = gen_noop();
  154. } |
  155. FuncDef FuncDefs {
  156. - $$ = block_bind($1, $2, OP_IS_CALL_PSEUDO);
  157. + $$ = block_join($1, $2);
  158. }
  159. Exp: