四、运行时数据区

 一、运行时数据区

https://blog.csdn.net/u011464536/article/details/78235438

 

二、实现

在jvmgo文件夹下面创建rtda文件夹,并在里面创建object.go文件

1 package rtda
2 
3 type Object struct {
4     // todo
5 }

 

1、线程

创建thread.go文件

 1 package rtda
 2 
 3 /*
 4 JVM
 5   Thread
 6     pc
 7     Stack
 8       Frame
 9         LocalVars
10         OperandStack
11 */
12 type Thread struct {
13     pc    int // the address of the instruction currently being executed
14     stack *Stack
15     // todo
16 }
17 
18 func NewThread() *Thread {
19     return &Thread{
20         stack: newStack(1024),
21     }
22 }
23 
24 func (self *Thread) PC() int {
25     return self.pc
26 }
27 func (self *Thread) SetPC(pc int) {
28     self.pc = pc
29 }
30 
31 func (self *Thread) PushFrame(frame *Frame) {
32     self.stack.push(frame)
33 }
34 func (self *Thread) PopFrame() *Frame {
35     return self.stack.pop()
36 }
37 
38 func (self *Thread) CurrentFrame() *Frame {
39     return self.stack.top()
40 }

定义了pc和stack字段,stack是Stack结构体的指针。NewThread()创建Thread实例,newStack()创建Stack结构体实例,参数表示要创建的Stack最多容纳多少帧,PushFrame()和PopFrame()方法调用Stack结构体的相应方法。CurrentFrame()方法返回当前帧。

2、java虚拟机栈

创建jvm_stack.go文件

 1 package rtda
 2 
 3 // jvm stack
 4 type Stack struct {
 5     maxSize uint
 6     size    uint
 7     _top    *Frame // stack is implemented as linked list
 8 }
 9 
10 func newStack(maxSize uint) *Stack {
11     return &Stack{
12         maxSize: maxSize,
13     }
14 }
15 
16 func (self *Stack) push(frame *Frame) {
17     if self.size >= self.maxSize {
18         panic("java.lang.StackOverflowError")
19     }
20 
21     if self._top != nil {
22         frame.lower = self._top
23     }
24 
25     self._top = frame
26     self.size++
27 }
28 
29 func (self *Stack) pop() *Frame {
30     if self._top == nil {
31         panic("jvm stack is empty!")
32     }
33 
34     top := self._top
35     self._top = top.lower
36     top.lower = nil
37     self.size--
38 
39     return top
40 }
41 
42 func (self *Stack) top() *Frame {
43     if self._top == nil {
44         panic("jvm stack is empty!")
45     }
46 
47     return self._top
48 }

maxSize保存栈的容量,size是当前大小,_top字段保存栈顶指针。其他函数不做解释。

 

3、帧

建立frame.go文件

 1 package rtda
 2 
 3 // stack frame
 4 type Frame struct {
 5     lower        *Frame // stack is implemented as linked list
 6     localVars    LocalVars
 7     operandStack *OperandStack
 8     // todo
 9 }
10 
11 func NewFrame(maxLocals, maxStack uint) *Frame {
12     return &Frame{
13         localVars:    newLocalVars(maxLocals),
14         operandStack: newOperandStack(maxStack),
15     }
16 }
17 
18 // getters
19 func (self *Frame) LocalVars() LocalVars {
20     return self.localVars
21 }
22 func (self *Frame) OperandStack() *OperandStack {
23     return self.operandStack
24 }

lower用来实现链表数据结构,localVars字段保存局部变量表指针,operandStack字段保存操作数栈指针。

4、局部变量表

创建slot.go文件。

1 package rtda
2 
3 type Slot struct {
4     num int32
5     ref *Object
6 }

num字段存放整数,ref存放引用。

创建local_vars.go文件

 1 package rtda
 2 
 3 import "math"
 4 
 5 type LocalVars []Slot
 6 
 7 func newLocalVars(maxLocals uint) LocalVars {
 8     if maxLocals > 0 {
 9         return make([]Slot, maxLocals)
10     }
11     return nil
12 }
13 
14 func (self LocalVars) SetInt(index uint, val int32) {
15     self[index].num = val
16 }
17 func (self LocalVars) GetInt(index uint) int32 {
18     return self[index].num
19 }
20 
21 func (self LocalVars) SetFloat(index uint, val float32) {
22     bits := math.Float32bits(val)
23     self[index].num = int32(bits)
24 }
25 func (self LocalVars) GetFloat(index uint) float32 {
26     bits := uint32(self[index].num)
27     return math.Float32frombits(bits)
28 }
29 
30 // long consumes two slots
31 func (self LocalVars) SetLong(index uint, val int64) {
32     self[index].num = int32(val)
33     self[index+1].num = int32(val >> 32)
34 }
35 func (self LocalVars) GetLong(index uint) int64 {
36     low := uint32(self[index].num)
37     high := uint32(self[index+1].num)
38     return int64(high)<<32 | int64(low)
39 }
40 
41 // double consumes two slots
42 func (self LocalVars) SetDouble(index uint, val float64) {
43     bits := math.Float64bits(val)
44     self.SetLong(index, int64(bits))
45 }
46 func (self LocalVars) GetDouble(index uint) float64 {
47     bits := uint64(self.GetLong(index))
48     return math.Float64frombits(bits)
49 }
50 
51 func (self LocalVars) SetRef(index uint, ref *Object) {
52     self[index].ref = ref
53 }
54 func (self LocalVars) GetRef(index uint) *Object {
55     return self[index].ref
56 }

