Skip to content

Optimize backref and lastline globals with pre/post call setup #9169

@headius

Description

@headius

Currently when we see any method call that could possibly set the magic backref or lastline globals ($~ or $_) we fully deoptimize the method to use a Frame on ThreadContext. We make this determination statically at compile time, based on whether the method name corresponds to a core class method that reads or writes those variables.

This frame setup and teardown adds significant overhead to the Ruby method making the call, even if we aren't actually calling a backref/lastline method. For example, any call to [] or []= must be ready to host a frame-local backref just in case we're calling String#[] or String#[]= with a regular expression. No other calls to these methods need backref, and they are extremely common.

A possible optimization for this would work as follows:

  • Method calls that might be backrefs dispatch through a special call site.
  • The special call site would look up the target method and lazily set up and tear down frame-local storage only if the method needs it.
  • After the call completes and a backref is available in the frame-local storage, it is passed back to the caller via some other thread-local mechanism and the storage is cleared.

The advantage to this is that we're only setting up backref storage for the specific cases that need it, avoiding the deoptimization altogether.

This may add overhead to method calls that do need backref/lastline, but if the storage were simple a thread-local stack with a numeric pointer, it would take many such calls to compare to a full Frame setup and teardown. We can also profile such call sites, and if we see that a given method clearly needs this storage all the time we simply recompile it with a normal frame.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions