第一篇 中我们曾提到,JavaScript 最终还得经过浏览器来解析。因此可以把一些优化工作,交给脚本引擎来完成。

现代浏览器的优化能力确实很强,但是,运行时的优化终归是有限的。如果能在事先实现,则可投入更多资源,优化得更充分。

优化尝试

指令 1:1 翻译成 JS,结果显然会存在一些累赘的逻辑。

例如状态标志,很多时候是不必计算的:

A = read(10)	// LDA 10
SR_N = ... // 无意义,可以去除
SR_Z = ... X = read(20) // LDX 20
SR_N = ... // 值得商榷
SR_Z = ... if (!SR_Z) { // BNE ..
nextFn = ...
return
} Y = read(30) // LDY 30
SR_N = ...
SR_Z = ...

第一步的状态标志,会被后面的覆盖,显然是没必要计算的。但第二步,就有一些奥妙了。

如果 !SR_Z 成立,那么进入下一个流程块;否则执行 LDY,状态被重置。因此,要不要计算 SR_N,可以先看 SR_Z 的结果。

于是,可将顺序调整成:

X = read(20)	// LDX 20
SR_Z = ... if (!SR_Z) { // BNE ..
SR_N = ... // 移到这里
...
}

这样,就能避免无意义的计算。

此外,再对表达式进行合并,最终变成:

A = read(10)	// LDA 10
X = read(20) // LDX 20 if (X != 0) { // BNE ..
SR_N = (X > 127)
nextFn = ...
return
} Y = read(30) // LDY 30
SR_N = (Y > 127)
SR_Z = (Y == 0)

看起来就更精简了。

再进一步,若能发现 nextFn 不依赖该流程的状态标记,那么 SR 的计算也可以省略!


其他,还有诸如 inline 优化。例如一些简单的跳转:

	JSR L1
XXX 1
XXX 2
L1:
XXX 3
XXX 4
RTS

直接将其展开,于是变成:

	XXX 3
XXX 4
XXX 1
XXX 2

这样就能减少指令块的分割,降低流程模拟的开销。

类似的优化方案还有很多。但是,若想亲自实现这些,则需要深厚的理论知识。并且实现起来也很麻烦,完全不适合这种周末时间的小研究。

借用工具

理论知识固然重要,但工程师的宗旨,就是最大程度利用现有资源,将想法快速变成现实。

这几篇文章都只是理论探讨,实现未必就得如此。事实上,我们应该借助现成的工具,快速验证想法。

既然前面提到优化,那就选择一个强大的优化方案 —— LLVM。

我们可以将 6502 指令逻辑,转换成 LLVM 中间表示。这样,即可用现成工具进行优化。

但是这么做有些麻烦。一是对 LLVM 不太熟悉,二是调试起来也不方便。

对于 LLVM 来说,最适合的输入语言当然是 C 了,毕竟 clang 就是为此产生的。

所以,我们不妨将 6502 指令翻译成 C 语言。C 不仅简单优雅,而且借助 IDE 开发调试都超级方便。

下一篇,我们尝试这个方案是否可行。

