A can just use X's method directly, because the X field is at offset 0 anyway.
B and C could use a single shared wrapper, because they need the same pointer adjustment before tail calling to (*X).m.
This would save some executable size, but I also think it could help slightly with CPU I-cache and branch predictions. For example, within the compiler itself, ir.Node's Op and Pos methods are always actually implemented by ir.miniNode (which we always embed at offset 0). But we create a wrapper method for each ir.Node implementation, which means (caveat: hypothesizing) a bunch of identical methods all end up taking up I-cache space and the branch predictor has to guess which one is going to be called.
The text was updated successfully, but these errors were encountered:
For direct call of A.m, we should be able to inline it and the caller would call A.X.m directly (same for B and C). (The bottom-up inlining strategy might mess this up in some cases?) So I guess this is mostly for methods used as function pointers (interface methods, method expressions)? Sounds like a reasonable thing to do.
Currently the wrappers are generated in the AST form. If we deduplicate the wrappers the AST would not be well typed. Maybe this is fine?
Another possibility: maybe we could allow link-time deduplication of compiler-generated functions. I think this might work if we mark them content-addressable symbols. So functions with identical bodies could be deduplicated. We'd want to limit it to compiler-generated functions, as user-defined functions generally have different line numbers, or we could add the line numbers to the content hash. Also compiler-generated functions are generally hidden from traceback.