Skip to content

Commit 2e4bfa9

Browse files
committed
Use single constant pool reference type for opcode reference
1 parent ffc4b0e commit 2e4bfa9

File tree

6 files changed

+120
-88
lines changed

6 files changed

+120
-88
lines changed

classfile/src/attribute.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use nom::{
1010
};
1111
use nom_derive::{NomBE, Parse};
1212

13-
use crate::{ValueConstant, constant_pool::ConstantPoolItem, opcode::Opcode};
13+
use crate::{ConstantPoolReference, constant_pool::ConstantPoolItem, opcode::Opcode};
1414

1515
pub struct CodeAttributeExceptionTable {
1616
pub start_pc: u16,
@@ -122,7 +122,7 @@ impl LocalVariableTableEntry {
122122
}
123123

124124
pub enum AttributeInfo {
125-
ConstantValue(ValueConstant),
125+
ConstantValue(ConstantPoolReference),
126126
Code(AttributeInfoCode),
127127
StackMap(Vec<u8>), // TODO Older variant of StackMapTable
128128
StackMapTable(Vec<u8>), // TODO
@@ -167,8 +167,8 @@ impl AttributeInfo {
167167
map(be_u16, |x| constant_pool.get(&x).unwrap().utf8())(data)
168168
}
169169

170-
fn parse_constant_value<'a>(data: &'a [u8], constant_pool: &BTreeMap<u16, ConstantPoolItem>) -> IResult<&'a [u8], ValueConstant> {
171-
map(be_u16, |x| ValueConstant::from_constant_pool(constant_pool, x as _))(data)
170+
fn parse_constant_value<'a>(data: &'a [u8], constant_pool: &BTreeMap<u16, ConstantPoolItem>) -> IResult<&'a [u8], ConstantPoolReference> {
171+
map(be_u16, |x| ConstantPoolReference::from_constant_pool(constant_pool, x as _))(data)
172172
}
173173

174174
fn parse_local_variable_table<'a>(

classfile/src/constant_pool.rs

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub enum ConstantPoolItem {
3434
#[nom(Selector = "10")]
3535
Methodref { class_index: u16, name_and_type_index: u16 },
3636
#[nom(Selector = "11")]
37-
InstanceMethodref { class_index: u16, name_and_type_index: u16 },
37+
InterfaceMethodref { class_index: u16, name_and_type_index: u16 },
3838
#[nom(Selector = "12")]
3939
NameAndType { name_index: u16, descriptor_index: u16 },
4040
}
@@ -105,18 +105,19 @@ impl ConstantPoolItem {
105105
}
106106

