-
Notifications
You must be signed in to change notification settings - Fork 561
Ignore - Testing CI for some TypeMap related changes #10533
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jtschuster
wants to merge
13
commits into
dotnet:main
Choose a base branch
from
jtschuster:TypeMapGeneration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,203
−160
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
/azp run |
|
Commenter does not have sufficient privileges for PR 10533 in repo dotnet/android |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
AndroidTypeManager -> TypeMapTypeManager diffdiff --git a/AndroidTypeManager.cs "b/src\\Mono.Android\\Java.Interop\\TypeMapAttributeTypeManager.cs"
index 72b9e13fd..ee26be20a 100644
--- a/AndroidTypeManager.cs
+++ "b/src\\Mono.Android\\Java.Interop\\TypeMapAttributeTypeManager.cs"
@@ -10,78 +10,82 @@ using Java.Interop.Tools.TypeNameMappings;
namespace Java.Interop
{
- class AndroidTypeManager : JniRuntime.JniTypeManager {
+ class TypeMapAttributeTypeManager : JniRuntime.JniTypeManager
+ {
struct JniRemappingReplacementMethod
{
public string target_type;
public string target_name;
- public bool is_static;
+ public bool is_static;
};
bool jniAddNativeMethodRegistrationAttributePresent;
+ static IReadOnlyDictionary<Type, Type> ProxyTypeMap { get; } = TypeMapping.GetOrCreateProxyTypeMapping<Java.Lang.Object> ();
+ static IReadOnlyDictionary<string, Type> ExternalTypeMap { get; } = TypeMapping.GetOrCreateExternalTypeMapping<Java.Lang.Object> ();
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
- public AndroidTypeManager (bool jniAddNativeMethodRegistrationAttributePresent)
+ public TypeMapAttributeTypeManager (bool jniAddNativeMethodRegistrationAttributePresent)
{
this.jniAddNativeMethodRegistrationAttributePresent = jniAddNativeMethodRegistrationAttributePresent;
}
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
{
+ if (!ExternalTypeMap.TryGetValue (jniSimpleReference, out Type? value)) {
+ if (Logger.LogAssembly) {
+ // Miss message is logged in the native runtime
+ JNIEnv.LogTypemapTrace (new System.Diagnostics.StackTrace (true));
+ }
+ } else {
+ yield return value;
+ }
+
foreach (var ti in base.GetTypesForSimpleReference (jniSimpleReference))
yield return ti;
-
- var t = Java.Interop.TypeManager.GetJavaToManagedType (jniSimpleReference);
- if (t != null)
- yield return t;
}
protected override string? GetSimpleReference (Type type)
{
- string? j = JNIEnv.TypemapManagedToJava (type);
- if (j != null) {
- return GetReplacementTypeCore (j) ?? j;
- }
+ if (!ProxyTypeMap.TryGetValue (type, out Type? proxyType))
+ return null;
+ if (proxyType.GetCustomAttribute<TypeMapProxyAttribute> () is { } attr)
+ return GetReplacementTypeCore(attr.JniName) ?? attr.JniName;
return null;
}
protected override IEnumerable<string> GetSimpleReferences (Type type)
{
- string? j = JNIEnv.TypemapManagedToJava (type);
- j = GetReplacementTypeCore (j) ?? j;
-
- if (j != null) {
- return new[]{j};
- }
- return Array.Empty<string> ();
+ if (GetSimpleReference (type) is { } str)
+ return [str];
+ return [];
}
protected override IReadOnlyList<string>? GetStaticMethodFallbackTypesCore (string jniSimpleReference)
{
- ReadOnlySpan<char> name = jniSimpleReference;
- int slash = name.LastIndexOf ('/');
- var desugarType = new StringBuilder (jniSimpleReference.Length + "Desugar".Length);
+ ReadOnlySpan<char> name = jniSimpleReference;
+ int slash = name.LastIndexOf ('/');
+ var desugarType = new StringBuilder (jniSimpleReference.Length + "Desugar".Length);
if (slash > 0) {
- desugarType.Append (name.Slice (0, slash+1))
+ desugarType.Append (name.Slice (0, slash + 1))
.Append ("Desugar")
- .Append (name.Slice (slash+1));
+ .Append (name.Slice (slash + 1));
} else {
desugarType.Append ("Desugar").Append (name);
}
- var typeWithPrefix = desugarType.ToString ();
- var typeWithSuffix = $"{jniSimpleReference}$-CC";
+ var typeWithPrefix = desugarType.ToString ();
+ var typeWithSuffix = $"{jniSimpleReference}$-CC";
- var replacements = new[]{
+ var replacements = new []{
GetReplacementTypeCore (typeWithPrefix) ?? typeWithPrefix,
GetReplacementTypeCore (typeWithSuffix) ?? typeWithSuffix,
};
if (Logger.LogAssembly) {
- var message = $"Remapping type `{jniSimpleReference}` to one one of {{ `{replacements[0]}`, `{replacements[1]}` }}";
+ var message = $"Remapping type `{jniSimpleReference}` to one one of {{ `{replacements [0]}`, `{replacements [1]}` }}";
Logger.Log (LogLevel.Debug, "monodroid-assembly", message);
}
return replacements;
@@ -113,7 +117,7 @@ namespace Java.Interop
}
var method = new JniRemappingReplacementMethod ();
- method = Marshal.PtrToStructure<JniRemappingReplacementMethod>(retInfo);
+ method = Marshal.PtrToStructure<JniRemappingReplacementMethod> (retInfo);
var newSignature = jniMethodSignature;
int? paramCount = null;
@@ -130,14 +134,14 @@ namespace Java.Interop
}
return new JniRuntime.ReplacementMethodInfo {
- SourceJniType = jniSourceType,
- SourceJniMethodName = jniMethodName,
- SourceJniMethodSignature = jniMethodSignature,
- TargetJniType = method.target_type,
- TargetJniMethodName = method.target_name,
- TargetJniMethodSignature = newSignature,
- TargetJniMethodParameterCount = paramCount,
- TargetJniMethodInstanceToStatic = method.is_static,
+ SourceJniType = jniSourceType,
+ SourceJniMethodName = jniMethodName,
+ SourceJniMethodSignature = jniMethodSignature,
+ TargetJniType = method.target_type,
+ TargetJniMethodName = method.target_name,
+ TargetJniMethodSignature = newSignature,
+ TargetJniMethodParameterCount = paramCount,
+ TargetJniMethodInstanceToStatic = method.is_static,
};
}
@@ -174,7 +178,7 @@ namespace Java.Interop
if (dynamic_callback_gen == null)
throw new InvalidOperationException ("The referenced Mono.Android.Export.dll does not match the expected version. The required method was not found.");
}
- return (Delegate)dynamic_callback_gen.Invoke (null, new object [] { method })!;
+ return (Delegate) dynamic_callback_gen.Invoke (null, new object [] { method })!;
}
static List<JniNativeMethodRegistration> sharedRegistrations = new List<JniNativeMethodRegistration> ();
@@ -210,7 +214,8 @@ namespace Java.Interop
return rv;
}
- class MagicRegistrationMap {
+ class MagicRegistrationMap
+ {
#pragma warning disable CS0649 // Field is never assigned to;
// assigned to in generated IL: https://github.com/xamarin/xamarin-android/blob/cbfa7e20acebd37b52ec4de9d5c1a4a66ddda799/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/MonoDroidMarkStep.cs#L204
static Dictionary<string, int>? typesMap;
@@ -268,7 +273,7 @@ namespace Java.Interop
try {
if (methods.IsEmpty) {
if (jniAddNativeMethodRegistrationAttributePresent)
- base.RegisterNativeMembers (nativeClass, type, methods.ToString ());
+ base.RegisterNativeMembers (nativeClass, type, methods);
return;
} else if (FastRegisterNativeMembers (nativeClass, type, methods)) {
return;
@@ -277,7 +282,7 @@ namespace Java.Interop
int methodCount = CountMethods (methods);
if (methodCount < 1) {
if (jniAddNativeMethodRegistrationAttributePresent) {
- base.RegisterNativeMembers (nativeClass, type, methods.ToString ());
+ base.RegisterNativeMembers (nativeClass, type, methods);
}
return;
}
@@ -325,7 +330,7 @@ namespace Java.Interop
}
GetCallbackHandler connector = (GetCallbackHandler) Delegate.CreateDelegate (typeof (GetCallbackHandler),
- callbackDeclaringType, callbackString.ToString ());
+ callbackDeclaringType, callbackString.ToString ());
callback = connector ();
}
@@ -344,15 +349,6 @@ namespace Java.Interop
} catch (Exception e) {
JniEnvironment.Runtime.RaisePendingException (e);
}
-
- bool ShouldRegisterDynamically (string callbackTypeName, string callbackString, string typeName, string callbackName)
- {
- if (String.Compare (typeName, callbackTypeName, StringComparison.Ordinal) != 0) {
- return false;
- }
-
- return String.Compare (callbackName, callbackString, StringComparison.Ordinal) == 0;
- }
}
static int CountMethods (ReadOnlySpan<char> methodsSpan)
AndroidValueManager => TypeMapTypeManager diffdiff --git a/AndroidValueManager.cs "b/src\\Mono.Android\\Java.Interop\\TypeMapAttributeValueManager.cs"
index 022ba91f8..d6a0c56a2 100644
--- a/AndroidValueManager.cs
+++ "b/src\\Mono.Android\\Java.Interop\\TypeMapAttributeValueManager.cs"
@@ -8,9 +8,9 @@ using Android.Runtime;
namespace Java.Interop
{
- class AndroidValueManager : JniRuntime.JniValueManager {
-
- Dictionary<IntPtr, IdentityHashTargets> instances = new Dictionary<IntPtr, IdentityHashTargets> ();
+ class TypeMapAttributeValueManager : JniRuntime.JniValueManager
+ {
+ Dictionary<IntPtr, IdentityHashTargets> instances = new Dictionary<IntPtr, IdentityHashTargets> ();
public override void WaitForGCBridgeProcessing ()
{
@@ -28,11 +28,105 @@ namespace Java.Interop
if (!reference.IsValid)
return null;
- var peer = Java.Interop.TypeManager.CreateInstance (reference.Handle, JniHandleOwnership.DoNotTransfer, targetType) as IJavaPeerable;
+ var peer = CreateInstance (reference.Handle, JniHandleOwnership.DoNotTransfer, targetType) as IJavaPeerable;
JniObjectReference.Dispose (ref reference, options);
return peer;
}
+ internal static IJavaPeerable? CreateInstance (IntPtr handle, JniHandleOwnership transfer, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]Type? targetType)
+ {
+ Type? type = null;
+ IntPtr class_ptr = JNIEnv.GetObjectClass (handle);
+ string? class_name = TypeManager.GetClassName (class_ptr);
+ System.Diagnostics.Debug.Assert (class_name == JNIEnv.GetClassNameFromInstance (handle));
+ lock (TypeManagerMapDictionaries.AccessLock) {
+ while (class_ptr != IntPtr.Zero) {
+ if (class_name != null) {
+ var class_signature = JniTypeSignature.Parse (class_name);
+ type = JNIEnvInit.androidRuntime!.TypeManager.GetType (class_signature);
+ if (type != null) {
+ break;
+ }
+ }
+
+ IntPtr super_class_ptr = JNIEnv.GetSuperclass (class_ptr);
+ JNIEnv.DeleteLocalRef (class_ptr);
+ class_name = null;
+ class_ptr = super_class_ptr;
+ if (class_ptr != IntPtr.Zero) {
+ class_name = TypeManager.GetClassName (class_ptr);
+ }
+ }
+ }
+
+ if (class_ptr != IntPtr.Zero) {
+ JNIEnv.DeleteLocalRef (class_ptr);
+ class_ptr = IntPtr.Zero;
+ }
+
+ if (targetType != null &&
+ (type == null ||
+ !targetType.IsAssignableFrom (type))) {
+ type = targetType;
+ }
+
+ if (type == null) {
+ class_name = JNIEnv.GetClassNameFromInstance (handle);
+ JNIEnv.DeleteRef (handle, transfer);
+ throw new NotSupportedException (
+ FormattableString.Invariant ($"Internal error finding wrapper class for '{class_name}'. (Where is the Java.Lang.Object wrapper?!)"),
+ TypeManager.CreateJavaLocationException ());
+ }
+
+ if (type.IsInterface || type.IsAbstract) {
+ var invokerType = JavaObjectExtensions.GetInvokerType (type);
+ if (invokerType == null)
+ throw new NotSupportedException ("Unable to find Invoker for type '" + type.FullName + "'. Was it linked away?",
+ TypeManager.CreateJavaLocationException ());
+ type = invokerType;
+ }
+
+ var typeSig = JNIEnvInit.androidRuntime?.TypeManager.GetTypeSignature (type) ?? default;
+ if (!typeSig.IsValid || typeSig.SimpleReference == null) {
+ throw new ArgumentException ($"Could not determine Java type corresponding to `{type.AssemblyQualifiedName}`.", nameof (targetType));
+ }
+
+ JniObjectReference typeClass = default;
+ JniObjectReference handleClass = default;
+ try {
+ try {
+ typeClass = JniEnvironment.Types.FindClass (typeSig.SimpleReference);
+ } catch (Exception e) {
+ throw new ArgumentException ($"Could not find Java class `{typeSig.SimpleReference}`.",
+ nameof (targetType),
+ e);
+ }
+
+ handleClass = JniEnvironment.Types.GetObjectClass (new JniObjectReference (handle));
+ if (!JniEnvironment.Types.IsAssignableFrom (handleClass, typeClass)) {
+ return null;
+ }
+ } finally {
+ JniObjectReference.Dispose (ref handleClass);
+ JniObjectReference.Dispose (ref typeClass);
+ }
+
+ IJavaPeerable? result = null;
+
+ try {
+ result = (IJavaPeerable) TypeManager.CreateProxy (type, handle, transfer);
+ if (Java.Interop.Runtime.IsGCUserPeer (result.PeerReference.Handle)) {
+ result.SetJniManagedPeerState (JniManagedPeerStates.Replaceable | JniManagedPeerStates.Activatable);
+ }
+ } catch (MissingMethodException e) {
+ var key_handle = JNIEnv.IdentityHash (handle);
+ JNIEnv.DeleteRef (handle, transfer);
+ throw new NotSupportedException (FormattableString.Invariant (
+ $"Unable to activate instance of type {type} from native handle 0x{handle:x} (key_handle 0x{key_handle:x})."), e);
+ }
+ return result;
+ }
+
public override void AddPeer (IJavaPeerable value)
{
if (value == null)
@@ -40,8 +134,8 @@ namespace Java.Interop
if (!value.PeerReference.IsValid)
throw new ArgumentException ("Must have a valid JNI object reference!", nameof (value));
- var reference = value.PeerReference;
- var hash = JNIEnv.IdentityHash (reference.Handle);
+ var reference = value.PeerReference;
+ var hash = JNIEnv.IdentityHash (reference.Handle);
AddPeer (value, reference, hash);
}
@@ -118,7 +212,7 @@ namespace Java.Interop
bool ShouldReplaceMapping (WeakReference<IJavaPeerable> current, JniObjectReference reference, IJavaPeerable value, out IJavaPeerable? target)
{
- target = null;
+ target = null;
if (current == null)
return true;
@@ -160,12 +254,12 @@ namespace Java.Interop
if (value == null)
throw new ArgumentNullException (nameof (value));
- var reference = value.PeerReference;
+ var reference = value.PeerReference;
if (!reference.IsValid) {
// Likely an idempotent DIspose(); ignore.
return;
}
- var hash = JNIEnv.IdentityHash (reference.Handle);
+ var hash = JNIEnv.IdentityHash (reference.Handle);
RemovePeer (value, hash);
}
@@ -199,11 +293,11 @@ namespace Java.Interop
if (!reference.IsValid)
return null;
- var hash = JNIEnv.IdentityHash (reference.Handle);
+ var hash = JNIEnv.IdentityHash (reference.Handle);
lock (instances) {
if (instances.TryGetValue (hash, out var targets)) {
for (int i = targets.Count - 1; i >= 0; i--) {
- var wref = targets [i];
+ var wref = targets [i];
if (!wref!.TryGetTarget (out var result) || !result.PeerReference.IsValid) {
targets.RemoveAt (i);
continue;
@@ -219,14 +313,14 @@ namespace Java.Interop
public override void ActivatePeer (IJavaPeerable? self, JniObjectReference reference, ConstructorInfo cinfo, object? []? argumentValues)
{
- Java.Interop.TypeManager.Activate (reference.Handle, cinfo, argumentValues);
+ TypeManager.Activate (reference.Handle, cinfo, argumentValues);
}
- protected override bool TryUnboxPeerObject (IJavaPeerable value, [NotNullWhen (true)]out object? result)
+ protected override bool TryUnboxPeerObject (IJavaPeerable value, [NotNullWhen (true)] out object? result)
{
var proxy = value as JavaProxyThrowable;
if (proxy != null) {
- result = proxy.InnerException;
+ result = proxy.InnerException;
return true;
}
return base.TryUnboxPeerObject (value, out result);
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.