5 ms·
I worked on JVMs (in a mostly research capacity) for a good number of years, but I soon gave up on the idea that classes and instances of classes (thus, heap-al
by titzer 4y ago
I worked on JVMs (in a mostly research capacity) for a good number of years, but I soon gave up on the idea that classes and instances of classes (thus, heap-allocated objects) are the only thing the VM and language should be designed around. But there is a lot of sunk cost in the engineering of the JVM and there seems to be a lot of inertia against adding new primitives like tuples or unboxed types. That limits the source language design somewhat and definitely brings down the performance ceiling, raising the complexity of the engine, ironically (because it has to work extra hard to maintain the fiction of objects with identity).
Well anyway, I diverged from that significantly now; Virgil has value types, tuples, ADTs, and closures and happily unboxes them all.
- vips7L 4y agoImo named tuples via records are better than tuples provided at the primitive level. They provide a ton more context for the next reader about what this thing actually is.
- yarg 4y agoIt'd be nice if you could inline the Tuple description into the method signature. There's a bit of unnecessary overhead in having to externally declare and import the return type. public [K key, V value] getElement(int index); This really comes down to the dynamic vs typed argument, and to me the answer is "minimise the boiler-plate, maximise the guarantees.".
- haimez 4y agoI think declaration vs use Sue distinction is much more helpful to reason about in this context, and named tuples are a classic example of “if you didn’t declare these tuples to be compatible at definition time, it’s probably a bug to let you pass them around as if they were”
- yarg 4y agoCodesmell sure - and a case for refactoring, but I wouldn't go as far as to say bug. But I wouldn't expect that to be the common use case - I'd generally expect that the caller would just be implicitly importing and using the type effectively declared in the method header.
- titzer 4y agoIn Virgil, you can have it either way, anonymous tuple types with members indexed with .N, or flattened data types (without identity) with field names: var p: (int, int) = (0, 0); var q = p.0 + p.1; type Point(x: int, y: int) #unboxed { } var p = Point(0, 0); var q = p.x + p.y; Both will generate identical machine code with no allocations. It requires no escape analysis or assumption of non-identity (both tuples and data types have structural equality).
- masklinn 4y ago> They provide a ton more context for the next reader about what this thing actually is. Right until there’s no more context than “this returns 2 elements” and you end up with 15 different Pair types and more verbosity for no value. Named tuples are not better than tuples, they’re complementary, both are useful tools.
- vips7L 4y agoThere's definitely always more context than "this returns 2 elements". What are they? What are you storing them in? What did they belong to?
- masklinn 4y ago> There's definitely always more context than "this returns 2 elements". Not usefully so. If you’re splitting a collection in two, whatever context you add is almost certainly worthless overhead not worth the extra type.
- titzer 4y agoI'm trying to let programmers make the call here, which is why Virgil gives you both options. In causal hacking, anonymous tuples can be very useful. I find that very true in test code, where I have a tendency to throw more bells and whistles at it to get meat of the tests really short (so I can write a lot of them). Requiring elaborate ceremonies (such defining a bunch of tuple types for no good reason) is just a waste of time.
- deleted 4y ago[deleted]
- pjmlp 4y agoThe biggest issue with the ongoing Valhala hurdles seems to be related to the goal of having old JARs still running on a Valhala world without recompiling. By now I also have my doubts that it will ever come, they should have had better inspiration from Modula-3/Eiffel/Oberon when Java was originally designed.
- pron 4y agoClearly we're adding a new kind of primitive to the language and VM. I don't see how whether the Java language's tuples are nominal or structural (there are pros and cons to either approach, but Java added nominal tuples just as it did with its lambdas) has any relation to performance or complexity at all.
- jules 4y agoWhat's the technique to unbox closures and ADTs?
- titzer 4y agoYou gotta use multiple (machine) words to represent them. The ADT can't be recursive and the closure environment needs to be small enough. E.g. for delegates, the closure environment is just the receiver object, so using a fat pointer of two words (one code pointer, one object pointer) is sufficient.
- jules 4y agoAh I see, so you represent all closures as two machine words, in a representation that the GC can understand?
- titzer 4y agoYes, all closures are represented as a reference word (traced by the GC) and a non-reference word[1], which is a pointer to the actual function entry point (i.e. code). For delegates (i.e. methods bound to an object), the reference is just the object, and the function pointer is the actual code (looked up through the v-table once). So that actually means a call to a first-class function is cheaper than a virtual call--it is literally an indirect call to the code pointer, passing the receiver object as the first argument. [1] The two words even become separate, independent scalar values in the compiler IR. Thus the runtime support is minimal, in that it doesn't know anything about multiple-word values: the GC just needs to know whether a word is a reference or not.