Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Should there be an "escape hatch" for vtable structural subtyping? #29

Closed
aardappel opened this issue Dec 1, 2017 · 3 comments
Closed

Comments

@aardappel
Copy link

The "median" target for this proposal appears to be Java-like languages (though others can certainly be represented) which will heavily make use of vtable calls. In that light, it seems odd that we're willing to put up with adding code like:

(block $fail (result (ref $D)) (set_local $this (cast_down (ref $Cthis) (ref $D) $fail (get_local $Cthis))))

to most methods, which is both a speed and code bloat issue.

I'm probably missing something, but maybe someone can clarify why we shouldn't special-case this super common use case.

I'd imagine we can have an escape hatch to structural subtyping that goes something like this:

  • Mark certain structs as being a vtable.
  • When checking structural subtyping between types A and B, allow B to be a subtype of A even if it has a vtable member whose function types have a B where an A is expected.
  • Disallow regular load/store on vtable structs, instead provide a new call operation on the parent of the vtable that enforces that parent as first argument.
@rossberg
Copy link
Member

rossberg commented Dec 4, 2017

There is a wealth of options for enriching the type system in a principled manner to avoid casts in certain situations. They all tend to conflict with simplicity, of course. We will need implementation experience to see what is bearable and what isn't -- such casts can be much cheaper than you'd expect and may already be dominated by the cost of a call. That said, a special type system hack for the benefit of Java-like languages -- and language bias in general -- is something we'd rather want to avoid.

@skuzmich
Copy link

I think we should make virtual calls in Kotlin-like languages efficient at runtime and in terms if code size.

We would get a lot of value having a simple type-check rule and an instruction call_vtable that can be easily desugared into existing struct.gets and ref_call.

Proposed shortcut can be completely ignored without any cost by languages that don't need this feature.

My main concern with current proposal is the size of generated code, a quality we absolutely want to have when targeting web clients.

Inside a function that overrides virtual method we would need 4 extra instructions and extra local:

(local $new-this ...) ;; if 'this' is used more than once
(set_local $new-this 
  (ref.cast ... ...
    (get_local $old-this)
    (get_global $rtt)))

If we would like to keep zero-overhead direct calls we'd put this cast into a bridge method. It would require an extra func and extra call. This would make virtual calls even slower.

Virtual methods become bloated, but call sites look even worse.
In order to translate a virtual call:

(<object-instance-expression>).foo(<arguments...>)

in some cases we would need 5 extra instructions and a temp local

(local $tmp)
...
(set_local $tmp                     ;; Store value in temp local 
   (<object-instance-expression>))  ;; if expression is big or has side-effects
(call_ref
    (get_local $tmp)
    (<arguments...>)
    (struct.get $vt <foo-slot> 
        (struct.get $class 0
            (get_local $tmp)))

compared to proposed call_vtable:

(call_vtable $class <foo-slot>
   (<object-instance-expression>)
   (<arguments...>))

rossberg pushed a commit that referenced this issue Feb 24, 2021
…able.copy`. (#29)

This would make it simpler to extend those instructions to support multiple memories/tables, and copying between different memories/tables.

The current encoding has a single placeholder zero byte for those instructions, which allows extension to multiple memories/tables, but would require a more complicated encoding to add two immediate indices.
@tlively
Copy link
Member

tlively commented Nov 1, 2022

We have discussed improved method dispatch as a potential high-priority post-MVP feature, but we won't be adding it to the MVP, so closing this.

@tlively tlively closed this as completed Nov 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants