[HN Gopher] Juice - Oberon JIT browser plugin (1996)
___________________________________________________________________
Juice - Oberon JIT browser plugin (1996)
Author : cylinder714
Score : 82 points
Date : 2024-02-02 08:48 UTC (14 hours ago)
(HTM) web link (www.modulaware.com)
(TXT) w3m dump (www.modulaware.com)
| cylinder714 wrote:
| Github: https://github.com/Spirit-of-Oberon/Juice
| cornholio wrote:
| > Juice's distribution format ... is based on a tree-shaped
| program representation as is typically used transiently within
| optimizing compilers. Rather than containing a linear code-
| sequence that can be interpreted byte-by-byte, a Juice-encoded
| applet contains a compressed tree that describes the actions of
| the original program. The tree preserves the control-flow
| structure of the original program, which makes it much easier to
| perform code optimization while the tree is translated into the
| native instruction set
|
| Wow, that came out of the left field. Shipping a lexical compiler
| IR and letting the target do the code generation sound like a
| very powerful technique compared to compiling for virtual targets
| like WASM, JVM etc. Wonder why it didn't caught on.
|
| Another intriguing tidbit:
|
| > By the very definition of our tree-encoding scheme, it is
| impossible to encode a tree that violates scoping rules of our
| source language. Such an "illegal" program cannot even be
| constructed by hand.
| ikari_pl wrote:
| > Shipping a lexical compiler IR and letting the target do the
| code generation sound like a very powerful technique compared
| to compiling for virtual targets like WASM, JVM. Wonder why it
| didn't catch on.
|
| This is somewhat similar to what V8 does with JIT compilation
| of javascript by now. I like the idea of doing it on AST rather
| than direct (heavier) source code. But maybe in the long run,
| gzipping the JS stream turned out to be just enough?
| vidarh wrote:
| Gzipping the JS stream is conceptually very different,
| though. With Juice's approach, the intent is in part that the
| compiler gets to do any amount of additional work before
| serializing. What is shipped is already "half compiled", not
| just serialized as a tree. It's closer to an intermediate
| representation in tree form than just a representation of the
| source syntax.
|
| Today, with a lot of JS toolchains involving source-to-source
| transformation first, _that_ could in theory achieve much of
| the same potential of modifying the original input, and
| lowering some things to a simpler subset etc., but just
| compression isn 't the same.
|
| The size reduction is pretty much a nice bonus with Juice
| rather than the point - the dictionary encoding matters
| because it means the decode gets similarity measures "for
| free" and can generated patchable code segments for partial
| subtrees that will be subsequently referenced.
| vidarh wrote:
| It's a direct continuation of Franz PhD thesis in '94 [1]. (I
| note I know need to keep my URLs stable, as it turns out one of
| the references to SDE in that Wikipedia article is my own
| summary...).
|
| I think there are two reasons it didn't catch on: The first
| obviously being Java, and the sheer amount of mindshare Sun was
| able to get for Java very quickly.
|
| The other is that Oberon had gaps. It's a very austere
| language. And while all of those gaps can be plugged - Franz
| himself proposed extensions, as did other students of Wirth -
| without someone putting in the effort to create an Oberon
| version with sufficient expansions to appeal to business users,
| the way Sun did with Java, that the underlying technology was
| interesting didn't really matter.
|
| I'm a big fan of the concept, but it's also more complex in
| some ways, even though a crude implementation is also
| potentially very simple. E.g. you "chop the compiler in two",
| and unlike a bytecode compiler you get a tree to work on. At
| the same time you can apply other JIT techniques - part of the
| work on SDE meant reconstituting the dictionary used to
| compress the tree on loading, and while doing so, if you
| generate code during the process, you can also directly
| reference the generated code to use as templates for a patching
| JIT and insert those templates directly into the dictionary.
|
| "One day" I hope to get time to explore SDE more, because it
| seems JIT's have gotten so far down the bytecode path that
| we're missing out on seeing what else might be viable.
|
| Franz own later research shifted a lot towards Java, but his
| students have interesting work in the JIT space too. Especially
| Andreas Gal, and his work on trace trees.
|
| [1] https://en.wikipedia.org/wiki/Semantic_dictionary_encoding
| kgeist wrote:
| Isn't it limiting? Say, the language evolves and its scoping
| rules change, new control flow features are added etc. Now you
| can't ship anything in the new version because of the old
| clients. With bytecode, language implementers have more freedom
| to change the language without having to force everyone to use
| a new runtime version. I guess it's not a problem if the
| language implementers also control the client (say, V8 in
| Chrome) but in case of Juice, they were just another third-
| party extension to Netscape, so overall it sounds like a bad
| idea to me (if I understood it correctly that they serialized
| and shipped AST to end users).
| vidarh wrote:
| You can read Franz' PhD dissertation on it here[1]. While
| it's reasonable to describe it as serialising an AST, most of
| the Oberon compilers of the time did not have an AST per se,
| and so what you serialize is entirely arbitrary to your
| choice of node types, and the operations used by the Oberon
| version are low-level enough that while some work would have
| needed to be done to be generic enough if one wanted to more
| easily support other languages, it's largely moot. There's no
| large semantic gap between what is serialized and the
| generated code.
|
| At that point it's no different from with Java - if you add
| new bytecodes, the JVM needs to support it. Same here - if
| you add new node types, the code generator will need to
| support it.
|
| Just as you wouldn't change the JVM bytecodes for every
| language change, you likewise wouldn't _need_ to add new node
| types to support most language changes for Juice either. You
| could just as well choose to generate what in effect would be
| an intermediate representation instead. You 'd only add new
| node types if they provide a sufficiently big win over
| generating more complex output, just as with the JVM
|
| That said, nothing would've prevented dynamically updating
| the code generator.
|
| [1] https://oberoncore.ru/_media/library/franz_m.code-
| generation...
| nickpsecurity wrote:
| It would also make client-side verification easier. You could
| statically analyze code for safety before running it. You could
| optimize it much further for your platform. Safe mashups might
| be easier. Quite a few benefits to this.
|
| One more is that, if you used an Oberon-based OS (eg A2
| Bluebottle), the system and browser languages were the same. No
| need to learn separate languages. Integration will be smoother,
| too.
| abricq wrote:
| Interesting to see that Oberon-2 tried to go where Java
| succeeded. I guess java worked better because of language
| limitation. From my experiences in Oberon-2 (I work with it), I
| find the following limitations enough to explain it.
|
| - No generic types. That's really limiting. You want to implement
| Linear Algebra for vectors ? You need a class for each possible
| types.
|
| - No proper error handling : no such thing as `TRY` or `CATCH`.
| Instead, you need to pass a `BOOLEAN` mutable flag in functions
| that may crash. That's just sad.
|
| - No distinction between a class, an abstract class and
| interfaces / pure abstract classes. If you want to write an
| abstract class, you just `HALT` in the base methods (like you
| would do in Python I guess). But there is no language semantic to
| define that this class is abstract. So the compiler can't help
| you out much with them.
|
| - No enumerations. They are just very powerful.
|
| (- Faulty garbage collector, even though that is not a a feature
| of the language but rather of the implementation that I am
| using.)
|
| I am quite sure that Oberon was written with a real focus on
| designing a language for which it is easy to write a compiler /
| garbage collector. It really made sense back then. And they
| succeeded in doing so. However, for broad distribution of
| executable, it probably wasn't the best guess. These glimpses of
| the past are so interesting though, discovery of the most optimal
| tech stack was a long and dense path of exploration !
| vidarh wrote:
| There were proposals for mechanism for extending types from
| several of Wirth's students, and Franz - one of the co-authors
| of Juice - was one of the people who around that time wrote a
| report on a proposal that'd enable runtime-loadable interface-
| based extension, so all of this would certainly be fixable.
|
| Juice also flows naturally from Franz PhD thesis, which was on
| JIT compilation of Oberon from what in some sense was a
| compressed serialized reduced form of the AST instead of
| bytecode [I'll stress this is a gross oversimplification - his
| compiler does do more processing, so I guess what is serialized
| is closer to an IR in tree form than the AST]. I don't know how
| much that changed in Juice, as I've never looked at it much but
| from the description it remains at least similar in concept.
| I've wished more work had gone into that ever since I read his
| PhD thesis in '94.
| pjmlp wrote:
| It was used on Oberon System 3, and AOS.
|
| When compiling you had the option to generate proper native
| binaries, or slim ones to be JITed on load.
| vidarh wrote:
| Yeah, I'm aware it "stuck around" in the Oberon world, but
| it's very annoying it hasn't escaped that niche, and hasn't
| been iterated on more.
| abricq wrote:
| > Franz was one of the people who around that time wrote a
| report on a proposal that'd enable runtime-loadable
| interface-based extension
|
| You seem to know a lot about this time. Would you have a
| reference on this report ? I am quite curious now !
| vidarh wrote:
| On a phone and without a reference handy but search for
| Franz and "Protocol Extension". It's a very short paper,
| and basically proposed a mechanism similar to vtables, but
| w/an extra level of indirection to allow whole interfaces
| to be slotted in, and to have subsequent loaded
| implementations addressed propagated down the class
| hierarchy on load.
|
| (I use a similar mechanism of propagating vtables updates
| down the class hierarchy, but without the extra indirection
| - at cost of more memory - in my prototype Ruby compiler)
| abricq wrote:
| Thank you, I got it: "Protocol extension, a technique for
| structuring large extensible software systems" [0] !
| Hoping to find time to read it soon, and also to look at
| your ruby compiler !
|
| [0]: https://www.research-
| collection.ethz.ch/bitstream/handle/20....
| vidarh wrote:
| My Ruby compiler is, I'm sad to say, languishing. I got
| it to a stage where it does compile itself successfully
| (to 32 bit x86 assembly - 32 bit was still a reasonable
| choice when I started...), but it has plenty of bugs (and
| only compiles itself due to workarounds for those in the
| compiler source to avoid triggering them) and doesn't
| support most newer Ruby syntax, nor Regexp's or Float's
| (other massively limitations too). I keep telling myself
| I should at least fix the bugs at some point and strip
| out the workarounds, but so many other projects at the
| moment.
| willvarfar wrote:
| > my experiences in Oberon-2 (I work with it)
|
| really interesting that you work with something as niche as
| Oberon! :)
|
| Can you talk about who is using Oberon, for what, and why?
| abricq wrote:
| About the what, I can't tell you too much unfortunately. We
| do realtime OS for autonomous robots in Oberon. About the
| why, it's a question of heritage from the past. The code
| works, so why taking the risk to migrate it. It's really a
| big code base, so migrating it would be (will be...) very
| risky for all of our running platforms.
| Rochus wrote:
| That's amazing. Which compiler are you using?
| abricq wrote:
| In-house compiler, specifically made for the architecture
| that we sell, we have to maintain it but we rarely touch
| it. I am quite sure that it was related to System3, I
| know that we used to use System3 in the past. But this
| part I am not sure, as I am quite young and I personally
| never worked with it. Unfortunately it's not open-source,
| but it's just a standard compiler pretty much without
| optimization. In our case, it's the responsibility of the
| developer to write optimal code, since our compiler does
| help. I'd be curious to chat about your version of
| embedded Oberon, I will write to you !
| Davidbrcz wrote:
| Bluebotics, in Switzerland, has its whole embedded box
| written in Oberon.
|
| Cool product, terrible boomer management.
| pjmlp wrote:
| I wasn't aware of them, most likely same path as Oberon
| microsystems which ended up creating Component Pascal, I
| was quite fond of, unfortunely didn't survive against Java
| and .NET.
|
| Nowadays Oberon microsystems business has nothing to do
| with Oberon.
| Davidbrcz wrote:
| I can assure you that company's Oberon code base is alive
| and will outlive COBOL.
| pjmlp wrote:
| As proven by Go, those limitation don't matter when the
| language has an overlord to push it.
|
| I was a big Oberon fan[0], not so much for Go, because in
| mid-90's using Native Oberon was an eye opening experience, in
| the hardware we had available back then.
|
| 20 years later (at Go 1.0 time), not so much.
|
| [0] - The whole linage, and still think Active Oberon is the
| best dialect (with AOS) that eventually came to be, after
| Oberon v1.0 from 1987.
| wirrbel wrote:
| To me Go seems like almost a copycat of Oberon with channels
| added. But I neither used Oberon nor Go so that's more of a
| spec-reading impression. What would you say having used both?
| pjmlp wrote:
| It is more like a Limbo copy cat, with a bit of Oberon
| influences.
|
| As strange as it may sound, UNIX folks were Oberon fans,
| hence why ACME in Plan 9 had a similar developer workflow
| as the whole Oberon UI, where clickable text is combined
| with dynamic UI actions.
|
| Plan 9 failed short of using a userspace systems language
| as C's successor (see Alef[0]).
|
| Plan 9's sucessor, Inferno, fixed this with Limbo [1],
| where C is only used for the kernel, disVM, and a couple of
| userspace libraries, everything else done in Limbo.
|
| Go ends up being a mix of Limbo, Oberon-2 method syntax and
| SYSTEM package.
|
| However one thing that both Limbo and Oberon based systems
| have, and Go misses out, in how the whole platform embraces
| dynamic linking to extend existing applications, and
| surface operations to the UI.
|
| By the way, I advise wasting a couple of hours diving into
| Inferno and Limbo's manuals[2],
|
| [0] -
| https://en.wikipedia.org/wiki/Alef_(programming_language)
|
| [1] - https://www.vitanuova.com/inferno/limbo.html
|
| [2] - https://www.vitanuova.com/inferno/docs.html
| mypalmike wrote:
| To be fair, Java didn't have generic types when Juice was
| announced.
| jbverschoor wrote:
| Nor enums.
|
| The thing that made Java great were conventions (file per
| class etc) and its standard library (esp collections)
|
| Unsurprisingly, that is exactly what made Ruby great
| Rochus wrote:
| > _No generic types .. No proper error handling .. No
| enumerations_
|
| Have a look at this version of Oberon which has generic
| modules, exceptions, enumerations and much more:
| https://oberon-lang.github.io/
|
| Also a concurrency concept is work in progress:
| https://github.com/oberon-lang/oberon-lang.github.io/blob/ma...
| abricq wrote:
| Every now and then I look at this site, I hope the project
| keeps growing !
| Rochus wrote:
| Since your project is apparently about robots, how do you
| handle concurrency with Oberon? Or how can you avoid it? In
| case you're willing to share experience, you can contact me
| on me@rochus-keller.ch. (Btw: I'm currently working on a
| low-level version of Oberon without GC which can be used as
| C substitute.)
| andai wrote:
| I thought exceptions were considered harmful in current year.
| (Opinions may differ.)
|
| Also the abstract class thing didn't stop C++, lol
| abricq wrote:
| I'm curious if you have some references about this, if you
| have read good blog posts or something ! I can think of Rust
| that does not have exception, but it's not because they
| didn't address the problem of error handling: exception are
| replaced by `Result`, if I'm not wrong. In Oberon there's
| simply no error handling mechanism.
| eterps wrote:
| There's nothing preventing you to use a Result type in
| Oberon. Just not as a fancy algebraic data type, but rather
| as a regular record/struct type.
| cmrdporcupine wrote:
| Can you really say Java succeeded in that sphere? It's simply
| not the case that Java applets had success. I was an early
| adopter, and was even paid to write a couple Java applets in
| '97, but I would say the whole thing was... questionable. They
| lingered about for a few years being badly supported and having
| a not-great security story, and then were unceremoniously
| killed.
|
| The potential was there, but in reality people just used Flash,
| and when the DOM/JavaScript interface became more competent,
| they switched to using JS.
|
| And, yeah, as others pointed out... Java did not have generics,
| or enums until 1.4, and its exception mechanism hasn't really
| stood the test of time.
| pjmlp wrote:
| Every time I have to track down exceptions in production on
| .NET projects, I deeply miss checked exceptions, because
| _some_ people just code away without caring one second to
| check their errors.
| cmrdporcupine wrote:
| When I worked in Java (11+ years ago) the style dogma was
| to never use checked exceptions.
| pjmlp wrote:
| That won't fly in code review in most Java shops I worked
| on.
|
| Also the way modern languages that are worshiped for
| forcing to handle return values, with pattern matching,
| try and ? operators, it is nothing other than proving the
| point checked exceptions matter, even if they come with a
| different flavour.
| cmrdporcupine wrote:
| Good to hear. I used to get scolded for using checked
| exceptions.
|
| But it was the 2010s.
|
| These days I work in languages with better static
| guarantees. Always wanted that back then, but felt like a
| minority.
| pjmlp wrote:
| I have been doing Java projects since 2006, and as
| mentioned on my edit you might have missed when replying,
| pattern matching, try and ? are just another way to
| package checked exceptions in a different coating.
| cmrdporcupine wrote:
| Yes and no. There's a non-local-control aspect to
| exceptions that's a bit different from explicit return or
| ? in that it's explicit in the text of the program rather
| than in the signature of the method. But yes, the
| compiler will stop you in either case, so that's fine.
|
| But there's no guarantee that someone under you didn't go
| and pull out a RuntimeException on you.
| syrusakbary wrote:
| So Juice was the WebAssembly from the Netscape era?
| blackoil wrote:
| No, it was an Applet from Java era.
| pjmlp wrote:
| Which nowadays you can replicate on top of WebAssembly.
|
| https://chromewebstore.google.com/detail/cheerpj-applet-
| runn...
| FullyFunctional wrote:
| WASM uses a block structured IR (that is, no arbitrary gotos)
| and I would characterize it as in between of the [serialized]
| Juice AST and the flat Java bytecodes.
|
| From the compiler's point of view the Juice AST is the same as
| source code so I'd expect the Juice JIT to have slight more
| code generation flexibility than the type-erased WASM.
| cybervegan wrote:
| I actually used that a bit at the time, but it the web was too
| young and browsers and HTML were too immature to support it well.
| basementcat wrote:
| I installed the Juice browser plug-in back then and remembered
| how Juice applets "loaded" much faster than their equivalent Java
| counterparts. Once loaded, Juice and Java applet performance was
| similar. Over time, Java benefited from a larger network effect
| and market share and I stopped seeing Juice applets on the web.
| eterps wrote:
| I remember that difference as well. It's a shame it didn't take
| off.
___________________________________________________________________
(page generated 2024-02-02 23:01 UTC)