Skip to content
  • John Hawthorn's avatar
    679ef345
    New constant caching insn: opt_getconstant_path · 679ef345
    John Hawthorn authored
    Previously YARV bytecode implemented constant caching by having a pair
    of instructions, opt_getinlinecache and opt_setinlinecache, wrapping a
    series of getconstant calls (with putobject providing supporting
    arguments).
    
    This commit replaces that pattern with a new instruction,
    opt_getconstant_path, handling both getting/setting the inline cache and
    fetching the constant on a cache miss.
    
    This is implemented by storing the full constant path as a
    null-terminated array of IDs inside of the IC structure. idNULL is used
    to signal an absolute constant reference.
    
        $ ./miniruby --dump=insns -e '::Foo::Bar::Baz'
        == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE)
        0000 opt_getconstant_path                   <ic:0 ::Foo::Bar::Baz>      (   1)[Li]
        0002 leave
    
    The motivation for this is that we had increasingly found the need to
    disassemble the instructions between the opt_getinlinecache and
    opt_setinlinecache in order to determine the constant we are fetching,
    or otherwise store metadata.
    
    This disassembly was done:
    * In opt_setinlinecache, to register the IC against the constant names
      it is using for granular invalidation.
    * In rb_iseq_free, to unregister the IC from the invalidation table.
    * In YJIT to find the position of a opt_getinlinecache instruction to
      invalidate it when the cache is populated
    * In YJIT to register the constant names being used for invalidation.
    
    With this change we no longe need disassemly for these (in fact
    rb_iseq_each is now unused), as the list of constant names being
    referenced is held in the IC. This should also make it possible to make
    more optimizations in the future.
    
    This may also reduce the size of iseqs, as previously each segment
    required 32 bytes (on 64-bit platforms) for each constant segment. This
    implementation only stores one ID per-segment.
    
    There should be no significant performance change between this and the
    previous implementation. Previously opt_getinlinecache was a "leaf"
    instruction, but it included a jump (almost always to a separate cache
    line). Now opt_getconstant_path is a non-leaf (it may
    raise/autoload/call const_missing) but it does not jump. These seem to
    even out.
    679ef345
    New constant caching insn: opt_getconstant_path
    John Hawthorn authored
    Previously YARV bytecode implemented constant caching by having a pair
    of instructions, opt_getinlinecache and opt_setinlinecache, wrapping a
    series of getconstant calls (with putobject providing supporting
    arguments).
    
    This commit replaces that pattern with a new instruction,
    opt_getconstant_path, handling both getting/setting the inline cache and
    fetching the constant on a cache miss.
    
    This is implemented by storing the full constant path as a
    null-terminated array of IDs inside of the IC structure. idNULL is used
    to signal an absolute constant reference.
    
        $ ./miniruby --dump=insns -e '::Foo::Bar::Baz'
        == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE)
        0000 opt_getconstant_path                   <ic:0 ::Foo::Bar::Baz>      (   1)[Li]
        0002 leave
    
    The motivation for this is that we had increasingly found the need to
    disassemble the instructions between the opt_getinlinecache and
    opt_setinlinecache in order to determine the constant we are fetching,
    or otherwise store metadata.
    
    This disassembly was done:
    * In opt_setinlinecache, to register the IC against the constant names
      it is using for granular invalidation.
    * In rb_iseq_free, to unregister the IC from the invalidation table.
    * In YJIT to find the position of a opt_getinlinecache instruction to
      invalidate it when the cache is populated
    * In YJIT to register the constant names being used for invalidation.
    
    With this change we no longe need disassemly for these (in fact
    rb_iseq_each is now unused), as the list of constant names being
    referenced is held in the IC. This should also make it possible to make
    more optimizations in the future.
    
    This may also reduce the size of iseqs, as previously each segment
    required 32 bytes (on 64-bit platforms) for each constant segment. This
    implementation only stores one ID per-segment.
    
    There should be no significant performance change between this and the
    previous implementation. Previously opt_getinlinecache was a "leaf"
    instruction, but it included a jump (almost always to a separate cache
    line). Now opt_getconstant_path is a non-leaf (it may
    raise/autoload/call const_missing) but it does not jump. These seem to
    even out.
Loading