-
Notifications
You must be signed in to change notification settings - Fork 1
/
constant_pool.go
106 lines (86 loc) · 2.94 KB
/
constant_pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package bytecode
import (
"fmt"
"reflect"
)
type ConstantPool struct {
buffer *Buffer
lastIndex uint16
cache map[string]uint16
}
func CreateConstantInfo() *ConstantPool {
return &ConstantPool{
buffer: CreateBuffer(),
lastIndex: 0,
cache: make(map[string]uint16, 0),
}
}
func (constPool *ConstantPool) AddAuto(data interface{}) uint16 {
switch value := data.(type) {
case int8:
return constPool.AddNumber(int(value))
case int16:
return constPool.AddNumber(int(value))
case int32:
return constPool.AddNumber(int(value))
case int:
return constPool.AddNumber(value)
case int64:
return constPool.AddLong(value)
case float32:
return constPool.AddFloat(value)
case float64:
return constPool.AddDouble(value)
case string:
return constPool.AddString(value)
}
panic("Can't add unknown type to const pool: " + reflect.TypeOf(data).Name())
}
func (constPool *ConstantPool) AddNumber(value int) uint16 {
return constPool.AddConst(Constant_Integer, int32(value))
}
func (constPool *ConstantPool) AddFloat(value float32) uint16 {
return constPool.AddConst(Constant_Float, value)
}
func (constPool *ConstantPool) AddDouble(value float64) uint16 {
return constPool.AddConst(Constant_Double, value)
}
func (constPool *ConstantPool) AddLong(value int64) uint16 {
return constPool.AddConst(Constant_Long, value)
}
func (constPool *ConstantPool) AddUtf8(value string) uint16 {
return constPool.AddConst(Constant_Utf8, uint16(len(value)), []byte(value))
}
func (constPool *ConstantPool) AddString(value string) uint16 {
return constPool.AddConst(Constant_String, constPool.AddUtf8(value))
}
func (constPool *ConstantPool) AddClass(name string) uint16 {
return constPool.AddConst(Constant_Class, constPool.AddUtf8(name))
}
func (constPool *ConstantPool) AddNameAndType(name string, descriptor string) uint16 {
return constPool.AddConst(Constant_NameAndType, constPool.AddUtf8(name), constPool.AddUtf8(descriptor))
}
func (constPool *ConstantPool) AddFieldRef(class string, name string, descriptor string) uint16 {
return constPool.AddConst(Constant_Fieldref, constPool.AddClass(class), constPool.AddNameAndType(name, descriptor))
}
func (constPool *ConstantPool) AddMethodRef(class string, name string, descriptor string) uint16 {
return constPool.AddConst(Constant_Methodref, constPool.AddClass(class), constPool.AddNameAndType(name, descriptor))
}
func (constPool *ConstantPool) AddConst(tag uint8, values ...interface{}) uint16 {
bytes := Parse(tag)
for _, value := range values {
bytes = append(bytes, Parse(value)...)
}
hex := fmt.Sprintf("%x", bytes)
if index, found := constPool.cache[hex]; found {
return index
}
constPool.lastIndex++
constPool.cache[hex] = constPool.lastIndex
constPool.buffer.Write(bytes)
if tag == Constant_Long || tag == Constant_Double {
constPool.lastIndex++ // 8-byte variables takes 2 indexes in Const Pool, but it must return first index
return constPool.lastIndex - 1
}
return constPool.lastIndex
}