DavidKinder / Inform6

The latest version of the Inform 6 compiler, used for generating interactive fiction games.
http://inform-fiction.org/
Other
199 stars 32 forks source link

adjust the cut-off length for inline text (zcode) #242

Closed heasm66 closed 9 months ago

heasm66 commented 10 months ago

Currently the cut-off for when a print statement gets its string compiled as a print <inline> to print_paddr <packed-address> is 32 characters, as seen in states.c.

{   case DQ_TT:
      if (token_text[0] == '^' && token_text[1] == '\0') {
          /* The string "^" is always a simple newline. */
          assemblez_0(new_line_zc);
          break;
      }
      if (strlen(token_text) > 32)
      {   INITAOT(&AO, LONG_CONSTANT_OT);
          AO.marker = STRING_MV;
          AO.value  = compile_string(token_text, STRCTX_GAME);
          assemblez_1(print_paddr_zc, AO);
          if (finally_return)
          {   get_next_token();
              if ((token_type == SEP_TT)
                  && (token_value == SEMICOLON_SEP))
              {   assemblez_0(new_line_zc);
                  assemblez_0(rtrue_zc);
                  return;
              }
              put_token_back();
          }
          break;
      }
      if (finally_return)
      {   get_next_token();
          if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
          {   assemblez_0(print_ret_zc); return;
          }
          put_token_back();
      }
      assemblez_0(print_zc);
      break;

This has the benefit of smaller jumps when branching but on the downside you'll potentially lose 2 bytes (print_paddr + address, instead of print) and an extra byte in padding on version 4 and later. print_ret have even more of a cost when a one byte instruction gets assembled to print_paddr + new_line + rtrue (5 bytes).

The suggestion is to expose this cut-off with a compile parameter ($ZCODE_INLINE_STRING_CUTOFF, maybe?) with a default value of 32, but adjustable from 0 to infinity.

(Disassembling old Infocom games show that they make much more use of printing inline and with much longer strings than Inform6 allows.)

erkyrath commented 10 months ago

The flip side:

That said, it's a reasonable suggestion for a compile option. It would be for power users only, though.

heasm66 commented 10 months ago

I've tested this new option, and the effect is quite big...

Curses!
=======
255.416 bytes with 6.41
252.532 bytes with 6.42, $OMIT_SYMBOL_TABLE=1
247.568 bytes with 6.42, $ZCODE_MAX_INLINE_STRING=9999

Hibernated 1
============
92.604 bytes with 6.41
90.396 bytes with 6.42, $OMIT_SYMBOL_TABLE=1
88.952 bytes with 6.42, $ZCODE_MAX_INLINE_STRING=9999

The optimization with ZCODE_MAX_INLINE_STRING is that you save 2 bytes for every string that uses print instead of print_paddr and 4 bytes every time a print_ret has a string longer than 32 characters. For z4+ you also save space because the padding with inline code is on average only one byte (a padding that you also share among multiple strings and the z-code itself), instead of on average 2 bytes that every single high string can have. For z3 you'll save a little less because the only saving you get are between multiple string and the z-code.