The Elusive Universal Web Bytecode
mozakai.blogspot.com
mozakai.blogspot.com
Incidentally, Arthur van Hoff just pointed out:
>Time flies. This week it is 20 years since we announced Java...
"Why Sun Thinks Hot Java Will Give You a Lift" - March 23 1995
http://web.archive.org/web/20060819094743/http://java.sun.co...
Edit: Are you this DonHopkins?
HyperNeWS aka HyperLook was like HyperCard implemented with PostScript programming and graphics, plus networking. In that alternate universe, PostScript would have been the universal bytecode for the web.
https://www.scribd.com/doc/77192884/HyperLook-Product-Info
https://www.scribd.com/doc/77164708/HyperLook-SimCity-Manual
Arthur's programming and entrepreneurial skills are indeed awesome, and I'm glad I quit my day job at Sun and left the country for the opportunity to work with him! He's now an advisor to my current company: http://pantomimecorp.com/the-team
I stopped working on that when I found out about Oak/Java in early '95.
The Network Extensible File System Protocol Specification 2/12/90
http://www.donhopkins.com/home/nfs3_0.pdf (pages in reverse order)
Introduction
The Network Extensible File System protocol (NeFS) provides transparent remote access to shared file systems over networks. The NeFS protocol is designed to be machine, operating system, network architecture, and transport protocol independent. This document is the draft specification for the protocol. It will remain in draft form during a period of public review. Italicized comments in the document are intended to present the rationale behind elements of the design and to raise questions where there are doubts. Comments and suggestions on this draft specification are most welcome.
1.1 The Network File System
The Network File System (NFS™) has become a de facto standard distributed file system. Since it was first made generally available in 1985 it has been licensed by more than 120 companies. If the NFS protocol has been so successful why does there need to be NeFS ? Because the NFS protocol has deficiencies and limitations that become more apparent and troublesome as it grows older.
1. Size limitations. The NFS version 2 protocol limits filehandles to 32 bytes, file sizes to the magnitude of a signed 32 bit integer, timestamp accuracy to 1 second. These and other limits need to be extended to cope with current and future demands.
2. Non-idempotent procedures. A significant number of the NFS procedures are not idempotent. In certain circumstances these procedures can fail unexpectedly if retried by the client. It is not always clear how the client should recover from such a failure.
3. Unix bias. The NFS protocol was designed and first implemented in a Unix environment. This bias is reflected in the protocol: there is no support for record-oriented files, file versions or non-Unix file attributes. This bias must be removed if NFS is to be truly machine and operating system independent.
4. No access procedure. Numerous security problems and program anomalies are attributable to the fact that clients have no facility to ask a server whether they have permission to carry out certain operations.
5. No facility to support atomic filesystem operations. For instance the POSIX O_EXCL flag makes a requirement for exclusive file creation. This cannot be guaranteed to work via the NFS protocol without the support of an auxiliary locking service. Similarly there is no way for a client to guarantee that data written to a file is appended to the current end of the file.
6. Performance. The NFS version 2 protocol provides a fixed set of operations between client and server. While a degree of client caching can significantly reduce the amount of client-server interaction, a level of interaction is required just to maintain cache consistency and there yet remain many examples of high client-server interaction that cannot be reduced by caching. The problem becomes more acute when a client’s set of filesystem operations does not map cleanly into the set of NFS procedures.
1.2 The Network Extensible File System
NeFS addresses the problems just described. Although a draft specification for a revised version of the NFS protocol has addressed many of the deficiencies of NFS version 2, it has not made non-Unix implementations easier, not does it provide opportunities for performance improvements. Indeed, the extra complexity introduced by modifications to the NFS protocol makes all implementations more difficult. A revised NFS protocol does not appear to be an attractive alternative to the existing protocol.
Although it has features in common with NFS, NeFS is a radical departure from NFS. The NFS protocol is built according to a Remote Procedure Call model (RPC) where filesystem operations are mapped across the network as remote procedure calls. The NeFS protocol abandons this model in favor of an interpretive model in which the filesystem operations become operators in an interpreted language. Clients send their requests to the server as programs to be interpreted. Execution of the request by the server’s interpreter results in the filesystem operations being invoked and results returned to the client. Using the interpretive model, filesystem operations can be defined more simply. Clients can build arbitrarily complex requests from these simple operations.
http://en.wikipedia.org/wiki/Oak_%28programming_language%29#...
If we were going with a bytecode, I wouldn't choose LLVM or JVM. Neither is really suited for the task.
What does that even mean?
So why did the author throw out LLVM byte code again? It's BSD, it has bytecode compilers for most platforms browsers exist on (100% vs. 50% speed), and doesn't rely on a subset of another language. It also doesn't have the requirement to fall back to vanilla Javascript. As an added bonus, Javascript could easily compile down to LLVM bytecode.
Seems like the author already preferred their answer and threw out some BS to "justify" their choice.
JS probably will remain the "byte code of the web", but this article adds nothing to that trajectory.
Interestingly, emscripten now also supports an interpreted byte code mode (called emterpreter), which stores code in a byte code format, and runs this inside an JS interpreter(!). The reason for this was quicker startup time for large scripts, but (my own speculation!) it might also be a path to a future byte code distribution format if there are indeed any other practical advantages.
Another interesting point is that Safari actually has now an LLVM based compilation layer in their Javascript engine, so it's coming together from both sides with LLVM being the glue (emscripten's front end is also LLVM).
The disadvantage is that compilation takes a not-insignificant amount of time, particularly if you want to go from running AST on a VM to running platform native code. It takes even longer if you're on an underpowered device which could take the most advantage of a simple IR bytecode -> native bytecode compilation.
This is evidenced in the 50% numbers from the OP's article.
I believe this is the same reason Khronos defined their own IR (SPIR) instead of using LLVM's. Needs to be stable.
LLVM has a single implementation, is very complex, isn't even remotely portable, and is primarily suited to C and C++, or similar languages.
We also already have a very performant transformation format for LLVM IR into JS: asm.js. And asm.js fixes most of LLVM IR's problems:
* It's very simple
* It's portable across architectures
* It doesn't have undefined behaviour
* It has multiple implementations
* It has forwards-compatibility (existing browsers, regardless of explicit support, can run asm.js code)
* It is standardised
It might not compile on an AT-MEGA, but it seems portable enough for the purposes of acting as a browser bytecode representation.
> So why did the author throw out LLVM byte code again?
"Again" is right. I don't particularly seek out discussions on this topic, but I've seen this question asked and answered at least half a dozen times before, which is enough for it to start getting annoying.
The problem is JavaScript-as-bytecode is not especially easy to improve. Anything you want to add/change that would make it a better bytecode has to be balanced with the language's use by humans.
The solution to one-VM-to-rule-them-all is not to cram everything into a higher-level system with lots of assumptions (JavaScript) or to ignore portability (NaCl, LLVM), but to use a bytecode that's low-level enough to implement the various assumptions needed by higher layers.
That way both C++ and JavaScript can run at full speed as well as have their implementations changed (even across websites!) without pushing every change through the browsers- just like native apps, with the browser providing only cross-platform and security, nothing more.
There are very few cases where human use causes problems. goto is the only one I can think of. Yet we've gotten loads of great improvements in ES6 to make it a good compiler target, like float32 and better integer multiplication.
A reply to a comment I made on another post says that the CLR and JVM suffer from GC pauses, which would not be acceptable for web apps.
Javascript happens to have none.
What are you on about?
Last time I looked at, there was no blocking IO at all (there is continuation, but it does not solve the problem because there isn't any locking mechanism - yep, I'd like atomic locking at my bytecode too). That's even the main "selling point" Node.js people throw around as if it was a good thing.
By easy integration I mean the hability of using capabilities available at the system, but not exported into the language runtime. It can be solved by something that would let me query the sandbox enviroment for the existence of a "library" that exports foreign functions, and use it. Also, something that by the other side lets me write and distribute one such "library" so people can install them on their browsers let JS use its functionality.
What? JS implements all numbers as 64-bit floating point, which happens to be able to perfectly represent the 32-bit integer space. It can actually perfectly represent a 52-bit integer space. See Number.MAX_SAFE_INTEGER [0] for details.
Now, JS does allow for type coercion between values when using the `==` operator. Luckily, the `===` operator also exists which eliminates this effect.
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
> Last time I looked at, there was no blocking IO at all.
What does blocking even mean in a single-threaded event-pump context? Does it mean other events can be processed while the IO executes? Because that's exactly what an asynchronous AJAX request does. Or does it mean it blocks the only thread available? Because that's what a synchronous AJAX call does.
Now, if your argument is that JS doesn't have an async / await construct in order to make asynchronous AJAX look like synchronous AJAX in the code, then that's in ES7.
Remember "The Great TCL War of 1994"?
Why you should not use Tcl
Richard Stallman (rms@gnu.ai.mit.edu)
Fri, 23 Sep 94 19:14:52 -0400
http://www.vanderburg.org/OldPages/Tcl/war/0000.htmlNo it doesn't. JS numbers are IEEE754-2008 64-bit double-precision floating point.
> Last time I looked at, there was no blocking IO at all
Huh? It's everywhere. XMLHttpRequests, prompt(), localStorage...
> By easy integration I mean the hability of using capabilities available at the system, but not exported into the language runtime.
Not doable for a sandbox. Sorry.