Skip to content

[TrimmableTypeMap] TypeMap assembly + JCW Java source generators #10799

@simonrozsival

Description

@simonrozsival

Part of #10789
Depends on: Scanner sub-issue (PR1)

Overview

Implement the IL assembly generator and JCW Java source generator that transform JavaPeerInfo scan results into:

  1. Per-assembly typemap assemblies + root _Microsoft.Android.TypeMaps.dll — using SRM Ecma335 APIs
  2. JCW Java source files — with registerNatives in static {} blocks

TypeMap Assembly Generator (TypeMapAssemblyGenerator)

Uses SRM types: MetadataBuilder, BlobBuilder, InstructionEncoder, ControlFlowBuilder, MethodBodyStreamEncoder, PEHeaderBuilder.

Generated assembly contents

Assembly-level attributes:

  • [assembly: IgnoresAccessChecksTo("Mono.Android")] etc. for all referenced assemblies
  • [assembly: TypeMap<Java.Lang.Object>("jni/name", typeof(Proxy), typeof(TrimTarget))] — one per type
  • [assembly: TypeMapAssociation<AliasesUniverse>(typeof(Source), typeof(AliasHolder))] — for aliases

Per-type proxy classesJavaPeerProxyAttribute subclasses:

  • Self-application: [Proxy] class Proxy : JavaPeerProxyAttribute
  • CreateInstance(IntPtr, JniHandleOwnership):
    • MCW with own ctor: new T(handle, transfer)
    • User type without own ctor: GetUninitializedObject(T) + direct call to base ctor (via IgnoresAccessChecksTo)
    • Interface: new TInvoker(handle, transfer)
    • Generic: throw new NotSupportedException()
  • GetContainerFactory(): return JavaPeerContainerFactory.Create<T>()
  • For ACW types: IAndroidCallableWrapper.RegisterNatives(JniType) + GetFunctionPointer(int)
  • [UnmanagedCallersOnly] UCO methods (delegation or inlined)

Per-assembly output model (for incremental builds):

  • One typemap assembly per input assembly with Java peer types
  • Root assembly uses [assembly: TypeMapAssemblyTarget<JLO>(assemblyName)] to reference per-assembly typemaps
  • Alias detection and cross-ref forcing handled in root assembly

JCW Java Source Generator (JcwJavaSourceGenerator)

Generates .java files for ACW types (DoNotGenerateAcw=false):

package example;
public class MainActivity extends android.app.Activity
    implements mono.android.IGCUserPeer
{
    static { mono.android.Runtime.registerNatives(MainActivity.class); }

    public MainActivity() { super(); if (getClass() == MainActivity.class) nctor_0(); }
    private native void nctor_0();

    @Override
    public void onCreate(android.os.Bundle p0) { n_onCreate(p0); }
    public native void n_onCreate(android.os.Bundle p0);
}

Key: generate Java class and IL proxy from the same ordered method list to ensure RegisterNatives connects the right native methods to the right UCO methods.

Tests

  • Produces valid PE assembly loadable by MetadataReader
  • Generated assembly has correct TypeMapAttribute entries (2-arg and 3-arg)
  • Proxy types have correct self-application pattern
  • CreateInstance IL is valid for each ctor style
  • RegisterNatives method has correct JNI registrations
  • UCO wrappers have [UnmanagedCallersOnly] attribute
  • Non-blittable params converted correctly (byte for bool)
  • Java source has registerNatives in static {} block
  • Correct nctor_N declarations and @Override annotations
  • Package names from [Register], not CRC-hashed

Metadata

Metadata

Assignees

Labels

Area: CoreCLRIssues that only occur when using CoreCLR.Area: NativeAOTIssues that only occur when using NativeAOT.needs-triageIssues that need to be assigned.trimmable-type-map

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions