diff --git a/src/Java.Interop/GlobalSuppressions.cs b/src/Java.Interop/GlobalSuppressions.cs index e5cc3b533..e1efbc7da 100644 --- a/src/Java.Interop/GlobalSuppressions.cs +++ b/src/Java.Interop/GlobalSuppressions.cs @@ -19,6 +19,10 @@ // See: 045b8af7, 6a42bb89, f60906cf, e10f7cb0, etc. [assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.Exceptions")] +[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.InstanceFields")] +[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.InstanceMethods")] +[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.StaticFields")] +[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.StaticMethods")] [assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniPeerMembers.JniStaticMethods")] [assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniRuntime.JniMarshalMemberBuilder")] [assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniPeerMembers.JniStaticFields")] diff --git a/src/Java.Interop/Java.Interop.csproj b/src/Java.Interop/Java.Interop.csproj index 1c4f0c681..0b90eb370 100644 --- a/src/Java.Interop/Java.Interop.csproj +++ b/src/Java.Interop/Java.Interop.csproj @@ -29,7 +29,7 @@ $(ToolOutputFullPath) $(ToolOutputFullPath)Java.Interop.xml $(BuildToolOutputFullPath) - 9.0 + 12.0 8.0 $(JICoreLibVersion) true diff --git a/src/Java.Interop/Java.Interop/JniEnvironment.InstanceFields.cs b/src/Java.Interop/Java.Interop/JniEnvironment.InstanceFields.cs new file mode 100644 index 000000000..2245069c3 --- /dev/null +++ b/src/Java.Interop/Java.Interop/JniEnvironment.InstanceFields.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; + +namespace Java.Interop; + +partial class JniEnvironment { + partial class InstanceFields { + public static unsafe JniFieldInfo GetFieldID (JniObjectReference type, ReadOnlySpan name, ReadOnlySpan signature) + { + if (!type.IsValid) + throw new ArgumentException ("Handle must be valid.", "type"); + + IntPtr env = JniEnvironment.EnvironmentPointer; + IntPtr field; + IntPtr thrown; + fixed (void* name_ptr = &MemoryMarshal.GetReference (name)) + fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) { + field = JniNativeMethods.GetFieldID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr); + thrown = JniNativeMethods.ExceptionOccurred (env); + } + + Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown); + if (__e != null) + ExceptionDispatchInfo.Capture (__e).Throw (); + + if (field == IntPtr.Zero) + throw new InvalidOperationException ("Should not be reached; `GetFieldID` should have thrown!"); + +#if DEBUG + return new JniFieldInfo (name.ToString (), signature.ToString (), field, isStatic: false); +#else // DEBUG + return new JniFieldInfo (null!, null!, field, isStatic: false); +#endif // DEBUG + } + } +} diff --git a/src/Java.Interop/Java.Interop/JniEnvironment.InstanceMethods.cs b/src/Java.Interop/Java.Interop/JniEnvironment.InstanceMethods.cs new file mode 100644 index 000000000..e84ce5837 --- /dev/null +++ b/src/Java.Interop/Java.Interop/JniEnvironment.InstanceMethods.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; + +namespace Java.Interop; + +partial class JniEnvironment { + partial class InstanceMethods { + public static unsafe JniMethodInfo GetMethodID (JniObjectReference type, ReadOnlySpan name, ReadOnlySpan signature) + { + if (!type.IsValid) + throw new ArgumentException ("Handle must be valid.", "type"); + + IntPtr env = JniEnvironment.EnvironmentPointer; + IntPtr method; + IntPtr thrown; + fixed (void* name_ptr = &MemoryMarshal.GetReference (name)) + fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) { + method = JniNativeMethods.GetMethodID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr); + thrown = JniNativeMethods.ExceptionOccurred (env); + } + + Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown); + if (__e != null) + ExceptionDispatchInfo.Capture (__e).Throw (); + + if (method == IntPtr.Zero) + throw new InvalidOperationException ("Should not be reached; `GetMethodID` should have thrown!"); + +#if DEBUG + return new JniMethodInfo (name.ToString (), signature.ToString (), method, isStatic: false); +#else // DEBUG + return new JniMethodInfo (null!, null!, method, isStatic: false); +#endif // DEBUG + } + } +} diff --git a/src/Java.Interop/Java.Interop/JniEnvironment.StaticFields.cs b/src/Java.Interop/Java.Interop/JniEnvironment.StaticFields.cs new file mode 100644 index 000000000..0433dec28 --- /dev/null +++ b/src/Java.Interop/Java.Interop/JniEnvironment.StaticFields.cs @@ -0,0 +1,38 @@ +using System; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; + +namespace Java.Interop; + +partial class JniEnvironment { + partial class StaticFields { + + public static unsafe JniFieldInfo GetStaticFieldID (JniObjectReference type, ReadOnlySpan name, ReadOnlySpan signature) + { + if (!type.IsValid) + throw new ArgumentException ("Handle must be valid.", "type"); + + IntPtr env = JniEnvironment.EnvironmentPointer; + IntPtr field; + IntPtr thrown; + fixed (void* name_ptr = &MemoryMarshal.GetReference (name)) + fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) { + field = JniNativeMethods.GetStaticFieldID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr); + thrown = JniNativeMethods.ExceptionOccurred (env); + } + + Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown); + if (__e != null) + ExceptionDispatchInfo.Capture (__e).Throw (); + + if (field == IntPtr.Zero) + throw new InvalidOperationException ("Should not be reached; `GetFieldID` should have thrown!"); + +#if DEBUG + return new JniFieldInfo (name.ToString (), signature.ToString (), field, isStatic: false); +#else // DEBUG + return new JniFieldInfo (null!, null!, field, isStatic: false); +#endif // DEBUG + } + } +} diff --git a/src/Java.Interop/Java.Interop/JniEnvironment.StaticMethods.cs b/src/Java.Interop/Java.Interop/JniEnvironment.StaticMethods.cs new file mode 100644 index 000000000..81ae95628 --- /dev/null +++ b/src/Java.Interop/Java.Interop/JniEnvironment.StaticMethods.cs @@ -0,0 +1,82 @@ +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; + +namespace Java.Interop; + +partial class JniEnvironment { + partial class StaticMethods { + + public static unsafe JniMethodInfo GetStaticMethodID (JniObjectReference type, ReadOnlySpan name, ReadOnlySpan signature) + { + if (!type.IsValid) + throw new ArgumentException ("Handle must be valid.", "type"); + + IntPtr env = JniEnvironment.EnvironmentPointer; + IntPtr method; + IntPtr thrown; + fixed (void* name_ptr = &MemoryMarshal.GetReference (name)) + fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) { + method = JniNativeMethods.GetStaticMethodID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr); + thrown = JniNativeMethods.ExceptionOccurred (env); + } + + Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown); + if (__e != null) + ExceptionDispatchInfo.Capture (__e).Throw (); + + if (method == IntPtr.Zero) + throw new InvalidOperationException ("Should not be reached; `GetStaticMethodID` should have thrown!"); + +#if DEBUG + return new JniMethodInfo (name.ToString (), signature.ToString (), method, isStatic: true); +#else // DEBUG + return new JniMethodInfo (null!, null!, method, isStatic: true); +#endif // DEBUG + } + + internal static unsafe bool TryGetStaticMethod ( + JniObjectReference type, + ReadOnlySpan name, + ReadOnlySpan signature, + [NotNullWhen(true)] + out JniMethodInfo? method) + { + method = null; + + if (!type.IsValid) + throw new ArgumentException ("Handle must be valid.", "type"); + + IntPtr env = JniEnvironment.EnvironmentPointer; + IntPtr id; + IntPtr thrown; + fixed (void* name_ptr = &MemoryMarshal.GetReference (name)) + fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) { + id = JniNativeMethods.GetStaticMethodID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr); + thrown = JniNativeMethods.ExceptionOccurred (env); + } + + if (thrown != IntPtr.Zero) { + JniNativeMethods.ExceptionClear (env); + JniEnvironment.References.RawDeleteLocalRef (env, thrown); + thrown = IntPtr.Zero; + return false; + } + + Debug.Assert (id != IntPtr.Zero); + if (id == IntPtr.Zero) { + return false; + } + +#if DEBUG + method = new JniMethodInfo (name.ToString (), signature.ToString (), id, isStatic: true); +#else // DEBUG + method = new JniMethodInfo (null!, null!, id, isStatic: true); +#endif // DEBUG + + return true; + } + } +} diff --git a/src/Java.Interop/Java.Interop/JniMemberInfoLookup.cs b/src/Java.Interop/Java.Interop/JniMemberInfoLookup.cs new file mode 100644 index 000000000..d0582c2a1 --- /dev/null +++ b/src/Java.Interop/Java.Interop/JniMemberInfoLookup.cs @@ -0,0 +1,22 @@ +using System; + +namespace Java.Interop; + +public ref struct JniMemberInfoLookup { + public string EncodedMember {get; private set;} + public ReadOnlySpan MemberName {get; private set;} + public ReadOnlySpan MemberSignature {get; private set;} + + [Obsolete ("Use the JniMemberInfoLookup(string, ReadOnlySpan, ReadOnlySpan) constructor.", error: true)] + public JniMemberInfoLookup () + { + throw new NotSupportedException (); + } + + public JniMemberInfoLookup (string encodedMember, ReadOnlySpan memberName, ReadOnlySpan memberSignature) + { + EncodedMember = encodedMember; + MemberName = memberName; + MemberSignature = memberSignature; + } +} diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.cs b/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.cs index ea9d0cb51..2eea2cc04 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.cs +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; @@ -28,6 +28,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, bool value) GC.KeepAlive (self); } + public bool GetBooleanValue ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetBooleanField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, bool value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetBooleanField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public sbyte GetSByteValue ( string encodedMember, IJavaPeerable self) @@ -49,6 +70,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, sbyte value) GC.KeepAlive (self); } + public sbyte GetSByteValue ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetByteField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, sbyte value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetByteField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public char GetCharValue ( string encodedMember, IJavaPeerable self) @@ -70,6 +112,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, char value) GC.KeepAlive (self); } + public char GetCharValue ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetCharField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, char value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetCharField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public short GetInt16Value ( string encodedMember, IJavaPeerable self) @@ -91,6 +154,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, short value) GC.KeepAlive (self); } + public short GetInt16Value ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetShortField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, short value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetShortField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public int GetInt32Value ( string encodedMember, IJavaPeerable self) @@ -112,6 +196,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, int value) GC.KeepAlive (self); } + public int GetInt32Value ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetIntField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, int value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetIntField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public long GetInt64Value ( string encodedMember, IJavaPeerable self) @@ -133,6 +238,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, long value) GC.KeepAlive (self); } + public long GetInt64Value ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetLongField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, long value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetLongField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public float GetSingleValue ( string encodedMember, IJavaPeerable self) @@ -154,6 +280,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, float value) GC.KeepAlive (self); } + public float GetSingleValue ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetFloatField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, float value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetFloatField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public double GetDoubleValue ( string encodedMember, IJavaPeerable self) @@ -175,6 +322,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, double value) GC.KeepAlive (self); } + public double GetDoubleValue ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetDoubleField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, double value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetDoubleField (self.PeerReference, f, value); + GC.KeepAlive (self); + } + public JniObjectReference GetObjectValue ( string encodedMember, IJavaPeerable self) @@ -195,6 +363,27 @@ public void SetValue (string encodedMember, IJavaPeerable self, JniObjectReferen JniEnvironment.InstanceFields.SetObjectField (self.PeerReference, f, value); GC.KeepAlive (self); } + + public JniObjectReference GetObjectValue ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.GetObjectField (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, JniObjectReference value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.SetObjectField (self.PeerReference, f, value); + GC.KeepAlive (self); + } } partial class JniStaticFields { @@ -211,6 +400,18 @@ public void SetValue (string encodedMember, bool value) JniEnvironment.StaticFields.SetStaticBooleanField (Members.JniPeerType.PeerReference, f, value); } + public bool GetBooleanValue (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticBooleanField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, bool value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticBooleanField (Members.JniPeerType.PeerReference, f, value); + } + public sbyte GetSByteValue (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -223,6 +424,18 @@ public void SetValue (string encodedMember, sbyte value) JniEnvironment.StaticFields.SetStaticByteField (Members.JniPeerType.PeerReference, f, value); } + public sbyte GetSByteValue (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticByteField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, sbyte value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticByteField (Members.JniPeerType.PeerReference, f, value); + } + public char GetCharValue (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -235,6 +448,18 @@ public void SetValue (string encodedMember, char value) JniEnvironment.StaticFields.SetStaticCharField (Members.JniPeerType.PeerReference, f, value); } + public char GetCharValue (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticCharField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, char value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticCharField (Members.JniPeerType.PeerReference, f, value); + } + public short GetInt16Value (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -247,6 +472,18 @@ public void SetValue (string encodedMember, short value) JniEnvironment.StaticFields.SetStaticShortField (Members.JniPeerType.PeerReference, f, value); } + public short GetInt16Value (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticShortField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, short value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticShortField (Members.JniPeerType.PeerReference, f, value); + } + public int GetInt32Value (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -259,6 +496,18 @@ public void SetValue (string encodedMember, int value) JniEnvironment.StaticFields.SetStaticIntField (Members.JniPeerType.PeerReference, f, value); } + public int GetInt32Value (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticIntField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, int value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticIntField (Members.JniPeerType.PeerReference, f, value); + } + public long GetInt64Value (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -271,6 +520,18 @@ public void SetValue (string encodedMember, long value) JniEnvironment.StaticFields.SetStaticLongField (Members.JniPeerType.PeerReference, f, value); } + public long GetInt64Value (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticLongField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, long value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticLongField (Members.JniPeerType.PeerReference, f, value); + } + public float GetSingleValue (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -283,6 +544,18 @@ public void SetValue (string encodedMember, float value) JniEnvironment.StaticFields.SetStaticFloatField (Members.JniPeerType.PeerReference, f, value); } + public float GetSingleValue (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticFloatField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, float value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticFloatField (Members.JniPeerType.PeerReference, f, value); + } + public double GetDoubleValue (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -295,6 +568,18 @@ public void SetValue (string encodedMember, double value) JniEnvironment.StaticFields.SetStaticDoubleField (Members.JniPeerType.PeerReference, f, value); } + public double GetDoubleValue (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticDoubleField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, double value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticDoubleField (Members.JniPeerType.PeerReference, f, value); + } + public JniObjectReference GetObjectValue (string encodedMember) { var f = GetFieldInfo (encodedMember); @@ -306,5 +591,17 @@ public void SetValue (string encodedMember, JniObjectReference value) var f = GetFieldInfo (encodedMember); JniEnvironment.StaticFields.SetStaticObjectField (Members.JniPeerType.PeerReference, f, value); } + + public JniObjectReference GetObjectValue (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStaticObjectField (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, JniObjectReference value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStaticObjectField (Members.JniPeerType.PeerReference, f, value); + } }} } diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.tt b/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.tt index f569b372b..3602a74e6 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.tt +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniFields.tt @@ -49,6 +49,27 @@ namespace Java.Interop { JniEnvironment.InstanceFields.Set<#= info.JniCallType #>Field (self.PeerReference, f, value); GC.KeepAlive (self); } + + public <#= info.ReturnType #> Get<#= info.ManagedType #>Value ( + JniMemberInfoLookup member, + IJavaPeerable self) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + var r = JniEnvironment.InstanceFields.Get<#= info.JniCallType #>Field (self.PeerReference, f); + GC.KeepAlive (self); + return r; + } + + public void SetValue (JniMemberInfoLookup member, IJavaPeerable self, <#= info.ParameterType #> value) + { + JniPeerMembers.AssertSelf (self); + + var f = GetFieldInfo (member); + JniEnvironment.InstanceFields.Set<#= info.JniCallType #>Field (self.PeerReference, f, value); + GC.KeepAlive (self); + } <# } #> @@ -70,6 +91,18 @@ namespace Java.Interop { var f = GetFieldInfo (encodedMember); JniEnvironment.StaticFields.SetStatic<#= info.JniCallType #>Field (Members.JniPeerType.PeerReference, f, value); } + + public <#= info.ReturnType #> Get<#= info.ManagedType #>Value (JniMemberInfoLookup member) + { + var f = GetFieldInfo (member); + return JniEnvironment.StaticFields.GetStatic<#= info.JniCallType #>Field (Members.JniPeerType.PeerReference, f); + } + + public void SetValue (JniMemberInfoLookup member, <#= info.ParameterType #> value) + { + var f = GetFieldInfo (member); + JniEnvironment.StaticFields.SetStatic<#= info.JniCallType #>Field (Members.JniPeerType.PeerReference, f, value); + } <# } #> diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceFields.cs b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceFields.cs index e0a5ae40d..48f6f9e16 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceFields.cs +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceFields.cs @@ -34,6 +34,17 @@ public JniFieldInfo GetFieldInfo (string encodedMember) return f; } } + + public JniFieldInfo GetFieldInfo (JniMemberInfoLookup member) + { + lock (InstanceFields) { + if (!InstanceFields.TryGetValue (member.EncodedMember, out var f)) { + f = Members.JniPeerType.GetInstanceField (member.MemberName, member.MemberSignature); + InstanceFields.Add (member.EncodedMember, f); + } + return f; + } + } }} } diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs index 04d96870e..dbf55b000 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods.cs @@ -157,6 +157,48 @@ JniMethodInfo GetMethodInfo (string method, string signature) return JniPeerType.GetInstanceMethod (method, signature); } + + public JniMethodInfo GetMethodInfo (JniMemberInfoLookup member) + { + lock (InstanceMethods) { + if (InstanceMethods.TryGetValue (member.EncodedMember, out var m)) { + return m; + } + } + var info = GetMethodInfo (member.MemberName, member.MemberSignature); + lock (InstanceMethods) { + if (InstanceMethods.TryGetValue (member.EncodedMember, out var m)) { + return m; + } + InstanceMethods.Add (member.EncodedMember, info); + } + return info; + } + + JniMethodInfo GetMethodInfo (ReadOnlySpan method, ReadOnlySpan signature) + { + var m = (JniMethodInfo?) null; + var newMethod = JniEnvironment.Runtime.TypeManager.GetReplacementMethodInfo (Members.JniPeerTypeName, method, signature); + if (newMethod.HasValue) { + var typeName = newMethod.Value.TargetJniType ?? Members.JniPeerTypeName; + var methodName = newMethod.Value.TargetJniMethodName ?? method.ToString (); + var methodSig = newMethod.Value.TargetJniMethodSignature ?? signature.ToString (); + + using var t = new JniType (typeName); + if (newMethod.Value.TargetJniMethodInstanceToStatic && + t.TryGetStaticMethod (methodName, methodSig, out m)) { + m.ParameterCount = newMethod.Value.TargetJniMethodParameterCount; + m.StaticRedirect = new JniType (typeName); + return m; + } + if (t.TryGetInstanceMethod (methodName, methodSig, out m)) { + return m; + } + Console.Error.WriteLine ($"warning: For declared method `{Members.JniPeerTypeName}.{method.ToString ()}.{signature.ToString ()}`, could not find requested method `{typeName}.{methodName}.{methodSig}`!"); + } + return JniPeerType.GetInstanceMethod (method, signature); + } + public unsafe JniObjectReference StartCreateInstance (string constructorSignature, Type declaringType, JniArgumentValue* parameters) { if (constructorSignature == null) diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs index 0e96fa29c..f8a834251 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs @@ -1,7 +1,8 @@ -#nullable enable +#nullable enable using System; using System.Diagnostics; +using System.Runtime.InteropServices; namespace Java.Interop { @@ -52,6 +53,25 @@ public unsafe void InvokeAbstractVoidMethod (string encodedMember, IJavaPeerable } } + public unsafe void InvokeAbstractVoidMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeVoidStaticRedirect (m, self, params_ptr)) { + return; + } + JniEnvironment.InstanceMethods.CallVoidMethod (self.PeerReference, m, params_ptr); + return; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe void InvokeVirtualVoidMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -81,6 +101,37 @@ public unsafe void InvokeVirtualVoidMethod (string encodedMember, IJavaPeerable } } + public unsafe void InvokeVirtualVoidMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeVoidStaticRedirect (m, self, params_ptr)) { + return; + } + JniEnvironment.InstanceMethods.CallVoidMethod (self.PeerReference, m, params_ptr); + return; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeVoidStaticRedirect (n, self, params_ptr)) { + return; + } + JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe void InvokeNonvirtualVoidMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -98,6 +149,25 @@ public unsafe void InvokeNonvirtualVoidMethod (string encodedMember, IJavaPeerab } } + public unsafe void InvokeNonvirtualVoidMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeVoidStaticRedirect (m, self, params_ptr)) { + return; + } + JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeBooleanStaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out bool r) { @@ -141,6 +211,25 @@ public unsafe bool InvokeAbstractBooleanMethod (string encodedMember, IJavaPeera } } + public unsafe bool InvokeAbstractBooleanMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeBooleanStaticRedirect (m, self, params_ptr, out bool r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallBooleanMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe bool InvokeVirtualBooleanMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -170,6 +259,37 @@ public unsafe bool InvokeVirtualBooleanMethod (string encodedMember, IJavaPeerab } } + public unsafe bool InvokeVirtualBooleanMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeBooleanStaticRedirect (m, self, params_ptr, out bool r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallBooleanMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeBooleanStaticRedirect (n, self, params_ptr, out bool r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualBooleanMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe bool InvokeNonvirtualBooleanMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -187,6 +307,25 @@ public unsafe bool InvokeNonvirtualBooleanMethod (string encodedMember, IJavaPee } } + public unsafe bool InvokeNonvirtualBooleanMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeBooleanStaticRedirect (m, self, params_ptr, out bool r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualBooleanMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeSByteStaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out sbyte r) { @@ -230,6 +369,25 @@ public unsafe sbyte InvokeAbstractSByteMethod (string encodedMember, IJavaPeerab } } + public unsafe sbyte InvokeAbstractSByteMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeSByteStaticRedirect (m, self, params_ptr, out sbyte r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallByteMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe sbyte InvokeVirtualSByteMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -259,6 +417,37 @@ public unsafe sbyte InvokeVirtualSByteMethod (string encodedMember, IJavaPeerabl } } + public unsafe sbyte InvokeVirtualSByteMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeSByteStaticRedirect (m, self, params_ptr, out sbyte r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallByteMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeSByteStaticRedirect (n, self, params_ptr, out sbyte r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualByteMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe sbyte InvokeNonvirtualSByteMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -276,6 +465,25 @@ public unsafe sbyte InvokeNonvirtualSByteMethod (string encodedMember, IJavaPeer } } + public unsafe sbyte InvokeNonvirtualSByteMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeSByteStaticRedirect (m, self, params_ptr, out sbyte r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualByteMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeCharStaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out char r) { @@ -319,6 +527,25 @@ public unsafe char InvokeAbstractCharMethod (string encodedMember, IJavaPeerable } } + public unsafe char InvokeAbstractCharMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeCharStaticRedirect (m, self, params_ptr, out char r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallCharMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe char InvokeVirtualCharMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -348,6 +575,37 @@ public unsafe char InvokeVirtualCharMethod (string encodedMember, IJavaPeerable } } + public unsafe char InvokeVirtualCharMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeCharStaticRedirect (m, self, params_ptr, out char r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallCharMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeCharStaticRedirect (n, self, params_ptr, out char r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualCharMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe char InvokeNonvirtualCharMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -365,6 +623,25 @@ public unsafe char InvokeNonvirtualCharMethod (string encodedMember, IJavaPeerab } } + public unsafe char InvokeNonvirtualCharMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeCharStaticRedirect (m, self, params_ptr, out char r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualCharMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeInt16StaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out short r) { @@ -408,6 +685,25 @@ public unsafe short InvokeAbstractInt16Method (string encodedMember, IJavaPeerab } } + public unsafe short InvokeAbstractInt16Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeInt16StaticRedirect (m, self, params_ptr, out short r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallShortMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe short InvokeVirtualInt16Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -437,6 +733,37 @@ public unsafe short InvokeVirtualInt16Method (string encodedMember, IJavaPeerabl } } + public unsafe short InvokeVirtualInt16Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeInt16StaticRedirect (m, self, params_ptr, out short r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallShortMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeInt16StaticRedirect (n, self, params_ptr, out short r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualShortMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe short InvokeNonvirtualInt16Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -454,6 +781,25 @@ public unsafe short InvokeNonvirtualInt16Method (string encodedMember, IJavaPeer } } + public unsafe short InvokeNonvirtualInt16Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeInt16StaticRedirect (m, self, params_ptr, out short r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualShortMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeInt32StaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out int r) { @@ -497,6 +843,25 @@ public unsafe int InvokeAbstractInt32Method (string encodedMember, IJavaPeerable } } + public unsafe int InvokeAbstractInt32Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeInt32StaticRedirect (m, self, params_ptr, out int r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallIntMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe int InvokeVirtualInt32Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -526,6 +891,37 @@ public unsafe int InvokeVirtualInt32Method (string encodedMember, IJavaPeerable } } + public unsafe int InvokeVirtualInt32Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeInt32StaticRedirect (m, self, params_ptr, out int r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallIntMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeInt32StaticRedirect (n, self, params_ptr, out int r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualIntMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe int InvokeNonvirtualInt32Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -543,6 +939,25 @@ public unsafe int InvokeNonvirtualInt32Method (string encodedMember, IJavaPeerab } } + public unsafe int InvokeNonvirtualInt32Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeInt32StaticRedirect (m, self, params_ptr, out int r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualIntMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeInt64StaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out long r) { @@ -586,6 +1001,25 @@ public unsafe long InvokeAbstractInt64Method (string encodedMember, IJavaPeerabl } } + public unsafe long InvokeAbstractInt64Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeInt64StaticRedirect (m, self, params_ptr, out long r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallLongMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe long InvokeVirtualInt64Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -615,6 +1049,37 @@ public unsafe long InvokeVirtualInt64Method (string encodedMember, IJavaPeerable } } + public unsafe long InvokeVirtualInt64Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeInt64StaticRedirect (m, self, params_ptr, out long r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallLongMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeInt64StaticRedirect (n, self, params_ptr, out long r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualLongMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe long InvokeNonvirtualInt64Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -632,6 +1097,25 @@ public unsafe long InvokeNonvirtualInt64Method (string encodedMember, IJavaPeera } } + public unsafe long InvokeNonvirtualInt64Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeInt64StaticRedirect (m, self, params_ptr, out long r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualLongMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeSingleStaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out float r) { @@ -675,6 +1159,25 @@ public unsafe float InvokeAbstractSingleMethod (string encodedMember, IJavaPeera } } + public unsafe float InvokeAbstractSingleMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeSingleStaticRedirect (m, self, params_ptr, out float r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallFloatMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe float InvokeVirtualSingleMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -704,6 +1207,37 @@ public unsafe float InvokeVirtualSingleMethod (string encodedMember, IJavaPeerab } } + public unsafe float InvokeVirtualSingleMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeSingleStaticRedirect (m, self, params_ptr, out float r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallFloatMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeSingleStaticRedirect (n, self, params_ptr, out float r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualFloatMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe float InvokeNonvirtualSingleMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -721,6 +1255,25 @@ public unsafe float InvokeNonvirtualSingleMethod (string encodedMember, IJavaPee } } + public unsafe float InvokeNonvirtualSingleMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeSingleStaticRedirect (m, self, params_ptr, out float r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualFloatMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeDoubleStaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out double r) { @@ -764,6 +1317,25 @@ public unsafe double InvokeAbstractDoubleMethod (string encodedMember, IJavaPeer } } + public unsafe double InvokeAbstractDoubleMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeDoubleStaticRedirect (m, self, params_ptr, out double r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallDoubleMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe double InvokeVirtualDoubleMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -793,6 +1365,37 @@ public unsafe double InvokeVirtualDoubleMethod (string encodedMember, IJavaPeera } } + public unsafe double InvokeVirtualDoubleMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeDoubleStaticRedirect (m, self, params_ptr, out double r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallDoubleMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeDoubleStaticRedirect (n, self, params_ptr, out double r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualDoubleMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe double InvokeNonvirtualDoubleMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -810,6 +1413,25 @@ public unsafe double InvokeNonvirtualDoubleMethod (string encodedMember, IJavaPe } } + public unsafe double InvokeNonvirtualDoubleMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeDoubleStaticRedirect (m, self, params_ptr, out double r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualDoubleMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + #pragma warning disable CA1801 static unsafe bool TryInvokeObjectStaticRedirect (JniMethodInfo method, IJavaPeerable self, JniArgumentValue* parameters, out JniObjectReference r) { @@ -853,6 +1475,25 @@ public unsafe JniObjectReference InvokeAbstractObjectMethod (string encodedMembe } } + public unsafe JniObjectReference InvokeAbstractObjectMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeObjectStaticRedirect (m, self, params_ptr, out JniObjectReference r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallObjectMethod (self.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe JniObjectReference InvokeVirtualObjectMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -882,6 +1523,37 @@ public unsafe JniObjectReference InvokeVirtualObjectMethod (string encodedMember } } + public unsafe JniObjectReference InvokeVirtualObjectMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvokeObjectStaticRedirect (m, self, params_ptr, out JniObjectReference r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallObjectMethod (self.PeerReference, m, params_ptr); + return r; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvokeObjectStaticRedirect (n, self, params_ptr, out JniObjectReference r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualObjectMethod (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + return r; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe JniObjectReference InvokeNonvirtualObjectMethod (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -898,6 +1570,25 @@ public unsafe JniObjectReference InvokeNonvirtualObjectMethod (string encodedMem GC.KeepAlive (self); } } + + public unsafe JniObjectReference InvokeNonvirtualObjectMethod (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvokeObjectStaticRedirect (m, self, params_ptr, out JniObjectReference r)) { + return r; + } + r = JniEnvironment.InstanceMethods.CallNonvirtualObjectMethod (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + return r; + } + } + finally { + GC.KeepAlive (self); + } + } } } } diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt index a326b6b1f..eb25f1b15 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.tt @@ -22,6 +22,7 @@ using System; using System.Diagnostics; +using System.Runtime.InteropServices; namespace Java.Interop { @@ -80,6 +81,25 @@ namespace Java.Interop { } } + public unsafe <#= returnType.ReturnType #> InvokeAbstract<#= returnType.ManagedType #>Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvoke<#= returnType.ManagedType #>StaticRedirect (m, self, params_ptr<#= byRefParamDecl #>)) { + <#= returnByRefParam #>; + } + <#= setByRefParam #>JniEnvironment.InstanceMethods.Call<#= returnType.JniCallType #>Method (self.PeerReference, m, params_ptr); + <#= returnByRefParam #>; + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe <#= returnType.ReturnType #> InvokeVirtual<#= returnType.ManagedType #>Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -109,6 +129,37 @@ namespace Java.Interop { } } + public unsafe <#= returnType.ReturnType #> InvokeVirtual<#= returnType.ManagedType #>Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + try { + var declaringType = DeclaringType; + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (Members.UsesVirtualDispatch (self, declaringType)) { + var m = GetMethodInfo (member); + if (TryInvoke<#= returnType.ManagedType #>StaticRedirect (m, self, params_ptr<#= byRefParamDecl #>)) { + <#= returnByRefParam #>; + } + <#= setByRefParam #>JniEnvironment.InstanceMethods.Call<#= returnType.JniCallType #>Method (self.PeerReference, m, params_ptr); + <#= returnByRefParam #>; + } + var j = Members.GetPeerMembers (self); + var n = j.InstanceMethods.GetMethodInfo (member); + do { + if (TryInvoke<#= returnType.ManagedType #>StaticRedirect (n, self, params_ptr<#= byRefParamDecl #>)) { + <#= returnByRefParam #>; + } + <#= setByRefParam #>JniEnvironment.InstanceMethods.CallNonvirtual<#= returnType.JniCallType #>Method (self.PeerReference, j.JniPeerType.PeerReference, n, params_ptr); + <#= returnByRefParam #>; + } while (false); + } + } + finally { + GC.KeepAlive (self); + } + } + public unsafe <#= returnType.ReturnType #> InvokeNonvirtual<#= returnType.ManagedType #>Method (string encodedMember, IJavaPeerable self, JniArgumentValue* parameters) { JniPeerMembers.AssertSelf (self); @@ -125,6 +176,25 @@ namespace Java.Interop { GC.KeepAlive (self); } } + + public unsafe <#= returnType.ReturnType #> InvokeNonvirtual<#= returnType.ManagedType #>Method (JniMemberInfoLookup member, IJavaPeerable self, ReadOnlySpan parameters) + { + JniPeerMembers.AssertSelf (self); + + var m = GetMethodInfo (member); + try { + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + if (TryInvoke<#= returnType.ManagedType #>StaticRedirect (m, self, params_ptr<#= byRefParamDecl #>)) { + <#= returnByRefParam #>; + } + <#= setByRefParam #>JniEnvironment.InstanceMethods.CallNonvirtual<#= returnType.JniCallType #>Method (self.PeerReference, JniPeerType.PeerReference, m, params_ptr); + <#= returnByRefParam #>; + } + } + finally { + GC.KeepAlive (self); + } + } <# } #> diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticFields.cs b/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticFields.cs index 7fe131b62..5a2626cb4 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticFields.cs +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticFields.cs @@ -30,6 +30,17 @@ public JniFieldInfo GetFieldInfo (string encodedMember) } } + public JniFieldInfo GetFieldInfo (JniMemberInfoLookup member) + { + lock (StaticFields) { + if (!StaticFields.TryGetValue (member.EncodedMember, out var f)) { + f = Members.JniPeerType.GetInstanceField (member.MemberName, member.MemberSignature); + StaticFields.Add (member.EncodedMember, f); + } + return f; + } + } + internal void Dispose () { StaticFields.Clear (); diff --git a/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs b/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs index 9ce77fbe3..55373862a 100644 --- a/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs +++ b/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace Java.Interop { @@ -66,6 +67,46 @@ JniMethodInfo GetMethodInfo (string method, string signature) return Members.JniPeerType.GetStaticMethod (method, signature); } + public JniMethodInfo GetMethodInfo (JniMemberInfoLookup member) + { + lock (StaticMethods) { + if (StaticMethods.TryGetValue (member.EncodedMember, out var m)) { + return m; + } + } + var info = GetMethodInfo (member.MemberName, member.MemberSignature); + lock (StaticMethods) { + if (StaticMethods.TryGetValue (member.EncodedMember, out var m)) { + return m; + } + StaticMethods.Add (member.EncodedMember, info); + } + return info; + } + + JniMethodInfo GetMethodInfo (ReadOnlySpan method, ReadOnlySpan signature) + { + var m = (JniMethodInfo?) null; + var newMethod = JniEnvironment.Runtime.TypeManager.GetReplacementMethodInfo (Members.JniPeerTypeName, method, signature); + if (newMethod.HasValue) { + using var t = new JniType (newMethod.Value.TargetJniType ?? Members.JniPeerTypeName); + if (t.TryGetStaticMethod ( + newMethod.Value.TargetJniMethodName ?? method.ToString (), + newMethod.Value.TargetJniMethodSignature ?? signature.ToString (), + out m)) { + return m; + } + } + if (Members.JniPeerType.TryGetStaticMethod (method, signature, out m)) { + return m; + } + m = FindInFallbackTypes (method, signature); + if (m != null) { + return m; + } + return Members.JniPeerType.GetStaticMethod (method, signature); + } + #pragma warning disable CA1801 JniType GetMethodDeclaringType (JniMethodInfo method) { @@ -105,65 +146,170 @@ JniType GetMethodDeclaringType (JniMethodInfo method) } #endif // NET + JniMethodInfo? FindInFallbackTypes (ReadOnlySpan method, ReadOnlySpan signature) + { + var fallbackTypes = JniEnvironment.Runtime.TypeManager.GetStaticMethodFallbackTypes (Members.JniPeerTypeName); + if (fallbackTypes == null) { + return null; + } + foreach (var ft in fallbackTypes) { + JniType? t = null; + try { + if (!JniType.TryParse (ft, out t)) { + continue; + } + if (t.TryGetStaticMethod (method, signature, out var m)) { + m.StaticRedirect = t; + t = null; + return m; + } + } + finally { + t?.Dispose (); + } + } + return null; + } + public unsafe void InvokeVoidMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); JniEnvironment.StaticMethods.CallStaticVoidMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe void InvokeVoidMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + JniEnvironment.StaticMethods.CallStaticVoidMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe bool InvokeBooleanMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticBooleanMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe bool InvokeBooleanMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticBooleanMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe sbyte InvokeSByteMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticByteMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe sbyte InvokeSByteMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticByteMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe char InvokeCharMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticCharMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe char InvokeCharMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticCharMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe short InvokeInt16Method (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticShortMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe short InvokeInt16Method (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticShortMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe int InvokeInt32Method (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticIntMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe int InvokeInt32Method (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticIntMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe long InvokeInt64Method (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticLongMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe long InvokeInt64Method (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticLongMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe float InvokeSingleMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticFloatMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe float InvokeSingleMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticFloatMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe double InvokeDoubleMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticDoubleMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + public unsafe double InvokeDoubleMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticDoubleMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } + public unsafe JniObjectReference InvokeObjectMethod (string encodedMember, JniArgumentValue* parameters) { var m = GetMethodInfo (encodedMember); return JniEnvironment.StaticMethods.CallStaticObjectMethod (GetMethodDeclaringType (m).PeerReference, m, parameters); } + + public unsafe JniObjectReference InvokeObjectMethod (JniMemberInfoLookup member, ReadOnlySpan parameters) + { + var m = GetMethodInfo (member); + fixed (JniArgumentValue* params_ptr = &MemoryMarshal.GetReference (parameters)) { + return JniEnvironment.StaticMethods.CallStaticObjectMethod (GetMethodDeclaringType (m).PeerReference, m, params_ptr); + } + } }} } diff --git a/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs b/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs index cc778dba7..45078568d 100644 --- a/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs +++ b/src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs @@ -423,6 +423,22 @@ IEnumerable CreateGetTypesForSimpleReferenceEnumerator (string jniSimpleRe protected virtual ReplacementMethodInfo? GetReplacementMethodInfoCore (string jniSimpleReference, string jniMethodName, string jniMethodSignature) => null; + public ReplacementMethodInfo? GetReplacementMethodInfo (string jniSimpleReference, ReadOnlySpan jniMethodName, ReadOnlySpan jniMethodSignature) + { + AssertValid (); + AssertSimpleReference (jniSimpleReference, nameof (jniSimpleReference)); + if (jniMethodName.IsEmpty) { + throw new ArgumentNullException (nameof (jniMethodName)); + } + if (jniMethodSignature.IsEmpty) { + throw new ArgumentNullException (nameof (jniMethodSignature)); + } + + return GetReplacementMethodInfoCore (jniSimpleReference, jniMethodName, jniMethodSignature); + } + + protected virtual ReplacementMethodInfo? GetReplacementMethodInfoCore (string jniSimpleReference, ReadOnlySpan jniMethodName, ReadOnlySpan jniMethodSignature) => null; + public virtual void RegisterNativeMembers ( JniType nativeClass, [DynamicallyAccessedMembers (MethodsAndPrivateNested)] diff --git a/src/Java.Interop/Java.Interop/JniType.cs b/src/Java.Interop/Java.Interop/JniType.cs index 396f5067b..f02d32936 100644 --- a/src/Java.Interop/Java.Interop/JniType.cs +++ b/src/Java.Interop/Java.Interop/JniType.cs @@ -210,6 +210,13 @@ public JniFieldInfo GetInstanceField (string name, string signature) return JniEnvironment.InstanceFields.GetFieldID (PeerReference, name, signature); } + public JniFieldInfo GetInstanceField (ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + return JniEnvironment.InstanceFields.GetFieldID (PeerReference, name, signature); + } + public JniFieldInfo GetCachedInstanceField ([NotNull] ref JniFieldInfo? cachedField, string name, string signature) { AssertValid (); @@ -223,6 +230,19 @@ public JniFieldInfo GetCachedInstanceField ([NotNull] ref JniFieldInfo? cachedFi return cachedField; } + public JniFieldInfo GetCachedInstanceField ([NotNull] ref JniFieldInfo? cachedField, ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + if (cachedField != null && cachedField.IsValid) + return cachedField; + var m = GetInstanceField (name, signature); + if (Interlocked.CompareExchange (ref cachedField, m, null) != null) { + // No cleanup required; let the GC collect the unused instance + } + return cachedField; + } + public JniFieldInfo GetStaticField (string name, string signature) { AssertValid (); @@ -230,6 +250,14 @@ public JniFieldInfo GetStaticField (string name, string signature) return JniEnvironment.StaticFields.GetStaticFieldID (PeerReference, name, signature); } + + public JniFieldInfo GetStaticField (ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + return JniEnvironment.StaticFields.GetStaticFieldID (PeerReference, name, signature); + } + public JniFieldInfo GetCachedStaticField ([NotNull] ref JniFieldInfo? cachedField, string name, string signature) { AssertValid (); @@ -243,6 +271,19 @@ public JniFieldInfo GetCachedStaticField ([NotNull] ref JniFieldInfo? cachedFiel return cachedField; } + public JniFieldInfo GetCachedStaticField ([NotNull] ref JniFieldInfo? cachedField, ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + if (cachedField != null && cachedField.IsValid) + return cachedField; + var m = GetStaticField (name, signature); + if (Interlocked.CompareExchange (ref cachedField, m, null) != null) { + // No cleanup required; let the GC collect the unused instance + } + return cachedField; + } + public JniMethodInfo GetInstanceMethod (string name, string signature) { AssertValid (); @@ -250,6 +291,13 @@ public JniMethodInfo GetInstanceMethod (string name, string signature) return JniEnvironment.InstanceMethods.GetMethodID (PeerReference, name, signature); } + public JniMethodInfo GetInstanceMethod (ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + return JniEnvironment.InstanceMethods.GetMethodID (PeerReference, name, signature); + } + #if NET internal bool TryGetInstanceMethod (string name, string signature, [NotNullWhen(true)] out JniMethodInfo? method) { @@ -308,6 +356,19 @@ public JniMethodInfo GetCachedInstanceMethod ([NotNull] ref JniMethodInfo? cache return cachedMethod; } + public JniMethodInfo GetCachedInstanceMethod ([NotNull] ref JniMethodInfo? cachedMethod, ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + if (cachedMethod != null && cachedMethod.IsValid) + return cachedMethod; + var m = GetInstanceMethod (name, signature); + if (Interlocked.CompareExchange (ref cachedMethod, m, null) != null) { + // No cleanup required; let the GC collect the unused instance + } + return cachedMethod; + } + public JniMethodInfo GetStaticMethod (string name, string signature) { AssertValid (); @@ -315,6 +376,13 @@ public JniMethodInfo GetStaticMethod (string name, string signature) return JniEnvironment.StaticMethods.GetStaticMethodID (PeerReference, name, signature); } + + public JniMethodInfo GetStaticMethod (ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + return JniEnvironment.StaticMethods.GetStaticMethodID (PeerReference, name, signature); + } #if NET internal bool TryGetStaticMethod (string name, string signature, [NotNullWhen(true)] out JniMethodInfo? method) { @@ -360,6 +428,13 @@ IntPtr RawGetStaticMethodID (IntPtr env, string name, string signature, out IntP } #endif // NET + internal bool TryGetStaticMethod (ReadOnlySpan name, ReadOnlySpan signature, [NotNullWhen(true)] out JniMethodInfo? method) + { + AssertValid (); + + return JniEnvironment.StaticMethods.TryGetStaticMethod (PeerReference, name, signature, out method); + } + public JniMethodInfo GetCachedStaticMethod ([NotNull] ref JniMethodInfo? cachedMethod, string name, string signature) { AssertValid (); @@ -372,5 +447,18 @@ public JniMethodInfo GetCachedStaticMethod ([NotNull] ref JniMethodInfo? cachedM } return cachedMethod; } + + public JniMethodInfo GetCachedStaticMethod ([NotNull] ref JniMethodInfo? cachedMethod, ReadOnlySpan name, ReadOnlySpan signature) + { + AssertValid (); + + if (cachedMethod != null && cachedMethod.IsValid) + return cachedMethod; + var m = GetStaticMethod (name, signature); + if (Interlocked.CompareExchange (ref cachedMethod, m, null) != null) { + // No cleanup required; let the GC collect the unused instance + } + return cachedMethod; + } } } diff --git a/src/Java.Interop/PublicAPI.Unshipped.txt b/src/Java.Interop/PublicAPI.Unshipped.txt index 3d4565551..60d8bcb41 100644 --- a/src/Java.Interop/PublicAPI.Unshipped.txt +++ b/src/Java.Interop/PublicAPI.Unshipped.txt @@ -1,3 +1,103 @@ #nullable enable +Java.Interop.JniMemberInfoLookup +Java.Interop.JniMemberInfoLookup.EncodedMember.get -> string! +Java.Interop.JniMemberInfoLookup.JniMemberInfoLookup() -> void +Java.Interop.JniMemberInfoLookup.JniMemberInfoLookup(string! encodedMember, System.ReadOnlySpan memberName, System.ReadOnlySpan memberSignature) -> void +Java.Interop.JniMemberInfoLookup.MemberName.get -> System.ReadOnlySpan +Java.Interop.JniMemberInfoLookup.MemberSignature.get -> System.ReadOnlySpan +Java.Interop.JniPeerMembers.JniInstanceFields.GetBooleanValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> bool +Java.Interop.JniPeerMembers.JniInstanceFields.GetCharValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> char +Java.Interop.JniPeerMembers.JniInstanceFields.GetDoubleValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> double +Java.Interop.JniPeerMembers.JniInstanceFields.GetFieldInfo(Java.Interop.JniMemberInfoLookup member) -> Java.Interop.JniFieldInfo! +Java.Interop.JniPeerMembers.JniInstanceFields.GetInt16Value(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> short +Java.Interop.JniPeerMembers.JniInstanceFields.GetInt32Value(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> int +Java.Interop.JniPeerMembers.JniInstanceFields.GetInt64Value(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> long +Java.Interop.JniPeerMembers.JniInstanceFields.GetObjectValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> Java.Interop.JniObjectReference +Java.Interop.JniPeerMembers.JniInstanceFields.GetSByteValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> sbyte +Java.Interop.JniPeerMembers.JniInstanceFields.GetSingleValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self) -> float +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, bool value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, char value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, double value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, float value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, int value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, Java.Interop.JniObjectReference value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, long value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, sbyte value) -> void +Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, short value) -> void +Java.Interop.JniPeerMembers.JniInstanceMethods.GetMethodInfo(Java.Interop.JniMemberInfoLookup member) -> Java.Interop.JniMethodInfo! +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractBooleanMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> bool +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractCharMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> char +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractDoubleMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> double +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractInt16Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> short +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractInt32Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> int +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractInt64Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> long +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractObjectMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> Java.Interop.JniObjectReference +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractSByteMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> sbyte +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractSingleMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> float +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractVoidMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> void +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualBooleanMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> bool +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualCharMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> char +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualDoubleMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> double +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualInt16Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> short +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualInt32Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> int +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualInt64Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> long +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualObjectMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> Java.Interop.JniObjectReference +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualSByteMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> sbyte +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualSingleMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> float +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualVoidMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> void +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualBooleanMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> bool +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualCharMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> char +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualDoubleMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> double +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualInt16Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> short +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualInt32Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> int +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualInt64Method(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> long +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualObjectMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> Java.Interop.JniObjectReference +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualSByteMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> sbyte +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualSingleMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> float +Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(Java.Interop.JniMemberInfoLookup member, Java.Interop.IJavaPeerable! self, System.ReadOnlySpan parameters) -> void +Java.Interop.JniPeerMembers.JniStaticFields.GetBooleanValue(Java.Interop.JniMemberInfoLookup member) -> bool +Java.Interop.JniPeerMembers.JniStaticFields.GetCharValue(Java.Interop.JniMemberInfoLookup member) -> char +Java.Interop.JniPeerMembers.JniStaticFields.GetDoubleValue(Java.Interop.JniMemberInfoLookup member) -> double +Java.Interop.JniPeerMembers.JniStaticFields.GetFieldInfo(Java.Interop.JniMemberInfoLookup member) -> Java.Interop.JniFieldInfo! +Java.Interop.JniPeerMembers.JniStaticFields.GetInt16Value(Java.Interop.JniMemberInfoLookup member) -> short +Java.Interop.JniPeerMembers.JniStaticFields.GetInt32Value(Java.Interop.JniMemberInfoLookup member) -> int +Java.Interop.JniPeerMembers.JniStaticFields.GetInt64Value(Java.Interop.JniMemberInfoLookup member) -> long +Java.Interop.JniPeerMembers.JniStaticFields.GetObjectValue(Java.Interop.JniMemberInfoLookup member) -> Java.Interop.JniObjectReference +Java.Interop.JniPeerMembers.JniStaticFields.GetSByteValue(Java.Interop.JniMemberInfoLookup member) -> sbyte +Java.Interop.JniPeerMembers.JniStaticFields.GetSingleValue(Java.Interop.JniMemberInfoLookup member) -> float +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, bool value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, char value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, double value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, float value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, int value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, Java.Interop.JniObjectReference value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, long value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, sbyte value) -> void +Java.Interop.JniPeerMembers.JniStaticFields.SetValue(Java.Interop.JniMemberInfoLookup member, short value) -> void +Java.Interop.JniPeerMembers.JniStaticMethods.GetMethodInfo(Java.Interop.JniMemberInfoLookup member) -> Java.Interop.JniMethodInfo! +Java.Interop.JniRuntime.JniTypeManager.GetReplacementMethodInfo(string! jniSimpleReference, System.ReadOnlySpan jniMethodName, System.ReadOnlySpan jniMethodSignature) -> Java.Interop.JniRuntime.ReplacementMethodInfo? +Java.Interop.JniType.GetCachedInstanceField(ref Java.Interop.JniFieldInfo? cachedField, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! +Java.Interop.JniType.GetCachedInstanceMethod(ref Java.Interop.JniMethodInfo? cachedMethod, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +Java.Interop.JniType.GetCachedStaticField(ref Java.Interop.JniFieldInfo? cachedField, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! +Java.Interop.JniType.GetCachedStaticMethod(ref Java.Interop.JniMethodInfo? cachedMethod, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +Java.Interop.JniType.GetInstanceField(System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! +Java.Interop.JniType.GetInstanceMethod(System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +Java.Interop.JniType.GetStaticField(System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! +Java.Interop.JniType.GetStaticMethod(System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +static Java.Interop.JniEnvironment.InstanceFields.GetFieldID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! +static Java.Interop.JniEnvironment.InstanceMethods.GetMethodID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +static Java.Interop.JniEnvironment.StaticFields.GetStaticFieldID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniFieldInfo! +static Java.Interop.JniEnvironment.StaticMethods.GetStaticMethodID(Java.Interop.JniObjectReference type, System.ReadOnlySpan name, System.ReadOnlySpan signature) -> Java.Interop.JniMethodInfo! +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeBooleanMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> bool +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeCharMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> char +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeDoubleMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> double +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeInt16Method(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> short +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeInt32Method(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> int +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeInt64Method(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> long +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeObjectMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> Java.Interop.JniObjectReference +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeSByteMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> sbyte +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeSingleMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> float +Java.Interop.JniPeerMembers.JniStaticMethods.InvokeVoidMethod(Java.Interop.JniMemberInfoLookup member, System.ReadOnlySpan parameters) -> void +virtual Java.Interop.JniRuntime.JniTypeManager.GetReplacementMethodInfoCore(string! jniSimpleReference, System.ReadOnlySpan jniMethodName, System.ReadOnlySpan jniMethodSignature) -> Java.Interop.JniRuntime.ReplacementMethodInfo? static Java.Interop.JavaPeerableExtensions.TryJavaCast(this Java.Interop.IJavaPeerable? self, out TResult? result) -> bool static Java.Interop.JavaPeerableExtensions.JavaAs(this Java.Interop.IJavaPeerable? self) -> TResult? diff --git a/tests/Java.Interop-PerformanceTests/Java.Interop-PerformanceTests.targets b/tests/Java.Interop-PerformanceTests/Java.Interop-PerformanceTests.targets index f3866e5d6..1f4b9340d 100644 --- a/tests/Java.Interop-PerformanceTests/Java.Interop-PerformanceTests.targets +++ b/tests/Java.Interop-PerformanceTests/Java.Interop-PerformanceTests.targets @@ -4,7 +4,7 @@ BeforeTargets="BeforeBuild" Inputs="@(JavaPerformanceTestJar)" Outputs="$(OutputPath)performance-test.jar"> - + diff --git a/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs b/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs index a4104ac70..28f903c09 100644 --- a/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs +++ b/tests/Java.Interop-PerformanceTests/Java.Interop/JavaTiming.cs @@ -128,6 +128,19 @@ public virtual unsafe int Timing_VirtualIntMethod_Marshal1Args (int value) return _members.InstanceMethods.InvokeVirtualInt32Method ("VirtualIntMethod1Args.(I)I", this, args); } + public virtual unsafe int Timing_Lookup_VirtualIntMethod_Marshal1Args (int value) + { + var member = new JniMemberInfoLookup ( + "VirtualIntMethod1Args.(I)I", + "VirtualIntMethod1Args"u8, + "(I)I"u8 + ); + var args = stackalloc JniArgumentValue [1]; + args [0] = new JniArgumentValue (value); + + return _members.InstanceMethods.InvokeVirtualInt32Method (member, this, new ReadOnlySpan (args, 1)); + } + public virtual int Timing_VirtualIntMethod_GenericMarshal1Args (int value) { return _members.InstanceMethods.InvokeGenericVirtualInt32Method ("VirtualIntMethod1Args.(I)I", this, value); @@ -277,6 +290,17 @@ public unsafe JniObjectReference Timing_ToString_JniPeerMembers () return _members.InstanceMethods.InvokeVirtualObjectMethod (id, this, null); } + public JniObjectReference Timing_ToString_JniPeerMembers_Lookup () + { + var member = new JniMemberInfoLookup ( + toString_name + "." + toString_sig, + "toString"u8, + "()Ljava/lang/String;"u8 + ); + ReadOnlySpan args = null; + return _members.InstanceMethods.InvokeVirtualObjectMethod (member, this, args); + } + public static unsafe JniObjectReference CreateRunnable () { return _members.StaticMethods.InvokeObjectMethod ("CreateRunnable.()Ljava/lang/Runnable;", null); diff --git a/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs b/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs index 67e4c1255..36496d2a6 100644 --- a/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs +++ b/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs @@ -357,6 +357,12 @@ public void MethodLookupTiming () } tp.Stop (); + var tl = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + var s = o.Timing_ToString_JniPeerMembers_Lookup (); + JniObjectReference.Dispose (ref s); + } + tl.Stop (); var vtt = Stopwatch.StartNew (); for (int i = 0; i < count; ++i) { @@ -370,6 +376,12 @@ public void MethodLookupTiming () } vti.Stop (); + var vtl = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + o.Timing_Lookup_VirtualIntMethod_Marshal1Args (i); + } + vtl.Stop (); + Console.WriteLine ("Method Lookup + Invoke Timing:"); Console.WriteLine ("\t Traditional: {0}", tt.Elapsed); @@ -377,9 +389,11 @@ public void MethodLookupTiming () Console.WriteLine ("\t Dict w/ lock: {0}", td.Elapsed); Console.WriteLine ("\tConcurrentDict: {0}", tc.Elapsed); Console.WriteLine ("\tJniPeerMembers: {0}", tp.Elapsed); + Console.WriteLine ("\t JPM+Lookup: {0}", tl.Elapsed); Console.WriteLine (); Console.WriteLine ("\t (I)I virtual+traditional: {0}", vtt.Elapsed); Console.WriteLine ("\t (I)I virtual+JniPeerMembers: {0}", vti.Elapsed); + Console.WriteLine ("\t (I)I virtual+JPM+Lookup: {0}", vtl.Elapsed); } using (var o = new DerivedJavaTiming ()) { var ntt = Stopwatch.StartNew (); @@ -402,6 +416,37 @@ public void MethodLookupTiming () } } + [TestFixture] + class JniFieldLookupTiming : Java.InteropTests.JavaVMFixture { + + [Test] + public void FieldLookupTiming () + { + const string JniType = "com/xamarin/interop/performance/JavaTiming"; + const string EncodedMember = "instanceIntField.I"; + const int count = 10000; + + var strLookupTime = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + var p = new JniPeerMembers (JniType, typeof (JavaTiming)); + var f = p.InstanceFields.GetFieldInfo (EncodedMember); + } + strLookupTime.Stop (); + + var encLookupTime = Stopwatch.StartNew (); + for (int i = 0; i < count; ++i) { + var p = new JniPeerMembers (JniType, typeof (JavaTiming)); + var lookup = new JniMemberInfoLookup (EncodedMember, "instanceIntField"u8, "I"u8); + var f = p.InstanceFields.GetFieldInfo (lookup); + } + encLookupTime.Stop (); + + Console.WriteLine ($"# {nameof (FieldLookupTiming)} Timing: looking up JavaTiming.instanceIntField {count} times"); + Console.WriteLine ($"# .InstanceMethods.GetFieldInfo(string): {strLookupTime.Elapsed}"); + Console.WriteLine ($"# .InstanceMethods.GetFieldInfo(JniMemberInfoLookup): {encLookupTime.Elapsed}"); + } + } + [TestFixture] class JavaArrayTiming : Java.InteropTests.JavaVMFixture { diff --git a/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java b/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java index ca45b787d..099e16de8 100644 --- a/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java +++ b/tests/Java.Interop-PerformanceTests/java/com/xamarin/interop/performance/JavaTiming.java @@ -2,6 +2,8 @@ public class JavaTiming { + public int instanceIntField; + public static void StaticVoidMethod () { } diff --git a/tests/Java.Interop-Tests/Java.Interop/JniTypeTest.cs b/tests/Java.Interop-Tests/Java.Interop/JniTypeTest.cs index f56002836..2ccb60474 100644 --- a/tests/Java.Interop-Tests/Java.Interop/JniTypeTest.cs +++ b/tests/Java.Interop-Tests/Java.Interop/JniTypeTest.cs @@ -48,10 +48,10 @@ public unsafe void Dispose_Exceptions () Assert.Throws (() => t.AllocObject ()); Assert.Throws (() => t.NewObject (null, null)); Assert.Throws (() => t.GetConstructor (null)); - Assert.Throws (() => t.GetInstanceField (null, null)); - Assert.Throws (() => t.GetInstanceMethod (null, null)); - Assert.Throws (() => t.GetStaticField (null, null)); - Assert.Throws (() => t.GetStaticMethod (null, null)); + Assert.Throws (() => t.GetInstanceField (null, (string) null)); + Assert.Throws (() => t.GetInstanceMethod (null, (string) null)); + Assert.Throws (() => t.GetStaticField (null, (string) null)); + Assert.Throws (() => t.GetStaticMethod (null, (string) null)); Assert.Throws (() => t.GetSuperclass ()); Assert.Throws (() => t.IsAssignableFrom (null)); Assert.Throws (() => t.IsInstanceOfType (new JniObjectReference ())); @@ -60,14 +60,14 @@ public unsafe void Dispose_Exceptions () Assert.Throws (() => t.UnregisterNativeMethods ()); JniFieldInfo jif = null; - Assert.Throws (() => t.GetCachedInstanceField (ref jif, null, null)); + Assert.Throws (() => t.GetCachedInstanceField (ref jif, (string) null, (string) null)); JniMethodInfo jim = null; Assert.Throws (() => t.GetCachedConstructor (ref jim, null)); - Assert.Throws (() => t.GetCachedInstanceMethod (ref jim, null, null)); + Assert.Throws (() => t.GetCachedInstanceMethod (ref jim, (string) null, (string) null)); JniFieldInfo jsf = null; - Assert.Throws (() => t.GetCachedStaticField (ref jsf, null, null)); + Assert.Throws (() => t.GetCachedStaticField (ref jsf, (string) null, (string) null)); JniMethodInfo jsm = null; - Assert.Throws (() => t.GetCachedStaticMethod (ref jsm, null, null)); + Assert.Throws (() => t.GetCachedStaticMethod (ref jsm, (string) null, (string) null)); } [Test]