classfile: writer honors itf flag for invokestatic on interfaces
This commit is contained in:
parent
5901c9eb69
commit
4b14eeb40f
5 changed files with 123 additions and 10 deletions
|
|
@ -96,8 +96,9 @@ pub(crate) fn convert(
|
|||
owner,
|
||||
name,
|
||||
descriptor,
|
||||
itf,
|
||||
..
|
||||
} => invoke(*kind, owner, name, descriptor, pool)?,
|
||||
} => invoke(*kind, owner, name, descriptor, *itf, pool)?,
|
||||
Insn::InvokeDynamic {
|
||||
name,
|
||||
descriptor,
|
||||
|
|
|
|||
|
|
@ -166,23 +166,28 @@ pub(super) fn convert_op(op: Convert) -> RtInsn {
|
|||
}
|
||||
}
|
||||
|
||||
/// `invoke*` family: the `itf` flag is authoritative (a Static/Special
|
||||
/// call may still target an interface method - `List.of`), so the pool
|
||||
/// entry kind follows it, not the opcode alone.
|
||||
pub(super) fn invoke(
|
||||
kind: InvokeKind,
|
||||
owner: &str,
|
||||
name: &str,
|
||||
descriptor: &str,
|
||||
itf: bool,
|
||||
pool: &mut Pool,
|
||||
) -> Result<RtInsn, ClassfileError> {
|
||||
let itf = itf || matches!(kind, InvokeKind::Interface);
|
||||
Ok(match kind {
|
||||
InvokeKind::Virtual => {
|
||||
RtInsn::Invokevirtual(pool.method_ref(owner, name, descriptor, kind)?)
|
||||
RtInsn::Invokevirtual(pool.method_ref(owner, name, descriptor, itf)?)
|
||||
}
|
||||
InvokeKind::Special => {
|
||||
RtInsn::Invokespecial(pool.method_ref(owner, name, descriptor, kind)?)
|
||||
RtInsn::Invokespecial(pool.method_ref(owner, name, descriptor, itf)?)
|
||||
}
|
||||
InvokeKind::Static => RtInsn::Invokestatic(pool.method_ref(owner, name, descriptor, kind)?),
|
||||
InvokeKind::Static => RtInsn::Invokestatic(pool.method_ref(owner, name, descriptor, itf)?),
|
||||
InvokeKind::Interface => {
|
||||
let index = pool.method_ref(owner, name, descriptor, kind)?;
|
||||
let index = pool.method_ref(owner, name, descriptor, itf)?;
|
||||
RtInsn::Invokeinterface(index, arg_count(descriptor)?)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
use ristretto_classfile::{Constant, ReferenceKind};
|
||||
|
||||
use crate::error::ClassfileError;
|
||||
use crate::insn::InvokeKind;
|
||||
|
||||
use super::{Pool, write_err};
|
||||
|
||||
|
|
@ -42,9 +41,8 @@ impl Pool {
|
|||
owner: &str,
|
||||
name: &str,
|
||||
descriptor: &str,
|
||||
kind: InvokeKind,
|
||||
itf: bool,
|
||||
) -> Result<u16, ClassfileError> {
|
||||
let itf = matches!(kind, InvokeKind::Interface);
|
||||
let key = (
|
||||
owner.to_string(),
|
||||
name.to_string(),
|
||||
|
|
@ -94,7 +92,7 @@ impl Pool {
|
|||
ClassfileError::Write(format!("некорректный reference_kind {kind}: {e}"))
|
||||
})?;
|
||||
let reference = if itf {
|
||||
self.method_ref(owner, name, descriptor, InvokeKind::Interface)?
|
||||
self.method_ref(owner, name, descriptor, true)?
|
||||
} else if matches!(
|
||||
reference_kind,
|
||||
ReferenceKind::GetField
|
||||
|
|
@ -104,7 +102,7 @@ impl Pool {
|
|||
) {
|
||||
self.field_ref(owner, name, descriptor)?
|
||||
} else {
|
||||
self.method_ref(owner, name, descriptor, InvokeKind::Static)?
|
||||
self.method_ref(owner, name, descriptor, false)?
|
||||
};
|
||||
let index = self
|
||||
.pool
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue