Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Serial-ATA committed Dec 27, 2024
1 parent c525405 commit 9bb456b
Show file tree
Hide file tree
Showing 80 changed files with 2,522 additions and 900 deletions.
8 changes: 5 additions & 3 deletions classfile/src/attribute.rs → classfile/src/attribute/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod resolved;

use common::int_types::{u1, u2};

macro_rules! attribute_getter_methods {
Expand Down Expand Up @@ -145,8 +147,8 @@ impl From<&[u1]> for AttributeTag {
b"PermittedSubclasses" => Self::PermittedSubclasses,
_ => unsafe {
panic!(
"Encountered unknown attribute type: {}",
std::str::from_utf8_unchecked(bytes)
"Encountered unknown attribute type: {:?}",
std::str::from_utf8(bytes)
);
},
}
Expand Down Expand Up @@ -583,7 +585,7 @@ pub enum ElementValueType {
annotation: Annotation,
},
Array {
values: Vec<ElementValueType>
values: Vec<ElementValue>
},
}

Expand Down
134 changes: 134 additions & 0 deletions classfile/src/attribute/resolved.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use super::{Annotation, ElementValue, ElementValuePair, ElementValueTag, ElementValueType};
use crate::constant_pool::ConstantPool;

use common::int_types::{s4, s8, u2};

pub struct ResolvedAnnotation {
pub name: String,
pub element_value_pairs: Vec<ResolvedElementValuePair>,
}

impl ResolvedAnnotation {
pub(crate) fn resolve_from(raw_annotation: &Annotation, constant_pool: &ConstantPool) -> Self {
let name = constant_pool.get_constant_utf8(raw_annotation.type_index);
let element_value_pairs = raw_annotation
.element_value_pairs
.iter()
.map(|pair| ResolvedElementValuePair::resolve_from(pair, constant_pool))
.collect();

Self {
name: String::from_utf8(name.to_vec()).unwrap(),
element_value_pairs,
}
}
}

pub struct ResolvedElementValuePair {
pub element_name: String,
pub value: ResolvedElementValue,
}

impl ResolvedElementValuePair {
fn resolve_from(raw_value_pair: &ElementValuePair, constant_pool: &ConstantPool) -> Self {
let element_name = constant_pool.get_constant_utf8(raw_value_pair.element_name_index);
let value = ResolvedElementValue::resolve_from(&raw_value_pair.value, constant_pool);

Self {
element_name: String::from_utf8(element_name.to_vec()).unwrap(),
value,
}
}
}

pub struct ResolvedElementValue {
pub tag: ElementValueTag,
pub value: ResolvedElementValueType,
}

impl ResolvedElementValue {
fn resolve_from(raw_element_value: &ElementValue, constant_pool: &ConstantPool) -> Self {
let tag = raw_element_value.tag;
let value = match &raw_element_value.ty {
ElementValueType::Byte { const_value_index } => {
ResolvedElementValueType::Byte(constant_pool.get_integer(*const_value_index))
},
ElementValueType::Char { const_value_index } => {
ResolvedElementValueType::Char(constant_pool.get_integer(*const_value_index))
},
ElementValueType::Double { const_value_index } => {
ResolvedElementValueType::Double(constant_pool.get_double(*const_value_index))
},
ElementValueType::Float { const_value_index } => {
ResolvedElementValueType::Float(constant_pool.get_float(*const_value_index))
},
ElementValueType::Int { const_value_index } => {
ResolvedElementValueType::Int(constant_pool.get_integer(*const_value_index))
},
ElementValueType::Long { const_value_index } => {
ResolvedElementValueType::Long(constant_pool.get_long(*const_value_index))
},
ElementValueType::Short { const_value_index } => {
ResolvedElementValueType::Short(constant_pool.get_integer(*const_value_index))
},
ElementValueType::Boolean { const_value_index } => {
ResolvedElementValueType::Boolean(constant_pool.get_integer(*const_value_index))
},

ElementValueType::String { const_value_index } => {
let value = constant_pool.get_constant_utf8(*const_value_index);
ResolvedElementValueType::String(String::from_utf8(value.to_vec()).unwrap())
},
ElementValueType::Enum {
type_name_index,
const_value_index,
} => {
let type_name = constant_pool.get_constant_utf8(*type_name_index);
let const_value = constant_pool.get_constant_utf8(*const_value_index);
ResolvedElementValueType::Enum {
type_name: String::from_utf8(type_name.to_vec()).unwrap(),
const_value: String::from_utf8(const_value.to_vec()).unwrap(),
}
},
ElementValueType::Class { .. } => todo!(),
ElementValueType::Annotation { annotation } => {
let annotation = ResolvedAnnotation::resolve_from(annotation, constant_pool);
ResolvedElementValueType::Annotation { annotation }
},
ElementValueType::Array { values } => {
let values = values
.iter()
.map(|value| ResolvedElementValue::resolve_from(value, constant_pool))
.collect();
ResolvedElementValueType::Array { values }
},
};

Self { tag, value }
}
}

