动态vs静态编译器(JavaScript)
Dynamic vs Static Compiler (JavaScript)
我目前正在用ANTLR+Java编写一个JavaScript编译器。
我在Stack Overflow上看到了一些关于如何继续执行的问题——答案总是说,对动态语言进行静态编译(没有jit信息)太难了——但这到底是为什么呢?当然有明显的"类型解析"问题,在JavaScript中可能是eval
函数的问题-但还有其他原因吗?(因为纯静态克服它们似乎并不太难(没有jit))
我排除了基于jit的编译,因为我认为这对我来说太难实现了。
我有一些编写字节码执行静态编译器的经验。
更新:你所有的答案都对理解这个问题很有帮助。澄清一下,这是否意味着JavaScript比其他动态语言更难实现?这是否也意味着我使用基于树的解释器比例如字节码更好(如果我们忘记了JS总是在原始源代码中发布的属性-因此增加了额外的时间来生成和IR,然后执行它)?——或者它们应该同样容易/难做吗?
(我是新来的;不知道这是否是更新问题的首选方式?)
这种对话有很多种方式。这是一个方向。在javascript中,几乎所有东西都是对象,并且可以在运行时向任何对象添加属性或方法。因此,在编译时您不知道什么方法或属性会或不会附加到对象上。因此,一切都必须在运行时查找。
例如:var myObj = {};
function configureObject() {
if (something in the environment) {
myObj.myfunc = function () {alert("Hi");}
} else {
myObj.myfunc = function () {document.write("Hello");}
}
}
现在,稍后在代码中你调用myObj.myfunc();
,在编译时不知道myfunc
是什么,或者它是否是myObj
的一个属性。它必须是运行时查找。
在另一个例子中,取这行代码:
var c = a + b;
他的意思完全取决于a和b的类型,而这些类型在编译时是未知的。
如果a和b都是数字,那么这是一个加法语句,c将是一个数字。
如果a或b是字符串,则另一个将被强制为字符串,并且c将是字符串。
不能将这种逻辑预编译为本机代码。执行环境必须记录这是对这两个操作数之间的加法运算符的请求,并且它必须(在运行时)检查这两个操作数的类型并决定做什么。
编写静态JavaScript编译器的挑战是,通常很难确定在任何程序点引用了什么对象或调用了什么函数。我可以利用JavaScript是动态的这一事实,根据图灵机的输出来决定调用哪个函数。例如:
var functionName = RunTuringMachineAndReportOutputOnTape(myTM, myInput);
eval(functionName + "();");
在这一点上,除非您预先知道myTM
和myInput
是什么,否则是不可能确定调用eval
将调用什么函数的,因为如果图灵机停止,则无法确定图灵机磁带上的内容(您可以将停止问题减少为此问题)。因此,无论您多么聪明,无论您构建的静态分析器有多好,您都永远无法正确地静态解析所有函数调用。你甚至不能绑定这里可能调用的函数集,因为图灵机的输出可能定义了一些函数,然后由上面的代码执行。
你能做的是编译代码,当一个函数被调用时,包含额外的逻辑来解析调用,并可能使用内联缓存等技术来加快速度。此外,在某些情况下,您可能能够证明正在调用某个函数(或将调用少数函数中的一个),然后可以在这些调用中进行硬编码。您还可以为一段代码编译多个版本,每种常见类型(对象、数字等)一个版本,然后发出代码,根据动态类型跳转到适当的编译跟踪。
V8就是这样做的。参见使用V8将JavaScript编译为本机代码
对于EcmaScript 3和5 non-strict,在作用域周围有一些你在其他动态语言中不会遇到的问题。您可能认为对局部变量进行编译器优化很容易,但是在语言中存在一些边缘情况,当它不是,甚至忽略eval
的范围自省。
function f(o, x, y) {
with (o) { return x + y + z; }
}
当用
调用时
o = {};
o = { z: 3 };
o = { x: 1, z: 2 };
Object.prototype.z = 3, o = {};
,根据EcmaScript 3
x = (function () { return toString(); })()
应该与
产生完全不同的结果x = toString();
因为EcmaScript 3将激活记录定义为带有原型链的对象。
- 当使用extern和目标JavaScript时,我如何强制Haxe编译器使用require语句
- 如何告诉闭包javascript编译器不要混淆webkitAudioContext的方法名称
- 在哪里可以找到R-to-JavaScript编译器
- 无法使用 ant 和闭包编译器编译 javascript,因为 Jquery 的 $ 是未声明的
- TypeScript 编译器在 WebStorm 中创建空的 JavaScript 文件
- C语言的Javascript编译器
- 如何在JavaScript中为Google闭包编译器设置参数类型
- 闭包编译器高级和服务器端注入的Javascript
- eval() 关键字究竟是如何破坏 JavaScript 中的编译器优化的
- 使用闭包编译器编写更好的面向对象JavaScript完整示例代码
- 在javascript中的即时Java编译器
- 如何使用闭包编译器在 javascript 中注释扩展泛型类型的类
- ChickenScheme Spock JavaScript编译器安装问题
- 什么是编译器?如何制作一个简单的ruby到javascript编译器
- javascript编译器中的死代码
- 准备脚本在JavaScript编译器中编译(Google Closure)
- 是否有一个独立的JavaScript编译器/解释器与控制台,我可以用它来练习浏览器之外的JavaScript
- c -我如何为Arduino或类似的微控制器编写JavaScript编译器
- ECMAScript:Harmony/ES6到JavaScript编译器
- 什么是最生产级别的Haskell到JavaScript编译器,编写在浏览器中运行的代码