本文系 Creating JVM language 翻译的第 14 篇。
原文中的代码和原文有不一致的地方均在新的代码仓库中更正过,建议参考新的代码仓库。
源码
支持新的类型
目前为止 Enkel 仅支持了整数类型和字符串类型。是时候支持其他的原始类型了。这也是为创建面向对象特性做准备。
指令集的抽象
字节码指令中有很多指令仅仅是在数据类型上有区别,以 return 指令举例:
- return - 方法返回
- ireturn - 返回interger
- freturn - 返回float
- dreturn - 返回double
- lreturn - 返回long
- areturn - 返回引用
字节码生成的时候,我们多写一点 case 语句可以实现,但是很丑陋。因此我用 TypeSpecificOpcodes 枚举存储了所有类型对应的字节码指令:
public enum TypeSpecificOpcodes {
INT (ILOAD, ISTORE, IRETURN,IADD,ISUB,IMUL,IDIV), //values (-127,127) - one byte.
LONG (LLOAD, LSTORE, LRETURN,LADD,LSUB,LMUL,LDIV),
FLOAT (FLOAD, FSTORE, FRETURN,FADD,FSUB,FMUL,FDIV),
DOUBLE (DLOAD, DSTORE, DRETURN,DADD,DSUB,DMUL,DDIV),
VOID(ALOAD, ASTORE, RETURN,0,0,0,0),
OBJECT (ALOAD,ASTORE,ARETURN,0,0,0,0);
TypeSpecificOpcodes(int load, int store, int ret, int add, int sub, int mul, int div) {
//assign each parameter to the field
}
//getters
类型相关的字节码指令,目前我们用到了:
- load - 从局部变量表中加载变量
- store - 存储至局部变量表
- ret - 返回
- add - 操作数栈中两个数相加
- sub - 栈中操作数相减
- mul - 栈中操作数相乘
- div - 栈中操作数相除
TypeSpecificOpcodes 是在 BultInType 类中:
public enum BultInType implements Type {
BOOLEAN("bool",boolean.class,"Z", TypeSpecificOpcodes.INT),
//other members
BultInType(String name, Class<?> typeClass, String descriptor, TypeSpecificOpcodes opcodes) {
//assign to fields
}
@Override
public int getMultiplyOpcode() {
return opcodes.getMultiply();
}
无论何时,两个数相乘,只要知道类型就可以了,再也不用查找类型对应的字节码指令:
public void generate(Multiplication expression) {
evaluateArthimeticComponents(expression);
Type type = expression.getType();
methodVisitor.visitInsn(type.getMultiplyOpcode());
}
示例
如下 Enkel 代码:
main(string[] args) {
var stringVar = "str"
var booleanVar = true
var integerVar = 2745 + 33
var doubleVar = 2343.05
var sumOfDoubleVars = 23.0 + doubleVar
}
编译后的字节码:
public class AllPrimitiveTypes {
public static void main(java.lang.String[]);
Code:
0: ldc #8 // String str
2: astore_1 //store it variable
3: ldc #9 // int 1 - bool values are represented as ints in JVM
5: istore_2 //store as int
6: ldc #10 // int 2745
8: ldc #11 // int 33
10: iadd // iadd - add integers
11: istore_3 //store result in integer varaible
12: ldc #12 // float 2343.05f
14: fstore 4 //store in float variable
16: ldc #13 // float 23.0f
18: fload 4 //load integer varaible (from index 4)
20: fadd //add float variables
21: fstore 5 //store float result
23: return
}
网友评论