4.从0开始的手写java虚拟机 - 指令集和解释器

本文详细介绍了从零开始构建Java虚拟机的过程,重点关注指令集和解释器的设计。涵盖的内容包括:通用指令接口、读取字节码操作、常量指令(如nop、const、ipush等)、加载和存储指令、栈操作指令、数学运算指令以及类型转换指令。
摘要由CSDN通过智能技术生成

4.从0开始的手写java虚拟机 - 指令集和解释器

上一节我们描述了jvm是通过一个死循环不断执行指令直至循环结束;
接下来我们将描述每一条指令

4.1.通用指令接口

package base

import "HandWritingJVM/rtda"

//指令通用接口
type Instruction interface {
   
	FetchOperands(reader *BytecodeReader)
	Execute(frame *rtda.Frame)
}

//对应无操作数指令,如return, add, mul...
type NoOperandsInstruction struct {
   
}


func (self *NoOperandsInstruction) FetchOperands(reader *BytecodeReader) {
   
	//...

}
//分支跳转指令
type BranchInstruction struct {
   
	Offset int
}

func (self *BranchInstruction) FetchOperands(reader *BytecodeReader) {
   
	self.Offset = int(reader.ReadInt16())
}
//操作数长度为8的相关指令
type Index8Instruction struct {
   
	Index uint
}

func (self *Index8Instruction) FetchOperands(reader *BytecodeReader) {
   
	self.Index = uint(reader.ReadUint8())
}

//操作数长度为16的相关指令
type Index16Instruction struct {
   
	Index uint
}

func (self *Index16Instruction) FetchOperands(reader *BytecodeReader) {
   
	self.Index = uint(reader.ReadUint16())
}

4.2.读取字节码相关操作

package base

type BytecodeReader struct {
   
	code []byte
	pc   int
}
//重置当前栈帧的pc以及将要执行的方法
func (self *BytecodeReader) Reset(code []byte, pc int) {
   
	self.code = code
	self.pc = pc
}

func (self *BytecodeReader) PC() int {
   
	return self.pc
}
//获取当前代码块中pc所指向的字节码指令
func (self *BytecodeReader) ReadUint8() uint8 {
   
	i := self.code[self.pc]
	self.pc++
	return i
}

func (self *BytecodeReader) ReadInt8() int8 {
   
	return int8(self.ReadUint8())
}

func (self *BytecodeReader) ReadUint16() uint16 {
   
	byte1 := uint16(self.ReadUint8())
	byte2 := uint16(self.ReadUint8())
	return (byte1 << 8) | byte2
}

func (self *BytecodeReader) ReadInt16() int16 {
   
	return int16(self.ReadUint16())
}
func (self *BytecodeReader) ReadInt32() int32 {
   
	byte1 := int32(self.ReadUint8())
	byte2 := int32(self.ReadUint8())
	byte3 := int32(self.ReadUint8())
	byte4 := int32(self.ReadUint8())
	return (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4
}

func (self *BytecodeReader) ReadInt32s(count int32) []int32 {
   
	ret := make([]int32, count)
	for i := 0; i < int(count); i++ {
   
		ret[i] = self.ReadInt32()
	}
	return ret
}

func (self *BytecodeReader) SkipPadding() {
   
	for self.pc%4 != 0 {
   
		self.ReadUint8()
	}
}

4.3.常量指令

4.3.1.nop

解释:
在这里插入图片描述

package constants

import (
	"HandWritingJVM/instructions/base"
	"HandWritingJVM/rtda"
)

type NOP struct {
   
	base.NoOperandsInstruction
}

func (self *NOP) Execute(frame *rtda.Frame) {
   
	//...
}

4.3.2.const

解释:将一个值推入操作数栈中

package constants

import (
	"HandWritingJVM/instructions/base"
	"HandWritingJVM/rtda"
)

//将null推入操作数栈顶
type ACONST_NULL struct {
   
	base.NoOperandsInstruction
}

/**
An aconst_null instruction is type safe if one can validly push the type
null onto the incoming operand stack yielding the outgoing type state.
*/
func (self *ACONST_NULL) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushRef(nil)
}

type DCONST_0 struct {
   
	base.NoOperandsInstruction
}

//将double 0推入操作数栈顶,其他以此类推
func (self *DCONST_0) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushDouble(0.0)
}
//将double 1推入操作数栈顶
type DCONST_1 struct {
   
	base.NoOperandsInstruction
}

