楼主提到的js.js不够给力啊。虽然把SpiderMonkey通过Emscripten编译成了JavaScript,但却无法使用SpiderMonkey的JIT而只能用其解释器,性能必然极其渣啊,还不如用JavaScript手写一个JavaScript解释器。不实现完整解释器的话像Erick Lavoie那样专门针对沙箱需求做个元循环间接层也好啊: In Praise of Metacircular Virtual Machine Layering
更给力的用JavaScript实现的JavaScript引擎是Tachyon:https://github.com/Tachyon-Team/Tachyon/tree/master/source
Tachyon能够自举(bootstrap),这是它与其它JavaScript元循环虚拟机最大的不同。能够自举意味着它虽然一开始要借助一个宿主JavaScript引擎来启动,但这过程中它可以将自己编译成机器码并保存到磁盘上,以后再运行就不需要依赖宿主JavaScript引擎而可以自己独立运行了。
上面提到“元循环虚拟机”的概念。所谓“元循环虚拟机”(metacircular virtual machine),就是用一种语言来实现它自己的虚拟机。不但JavaScript有,Smalltalk也有(例如Squeak),Python也有(例如PyPy),Java也有(例如Maxine VM与Jikes RVM )。差点忘了提SICP里写的Scheme Metacircular Evaluator。
使用一门编程语言来实现自己,或者更进一步达到自举,是许多编程语言用来验证自身设计的方法。例如说Oberon就属于这类。
能自举的语言还有一种好处就是减少了对别的语言的依赖,更加self-contained。
上面计子大大(@程劭非 )提到的JavaScript之父Brendan Eich所编写的Narcissus则是为了探索研发JavaScript的新功能而写的。
如果单说元循环虚拟机有啥技术优势,那么最大的优势在于它的可优化范围更大。通常虚拟机的优化边界受限于其要实现的源语言与实现语言之间的边界。
以Java为例,如果有Java方法通过JNI调用了C实现的native方法,那么这个调用就通常无法被进一步优化(像Joeq所宣称的能对Java到native的调用优化其实很有限);而如果是Java方法调用Java方法,这个调用就可以做非常多的优化,包括方法调用内联以致完全消除调用开销。这里Java/C的边界就是JVM能优化范围的一个限制;通常JVM是C/C++实现的,所以Java方法与JVM内部会有明显的边界,从Java调用JVM内部函数(所谓VM runtime call)就会比较慢因而要尽量减少。
假如虚拟机的实现语言就是源语言自身,则优化边界可以一直渗透到虚拟机内部,可以做更多优化。
另外一点主要是让虚拟机开发者受惠,那就是有许多基础功能不需要在实现语言与源语言层面各自实现一遍。一个很明显的例子是抛异常的功能。
还是用Java来具体举例,在Maxine VM里,VM自身的实现就大量使用Java语言内建的异常处理,异常处理功能只要在VM里实现一遍就好了。
而在用C++实现的HotSpot JVM里,既要为Java层实现一次异常处理功能(这里实现的是Java->Java的抛/接异常),还得在VM内部需要抛出Java层异常的地方写很多特殊处理(这里实现的是JVM->Java或者Java->JVM的抛/接异常),同样的功能得实现两遍,自然会比较不爽。
— 完 —
本文作者:RednaxelaFX
【知乎日报】
你都看到这啦,快来点我嘛 Σ(▼□▼メ)
此问题还有 10 个回答,查看全部。
延伸阅读:
javascript 正则表达式 [\w\W]+ 这样有什么意义?与.+有区别么?
JavaScript 为什么不内建选择器?