参考博文:
(1)分析Item
(3)Gen对于break、continue与return的处理
(4)虚拟机比较指令
(5)Gen类的字符串操作
(6)Gen中的switch分析及lookupswitch与tableswitch指令
(8)Java的运算符
(9)关于Item
1、简介
编程语言虚拟机一般有两种类型,基于栈,或者基于寄存器。大部分我们所熟知的语言都采用基于栈的虚拟机,比如最著名的Java虚拟机。在游戏领域非常流行的Lua语言则采用了基于寄存器的虚拟机。和JVM一样,EVM也是基于栈的虚拟机。
Java堆栈的指令集是面向堆栈的指令集
所以除了Java,其他的比如Scala,Groovy,JRuby等语言,都可以放在JVM来执行。
在GJC中代码生成需要完成的主要任务有:
(1)指令翻译:从Java虚拟机的指令集中选择合适的指令,对源程序方法中定义的代码逻辑进行翻译
(2)存储管理:将源程序中的局部变量映射为运行时局部数据区中数据对象的地址,并且将源程序中的静态变量映射为Java类文件格式中常量池表项的索引。
(3)字节码生成:将指令逐条按照Java虚拟机指令集中的规定进行编码,生成最终的字节码文件。
2、字节码指令集
3、Javac生成字节码
由于Java是以栈为架构,所以JVM在执行Javac生成的class文件时会以入栈与出栈的方式执行。Java会为每个新创建的线程分配一个Java栈,同时分配一个PC寄存器,这个PC寄存器保存了JVM正在执行的字节码指令的地址。当调用一个方法时会在这个栈上新创建一个栈桢。每个栈桢内部都包含一组称为局部变量表的变量列表,同时还包含一个称为操作数栈的栈。Javac在生成方法内代码的字节码指令时也会模拟JVM的执行过程,用来进行类型验证及更好的生成字节码指令。
3.1 定义本地变量表
本地变量表通过操作数组来完成,如下:
/** Local variables, indexed by register. */
LocalVar[] lvar; // 表示本地变量表,类似于寄存器的作用
用LocalVar类来代表操作的本地变量。另外定义了操作这个数组的几个方法,如下:
(1)addLocalVar
(2)setDefined
(3)setUndefined
(4)putVar
(5)endScope
(6)newLocal
3.2 定义操作数栈
/** The set of registers containing values. */
Bits defined;
/** The (types of the) contents of the machine stack. */
// 栈除了辅助进行类型验证外,还能得出代码在运行过程中需要使用
// 的最大栈空间等,
Type[] stack;
/** The first stack position currently unused. */
public int stacksize; // 栈顶指针
(2)Item类
栈架构会频繁的对某些数值进行入栈与出栈操作,而且也伴随着局部变量表的存储与删除
(3)示例分析
4、控制结构的生成
(1)while
(2)do-while
(3)if
5、方法调用
6、异常与finally语句块