从零构建的JavaScript到WebAssembly编译器和运行时
Porffor是一个从零开始构建的JavaScript到WebAssembly/C编译器和运行时。它采用全AOT编译,无常量运行时代码,最少化Wasm导入。Porffor支持部分JavaScript功能,包括基本语言特性、内置函数和一些提案。项目还包含Wasm引擎Asur、正则表达式引擎Rhemyn和Wasm到C编译器2c。Porffor在支持的功能范围内性能表现优异,尤其是编译为原生二进制文件时。
一个从零开始的实验性 AOT 优化 JS/TS -> Wasm/C 引擎/编译器/运行时,用 JS 编写。研究项目,目前尚不适合严肃使用。<br>
<img src="https://github.com/CanadaHonk/porffor/assets/19228318/de8ad753-8ce3-4dcd-838e-f4d49452f8f8" alt="终端截图显示 Porffor 运行和编译 hello world" width="60%">Porffor 是一个非常独特的 JS 引擎,采用了许多完全不同的方法。它有严重的限制,但它能做的事情,做得相当不错。主要区别:
Porffor 主要是从零开始构建的,唯一不是的部分是解析器(使用 Acorn)。不使用 Binaryen 等,我们自己制作最终的 wasm 二进制文件。你可以将其想象成编译一种是 JavaScript 的子集(某些功能不支持)和超集(新的/自定义 API)的语言。不基于任何特定的规范版本。
不要期望一切都能正常工作!目前仅支持非常有限的 JS。请参见 bench
文件夹中的示例。
npm install -g porffor@latest
。就是这么简单(希望如此):)
porf
。直接运行,不带脚本文件参数。
porf path/to/script.js
porf wasm path/to/script.js out.wasm
。目前它不使用像 WASI 这样的导入标准,所以单独使用基本上是不可用的。
[!警告] 编译为原生二进制 文件使用 2c,Porffor 自己的 Wasm -> C 编译器,这是实验性的。
porf native path/to/script.js out(.exe)
。你可以用 --compiler=clang|gcc|zig
指定编译器(默认为 clang
),用 --cO=Ofast|O3|O2|O1|O0
指定使用的优化级别(默认为 Ofast
)。输出的二进制文件默认也会被剥离。
[!警告] 编译为 C 使用 2c,Porffor 自己的 Wasm -> C 编译器,这是实验性的。
porf c path/to/script.js (out.c)
。当不包含输出文件时,将会打印到标准输出。
[!警告] 非常实验性的进行中功能!
porf profile path/to/script.js
[!警告] 非常实验性的进行中功能!
porf debug path/to/script.js
[!警告] 非常实验性的进行中功能!
porf debug-wasm path/to/script.js
--parser=acorn|@babel/parser|meriyah|hermes-parser
(默认:acorn
)设置使用哪个解析器--parse-types
启用解析类型注解/typescript。如果未设置 -parser
,默认更改为 @babel/parser
。不进行类型检查--opt-types
使用类型注解作为编译器提示进行优化。不进行类型检查--valtype=i32|i64|f64
(默认:f64
)设置值类型-O0
禁用优化-O1
(默认)启用基本优化(简化指令,树摇 wasm 导入)-O2
启用高级优化(部分求值)。不稳定!eval()
/Function()
等(因为是 AOT)Asur 是 Porffor 自己的 Wasm 引擎;它是一个用 JS 编写的有意简化的解释器。它还在开发中。更多详情请参见其自述文件。
Rhemyn 是 Porffor 自己的正则表达式引擎;它将字面正则表达式 AOT 编译为 Wasm 字节码(想起什么了吗?)。它相当基础且还在开发中。更多详情请参见其自述文件。
2c 是 Porffor 自己的 Wasm -> C 编译器,使用生成的 Wasm 字节码和内部信息来生成特定且高效/快速的 C 代码。很少的样板/前置代码或所需的外部文件,仅用于 CLI 二进制文件(与 wasm2c 非常不同)。
有关已实现/支持的优化,请参见优化部分。
这些包括一些早期(阶段 1/0)和/或已停止(最后提交已多年)的提案,但我认为它们相当不错,所以。
Math
提案(阶段 1/0)Math.clamp
提案:Math.clamp
(阶段 0 - 最后提交于 2023 年 4 月)Math
扩展提案:Math.scale
、Math.radians
、Math.degrees
、Math.RAD_PER_DEG
、Math.DEG_PER_RAD
(阶段 1 - 最后提交于 2020 年 9 月)Math.signbit
提案:Math.signbit
(阶段 1 - 最后提交于 2020 年 2 月)return
let
/const
/var
)+-/*%
)&|
)==
、!=
等)>
、<
、>=
等)!
、+
、-
)&&
、||
)let a, b = 0
)let [a, ...b] = foo
)var
/无修饰符)if
和if ... else
const foo = function() { ... }
)undefined
/null
a++
、++b
、c--
等)for
循环(for (let i = 0; i < N; i++)
等)console.log
while
循环break
和continue
+=
、-=
、>>=
、&&=
等)cond ? a : b
)return
)throw
(仅支持字面量,用于new Error
的hack)try { ... } catch { ... }
(不提供错误信息)f(a, b); f(0); f(1, 2, 3);
)typeof
ReferenceError
), 非函数的运行时错误(TypeError
)[]
创建数组(如let arr = [ 1, 2, 3 ]
)arr[ind]
访问数组成员(如arr[0]
)'hello world'
)str[ind]
访问字符串成员(字符)(如str[0]
)+
)(如'a' + 'b'
)!'' == true
)'a' == 'a'
、'a' != 'b'
)??
)for...of
(数组和字符串)for...in
arr[0] = 2
、arr[0] += 2
等)Array(5)
、new Array(1, 2, 3)
)foo: while (...)
)do...while
循环(foo = 'bar') => { ... }
)(...foo) => { ... }
)this
new Foo
)class A {}
)await promise
)NaN
和Infinity
isNaN()
和isFinite()
Number
的大部分功能(MAX_VALUE
、MIN_VALUE
、MAX_SAFE_INTEGER
、MIN_SAFE_INTEGER
、POSITIVE_INFINITY
、NEGATIVE_INFINITY
、EPSILON
、NaN
、isNaN
、isFinite
、isInteger
、isSafeInteger
)Math
函数(sqrt
、abs
、floor
、sign
、round
、trunc
、clz32
、fround
、random
、exp
、log
、log2
、log10
、pow
、expm1
、log1p
、sqrt
、cbrt
、hypot
、sin
、cos
、tan
、sinh
、cosh
、tanh
、asinh
、acosh
、atanh
、asin
、acos
、atan
、atan2
)globalThis
支持Boolean
和Number
eval
用于字面量Math.random()
performance
的部分功能(now()
、timeOrigin
)Array.prototype
的大部分方法(at
、push
、pop
、shift
、fill
、slice
、indexOf
、lastIndexOf
、includes
、with
、reverse
、toReversed
、forEach
、filter
、map
、find
、findLast
、findIndex
、findLastIndex
、every
、some
、reduce
、reduceRight
、join
、toString
)Array
的大部分方法(of
、isArray
)String.prototype
的大部分方法(at
、charAt
、charCodeAt
、toUpperCase
、toLowerCase
、startsWith
、endsWith
、indexOf
、lastIndexOf
、includes
、padStart
、padEnd
、substring
、substr
、slice
、trimStart
、trimEnd
、trim
、toString
、big
、blink
、bold
、fixed
、italics
、small
、strike
、sub
、sup
、trimLeft
、trimRight
、trim
)crypto
的部分功能(randomUUID
)escape
btoa
Number.prototype
的大部分方法(toString
、toFixed
、toExponential
)parseInt
Date
Uint8Array
、Int32Array
等)Promise
Porffor使用独特的版本控制系统,示例如下:0.18.2+2aa3f0589
。让我们来分解一下:
0
- 主版本号,始终为0
,因为Porffor还未准备就绪18
- 次版本号,总Test262通过百分比(向下取整到最接近的整数)2
- 微版本号,该次版本的构建编号(每次发布/git推送时递增)2aa3f0589
- 提交哈希值对于大多数支持的功能,Porffor与大多数解释器和常见引擎(在不使用JIT的情况下)相比速度极快。对于那些使用JIT的引擎,默认情况下通常较慢,但可以通过编译器参数和类型化输入赶上,在编译为本机二进制文件时更是如此。
主要用于减小体积。我不太关心编译器性能/时间,只要合理即可。我们不使用/依赖外部优化工具(如wasm-opt
等),而是在编译器内部进行优化,创建比wasm-opt
本身产生的代码体积更小的代码,因为我们拥有更多内部信息。
--tail-call
标志后面)local.set
、local.get
-> local.tee
i32.const 0
、i32.eq
-> i32.eqz
i64.extend_i32_s
、i32.wrap_i64
-> ``f64.convert_i32_u
、i32.trunc_sat_f64_s
-> ``return
、end
-> end
f64.const
、i32.trunc_sat_f64_s
-> i32.const
)br
指令)Porffor 可以通过一些技巧/转换来运行 Test262,这些技巧/转换移除了不支持的特性,同时仍然执行相同的断言(例如使用仅包含字面量的简化错误消息)。目前通过率超过 14%(具体数据和详情请查看最新提交描述)。使用 node test262
进行测试,它还会显示上次提交和当前结果之间的整体差异。
compiler
:包含编译 器本身
2c.js
:porffor 的自定义 wasm-to-c 引擎allocators.js
:支持各种语言特性的静态和动态分配器assemble.js
:将 wasm 操作和元数据组装成 wasm 模块/文件builtins.js
:引擎的所有手动编写的内置功能(规范、自定义、变量、函数)builtins_object.js
:所有各种内置对象(如 String
、globalThis
等)builtins_precompiled.js
:从 builtins/
文件夹动态生成的内置功能codegen.js
:代码(wasm)生成,ast -> wasm。主要工作量在此cyclone.js
:wasm 部分常量求值器(快速且危险,因此称为"cyclone")decompile.js
:用于调试信息的基本 wasm 反编译器diagram.js
:生成 Mermaid 图表embedding.js
:嵌入常量的工具encoding.js
:将内容编码为 wasm 所需字节的工具expression.js
:将大多数运算符映射到操作码(高级运算符作为内置功能,如 f64_%
)havoc.js
:wasm 重写库(它对 wasm 字节码造成破坏,因此称为"havoc")index.js
:执行所有编译器步骤,输入代码,输出 wasmopt.js
:自制的 wasm 字节码优化器parse.js
:简单封装 acorn 的解析器pgo.js
:基于概要引导的优化器precompile.js
:生成 builtins_precompied.js
的工具prefs.js
:读取命令行参数的工具prototype.js
:一些内置原型函数types.js
:每个内置类型的定义wasmSpec.js
:来自 wasm 规范的"枚举"/信息wrap.js
:编译器的包装器,实例化并生成友好的导出runner
:包含使用编译器运行 JS 的工具
index.js
:主文件,您可能想使用这个info.js
:运行时打印额外信息repl.js
:基本的 repl(使用 node:repl
)rhemyn
:包含 Rhemyn - 我们的正则表达式引擎(由 Porffor 使用)
compile.js
:将正则表达式 ast 编译为 wasm 字节码parse.js
:自己的正则表达式解析器test
:包含许多测试文件,用于测试大多数支持的功能
test262
:test262 运行器和工具
目前,Porffor 在功能和特性上有严重限制,但它有一些关键优势:
没有特定顺序,也不做保证,只是可能很快发生的事情™
escape()
优化vscode-ext
中有一个 vscode 扩展,它调整了 JS 语法高亮,使其更适合 porffor 特性(例如,在内联汇编中高亮 wasm)。
Porffor 有意不使用尚未广泛实现的 Wasm 提案(例如 GC),以便它可以在尽可能多的地方使用。
威尔士语中的"紫色"是 porffor
。为什么选择紫色?
是的!
不,它们在内部完全不同,并且有着非常不同的目标和理念:
AI数字人视频创作平台
Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。
一站式AI创作平台
提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作
AI办公助手,复杂任务高效处理
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让 学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号