机器指令翻译成 JavaScript —— No.6 深度优化的更多相关文章

  1. 【探索】机器指令翻译成 JavaScript

    前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...

  2. 机器指令翻译成 JavaScript —— No.5 指令变化

    上一篇,我们通过内置解释器的方案,解决任意跳转的问题.同时,也提到另一个问题:如果指令发生变化,又该如何应对. 指令自改 如果指令加载到 RAM 中,那就和普通数据一样,也是可以随意修改的.然而,对应 ...

  3. 机器指令翻译成 JavaScript —— No.7 过渡语言

    上一篇,我们决定使用 LLVM 来优化程序,并打算用 C 作为输入语言.现在我们来研究一下,将 6502 指令转换成 C 的可行性. 跳转支持 翻译成 C 语言,可比 JS 容易多了.因为 C 支持 ...

  4. 机器指令翻译成 JavaScript —— 终极目标

    上一篇,我们顺利将 6502 指令翻译成 C 代码,并演示了一个案例. 现在,我们来完成最后的目标 -- 转换成 JavaScript. 中间码输出 我们之所以选择 C,就是为了使用 LLVM.现在来 ...

  5. 机器指令翻译成 JavaScript —— No.3 流程分割

    上一篇 我们讨论了跳转指令,并实现「正跳转」的翻译,但最终困在「负跳转」上.而且,由于线程模型的差异,我们不能 1:1 的翻译,必须对流程进行一些改造. 当初之所以选择翻译,而不是模拟,就是出于性能考 ...

  6. 机器指令翻译成 JavaScript —— No.2 跳转处理

    上一篇,我们发现大多数 6502 指令都可以直接 1:1 翻译成 JS 代码,但除了「跳转指令」. 跳转指令,分无条件跳转.条件跳转.从另一个角度,也可分: 静态跳转:目标地址已知 动态跳转:目标地址 ...

  7. 机器指令翻译成 JavaScript —— No.4 动态跳转

    上一篇,我们用模拟流程的方式,解决了跳转问题. 不过静态跳转,好歹事先是知道来龙去脉的.而动态跳转,只有运行时才知道要去哪.既然流程都是未知的,翻译从何谈起? 动态跳转,平时出现的多吗?非常多!除了 ...

  8. 深度优化LNMP之Nginx [2]

    深度优化LNMP之Nginx [2]   配置Nginx gzip 压缩实现性能优化 1.Nginx gzip压缩功能介绍        Nginx gzuo压缩模块提供了压缩文件内容的功能,用户请求 ...

  9. 四十年前的 6502 CPU 指令翻译成 JS 代码会是怎样

    去年折腾的一个东西,之前 blog 里也写过,不过那时边琢磨边写,所以比较杂乱,现在简单完整地讲解一下. 前言 当时看到一本虚拟机相关的书,正好又在想 JS 混淆相关的事,无意中冒出个问题:能不能把某 ...

随机推荐

  1. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  2. 告别被拒,如何提升iOS审核通过率(上篇)

    iOS审核一直是每款移动产品上架苹果商店时面对的一座大山,每次提审都像是一次漫长而又悲壮的旅行,经常被苹果拒之门外,无比煎熬.那么问题来了,我们有没有什么办法准确把握苹果审核准则,从而提升审核的通过率 ...

  3. C语言 · 乘法表

    问题描述 输出九九乘法表. 输出格式 输出格式见下面的样例.乘号用"*"表示. 样例输出 下面给出输出的前几行:1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94 ...

  4. 做一个gulp+webpack+vue的单页应用开发架子

    1.目标 最近项目上的事情不多,根据我自己的开发习惯,决定开发一些简单的开发架子,方便以后事情多的时候直接套用.本文讲的一个gulp+webpack+vue的单页应用架子,想要达到的目的: 可以通过命 ...

  5. geotrellis使用(二十八)栅格数据色彩渲染(多波段真彩色)

    目录 前言 实现过程 总结 一.前言        上一篇文章介绍了如何使用Geotrellis渲染单波段的栅格数据,已然很是头疼,这几天不懈努力之后工作又进了一步,整清楚了如何使用Geotrelli ...

  6. RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密

    最近换了一份工作,工作了大概一个多月了吧.差不多得有两个月没有更新博客了吧.在新公司自己写了一个iOS的比较通用的可以架构一个中型应用的不算是框架的一个结构,并已经投入使用.哈哈 说说文章标题的相关的 ...

  7. ADO.NET一小记-select top 参数问题

    异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 最近使用ADO.NET的时候,发现select top @count xxxx 不 ...

  8. swift开发新项目总结

    新项目用swift3.0开发,现在基本一个月,来总结一下遇到的问题及解决方案   1,在确定新项目用swift后,第一个考虑的问题是用纯swift呢?还是用swift跟OC混编      考虑到新项目 ...

  9. SQL-类型转换函数

    CAST ( expression AS data_type)CONVERT ( data_type, expression,[style]) Select '您的班级编号'+ 1  错误这里+是数学 ...

  10. mysql查询性能优化

    mysql查询过程: 客户端发送查询请求. 服务器检查查询缓存,如果命中缓存,则返回结果,否则,继续执行. 服务器进行sql解析,预处理,再由优化器生成执行计划. Mysql调用存储引擎API执行优化 ...