Skip to content

Commit f6babec

Browse files
jonathanpeppersjonpryor
authored andcommitted
[Java.Interop] remove Type.GetTypeInfo() calls (#557)
Java.Interop used to be a PCL, but is now a netstandard 2.0 library. We make use of `IntrospectionExtensions.GetTypeInfo()`: * https://github.com/mono/mono/blob/c5b88ec4f323f2bdb7c7d0a595ece28dae66579c/mcs/class/referencesource/mscorlib/system/reflection/introspectionextensions.cs#L24 * https://github.com/mono/mono/blob/c5b88ec4f323f2bdb7c7d0a595ece28dae66579c/mcs/class/corlib/ReferenceSources/RuntimeType.cs This is a "compat layer", because some of the System.Reflection APIs are different for PCLs and netstandard 1.x. If we remove these calls and just use the regular `System.Type` APIs, the code is simpler and makes fewer method calls. API differences to mention: * `TypeInfo.GetDeclaredNestedType()` is equivalent to `Type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic)` * `TypeInfo.DeclaredConstructors()` is equivalent to `Type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)` Places checking `IsStatic` can drop `BindingFlags.Static`. ~~ Results ~~ Testing a Release build of the Xamarin.Forms integration project in xamarin-android: * Before: 01-09 16:21:41.904 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +756ms 01-09 16:21:45.886 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +749ms 01-09 16:21:49.851 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +758ms 01-09 16:21:53.818 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +757ms 01-09 16:21:57.785 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +747ms 01-09 16:22:01.783 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +763ms 01-09 16:22:05.832 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +756ms 01-09 16:22:09.782 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +754ms 01-09 16:22:13.798 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +757ms 01-09 16:22:17.798 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +757ms * Average(ms): 755.4 * Std Err(ms): 1.43913554299486 * Std Dev(ms): 4.55094617756694 * After: 01-09 17:07:41.164 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +757ms 01-09 17:07:45.148 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +758ms 01-09 17:07:49.113 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +747ms 01-09 17:07:53.096 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +748ms 01-09 17:07:57.062 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +747ms 01-09 17:08:01.045 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +756ms 01-09 17:08:05.012 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +745ms 01-09 17:08:08.994 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +753ms 01-09 17:08:13.011 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +765ms 01-09 17:08:17.026 1473 1503 I ActivityTaskManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +752ms * Average(ms): 752.8 * Std Err(ms): 1.98774020211674 * Std Dev(ms): 6.28578643537236 This might save ~3ms on startup? Comparing the number of calls: Method call summary Total(ms) Self(ms) Calls Method name - 4 3 3457 System.Reflection.IntrospectionExtensions:GetTypeInfo (System.Type) + 3 2 3020 System.Reflection.IntrospectionExtensions:GetTypeInfo (System.Type) `GetTypeInfo()` is reduced by ~437 calls. Xamarin.Forms still supports netstandard 1.x, so that is where some of the remaining calls are coming from.
1 parent 4565369 commit f6babec

File tree

7 files changed

+34
-38
lines changed

7 files changed

+34
-38
lines changed

src/Java.Interop/Java.Interop/JavaArray.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ internal IList<T> ToTargetType (Type targetType, bool dispose)
102102
{
103103
if (TargetTypeIsCurrentType (targetType))
104104
return this;
105-
if (targetType == typeof (T[]) || targetType.GetTypeInfo ().IsAssignableFrom (typeof (IList<T>).GetTypeInfo ())) {
105+
if (targetType == typeof (T[]) || targetType.IsAssignableFrom (typeof (IList<T>))) {
106106
try {
107107
return ToArray ();
108108
} finally {

src/Java.Interop/Java.Interop/JniPeerMembers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public JniPeerMembers (string jniPeerTypeName, Type managedPeerType)
1919
{
2020
if (managedPeerType == null)
2121
throw new ArgumentNullException (nameof (managedPeerType));
22-
if (!typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (managedPeerType.GetTypeInfo ()))
22+
if (!typeof (IJavaPeerable).IsAssignableFrom (managedPeerType))
2323
throw new ArgumentException ("'managedPeerType' must implement the IJavaPeerable interface.", nameof (managedPeerType));
2424

2525
#if !XA_INTEGRATION
@@ -42,7 +42,7 @@ public JniPeerMembers (string jniPeerTypeName, Type managedPeerType)
4242
if (checkManagedPeerType) {
4343
if (managedPeerType == null)
4444
throw new ArgumentNullException (nameof (managedPeerType));
45-
if (!typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (managedPeerType.GetTypeInfo ()))
45+
if (!typeof (IJavaPeerable).IsAssignableFrom (managedPeerType))
4646
throw new ArgumentException ("'managedPeerType' must implement the IJavaPeerable interface.", nameof (managedPeerType));
4747

4848
#if !XA_INTEGRATION

src/Java.Interop/Java.Interop/JniRuntime.JniTypeManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ protected bool TryRegisterNativeMembers (JniType nativeClass, Type type, string
226226

227227
static bool TryLoadJniMarshalMethods (JniType nativeClass, Type type, string methods)
228228
{
229-
var marshalType = type.GetTypeInfo ()?.GetDeclaredNestedType ("__<$>_jni_marshal_methods")?.AsType ();
230-
if (marshalType == null || !(marshalType is Type))
229+
var marshalType = type?.GetNestedType ("__<$>_jni_marshal_methods", BindingFlags.NonPublic);
230+
if (marshalType == null)
231231
return false;
232232

233233
var registerMethod = marshalType.GetRuntimeMethod ("__RegisterNativeMembers", registerMethodParameters);

src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Linq.Expressions;
@@ -260,7 +260,7 @@ public virtual IJavaPeerable CreatePeer (ref JniObjectReference reference, JniOb
260260
targetType = targetType ?? typeof (JavaObject);
261261
targetType = GetPeerType (targetType);
262262

263-
if (!typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ()))
263+
if (!typeof (IJavaPeerable).IsAssignableFrom (targetType))
264264
throw new ArgumentException ($"targetType `{targetType.AssemblyQualifiedName}` must implement IJavaPeerable!", nameof (targetType));
265265

266266
var ctor = GetPeerConstructor (reference, targetType);
@@ -321,7 +321,7 @@ ConstructorInfo GetPeerConstructor (JniObjectReference instance, Type fallbackTy
321321
static ConstructorInfo GetActivationConstructor (Type type)
322322
{
323323
return
324-
(from c in type.GetTypeInfo ().DeclaredConstructors
324+
(from c in type.GetConstructors (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
325325
let p = c.GetParameters ()
326326
where p.Length == 2 && p [0].ParameterType == ByRefJniObjectReference && p [1].ParameterType == typeof (JniObjectReferenceOptions)
327327
select c)
@@ -337,7 +337,7 @@ public object CreateValue (ref JniObjectReference reference, JniObjectReferenceO
337337
if (!reference.IsValid)
338338
return null;
339339

340-
if (targetType != null && typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ())) {
340+
if (targetType != null && typeof (IJavaPeerable).IsAssignableFrom (targetType)) {
341341
return JavaPeerableValueMarshaler.Instance.CreateGenericValue (ref reference, options, targetType);
342342
}
343343

@@ -366,7 +366,7 @@ public T CreateValue<T> (ref JniObjectReference reference, JniObjectReferenceOpt
366366
if (!reference.IsValid)
367367
return default (T);
368368

369-
if (targetType != null && !typeof (T).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ()))
369+
if (targetType != null && !typeof (T).IsAssignableFrom (targetType))
370370
throw new ArgumentException (
371371
string.Format ("Requested runtime '{0}' value of '{1}' is not compatible with requested compile-time type T of '{2}'.",
372372
nameof (targetType),
@@ -382,7 +382,7 @@ public T CreateValue<T> (ref JniObjectReference reference, JniObjectReferenceOpt
382382

383383
targetType = targetType ?? typeof (T);
384384

385-
if (typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ())) {
385+
if (typeof (IJavaPeerable).IsAssignableFrom (targetType)) {
386386
return (T) JavaPeerableValueMarshaler.Instance.CreateGenericValue (ref reference, options, targetType);
387387
}
388388

@@ -407,12 +407,12 @@ public object GetValue (ref JniObjectReference reference, JniObjectReferenceOpti
407407
return null;
408408

409409
var existing = PeekValue (reference);
410-
if (existing != null && (targetType == null || targetType.GetTypeInfo ().IsAssignableFrom (existing.GetType ().GetTypeInfo ()))) {
410+
if (existing != null && (targetType == null || targetType.IsAssignableFrom (existing.GetType ()))) {
411411
JniObjectReference.Dispose (ref reference, options);
412412
return existing;
413413
}
414414

415-
if (targetType != null && typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ())) {
415+
if (targetType != null && typeof (IJavaPeerable).IsAssignableFrom (targetType)) {
416416
return JavaPeerableValueMarshaler.Instance.CreateGenericValue (ref reference, options, targetType);
417417
}
418418

@@ -436,7 +436,7 @@ public T GetValue<T> (ref JniObjectReference reference, JniObjectReferenceOption
436436
if (!reference.IsValid)
437437
return default (T);
438438

439-
if (targetType != null && !typeof (T).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ()))
439+
if (targetType != null && !typeof (T).IsAssignableFrom (targetType))
440440
throw new ArgumentException (
441441
string.Format ("Requested runtime '{0}' value of '{1}' is not compatible with requested compile-time type T of '{2}'.",
442442
nameof (targetType),
@@ -447,12 +447,12 @@ public T GetValue<T> (ref JniObjectReference reference, JniObjectReferenceOption
447447
targetType = targetType ?? typeof (T);
448448

449449
var existing = PeekValue (reference);
450-
if (existing != null && (targetType == null || targetType.GetTypeInfo ().IsAssignableFrom (existing.GetType ().GetTypeInfo ()))) {
450+
if (existing != null && (targetType == null || targetType.IsAssignableFrom (existing.GetType ()))) {
451451
JniObjectReference.Dispose (ref reference, options);
452452
return (T) existing;
453453
}
454454

455-
if (typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (targetType.GetTypeInfo ())) {
455+
if (typeof (IJavaPeerable).IsAssignableFrom (targetType)) {
456456
return (T) JavaPeerableValueMarshaler.Instance.CreateGenericValue (ref reference, options, targetType);
457457
}
458458

@@ -486,11 +486,10 @@ public JniValueMarshaler GetValueMarshaler (Type type)
486486

487487
if (type == null)
488488
throw new ArgumentNullException (nameof (type));
489-
var info = type.GetTypeInfo ();
490-
if (info.ContainsGenericParameters)
489+
if (type.ContainsGenericParameters)
491490
throw new ArgumentException ("Generic type definitions are not supported.", nameof (type));
492491

493-
var marshalerAttr = info.GetCustomAttribute<JniValueMarshalerAttribute> ();
492+
var marshalerAttr = type.GetCustomAttribute<JniValueMarshalerAttribute> ();
494493
if (marshalerAttr != null)
495494
return (JniValueMarshaler) Activator.CreateInstance (marshalerAttr.MarshalerType);
496495

@@ -505,32 +504,31 @@ public JniValueMarshaler GetValueMarshaler (Type type)
505504
return marshaler.Value;
506505
}
507506

508-
var listIface = typeof(IList<>).GetTypeInfo ();
507+
var listIface = typeof (IList<>);
509508
var listType =
510-
(from iface in info.ImplementedInterfaces.Concat (new[]{type})
511-
let iinfo = iface.GetTypeInfo ()
512-
where (listIface).IsAssignableFrom (iinfo.IsGenericType ? iinfo.GetGenericTypeDefinition ().GetTypeInfo () : iinfo)
513-
select iinfo)
509+
(from iface in type.GetInterfaces ().Concat (new[]{type})
510+
where (listIface).IsAssignableFrom (iface.IsGenericType ? iface.GetGenericTypeDefinition () : iface)
511+
select iface)
514512
.FirstOrDefault ();
515513
if (listType != null) {
516514
var elementType = listType.GenericTypeArguments [0];
517-
if (elementType.GetTypeInfo ().IsValueType) {
515+
if (elementType.IsValueType) {
518516
foreach (var marshaler in JniPrimitiveArrayMarshalers.Value) {
519-
if (info.IsAssignableFrom (marshaler.Key.GetTypeInfo ()))
517+
if (type.IsAssignableFrom (marshaler.Key))
520518
return marshaler.Value;
521519
}
522520
}
523521

524522
return GetObjectArrayMarshaler (elementType);
525523
}
526524

527-
if (typeof (IJavaPeerable).GetTypeInfo ().IsAssignableFrom (info)) {
525+
if (typeof (IJavaPeerable).IsAssignableFrom (type)) {
528526
return JavaPeerableValueMarshaler.Instance;
529527
}
530528

531529
JniValueMarshalerAttribute ifaceAttribute = null;
532-
foreach (var iface in info.ImplementedInterfaces) {
533-
marshalerAttr = iface.GetTypeInfo ().GetCustomAttribute<JniValueMarshalerAttribute> ();
530+
foreach (var iface in type.GetInterfaces ()) {
531+
marshalerAttr = iface.GetCustomAttribute<JniValueMarshalerAttribute> ();
534532
if (marshalerAttr != null) {
535533
if (ifaceAttribute != null)
536534
throw new NotSupportedException ($"There is more than one interface with custom marshaler for type {type}.");

src/Java.Interop/Java.Interop/JniRuntime.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,7 @@ public virtual string GetCurrentManagedThreadStackTrace (int skipFrames = 0, boo
277277

278278
public virtual void FailFast (string message)
279279
{
280-
var t = typeof (Environment).GetTypeInfo ();
281-
var m = t.DeclaredMethods.FirstOrDefault (x => x.Name == "FailFast");
280+
var m = typeof (Environment).GetMethod ("FailFast");
282281
m.Invoke (null, new object[]{ message });
283282
}
284283

src/Java.Interop/Java.Interop/JniValueMarshalerAttribute.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Reflection;
33

44
namespace Java.Interop {
@@ -15,7 +15,7 @@ public JniValueMarshalerAttribute (Type marshalerType)
1515
{
1616
if (marshalerType == null)
1717
throw new ArgumentNullException (nameof (marshalerType));
18-
if (!typeof (JniValueMarshaler).GetTypeInfo ().IsAssignableFrom (marshalerType.GetTypeInfo ()))
18+
if (!typeof (JniValueMarshaler).IsAssignableFrom (marshalerType))
1919
throw new ArgumentException (
2020
string.Format ("`{0}` must inherit from JniValueMarshaler!", marshalerType.FullName),
2121
nameof (marshalerType));

src/Java.Interop/Java.Interop/ManagedPeer.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Diagnostics;
33
using System.Linq;
44
using System.Linq.Expressions;
@@ -83,17 +83,16 @@ static void Construct (
8383
}
8484

8585
var type = Type.GetType (JniEnvironment.Strings.ToString (n_assemblyQualifiedName), throwOnError: true);
86-
var info = type.GetTypeInfo ();
87-
if (info.IsGenericTypeDefinition) {
86+
if (type.IsGenericTypeDefinition) {
8887
throw new NotSupportedException (
8988
"Constructing instances of generic types from Java is not supported, as the type parameters cannot be determined.",
9089
CreateJniLocationException ());
9190
}
9291

9392
var ptypes = GetParameterTypes (JniEnvironment.Strings.ToString (n_constructorSignature));
9493
var pvalues = GetValues (runtime, new JniObjectReference (n_constructorArguments), ptypes);
95-
var ctor = info.DeclaredConstructors
96-
.FirstOrDefault (c => !c.IsStatic &&
94+
var ctor = type.GetConstructors (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
95+
.FirstOrDefault (c =>
9796
c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (ptypes));
9897
if (ctor == null) {
9998
throw CreateMissingConstructorException (type, ptypes);

0 commit comments

Comments
 (0)