Stack machines tend to have small bytecode and it's relatively easy to write a small low-performance stack machine interpreter. Register machine bytecodes tend to take up more space, but it tends to be easier to write high performance interpreters and reasonable JITs. If you're always going to generate machine code, an SSA format minimizes the work/time necessary for a JIT to generate high-performing machine code, but it's difficult to write a high performance non-JITing interpreter for SSA-based bytecodes.
SpiderMonkey, Java, CPython, Forth, and SmallTalk (blue book) all use stack-based bytecodes. LuaJIT, Android's Dalvik, Squirelfish, and Parrot use register-based bytecodes. Michael Franz's SafeTSA (alternative JVM bytecode) and LLVM bitcode are compactly serialized SSA representations.
Microsoft has done some research on using arithmetically compressed syntax trees as an alternative JavaScript format. Part of me feels this is the best approach, as it speeds up transmission and parsing that all JavaScript engines have to do anyway, without performing transformations that JITs spend a fair amount of effort undoing later.
Ideally, I'd like to see a compressed SSA format, with optional debugging symbols and optional decompiling hints, analogous to WavPack's hybrid lossless audio format. The format could be losslessly expanded back into the original JavaScript source, or it could be stripped down to something like a binary with debugging symbols, or it could be further stripped down to just the data necessary to generate fast machine code.
The Mill CPU is interesting here, in that it's a belt machine, so SSA is very close to what its native machine/assembly looks like. It basically takes what is currently register renaming and drops the layer of ISA registers, and just refers to the results of previous instructions relative to the current one. That sort of architecture would be almost trivial to JIT SSA for- you wouldn't even need register allocation, just instruction scheduling.
Another consideration to go along with decompiling hints, debug symbols, etc. is that web pages are very transparent and manipulable with the browser's inspector and JS console. Any new bytecode would ideally keep the ability to poke around the app's data and interface- it's a very nice REPL-type tool.
PS: no transpilation and other 3+ step "compilation" offers.
asm.js is a really clever play to leverage Javascript to get JS out of the way, while never making it obvious that's what it's doing.
What? You're stuck dealing with ints and a heap of memory... which is exactly what you get when developing native code. On top of that, you can implement any memory model and type system you want.
Are you saying you want a managed VM, so something further away from the processor? What features do you want, and which tradeoffs would it make? Why can't you just implement your managed VM on top of asm.js?
It's a nice idea, and works pretty well. But instead of the idea of JavaScript-as-assembly, I'd like to see a standard bytecode, integrated into the browser as well as JS, designed for apps as well as/rather than document tweaking, with better control over the memory model, data manipulation, and thus performance. We could still run JavaScript, and even crazy C++-emscripten-asm.js stuff on top of that bytecode, but it would enable much faster (startup and runtime) and more power-efficient apps with a much simpler stack.