107107
#[derive(Clone, Debug)]
108-
pub enum ValueConstant {
108+
pub enum ConstantPoolReference {
109109
Integer(i32),
110110
Float(f32),
111111
Long(i64),
112112
Double(f64),
113113
String(Arc<String>),
114114
Class(Arc<String>),
115-
Method(ReferenceConstant),
116-
Field(ReferenceConstant),
115+
Method(FieldMethodref),
116+
InterfaceMethodref(FieldMethodref),
117+
Field(FieldMethodref),
117118
}
118119

119-
impl ValueConstant {
120+
impl ConstantPoolReference {
120121
pub fn from_constant_pool(constant_pool: &BTreeMap<u16, ConstantPoolItem>, index: u16) -> Self {
121122
match &constant_pool.get(&index).unwrap() {
122123
ConstantPoolItem::Integer(x) => Self::Integer(*x),
@@ -129,15 +130,23 @@ impl ValueConstant {
129130
ConstantPoolItem::Methodref {
130131
class_index,
131132
name_and_type_index,
132-
} => Self::Method(ReferenceConstant::from_reference_info(
133+
} => Self::Method(FieldMethodref::from_reference_info(
133134
constant_pool,
134135
*class_index as _,
135136
*name_and_type_index as _,
136137
)),
137138
ConstantPoolItem::Fieldref {
138139
class_index,
139140
name_and_type_index,
140-
} => Self::Field(ReferenceConstant::from_reference_info(
141+
} => Self::Field(FieldMethodref::from_reference_info(
142+
constant_pool,
143+
*class_index as _,
144+
*name_and_type_index as _,
145+
)),
146+
ConstantPoolItem::InterfaceMethodref {
147+
class_index,
148+
name_and_type_index,
149+
} => Self::InterfaceMethodref(FieldMethodref::from_reference_info(
141150
constant_pool,
142151
*class_index as _,
143152
*name_and_type_index as _,
@@ -153,34 +162,40 @@ impl ValueConstant {
153162
panic!("Invalid constant pool item");
154163
}
155164
}
165+
166+
pub fn as_field_ref(&self) -> &FieldMethodref {
167+
if let Self::Field(x) = self {
168+
x
169+
} else {
170+
panic!("Invalid constant pool item");
171+
}
172+
}
173+
174+
pub fn as_method_ref(&self) -> &FieldMethodref {
175+
if let Self::Method(x) = self {
176+
x
177+
} else {
178+
panic!("Invalid constant pool item");
179+
}
180+
}
181+
182+
pub fn as_interface_method_ref(&self) -> &FieldMethodref {
183+
if let Self::InterfaceMethodref(x) = self {
184+
x
185+
} else {
186+
panic!("Invalid constant pool item");
187+
}
188+
}
156189
}
157190

158191
#[derive(Clone, Debug)]
159-
pub struct ReferenceConstant {
192+
pub struct FieldMethodref {
160193
pub class: Arc<String>,
161194
pub name: Arc<String>,
162195
pub descriptor: Arc<String>,
163196
}
164197

165-
impl ReferenceConstant {
166-
pub fn from_constant_pool(constant_pool: &BTreeMap<u16, ConstantPoolItem>, index: u16) -> Self {
167-
match &constant_pool.get(&index).unwrap() {
168-
ConstantPoolItem::Fieldref {
169-
class_index,
170-
name_and_type_index,
171-
} => Self::from_reference_info(constant_pool, *class_index, *name_and_type_index),
172-
ConstantPoolItem::Methodref {
173-
class_index,
174-
name_and_type_index,
175-
} => Self::from_reference_info(constant_pool, *class_index, *name_and_type_index),
176-
ConstantPoolItem::InstanceMethodref {
177-
class_index,
178-
name_and_type_index,
179-
} => Self::from_reference_info(constant_pool, *class_index, *name_and_type_index),
180-
_ => panic!("Invalid constant pool item {:?}", constant_pool.get(&index).unwrap()),
181-
}
182-
}
183-
198+
impl FieldMethodref {
184199
pub fn from_reference_info(constant_pool: &BTreeMap<u16, ConstantPoolItem>, class_index: u16, name_and_type_index: u16) -> Self {
185200
let class_name_index = constant_pool.get(&class_index).unwrap().class_name_index();
186201
let class_name = constant_pool.get(&class_name_index).unwrap().utf8();

classfile/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod opcode;
1212
pub use {
1313
attribute::{AttributeInfo, AttributeInfoCode},
1414
class::ClassInfo,
15-
constant_pool::{ReferenceConstant, ValueConstant},
15+
constant_pool::{ConstantPoolReference, FieldMethodref},
1616
field::FieldInfo,
1717
method::MethodInfo,
1818
opcode::Opcode,

classfile/src/opcode.rs

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ use nom::{
99
sequence::tuple,
1010
};
1111

12-
use crate::constant_pool::{ConstantPoolItem, ReferenceConstant, ValueConstant};
12+
use crate::constant_pool::{ConstantPoolItem, ConstantPoolReference};
1313

1414
#[derive(Clone, Debug)]
1515
pub enum Opcode {
1616
Aaload,
1717
Aastore,
1818
AconstNull,
1919
Aload(u8),
20-
Anewarray(ValueConstant),
20+
Anewarray(ConstantPoolReference),
2121
Areturn,
2222
Arraylength,
2323
Astore(u8),
@@ -27,7 +27,7 @@ pub enum Opcode {
2727
Bipush(i8),
2828
Caload,
2929
Castore,
30-
Checkcast(ValueConstant),
30+
Checkcast(ConstantPoolReference),
3131
D2f,
3232
D2i,
3333
D2l,
@@ -68,8 +68,8 @@ pub enum Opcode {
6868
Freturn,
6969
Fstore(u8),
7070
Fsub,
71-
Getfield(ReferenceConstant),
72-
Getstatic(ReferenceConstant),
71+
Getfield(ConstantPoolReference),
72+
Getstatic(ConstantPoolReference),
7373
Goto(i16),
7474
GotoW(i32),
7575
I2b,
@@ -104,12 +104,12 @@ pub enum Opcode {
104104
Iload(u8),
105105
Imul,
106106
Ineg,
107-
Instanceof(ValueConstant),
108-
Invokedynamic(ReferenceConstant),
109-
Invokeinterface(ReferenceConstant, u8, u8),
110-
Invokespecial(ReferenceConstant),
111-
Invokestatic(ReferenceConstant),
112-
Invokevirtual(ReferenceConstant),
107+
Instanceof(ConstantPoolReference),
108+
Invokedynamic(ConstantPoolReference),
109+
Invokeinterface(ConstantPoolReference, u8, u8),
110+
Invokespecial(ConstantPoolReference),
111+
Invokestatic(ConstantPoolReference),
112+
Invokevirtual(ConstantPoolReference),
113113
Ior,
114114
Irem,
115115
Ireturn,
@@ -130,9 +130,9 @@ pub enum Opcode {
130130
Lastore,
131131
Lcmp,
132132
Lconst(u8),
133-
Ldc(ValueConstant),
134-
LdcW(ValueConstant),
135-
Ldc2W(ValueConstant),
133+
Ldc(ConstantPoolReference),
134+
LdcW(ConstantPoolReference),
135+
Ldc2W(ConstantPoolReference),
136136
Ldiv,
137137
Lload(u8),
138138
Lmul,
@@ -149,14 +149,14 @@ pub enum Opcode {
149149
Lxor,
150150
Monitorenter,
151151
Monitorexit,
152-
Multianewarray(ValueConstant, u8),
153-
New(ValueConstant),
152+
Multianewarray(ConstantPoolReference, u8),
153+
New(ConstantPoolReference),
154154
Newarray(u8),
155155
Nop,
156156
Pop,
157157
Pop2,
158-
Putfield(ReferenceConstant),
159-
Putstatic(ReferenceConstant),
158+
Putfield(ConstantPoolReference),
159+
Putstatic(ConstantPoolReference),
160160
Ret(u8),
161161
Return,
162162
Saload,
@@ -182,7 +182,9 @@ impl Opcode {
182182
0x2b => success(Opcode::Aload(1))(data),
183183
0x2c => success(Opcode::Aload(2))(data),
184184
0x2d => success(Opcode::Aload(3))(data),
185-
0xbd => map(be_u16, |x| Opcode::Anewarray(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
185+
0xbd => map(be_u16, |x| {
186+
Opcode::Anewarray(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
187+
})(data),
186188
0xb0 => success(Opcode::Areturn)(data),
187189
0xbe => success(Opcode::Arraylength)(data),
188190
0x3a => map(u8, Opcode::Astore)(data),
@@ -196,7 +198,9 @@ impl Opcode {
196198
0x10 => map(i8, Opcode::Bipush)(data),
197199
0x34 => success(Opcode::Caload)(data),
198200
0x55 => success(Opcode::Castore)(data),
199-
0xc0 => map(be_u16, |x| Opcode::Checkcast(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
201+
0xc0 => map(be_u16, |x| {
202+
Opcode::Checkcast(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
203+
})(data),
200204
0x90 => success(Opcode::D2f)(data),
201205
0x8e => success(Opcode::D2i)(data),
202206
0x8f => success(Opcode::D2l)(data),
@@ -256,9 +260,11 @@ impl Opcode {
256260
0x45 => success(Opcode::Fstore(2))(data),
257261
0x46 => success(Opcode::Fstore(3))(data),
258262
0x66 => success(Opcode::Fsub)(data),
259-
0xb4 => map(be_u16, |x| Opcode::Getfield(ReferenceConstant::from_constant_pool(constant_pool, x as _)))(data),
263+
0xb4 => map(be_u16, |x| {
264+
Opcode::Getfield(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
265+
})(data),
260266
0xb2 => map(be_u16, |x| {
261-
Opcode::Getstatic(ReferenceConstant::from_constant_pool(constant_pool, x as _))
267+
Opcode::Getstatic(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
262268
})(data),
263269
0xa7 => map(be_i16, Opcode::Goto)(data),
264270
0xc8 => map(be_i32, Opcode::GotoW)(data),
@@ -304,21 +310,23 @@ impl Opcode {
304310
0x1d => success(Opcode::Iload(3))(data),
305311
0x68 => success(Opcode::Imul)(data),
306312
0x74 => success(Opcode::Ineg)(data),
307-
0xc1 => map(be_u16, |x| Opcode::Instanceof(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
313+
0xc1 => map(be_u16, |x| {
314+
Opcode::Instanceof(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
315+
})(data),
308316
0xba => map(be_u16, |x| {
309-
Opcode::Invokedynamic(ReferenceConstant::from_constant_pool(constant_pool, x as _))
317+
Opcode::Invokedynamic(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
310318
})(data),
311319
0xb9 => map(be_u16, |x| {
312-
Opcode::Invokeinterface(ReferenceConstant::from_constant_pool(constant_pool, x as _), 0, 0)
320+
Opcode::Invokeinterface(ConstantPoolReference::from_constant_pool(constant_pool, x as _), 0, 0)
313321
})(data),
314322
0xb7 => map(be_u16, |x| {
315-
Opcode::Invokespecial(ReferenceConstant::from_constant_pool(constant_pool, x as _))
323+
Opcode::Invokespecial(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
316324
})(data),
317325
0xb8 => map(be_u16, |x| {
318-
Opcode::Invokestatic(ReferenceConstant::from_constant_pool(constant_pool, x as _))
326+
Opcode::Invokestatic(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
319327
})(data),
320328
0xb6 => map(be_u16, |x| {
321-
Opcode::Invokevirtual(ReferenceConstant::from_constant_pool(constant_pool, x as _))
329+
Opcode::Invokevirtual(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
322330
})(data),
323331
0x80 => success(Opcode::Ior)(data),
324332
0x70 => success(Opcode::Irem)(data),
@@ -345,9 +353,11 @@ impl Opcode {
345353
0x94 => success(Opcode::Lcmp)(data),
346354
0x09 => success(Opcode::Lconst(0))(data),
347355
0x0a => success(Opcode::Lconst(1))(data),
348-
0x12 => map(u8, |x| Opcode::Ldc(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
349-
0x13 => map(be_u16, |x| Opcode::LdcW(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
350-
0x14 => map(be_u16, |x| Opcode::Ldc2W(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
356+
0x12 => map(u8, |x| Opcode::Ldc(ConstantPoolReference::from_constant_pool(constant_pool, x as _)))(data),
357+
0x13 => map(be_u16, |x| Opcode::LdcW(ConstantPoolReference::from_constant_pool(constant_pool, x as _)))(data),
358+
0x14 => map(be_u16, |x| {
359+
Opcode::Ldc2W(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
360+
})(data),
351361
0x6d => success(Opcode::Ldiv)(data),
352362
0x16 => map(u8, Opcode::Lload)(data),
353363
0x1e => success(Opcode::Lload(0))(data),
@@ -379,16 +389,18 @@ impl Opcode {
379389
0xc2 => success(Opcode::Monitorenter)(data),
380390
0xc3 => success(Opcode::Monitorexit)(data),
381391
0xc5 => map(tuple((be_u16, u8)), |(index, dimensions)| {
382-
Opcode::Multianewarray(ValueConstant::from_constant_pool(constant_pool, index as _), dimensions)
392+
Opcode::Multianewarray(ConstantPoolReference::from_constant_pool(constant_pool, index as _), dimensions)
383393
})(data),
384-
0xbb => map(be_u16, |x| Opcode::New(ValueConstant::from_constant_pool(constant_pool, x as _)))(data),
394+
0xbb => map(be_u16, |x| Opcode::New(ConstantPoolReference::from_constant_pool(constant_pool, x as _)))(data),
385395
0xbc => map(u8, Opcode::Newarray)(data),
386396
0x00 => success(Opcode::Nop)(data),
387397
0x57 => success(Opcode::Pop)(data),
388398
0x58 => success(Opcode::Pop2)(data),
389-
0xb5 => map(be_u16, |x| Opcode::Putfield(ReferenceConstant::from_constant_pool(constant_pool, x as _)))(data),
399+
0xb5 => map(be_u16, |x| {
400+
Opcode::Putfield(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
401+
})(data),
390402
0xb3 => map(be_u16, |x| {
391-
Opcode::Putstatic(ReferenceConstant::from_constant_pool(constant_pool, x as _))
403+
Opcode::Putstatic(ConstantPoolReference::from_constant_pool(constant_pool, x as _))
392404
})(data),
393405
0xa9 => map(u8, Opcode::Ret)(data),
394406
0xb1 => success(Opcode::Return)(data),

classfile/tests/test.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use java_constants::ClassAccessFlags;
22

3-
use classfile::{AttributeInfo, ClassInfo, Opcode, ValueConstant};
3+
use classfile::{AttributeInfo, ClassInfo, ConstantPoolReference, Opcode};
44

55
#[test]
66
fn test_hello() {
@@ -26,9 +26,9 @@ fn test_hello() {
2626
if let AttributeInfo::Code(x) = &class.methods[0].attributes[0] {
2727
assert_eq!(x.code.len(), 3);
2828
assert!(matches!(x.code.get(&0).unwrap(), Opcode::Aload(0)));
29-
assert!(
30-
matches!(x.code.get(&1).unwrap(), Opcode::Invokespecial(x) if x.class == "java/lang/Object".to_string().into() && x.name == "<init>".to_string().into() && x.descriptor == "()V".to_string().into())
31-
);
29+
assert!(matches!(x.code.get(&1).unwrap(),
30+
Opcode::Invokespecial(
31+
ConstantPoolReference::Method(x)) if x.class == "java/lang/Object".to_string().into() && x.name == "<init>".to_string().into() && x.descriptor == "()V".to_string().into()));
3232
assert!(matches!(x.code.get(&4).unwrap(), Opcode::Return));
3333
} else {
3434
panic!("Expected code attribute");
@@ -39,15 +39,12 @@ fn test_hello() {
3939
assert!(matches!(class.methods[1].attributes[0], AttributeInfo::Code { .. }));
4040
if let AttributeInfo::Code(x) = &class.methods[1].attributes[0] {
4141
assert_eq!(x.code.len(), 4);
42-
assert!(
43-
matches!(x.code.get(&0).unwrap(), Opcode::Getstatic(x) if x.class == "java/lang/System".to_string().into() && x.name == "out".to_string().into() && x.descriptor == "Ljava/io/PrintStream;".to_string().into())
44-
);
45-
assert!(
46-
matches!(x.code.get(&3).unwrap(), Opcode::Ldc(x) if matches!(x, ValueConstant::String(y) if *y == "Hello, world!".to_string().into()))
47-
);
48-
assert!(
49-
matches!(x.code.get(&5).unwrap(), Opcode::Invokevirtual(x) if x.class == "java/io/PrintStream".to_string().into() && x.name == "println".to_string().into() && x.descriptor == "(Ljava/lang/String;)V".to_string().into())
50-
);
42+
assert!(matches!(x.code.get(&0).unwrap(),
43+
Opcode::Getstatic(ConstantPoolReference::Field(x)) if x.class == "java/lang/System".to_string().into() && x.name == "out".to_string().into() && x.descriptor == "Ljava/io/PrintStream;".to_string().into()));
44+
assert!(matches!(x.code.get(&3).unwrap(),
45+
Opcode::Ldc(x) if matches!(x, ConstantPoolReference::String(y) if *y == "Hello, world!".to_string().into())));
46+
assert!(matches!(x.code.get(&5).unwrap(),
47+
Opcode::Invokevirtual(ConstantPoolReference::Method(x)) if x.class == "java/io/PrintStream".to_string().into() && x.name == "println".to_string().into() && x.descriptor == "(Ljava/lang/String;)V".to_string().into()));
5148
assert!(matches!(x.code.get(&8).unwrap(), Opcode::Return));
5249
} else {
5350
panic!("Expected code attribute");

0 commit comments

Comments
 (0)