pub enum ResolvedElementValueType {
Byte(s4),
Char(s4),
Double(f64),
Float(f32),
Int(s4),
Long(s8),
Short(s4),
Boolean(s4),
String(String),
Enum {
type_name: String,
const_value: String,
},
Class {
class_info_index: u2,
},
Annotation {
annotation: ResolvedAnnotation,
},
Array {
values: Vec<ResolvedElementValue>,
},
}
4 changes: 2 additions & 2 deletions classfile/src/classfile.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::accessflags::ClassAccessFlags;
use crate::attribute::{Attribute, SourceFile};
use crate::constant_pool::ConstantPoolRef;
use crate::constant_pool::ConstantPool;
use crate::fieldinfo::FieldInfo;
use crate::methodinfo::MethodInfo;
use crate::parse::error::Result;
Expand All @@ -15,7 +15,7 @@ use common::int_types::{u1, u2};
pub struct ClassFile {
pub minor_version: u2,
pub major_version: u2,
pub constant_pool: ConstantPoolRef,
pub constant_pool: ConstantPool,
pub access_flags: ClassAccessFlags,
pub this_class: u2,
pub super_class: u2,
Expand Down
8 changes: 4 additions & 4 deletions classfile/src/constant_pool.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use std::fmt::{Debug, Formatter};
use std::ops::{Deref, Index};
use std::sync::Arc;

use common::int_types::{s4, s8, u1, u2, u4};

// https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-4.html#jvms-4.4

pub type ConstantPoolRef = Arc<ConstantPool>;

// TODO: Need to make a cache so we don't need to keep resolving classes and interning strings

#[derive(PartialEq, Clone)]
Expand All @@ -27,7 +24,10 @@ impl ConstantPool {
self.inner.push(value);
}

// TODO: Should return a Symbol
pub fn into_inner(self) -> Vec<ConstantPoolValueInfo> {
self.inner
}

pub fn get_class_name(&self, idx: u2) -> &[u1] {
let constant = &self[idx];

Expand Down
3 changes: 2 additions & 1 deletion classfile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ mod methodinfo;
pub mod parse;

pub use self::classfile::ClassFile;
pub use attribute::resolved::*;
pub use attribute::{
Annotation, Attribute, AttributeTag, AttributeType, BootstrapMethod, Code, CodeException,
ElementValue, ElementValuePair, ElementValueTag, ElementValueType, InnerClass, LineNumber,
LocalVariable, LocalVariableType, MethodParameter, ModuleExport, ModuleOpen, ModuleProvide,
ModuleRequire, RecordComponentInfo, StackMapFrame, StackMapTable, VerificationTypeInfo,
};
pub use constant_pool::{ConstantPool, ConstantPoolRef, ConstantPoolTag, ConstantPoolValueInfo};
pub use constant_pool::{ConstantPool, ConstantPoolTag, ConstantPoolValueInfo};
pub use fieldinfo::{FieldInfo, FieldType};
pub use methodinfo::{MethodDescriptor, MethodInfo};
pub use parse::error;
32 changes: 18 additions & 14 deletions classfile/src/methodinfo.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::accessflags::MethodAccessFlags;
use crate::attribute::{Attribute, AttributeType, Code, LineNumberTable};
use crate::constant_pool::ConstantPoolRef;
use crate::attribute::resolved::ResolvedAnnotation;
use crate::attribute::{Attribute, AttributeType, Code, LineNumber, LineNumberTable};
use crate::constant_pool::ConstantPool;
use crate::error::ClassFileParseError;
use crate::fieldinfo::FieldType;
use crate::parse::error::Result;
use crate::LineNumber;

use common::int_types::{u1, u2};
use common::traits::JavaReadExt;
Expand Down Expand Up @@ -42,20 +42,24 @@ impl MethodInfo {
None
}

pub fn is_intrinsic_candidate(&self, constant_pool: ConstantPoolRef) -> bool {
const INTRINSIC_CANDIDATE_TYPE: &[u1] = b"Ljdk/internal/vm/annotation/IntrinsicCandidate;";

pub fn runtime_visible_annotations<'a>(
&'a self,
constant_pool: &'a ConstantPool,
) -> Option<impl Iterator<Item = ResolvedAnnotation> + 'a> {
for attr in &self.attributes {
if let Some(anno) = attr.runtime_visible_annotations() {
if anno.annotations.iter().any(|anno| {
constant_pool.get_constant_utf8(anno.type_index) == INTRINSIC_CANDIDATE_TYPE
}) {
return true;
}
}
let Some(raw_annotations) = attr.runtime_visible_annotations() else {
continue;
};

let iter = raw_annotations
.annotations
.iter()
.map(move |anno| ResolvedAnnotation::resolve_from(anno, constant_pool));

return Some(iter);
}

false
None
}
}