对不同的变量有不同的存取方法。

5、操作数栈

与局部变量表的实现方法类似。创建operand_stack.go文件

 1 package rtda
 2 
 3 import "math"
 4 
 5 type OperandStack struct {
 6     size  uint
 7     slots []Slot
 8 }
 9 
10 func newOperandStack(maxStack uint) *OperandStack {
11     if maxStack > 0 {
12         return &OperandStack{
13             slots: make([]Slot, maxStack),
14         }
15     }
16     return nil
17 }
18 
19 func (self *OperandStack) PushInt(val int32) {
20     self.slots[self.size].num = val
21     self.size++
22 }
23 func (self *OperandStack) PopInt() int32 {
24     self.size--
25     return self.slots[self.size].num
26 }
27 
28 func (self *OperandStack) PushFloat(val float32) {
29     bits := math.Float32bits(val)
30     self.slots[self.size].num = int32(bits)
31     self.size++
32 }
33 func (self *OperandStack) PopFloat() float32 {
34     self.size--
35     bits := uint32(self.slots[self.size].num)
36     return math.Float32frombits(bits)
37 }
38 
39 // long consumes two slots
40 func (self *OperandStack) PushLong(val int64) {
41     self.slots[self.size].num = int32(val)
42     self.slots[self.size+1].num = int32(val >> 32)
43     self.size += 2
44 }
45 func (self *OperandStack) PopLong() int64 {
46     self.size -= 2
47     low := uint32(self.slots[self.size].num)
48     high := uint32(self.slots[self.size+1].num)
49     return int64(high)<<32 | int64(low)
50 }
51 
52 // double consumes two slots
53 func (self *OperandStack) PushDouble(val float64) {
54     bits := math.Float64bits(val)
55     self.PushLong(int64(bits))
56 }
57 func (self *OperandStack) PopDouble() float64 {
58     bits := uint64(self.PopLong())
59     return math.Float64frombits(bits)
60 }
61 
62 func (self *OperandStack) PushRef(ref *Object) {
63     self.slots[self.size].ref = ref
64     self.size++
65 }
66 func (self *OperandStack) PopRef() *Object {
67     self.size--
68     ref := self.slots[self.size].ref
69     self.slots[self.size].ref = nil
70     return ref
71 }

三、测试

在main.go中加入import “jvmgo/rtda"

修改startJVM()方法

 1 func startJVM(cmd *Cmd) {
 2     frame := rtda.NewFrame(100, 100)
 3     testLocalVars(frame.LocalVars())
 4     testOperandStack(frame.OperandStack())
 5 }
 6 
 7 func testLocalVars(vars rtda.LocalVars) {
 8     vars.SetInt(0, 100)
 9     vars.SetInt(1, -100)
10     vars.SetLong(2, 2997924580)
11     vars.SetLong(4, -2997924580)
12     vars.SetFloat(6, 3.1415926)
13     vars.SetDouble(7, 2.71828182845)
14     vars.SetRef(9, nil)
15     println(vars.GetInt(0))
16     println(vars.GetInt(1))
17     println(vars.GetLong(2))
18     println(vars.GetLong(4))
19     println(vars.GetFloat(6))
20     println(vars.GetDouble(7))
21     println(vars.GetRef(9))
22 }
23 
24 func testOperandStack(ops *rtda.OperandStack) {
25     ops.PushInt(100)
26     ops.PushInt(-100)
27     ops.PushLong(2997924580)
28     ops.PushLong(-2997924580)
29     ops.PushFloat(3.1415926)
30     ops.PushDouble(2.71828182845)
31     ops.PushRef(nil)
32     println(ops.PopRef())
33     println(ops.PopDouble())
34     println(ops.PopFloat())
35     println(ops.PopLong())
36     println(ops.PopLong())
37     println(ops.PopInt())
38     println(ops.PopInt())
39 }

在命令行窗口执行 go install jvmgo,编译成功后对jvmgo.exe进行测试

PS D:\Program_Files\go\bin> .\jvmgo.exe test
100
-100
2997924580
-2997924580
+3.141593e+000
+2.718282e+000
0x0
0x0
+2.718282e+000
+3.141593e+000
-2997924580
2997924580
-100
100

 

posted @ 2018-08-14 16:13  平心  阅读(253)  评论(0编辑  收藏  举报