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

Will this include non gc references? #2

Closed
ghost opened this issue Apr 13, 2017 · 12 comments
Closed

Will this include non gc references? #2

ghost opened this issue Apr 13, 2017 · 12 comments

Comments

@ghost
Copy link

ghost commented Apr 13, 2017

References are very important to modern languages, but recent languages like rust and swift leverage alternatives like Box types(non copy able heap references) and ARC(Automatic Reference Counting). Sometimes the docs refer to "opaque reference types" suggesting all of these are options. Can someone clarify?

@lukewagner
Copy link
Member

The "opaque reference types" from the older GC.md are basically the type imports in @rossberg-chromium 's PR, where the type is imported from the host environment. Fundamentally, though, these would be references to some GC object with an embedding-specific type (say, a DOM Node on the web).

IIUC, ARC would not use the GC feature at all, but rather linear memory, using explicit reference counting, malloc and free. I'm afraid I don't know enough about Box types to comment on them.

@ghost
Copy link
Author

ghost commented Apr 13, 2017

could an ARC reference be represented by a foreignref?

@rossberg
Copy link
Member

rossberg commented Apr 13, 2017 via email

@ghost
Copy link
Author

ghost commented Apr 14, 2017

I don't think I was clear enough. I know browsers want to integrate WASM into their current JavaScript GC and don't wan't to switch to ARC. My point is that I'd imagine ARC and Box references share quite a bit with GC and if the spec were more abstract they could benefit.

Maybe only implement structs, ref, new, etc in WASM itself and put upcast, downcast in a WebAssembly.GC API. If WASM allowed references to values inside a module you could create an RC allocator like this (kind of).

(struct $RC (field $c i32) (field $ref f64))
(global (array $RC) $references)

(func $new_f64 (result (ref f64))
  (i32.const 1)
  (f64.const 0)
  (new $RC) ;;create RC value
  (array_size) ;;get index of next value
  (set_global $references) ;;append RC to array
  ;;stack empty
  (ref_global $RC) ;;get pointer to RC array
  (array_size)
  (i32.const 1)
  (i32.sub) ;;get index of last RC
  (array_ref) ;;reference last element in the array
)

I know references are very important, but think that if WASM implements inheritance it may look dated years from now like XMLHttpRequest or var. languages like Rust, Swift, Haskell, and Go would be cut out because they implement references in a different way or not be able to take advantage. And WASM is supposed to be language neutral.

@rossberg
Copy link
Member

rossberg commented Apr 14, 2017

@dmTmp, there is no intention to have inheritance in Wasm. What's proposed is solely subtyping, which is a different beast (even if the OO community chooses to continue to conflate the two). Moreover, the subtyping relation is supposed to be structural, i.e., purely driven by what types of data can soundly be used in place of other types of data.

I expect that almost all languages compiling to Wasm will need to exercise its subtyping and casts to some extend, because the Wasm type system is never gonna be expressive enough to encompass all source level type systems. See the use case examples in the PR. There is no specific language bias intended or implied -- rest assured that some of us care at least as much about languages like Haskell or ML or Rust as they do about old-fashioned OOPLs. ;)

That also means that casts are central to the design and need to be maximally cheap and simple. I don't see how we could afford the level of abstraction you have in mind. Nor, honestly, do I see the benefit -- why would user side reference counting need to be overlayed with Wasm's built-in GC types? Keep in mind that the Wasm type system isn't intended to build user-facing abstractions, it is intended to describe machine-facing data representations.

@ghost
Copy link
Author

ghost commented Apr 15, 2017

So WASM implements "type inheritance" vs "object inheritance", ie completely static? no built in dynamic dispatch. Does this mean down casting is like taking a reference to a subset of the struct without keeping track of the typing track of the type in a static way?

@rossberg
Copy link
Member

rossberg commented Apr 19, 2017

@dmTmp, right, "dynamic dispatch" is just an OO abstraction for calling a function pointer, not something that's primitve on the Wasm level. A downcast takes e.g. a struct and dynamically checks whether it is actually a larger struct (subtypes of structs contain a superset of fields), but this generalises to other types in the canonical way. The result is statically known to have the subtype.

@MikeInnes
Copy link

One case worth considering is hybrid memory management strategies that (for example) primarily use ref counting but have a backup tracing GC for cycles, or do static analysis to free objects with a known lifetime more quickly, or implement memory re-use, etc. You don't need much support from the GC for that, so long as you have atomic operations on references (to implement counts) and an explicit free.

Atomics seem likely after the MVP. I'm more interested in free: Is this something wasm could support? Naively, it doesn't inherently seem to compromise VM safety (use-after-free could trap or return junk, just like a user-implemented malloc over linear memory would). But perhaps this is difficult to implement efficiently, or has other issues I'm not aware of.

I fully understand if free is just out of scope, but would be very interested to hear the thinking behind this and/or see it mentioned in the proposal, if possible.

@rossberg
Copy link
Member

@MikeInnes:

Naively, it doesn't inherently seem to compromise VM safety

Maybe I misunderstand your suggestion, but AFAICS it surely does, unless the VM performs some form of liveness check at every access to a reference, which would be a severe cost.

@MikeInnes
Copy link

Thanks a lot for the response. I fully agree that some kind of check would be needed, and this would only be viable if it were very cheap. I imagine that there are tradeoffs that may make this achievable (e.g. making free opt-in per object, limiting it to large allocations, or having it be a hint/prioritisation rather than a guarantee that memory is reclaimed immediately).

Sorry if that's too vague. I'm not trying to make a proposal at this point, just wondering if the experts have already considered this use case at all, and whether it does or doesn't appear to conflict with the GC proposal's goals at first glance. If not, perhaps a more complete proposal could stand to be considered in future.

@lars-t-hansen
Copy link
Contributor

FWIW, there's a tie-in with fallible allocation (#87) in that for large objects it is sometimes desirable to handle allocation failure and lifetimes explicitly. An implementation that allows for that on an opt-in basis is not free but doesn't have to be horrifically expensive, for example, a facade that's GC'd can safely hide a large array that's freed explicitly. (Like detaching an ArrayBuffer.)

@tlively
Copy link
Member

tlively commented Feb 16, 2022

Closing this because it looks like the questions have been answered. Feel free to reopen if there is more to add.

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

No branches or pull requests

5 participants