@@ -3,18 +3,24 @@ package main
3
3
import (
4
4
"fmt"
5
5
"os"
6
- "strings"
7
6
)
8
7
9
8
type Frame struct {
10
- operandStack []interface {}
9
+ stack []interface {}
11
10
localVariables []interface {} // function parameters basically
12
11
code []byte
13
12
instructionPointer uint32
14
- class Class
13
+ class * Class
15
14
}
16
15
17
- func (frame * Frame ) Exec () interface {} {
16
+ func (frame * Frame ) getIndex () u2 {
17
+ indexByte1 := frame .code [frame .instructionPointer + 1 ]
18
+ indexByte2 := frame .code [frame .instructionPointer + 2 ]
19
+ frame .instructionPointer = frame .instructionPointer + 2
20
+ return (u2 (indexByte1 ) << 8 ) | u2 (indexByte2 )
21
+ }
22
+
23
+ func (jvm * JVM ) Exec (frame * Frame ) interface {} {
18
24
19
25
for {
20
26
op := frame .code [frame .instructionPointer ]
@@ -23,52 +29,52 @@ func (frame *Frame) Exec() interface{} {
23
29
case 0 : // noop
24
30
25
31
case 4 : // iconst_1
26
- frame .operandStack = append (frame .operandStack , 1 )
32
+ frame .stack = append (frame .stack , 1 )
27
33
case 5 : // iconst_2
28
- frame .operandStack = append (frame .operandStack , 2 )
34
+ frame .stack = append (frame .stack , 2 )
29
35
case 6 : // iconst_3
30
- frame .operandStack = append (frame .operandStack , 3 )
36
+ frame .stack = append (frame .stack , 3 )
31
37
case 7 : // iconst_4
32
- frame .operandStack = append (frame .operandStack , 4 )
38
+ frame .stack = append (frame .stack , 4 )
33
39
case 17 : // sipush
34
40
case 26 : // iload_0
35
- frame .operandStack = append (frame .operandStack , frame .localVariables [0 ])
41
+ frame .stack = append (frame .stack , frame .localVariables [0 ])
36
42
case 27 : // iload_1
37
- frame .operandStack = append (frame .operandStack , frame .localVariables [1 ])
43
+ frame .stack = append (frame .stack , frame .localVariables [1 ])
38
44
case 42 : // aload0
39
- frame .operandStack = append (frame .operandStack , frame .localVariables [0 ])
45
+ frame .stack = append (frame .stack , frame .localVariables [0 ])
40
46
case 43 : // aload1
41
- frame .operandStack = append (frame .operandStack , frame .localVariables [1 ])
47
+ frame .stack = append (frame .stack , frame .localVariables [1 ])
42
48
case 60 : // istore_1
43
- last := frame .operandStack [len (frame .operandStack )- 1 ].(int )
44
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
49
+ last := frame .stack [len (frame .stack )- 1 ].(int )
50
+ frame .stack = frame .stack [:len (frame .stack )- 1 ]
45
51
frame .localVariables [1 ] = last
46
52
case 61 : // istore2
47
- last := frame .operandStack [len (frame .operandStack )- 1 ].(int )
48
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
53
+ last := frame .stack [len (frame .stack )- 1 ].(int )
54
+ frame .stack = frame .stack [:len (frame .stack )- 1 ]
49
55
frame .localVariables [2 ] = last
50
56
case 76 : // astore_1
51
- last := frame .operandStack [len (frame .operandStack )- 1 ]
52
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
57
+ last := frame .stack [len (frame .stack )- 1 ]
58
+ frame .stack = frame .stack [:len (frame .stack )- 1 ]
53
59
frame .localVariables [1 ] = last
54
60
case 87 : // pop
55
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
61
+ frame .stack = frame .stack [:len (frame .stack )- 1 ]
56
62
case 89 : // dup
57
- last := frame .operandStack [len (frame .operandStack )- 1 ]
58
- frame .operandStack = append (frame .operandStack , last )
63
+ last := frame .stack [len (frame .stack )- 1 ]
64
+ frame .stack = append (frame .stack , last )
59
65
case 96 : // iadd
60
- first := frame .operandStack [len (frame .operandStack )- 1 ].(int )
61
- second := frame .operandStack [len (frame .operandStack )- 2 ].(int )
62
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 2 ]
63
- frame .operandStack = append (frame .operandStack , first + second )
66
+ first := frame .stack [len (frame .stack )- 1 ].(int )
67
+ second := frame .stack [len (frame .stack )- 2 ].(int )
68
+ frame .stack = frame .stack [:len (frame .stack )- 2 ]
69
+ frame .stack = append (frame .stack , first + second )
64
70
case 104 : // imul
65
71
first := frame .pop ().(int )
66
72
second := frame .pop ().(int )
67
- frame .operandStack = append (frame .operandStack , first * second )
73
+ frame .stack = append (frame .stack , first * second )
68
74
case 172 : // ireturn
69
- return nil
75
+ return frame . pop ()
70
76
case 177 : // return
71
- frame .operandStack = append (frame .operandStack , nil )
77
+ frame .stack = append (frame .stack , nil )
72
78
return nil
73
79
case 180 : // getField
74
80
frame .instructionPointer ++
@@ -77,10 +83,10 @@ func (frame *Frame) Exec() interface{} {
77
83
indexByte2 := frame .code [frame .instructionPointer ]
78
84
_ = (indexByte1 << 8 ) | indexByte2
79
85
80
- objectRef := frame .pop ().(Class )
86
+ objectRef := frame .pop ().(* Class )
81
87
frame .push (objectRef .fields [0 ].value )
82
- //frame.operandStack = frame.operandStack [:len(frame.operandStack )-1]
83
- //frame.operandStack = append(frame.operandStack , frame.class.constantPool.resolveFieldRef(u2(fieldRefIndex)))
88
+ //frame.stack = frame.stack [:len(frame.stack )-1]
89
+ //frame.stack = append(frame.stack , frame.class.constantPool.resolveFieldRef(u2(fieldRefIndex)))
84
90
case 181 : // putField
85
91
frame .instructionPointer ++
86
92
indexByte1 := frame .code [frame .instructionPointer ]
@@ -89,85 +95,45 @@ func (frame *Frame) Exec() interface{} {
89
95
_ = (indexByte1 << 8 ) | indexByte2
90
96
91
97
value := frame .pop ().(int )
92
- objectRef := frame .pop ().(Class )
98
+ objectRef := frame .pop ().(* Class )
93
99
94
100
objectRef .fields [0 ].value = value
95
- case 182 , 183 : // invokespecial
96
- frame .instructionPointer ++
97
- indexByte1 := frame .code [frame .instructionPointer ]
98
- frame .instructionPointer ++
99
- indexByte2 := frame .code [frame .instructionPointer ]
100
- methodRefIndex := (indexByte1 << 8 ) | indexByte2
101
-
102
- resolved := frame .class .constantPool .resolveMethodRef (u2 (methodRefIndex ))
103
-
104
- // now we need to execute this again
105
- var method Method
106
- if resolved .class == frame .class .name {
107
- method = frame .class .findMethod (resolved .name )
108
-
109
- start := strings .Index (resolved .methodType , "(" )
110
- end := strings .Index (resolved .methodType , ")" )
111
- params := resolved .methodType [start + 1 : end ]
112
- returnTypes := resolved .methodType [end + 1 :]
113
-
114
- methodCodeAttribute := method .findCodeAttribute ()
115
- args := make ([]interface {}, 0 )
116
- for _ = range len (params ) {
117
- arg := frame .operandStack [len (frame .operandStack )- 1 ]
118
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
119
- args = append (args , arg )
120
- }
121
- objectRef := frame .operandStack [len (frame .operandStack )- 1 ]
122
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
123
- args = append ([]interface {}{objectRef .(Class )}, args ... )
124
-
125
- methodFrame := methodCodeAttribute .toFrame (objectRef .(Class ), args ... )
126
- methodFrame .Exec ()
127
-
128
- if len (returnTypes ) != 0 && returnTypes != "V" {
129
- frame .operandStack = append (frame .operandStack , methodFrame .operandStack [len (methodFrame .operandStack )- 1 ])
130
- }
131
-
132
- } else if resolved .class == "java/lang/Object" {
133
- } else {
134
- panic ("we do not know this class" )
101
+ case 182 , 183 : // invokespecial, invokeVirtual
102
+ methodRefIndex := frame .getIndex ()
103
+ methodRef := frame .class .constantPool .resolveMethodRef (methodRefIndex )
104
+
105
+ methodDescriptorDetailed , _ := findMethodDescriptorDetailed (methodRef .descriptor )
106
+ params , returnType := methodDescriptorDetailed .params , methodDescriptorDetailed .returnType
107
+ args := frame .stack [len (frame .stack )- len (params )- 1 :]
108
+ frame .stack = frame .stack [:len (frame .stack )- len (params )- 1 ]
109
+
110
+ result , err := jvm .executeMethod (methodRef .class , methodRef .name , methodRef .descriptor , args ... )
111
+ if err != nil {
112
+ return nil
135
113
}
136
114
137
- fmt .Printf ("%d" , methodRefIndex )
115
+ if len (returnType ) != 0 && returnType != "V" {
116
+ frame .stack = append (frame .stack , result )
117
+ }
138
118
139
119
case 184 : // (0xb8) invokestatic
140
- frame .instructionPointer ++
141
- indexByte1 := frame .code [frame .instructionPointer ]
142
- frame .instructionPointer ++
143
- indexByte2 := frame .code [frame .instructionPointer ]
144
- methodRefIndex := (indexByte1 << 8 ) | indexByte2
120
+ methodRefIndex := frame .getIndex ()
121
+ methodRef := frame .class .constantPool .resolveMethodRef (methodRefIndex )
145
122
146
- resolved := frame .class .constantPool .resolveMethodRef (u2 (methodRefIndex ))
123
+ methodDescriptorDetailed , _ := findMethodDescriptorDetailed (methodRef .descriptor )
124
+ params , returnType := methodDescriptorDetailed .params , methodDescriptorDetailed .returnType
125
+ args := frame .stack [len (frame .stack )- len (params ):]
126
+ frame .stack = frame .stack [:len (frame .stack )- len (params )]
147
127
148
- // now we need to execute this again
149
- method := frame .class .findMethod (resolved .name )
150
-
151
- // the variables are already on the stack, does the internal stack get passed along????
152
-
153
- start := strings .Index (resolved .methodType , "(" )
154
- end := strings .Index (resolved .methodType , ")" )
155
- params := resolved .methodType [start + 1 : end ]
156
- returnTypes := resolved .methodType [end + 1 :]
157
-
158
- methodCodeAttribute := method .findCodeAttribute ()
159
- args := make ([]interface {}, 0 )
160
- for _ = range len (params ) {
161
- arg := frame .operandStack [len (frame .operandStack )- 1 ]
162
- frame .operandStack = frame .operandStack [:len (frame .operandStack )- 1 ]
163
- args = append (args , arg )
128
+ result , err := jvm .executeMethod (methodRef .class , methodRef .name , methodRef .descriptor , args ... )
129
+ if err != nil {
130
+ return nil
164
131
}
165
- methodFrame := methodCodeAttribute .toFrame (frame .class , args ... )
166
- methodFrame .Exec ()
167
132
168
- if len (returnTypes ) != 0 && returnTypes != "V" {
169
- frame .operandStack = append (frame .operandStack , methodFrame . operandStack [ len ( methodFrame . operandStack ) - 1 ] )
133
+ if len (returnType ) != 0 && returnType != "V" {
134
+ frame .stack = append (frame .stack , result )
170
135
}
136
+
171
137
case 187 : // new
172
138
frame .instructionPointer ++
173
139
indexByte1 := frame .code [frame .instructionPointer ]
@@ -181,7 +147,7 @@ func (frame *Frame) Exec() interface{} {
181
147
loader := & ClassLoader {reader : file }
182
148
183
149
newClass := loader .loadClass ()
184
- frame .operandStack = append (frame .operandStack , newClass )
150
+ frame .stack = append (frame .stack , & newClass )
185
151
186
152
default :
187
153
fmt .Printf ("wooops unimplemented op code %d\n " , op )
0 commit comments