func (self *DCONST_1) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushDouble(1.0)

}

//将float 0推入栈顶,其他以此类推
type FCONST_0 struct {
   
	base.NoOperandsInstruction
}

func (self *FCONST_0) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushFloat(0.0)
}

type FCONST_1 struct {
   
	base.NoOperandsInstruction
}

func (self *FCONST_1) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushFloat(1.0)
}

type FCONST_2 struct {
   
	base.NoOperandsInstruction
}

func (self *FCONST_2) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushFloat(2)
}
//将int -1 推入栈顶,其他以此类推
type ICONST_M1 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_M1) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(-1)
}
//将int 0推入栈顶,其他以此类推
type ICONST_0 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_0) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(0)
}

type ICONST_1 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_1) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(1)
}

type ICONST_2 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_2) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(2)
}

type ICONST_3 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_3) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(3)
}

type ICONST_4 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_4) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(4)
}

type ICONST_5 struct {
   
	base.NoOperandsInstruction
}

func (self *ICONST_5) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(5)
}
//将long 0推入栈顶,其他以此类推
type LCONST_0 struct {
   
	base.NoOperandsInstruction
}

func (self *LCONST_0) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushLong(0)
}

type LCONST_1 struct {
   
	base.NoOperandsInstruction
}

func (self *LCONST_1) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushLong(1)
}
4.3.3.ipush

解释:读取一个值并推入操作数栈中

package constants

import (
	"HandWritingJVM/instructions/base"
	"HandWritingJVM/rtda"
)
type BIPUSH struct {
   
	val int8
}

//从操作数中获取一个byte类型数据,扩展成int,然后推入栈顶
func (self *BIPUSH) FetchOperands(reader *base.BytecodeReader) {
   
	self.val = reader.ReadInt8()
}

func (self *BIPUSH) Execute(frame *rtda.Frame) {
   
	i := int32(self.val)
	frame.OperandStack().PushInt(i)
}

type SIPUSH struct {
   
	val int16
}

//从操作数中获取一个short类型数据,扩展成int,然后推入栈顶
func (self *SIPUSH) FetchOperands(reader *base.BytecodeReader) {
   
	self.val = reader.ReadInt16()
}

func (self *SIPUSH) Execute(frame *rtda.Frame) {
   
	frame.OperandStack().PushInt(int32(self.val))
}
4.3.4.ldc

解释:从运行时常量池中取出元素并推入操作数栈顶
在这里插入图片描述

package constants

import (
	"HandWritingJVM/instructions/base"
	"HandWritingJVM/rtda"
	"HandWritingJVM/rtda/heap"
)

//从常量池中取出元素然后推入操作数栈中,下标长度为8
//且推入的元素类型为int, float, string, classRef
type LDC struct {
   
	base.Index8Instruction
}

//从常量池中取出元素然后推入操作数栈中,下标长度为16
//且推入的元素类型为int, float, string, classRef
type LDC_W struct {
   
	base.Index16Instruction
}

//从常量池中取出元素然后推入操作数栈中,下标长度为16
//且推入的元素类型为long,double
type LDC2_W struct {
   
	base.Index16Instruction
}

func (self *LDC) Execute(frame *rtda.Frame) {
   
	_ldc(frame, self.Index)
}

func (self *LDC_W) Execute(frame *rtda.Frame) {
   
	_ldc(frame, self.Index)
}

func _ldc(frame *rtda.Frame, index uint) {
   
	stack := frame.OperandStack()
	clazz := frame.Method().Class()
	cp := clazz.ConstantPool()
	c := cp.GetConstant(index)
	switch c.(type) {
   
	case int32:
		stack.PushInt(c.(int32))
	case float32:
		stack.PushFloat(c.(float32))
	case string:
		internedStr := heap.JString(clazz.Loader(), c.(string))
		stack.PushRef(internedStr)
	case *heap.ClassRef:
		classRef := c.(*heap.ClassRef)
		classObj := classRef.ResolvedClass().JClass()
		stack.PushRef(classObj)
	default:
		panic("todo: ldc!")
	}
}

func (self *LDC2_W) Execute(frame *rtda.Frame) {
   
	stack := frame.OperandStack()
	cp := frame.Method().Class().ConstantPool()
	c := cp.GetConstant(self.Index)
	switch c.(type) {
   
	case int64:
		stack.PushLong(c.(int64))
	case 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值