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.

119 lines
4.2 KiB

  1. From a949ffe9554b5af5614d31b795805f56939a031b Mon Sep 17 00:00:00 2001
  2. From: Muh Muhten <muh.muhten@gmail.com>
  3. Date: Fri, 8 Feb 2019 16:52:04 -0500
  4. Subject: [PATCH 1/9] Improve linking time by marking subtrees with unbound
  5. symbols
  6. ---
  7. src/compile.c | 29 +++++++++++++++++++++++++----
  8. 1 file changed, 25 insertions(+), 4 deletions(-)
  9. --- a/src/compile.c
  10. +++ b/src/compile.c
  11. @@ -49,9 +49,10 @@ struct inst {
  12. // Unbound instructions (references to other things that may or may not
  13. // exist) are created by "gen_foo_unbound", and bindings are created by
  14. // block_bind(definition, body), which binds all instructions in
  15. - // body which are unboudn and refer to "definition" by name.
  16. + // body which are unbound and refer to "definition" by name.
  17. struct inst* bound_by;
  18. char* symbol;
  19. + int any_unbound;
  20. int nformals;
  21. int nactuals;
  22. @@ -73,6 +74,7 @@ static inst* inst_new(opcode op) {
  23. i->bytecode_pos = -1;
  24. i->bound_by = 0;
  25. i->symbol = 0;
  26. + i->any_unbound = 0;
  27. i->nformals = -1;
  28. i->nactuals = -1;
  29. i->subfn = gen_noop();
  30. @@ -156,6 +158,7 @@ block gen_const_global(jv constant, cons
  31. inst* i = inst_new(STORE_GLOBAL);
  32. i->imm.constant = constant;
  33. i->symbol = strdup(name);
  34. + i->any_unbound = 0;
  35. return inst_block(i);
  36. }
  37. @@ -211,6 +214,7 @@ block gen_op_unbound(opcode op, const ch
  38. assert(opcode_describe(op)->flags & OP_HAS_BINDING);
  39. inst* i = inst_new(op);
  40. i->symbol = strdup(name);
  41. + i->any_unbound = 1;
  42. return inst_block(i);
  43. }
  44. @@ -224,6 +228,7 @@ block gen_op_bound(opcode op, block bind
  45. assert(block_is_single(binder));
  46. block b = gen_op_unbound(op, binder.first->symbol);
  47. b.first->bound_by = binder.first;
  48. + b.first->any_unbound = 0;
  49. return b;
  50. }
  51. @@ -324,7 +329,7 @@ static int block_count_refs(block binder
  52. return nrefs;
  53. }
  54. -static int block_bind_subblock(block binder, block body, int bindflags, int break_distance) {
  55. +static int block_bind_subblock_inner(int* any_unbound, block binder, block body, int bindflags, int break_distance) {
  56. assert(block_is_single(binder));
  57. assert((opcode_describe(binder.first->op)->flags & bindflags) == (bindflags & ~OP_BIND_WILDCARD));
  58. assert(binder.first->symbol);
  59. @@ -336,6 +341,9 @@ static int block_bind_subblock(block bin
  60. binder.first->nformals = block_count_formals(binder);
  61. int nrefs = 0;
  62. for (inst* i = body.first; i; i = i->next) {
  63. + if (i->any_unbound == 0)
  64. + continue;
  65. +
  66. int flags = opcode_describe(i->op)->flags;
  67. if ((flags & bindflags) == (bindflags & ~OP_BIND_WILDCARD) && i->bound_by == 0 &&
  68. (!strcmp(i->symbol, binder.first->symbol) ||
  69. @@ -357,14 +365,25 @@ static int block_bind_subblock(block bin
  70. // a break whenever we come across a STOREV of *anonlabel...
  71. break_distance++;
  72. }
  73. +
  74. + i->any_unbound = (i->symbol && !i->bound_by);
  75. +
  76. // binding recurses into closures
  77. - nrefs += block_bind_subblock(binder, i->subfn, bindflags, break_distance);
  78. + nrefs += block_bind_subblock_inner(&i->any_unbound, binder, i->subfn, bindflags, break_distance);
  79. // binding recurses into argument list
  80. - nrefs += block_bind_subblock(binder, i->arglist, bindflags, break_distance);
  81. + nrefs += block_bind_subblock_inner(&i->any_unbound, binder, i->arglist, bindflags, break_distance);
  82. +
  83. + if (i->any_unbound)
  84. + *any_unbound = 1;
  85. }
  86. return nrefs;
  87. }
  88. +static int block_bind_subblock(block binder, block body, int bindflags, int break_distance) {
  89. + int any_unbound;
  90. + return block_bind_subblock_inner(&any_unbound, binder, body, bindflags, break_distance);
  91. +}
  92. +
  93. static int block_bind_each(block binder, block body, int bindflags) {
  94. assert(block_has_only_binders(binder, bindflags));
  95. bindflags |= OP_HAS_BINDING;
  96. @@ -550,6 +569,7 @@ block gen_function(const char* name, blo
  97. }
  98. i->subfn = body;
  99. i->symbol = strdup(name);
  100. + i->any_unbound = -1;
  101. i->arglist = formals;
  102. block b = inst_block(i);
  103. block_bind_subblock(b, b, OP_IS_CALL_PSEUDO | OP_HAS_BINDING, 0);
  104. @@ -1081,6 +1101,7 @@ block gen_cbinding(const struct cfunctio
  105. inst* i = inst_new(CLOSURE_CREATE_C);
  106. i->imm.cfunc = &cfunctions[cfunc];
  107. i->symbol = strdup(i->imm.cfunc->name);
  108. + i->any_unbound = 0;
  109. code = block_bind(inst_block(i), code, OP_IS_CALL_PSEUDO);
  110. }
  111. return code;