Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve reflection #1727

Merged
merged 5 commits into from
Mar 23, 2021
Merged

Improve reflection #1727

merged 5 commits into from
Mar 23, 2021

Commits on Mar 23, 2021

  1. compiler: merge runtime.typecodeID and runtime.typeInInterface

    This distinction was useful before when reflect wasn't properly
    supported. Back then it made sense to only include method sets that were
    actually used in an interface. But now that it is possible to get to
    other values (for example, by extracting fields from structs) and it is
    possible to turn them back into interfaces, it is necessary to preserve
    all method sets that can possibly be used in the program in a type
    assert, interface assert or interface method call.
    
    In the future, this logic will need to be revisited again when
    reflect.New or reflect.Zero gets implemented.
    
    Code size increases a bit in some cases, but usually in a very limited
    way (except for one outlier in the drivers smoke tests). The next commit
    will improve the situation significantly.
    aykevl committed Mar 23, 2021
    Configuration menu
    Copy the full SHA
    7f887ba View commit details
    Browse the repository at this point in the history
  2. compiler: do not check for impossible type asserts

    Previously there was code to avoid impossible type asserts but it wasn't
    great and in fact was too aggressive when combined with reflection.
    
    This commit improves this by checking all types that exist in the
    program that may appear in an interface (even struct fields and the
    like) but without creating runtime.typecodeID objects with the type
    assert. This has two advantages:
    
      * As mentioned, it optimizes impossible type asserts away.
      * It allows methods on types that were only asserted on (in
        runtime.typeAssert) but never used in an interface to be optimized
        away using GlobalDCE. This may have a cascading effect so that other
        parts of the code can be further optimized.
    
    This sometimes massively improves code size and mostly negates the code
    size regression of the previous commit.
    aykevl committed Mar 23, 2021
    Configuration menu
    Copy the full SHA
    1fb5ace View commit details
    Browse the repository at this point in the history
  3. interp: handle (reflect.Type).Elem()

    The errors package has a call like this in the package initializer. This
    commit adds support for running it at compile time, avoiding the call at
    runtime.
    
    This doesn't always help (the call is already optimized away in many
    small programs) but it does help to shave off some binary size in larger
    programs. Perhaps more importantly, it will avoid a penalty in code size
    when the reflect package will convert reflect.Type from a regular type
    to an interface type.
    aykevl committed Mar 23, 2021
    Configuration menu
    Copy the full SHA
    fc46b1f View commit details
    Browse the repository at this point in the history
  4. interp: add support for runtime.interfaceMethod

    This is necessary so that when reflect.Type is converted from a concrete
    type to an interface type, the errors package can still be interpreted.
    Without this change, basically every program would grow in size by a few
    bytes.
    aykevl committed Mar 23, 2021
    Configuration menu
    Copy the full SHA
    5347717 View commit details
    Browse the repository at this point in the history
  5. reflect: let reflect.Type be of interface type

    This matches the main Go implementation and (among others) fixes a
    compatibility issue with the encoding/json package. The encoding/json
    package compares reflect.Type variables against nil, which does not work
    as long as reflect.Type is of integer type.
    
    This also adds a reflect.RawType() function (like reflect.Type()) that
    makes it easier to avoid working with interfaces in the runtime package.
    It is internal only, but exported to let the runtime package use it.
    
    This change introduces a small code size increase when working with the
    reflect package, but I've tried to keep it to a minimum. Most programs
    that don't make extensive use of the reflect package (and don't use
    package like fmt) should not be impacted by this.
    aykevl committed Mar 23, 2021
    Configuration menu
    Copy the full SHA
    9ad9da2 View commit details
    Browse the repository at this point in the history