From 5b7837926a0c04a2ff1329622bcb8b26151940ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Sun, 24 Mar 2019 19:51:36 +0100 Subject: [PATCH] Make default comparers a removable feature Adding to make it possible to work around current problems in #7208 when reflection is disabled. Comparers also root the entire type loader, so making this optional puts as on a path where we can make type loader optional too. Type loader is about 500 kB of junk. If we can remove it, our Hello world size becomes competitive with Go. People who are willing to walk the extra mile to make their code compatible with this get very small deployment sizes that are especially important for e.g. the WASM target. --- src/ILCompiler/src/Program.cs | 2 ++ src/ILCompiler/src/RemovingILProvider.cs | 40 +++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs index 5efabc2d5ad..5d1ddae6fd4 100644 --- a/src/ILCompiler/src/Program.cs +++ b/src/ILCompiler/src/Program.cs @@ -493,6 +493,8 @@ private int Run(string[] args) removedFeatures |= RemovedFeature.FrameworkResources; else if (feature == "Globalization") removedFeatures |= RemovedFeature.Globalization; + else if (feature == "Comparers") + removedFeatures |= RemovedFeature.Comparers; } ILProvider ilProvider = _isReadyToRunCodeGen ? (ILProvider)new ReadyToRunILProvider() : new CoreRTILProvider(); diff --git a/src/ILCompiler/src/RemovingILProvider.cs b/src/ILCompiler/src/RemovingILProvider.cs index 9beb2cf4d19..3d0b4c23adc 100644 --- a/src/ILCompiler/src/RemovingILProvider.cs +++ b/src/ILCompiler/src/RemovingILProvider.cs @@ -23,7 +23,8 @@ public RemovingILProvider(ILProvider baseILProvider, RemovedFeature feature) public override MethodIL GetMethodIL(MethodDesc method) { - switch (GetAction(method)) + RemoveAction action = GetAction(method); + switch (action) { case RemoveAction.Nothing: return _baseILProvider.GetMethodIL(method); @@ -48,6 +49,26 @@ public override MethodIL GetMethodIL(MethodDesc method) case RemoveAction.ConvertToThrow: return new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty(), null); + case RemoveAction.ConvertToGetKnownObjectComparer: + case RemoveAction.ConvertToGetKnownObjectEqualityComparer: + { + TypeSystemContext context = method.Context; + MetadataType comparerType = + action == RemoveAction.ConvertToGetKnownObjectComparer ? + context.SystemModule.GetType("System.Collections.Generic", "ObjectComparer`1") : + context.SystemModule.GetType("System.Collections.Generic", "ObjectEqualityComparer`1"); + + MethodDesc methodDef = method.GetTypicalMethodDefinition(); + + ILEmitter emitter = new ILEmitter(); + ILCodeStream codeStream = emitter.NewCodeStream(); + codeStream.Emit(ILOpcode.newobj, emitter.NewToken(comparerType.MakeInstantiatedType(context.GetSignatureVariable(0, method: false)).GetDefaultConstructor())); + codeStream.Emit(ILOpcode.dup); + codeStream.Emit(ILOpcode.stsfld, emitter.NewToken(methodDef.OwningType.InstantiateAsOpen().GetField("_default"))); + codeStream.Emit(ILOpcode.ret); + return new InstantiatedMethodIL(method, emitter.Link(methodDef)); + } + default: throw new NotImplementedException(); } @@ -131,6 +152,20 @@ owningType is Internal.TypeSystem.Ecma.EcmaType mdType && } } + if ((_removedFeature & RemovedFeature.Comparers) != 0) + { + if (owningType.GetTypeDefinition() is Internal.TypeSystem.Ecma.EcmaType mdType + && mdType.Module == method.Context.SystemModule + && method.Name == "Create" + && mdType.Namespace == "System.Collections.Generic") + { + if (mdType.Name == "EqualityComparer`1") + return RemoveAction.ConvertToGetKnownObjectEqualityComparer; + else if (mdType.Name == "Comparer`1") + return RemoveAction.ConvertToGetKnownObjectComparer; + } + } + return RemoveAction.Nothing; } @@ -170,6 +205,8 @@ private enum RemoveAction ConvertToTrueStub, ConvertToGetResourceStringStub, + ConvertToGetKnownObjectComparer, + ConvertToGetKnownObjectEqualityComparer, } } @@ -179,5 +216,6 @@ public enum RemovedFeature Etw = 0x1, FrameworkResources = 0x2, Globalization = 0x4, + Comparers = 0x8, } }