为什么JavaScript会被编译成机器码?

4

我最近开始做一些与ASP.NET和JavaScript相关的Web开发,有一些问题让我很困惑。

我经常听说JavaScript以前是解释执行的,直到JIT逐渐使一些代码块编译成机器代码(这使浏览器运行更快)。

这对我来说毫无意义。如果传统的JavaScript应用程序一开始就没有针对机器/CPU,那么它又怎么能编译成本地机器代码呢?

如果electron.js应用程序使用NodeJS运行时编译成机器代码,我就理解了。因为它可以原生地编译成机器代码,据我所知,不在浏览器中运行

如果传统的JavaScript应用程序在浏览器中运行,为什么必须将其编译成机器代码呢?浏览器负责运行代码,而不是CPU。CPU运行浏览器本身。实际上,我并不认为本地操作系统可以影响浏览器中发生的任何事情,反之亦然。似乎也涉及到安全问题。

如果我的问题很愚蠢,请见谅,但我找不到任何超越“Javascript使用JIT”的资源。

谢谢!

Lauren


电子应用程序中的 JavaScript 并没有完全编译成本地代码,因为构建的可执行文件实际上是一个基于 Chromium 的 Web 应用程序。 - Ted Brownlow
或许有帮助:https://softwareengineering.stackexchange.com/questions/291230/how-does-chrome-v8-work-and-why-was-javascript-not-jit-compiled-in-the-first-place - Thilo
2个回答

6
最终,CPU 必须运行代码。将其 J即时编译为机器码是加速的一种方式。
“传统 JavaScript 应用程序” 本来就没有针对机器/CPU 开发,那么 JavaScript 如何编译成本地机器码呢?
实际上并非 "JavaScript" 进行编译,而是浏览器(或者说浏览器内部的 JavaScript 执行引擎),因为它是 "JIT",所以它知道要针对哪个 CPU(这不是通用的,而是根据浏览器当前运行的特定 CPU 进行的)。
所以,是的,这里确实存在一些不匹配,因为 JavaScript 不会使用低级别的原始类型,直接使用这些类型可以让 CPU 更好地工作,这就是为什么会有很多间接性和猜测类型推断的原因。生成的机器码与手工编写的汇编代码大不相同,但仍然可能是一种净增效果。为了解决这个问题,WASM 被开发出来,更接近于 "正常" 的机器码。
其他中间的、非 CPU 特定格式,例如 JVM bytecode 或 CLR bytecode 或 LLVM bitcode,都处于类似的情况下(可以编译为它们不直接目标的机器码),但它们已经从语言源代码“降低”到接近机器码的东西了。
似乎也是一个安全问题?
是的,有可能。浏览器在这里的操作必须小心谨慎,而操作系统应该尽可能地对浏览器进行沙盒隔离。

0

执行指令比运行解释器更容易,而JIT旨在利用这一点来提高性能。所有在计算机上运行的程序最终都会变成机器码,唯一的问题是执行哪些指令。

let x=0;
for (let i=0;i<100;++i) {
  x+=2;
}

由于像这样的代码块没有副作用,直接编译指令比逐行解释更快。

// NIOS 2 assembly, sorry its the only one i know
movi r2,0
movi r3,0
movi r4,100
loop:
  addi r2,2
  addi r3,1
  blt r3,r4,loop

执行此操作将比对每个单独指令执行解析逻辑更快。

简而言之:所有程序都始终在运行CPU指令,因此尽可能跳过解析阶段以最小化指令数量可以提高速度。


1
请注意,JavaScript 的一个大问题是 JIT 编译器必须找出 x 是否可以成为本地整数类型(然后直接放入 CPU 寄存器并与 addi 一起使用)或者是否需要更多的工作。JavaScript 没有声明类型,你可以在下一行中执行 x = x*2.87 或者甚至 x = "Hello"。而像 JVM 字节码或 WASM 这样的东西,至少有精确的类型。 - Thilo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接