Expand Down
2 changes: 1 addition & 1 deletion classfile/src/parse/attributes/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ fn read_element_value_type<R>(reader: &mut R, tag: ElementValueTag, constant_poo
let mut values = Vec::with_capacity(num_values as usize);

for _ in 0..num_values {
values.push(read_element_value_type(reader, tag, constant_pool)?);
values.push(read_elementvalue(reader, constant_pool)?);
}

Ok(ElementValueType::Array { values })
Expand Down
4 changes: 2 additions & 2 deletions classfile/src/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod methodinfo;

use crate::accessflags::ClassAccessFlags;
use crate::classfile::ClassFile;
use crate::constant_pool::{ConstantPool, ConstantPoolRef};
use crate::constant_pool::ConstantPool;
use crate::parse::attributes::Location;
use crate::parse::error::Result;

Expand Down Expand Up @@ -69,7 +69,7 @@ where
Ok(ClassFile {
minor_version,
major_version,
constant_pool: ConstantPoolRef::new(constant_pool),
constant_pool,
access_flags: ClassAccessFlags::from(access_flags),
this_class,
super_class,
Expand Down
1 change: 1 addition & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ pub mod endian;
pub mod error;
pub mod int_types;
pub mod macros;
pub mod sync;
pub mod traits;
19 changes: 19 additions & 0 deletions common/src/sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use std::ops::Deref;

pub struct ForceSync<T>(pub T);

unsafe impl<T> Sync for ForceSync<T> {}

impl<T> ForceSync<T> {
pub const fn new(value: T) -> Self {
ForceSync(value)
}
}

impl<T> Deref for ForceSync<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}
27 changes: 26 additions & 1 deletion jni/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::error::{JniError, Result};
use crate::objects::{JClass, JMethodId, JObject, JObjectArray, JString, JValue};
use crate::string::JCesu8String;
use crate::version::JniVersion;
use jni_sys::jsize;
use jni_sys::{jsize, JNI_TRUE};

/// Safer wrapper around `jni_sys::JNIEnv`
#[repr(transparent)]
Expand Down Expand Up @@ -71,6 +71,31 @@ impl JniEnv {
Ok(unsafe { JClass::from_raw(ret) })
}

/// Determines whether an object of `sub` can be safely cast to `sup`.
///
/// ## PARAMETERS
///
/// `sub`: the first class argument.
///
/// `sup`: the second class argument.
///
/// ## RETURNS
///
/// Returns `true` if any of the following are true:
///
/// * `sub` and `sup` refer to the same Java class.
/// * `sub` is a subclass of `sup`.
/// * `sub` has `sup` as one of its interfaces.
pub fn is_assignable_from(&self, sub: JClass, sup: JClass) -> bool {
let ret;
unsafe {
let invoke_interface = self.as_native_interface();
ret = ((*invoke_interface).IsAssignableFrom)(self.0 as _, sub.raw(), sup.raw());
}

ret == JNI_TRUE
}

/// Returns the method ID for a static method of a class.
///
/// # Parameters
Expand Down
6 changes: 6 additions & 0 deletions platform/src/family/unix/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::fs::File;
use std::os::unix::fs::FileExt;

pub fn write_at(file: &mut File, content: &[u8], offset: u64) -> std::io::Result<usize> {
file.write_at(content, offset)
}
1 change: 1 addition & 0 deletions platform/src/family/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ match_cfg_meta! {

// Exports

pub mod io;
pub mod properties;
pub(super) mod signals;
6 changes: 6 additions & 0 deletions platform/src/family/windows/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::fs::File;
use std::os::windows::fs::FileExt;

pub fn write_at(file: &mut File, content: &[u8], offset: u64) -> std::io::Result<usize> {
file.seek_write(content, offset)
}
1 change: 1 addition & 0 deletions platform/src/family/windows/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod io;
pub mod properties;
pub(super) mod signals;
Loading

0 comments on commit 9bb456b

Please sign in to comment.