-
Notifications
You must be signed in to change notification settings - Fork 40
Why is nullref not allowed in binary and text format? #60
Comments
In the first version of the proposal nullref was available. Removing it was a form of compromise, because there was some dislike of having this type. I am not sure what the arguments were. If you have a good use case, we can discuss bringing it back. It would be an easy change. |
It is mostly that block/loop/if/try doesn't have self-sufficient type information within itself. For example, (block (type ???)
(ref.null)
) When we create this block, we don't know which type to assign to this block, because we cannot assign |
For a number of tooling purposes, you should ensure that every instruction has a principal output type for any given input type. For |
Some languages, among which Scala, even have a user-space class Foo
class Bar
def giveMeNull(): Null = null
val x: Foo = giveMeNull()
val y: Bar = giveMeNull() When compiling |
Yep, though that's more relevant to the GC proposal (where it's planned to be addressed). Nonetheless, it's a good point that something like |
Just to clarify, the proposal already includes a nullref type, for the reasons @RossTate mentions. The question @aheejin is asking is whether it should be expressible in concrete syntax. As mentioned above, that was the case originally, but there was some resistance, so it was removed. I'm all for bringing it back if we can get consensus on that. |
I found some relevant previous discussion threads: thread1 thread2 @lukewagner Are there advantages specific to allowing |
Keeping |
I don't understand this part very well, maybe because I'm not familiar with VM implementations. Locals/globals/params/... can have all other types already, and why would allowing them to have
I don't understand what you mean by optimize |
There tends to be case analysis (one case per type) for the operations on all these kinds of types (in codegen, in stub generation, in JS API, in the runtime functions). Again, it's not a ton, it's just annoying to have to add all these for a type that should never be meaningfully used in all these contexts. The "optimization" for nulltype would be for it to take no space (and take no instructions when passing around) since it has only one value. Noone would do this initially, but maybe someone writes a silly benchmark one day and then someone does a silly optimization for it (e.g., as happened with the computation-on- I mean, it's not a big deal, but the origin for all this was that it seemed simpler to not have a |
I see. I understand there are many parts (codegen, in stub generation, in JS API, ...) in the VM that has to have handling routines for I think at this point the problem is where we put the complexities. Currently in tools (specifically Binaryen) we can't figure out a node's type independently in some cases without looking at its parent node. Examples include (block (type ???)
...
(ref.null)
) (select (type ???)
(ref.null)
(ref.null)
) So we either need to take special care in Binaryen not to produce those kind of code (which has been proven to be very difficult) or do a special separate transformation to remove We can possibly hear more opinions in the CG meeting too. |
I agree with @aheejin and @rossberg - it seems simplest to just consider In particular, it just seems odd that (local $foo nullref)
(local.set $foo
(ref.null)
) I think we should allow that. It makes the spec simpler, more regular, and easier to understand. |
@aheejin Ah, that's a good point; I can see how that's problematic. If we consider changing the proposal to allow |
@lukewagner If we don't have |
I think the alternative would be just to have a different |
The type of FWIW, this change would remove ~100 lines of code in FF at the cost of adding maybe 5 lines in the decoding/validation of |
Unless we want to merge this proposal with the function reference proposal, we either need |
I am puzzled by this. Soon (with the typed reference proposal) there will be an infinite number of reference types, so doing individual case distinctions seems like the wrong approach already. After validation, there ought to be very little reason for distinguishing the different ref types in generic constructs -- they all have the exact same behaviour. Otherwise, things like type imports cannot possibly work in the future, since they can be any reference type. Sure, I can imagine a few representation optimisations for single-value types like nullref -- but those would apply to other singleton types as well (e.g. if we had variant types), and don't have anything to do with nullref per se. And I honestly see no practical gain or reason why a VM should ever bother with such optimisations. Either way, their optimisability seems like an odd argument against the possibility of single-value types. |
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
Forgive the intrusion ... but, as the function reference type proposal makes clear, not all reference types are nullable. IMO, it would have been better not to split reftype from function reftype proposal. |
@aheejin We don't need to merge it with the function references, just borrow the a tiny subset of the encoding of @rossberg It's not a case per reference type, but per type constructor. So there is one case for As I see it, both |
@lukewagner Makes sense, I like |
@lukewagner Do you mean you want to make But is
This sounds like So the problem for toolchain is not we have to do more implementation work, but it's tricky to transform code in the presence of the subtle differences between types, in which all other types are allowed to be written in binary/text but not |
Correct. I've written this as |
Sorry, I'm still not getting it. You have to distinguish between numeric and reference types. But all reference types are treated the same. There are already multiple type constructors for reference types, and there will almost certainly be more in the future. Whether this subgroup has one more entry shouldn't make any significant difference. FWIW, with the function reference proposal that @aheejin pointed to above, all reference types will explicitly turn into the single case |
@rossberg It's just an impl detail: there's an But as a non-impl-detail example, should we support |
For languages with a proper "null" type, |
@lukewagner, the nuisance of not having nullref would be much bigger:
|
Bullets 1 and 3 seem like filler arguments (the encoding of For bullet 4, compilers should be able to deal with this easily by just "const-propagating" the null to where it's used, making this another of the classic "but what about toy compilers?" arguments. But bullet 2 is a new and potentially compelling point :) Maybe that's enough? |
@lukewagner, to clarify, bullet 4 was alluding to possible examples like this:
Const-propagating null is unrelated. There is no actual null value, only an empty array that is shared across multiple types. (Perhaps not the most compelling example, but hopefully conveys the idea. Things like this pop up occasionally.) It's also useful to avoid problems with compiling languages that indeed have the equivalent of a (Of course, all this is primarily relevant in the presence of the GC proposal. But if the likelihood is that we're gonna want it anyway, then we should utilise it where we can.) |
@skuzmich's example pertains more to the gc proposal, and actually I've found that, while the use case does need something like |
@rossberg Ah, I see. Sorry, I skimmed that bullet too quickly. Yes, I suppose as part of a compound type So I suppose I'm fine with giving |
cc @gahaas for possible V8 implementation changes |
Thanks @lukewagner! In order to unblock @aheejin fast, I created #66. |
@aheejin, yes, you should cc me :-) |
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This adds support for the reference type proposal. This adds support for all reference types (anyref, funcref(=anyfunc), and nullref) and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and new typed `select`. This also adds subtype relationship support between reference types. This does not include table instructions yet. This also does not include wasm2js support. This does not pass `fuzz_opt.py` yet because there are remaining bugs related to `nullref` handling, because `nullref` is not allowed to be written to text or binary format. We are discussing whether we should allow it to be written in WebAssembly/reference-types#60 now. This is not ready for review yet because it does not pass fuzzer now; I'm uploading this just to show how the current a bit ad-hoc `nullref` handling looks like. So don't spend too much time on reviewing each detail for now. I apprciate some high-level comments on how we should handle `nullref` or other stuff.
This has been fixed, though #69 may require revisiting it. |
This makes writing transformation passes in toolchain somewhat tricky. I'm not necessarily arguing for allowing it at this point, but I don't precisely remember what the reason for disallowing that was.
The text was updated successfully, but these errors were encountered: