// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; namespace Internal.IL.Stubs { /// /// Thunk that replaces calls to MethodBase.GetCurrentMethod in user code. The purpose of the thunk /// is to LDTOKEN the method considered "current method" and call into the class library to /// retrieve the associated MethodBase object instance. /// internal sealed partial class MethodBaseGetCurrentMethodThunk : ILStubMethod { public MethodBaseGetCurrentMethodThunk(MethodDesc method) { Debug.Assert(method.IsTypicalMethodDefinition); Method = method; Signature = new MethodSignature(MethodSignatureFlags.Static, 0, Context.SystemModule.GetKnownType("System.Reflection", "MethodBase"), TypeDesc.EmptyTypes); } public override TypeSystemContext Context { get { return Method.Context; } } public MethodDesc Method { get; } public override string Name { get { return Method.Name; } } public override string DiagnosticName { get { return Method.DiagnosticName; } } public override TypeDesc OwningType { get { return Method.OwningType; } } public override MethodSignature Signature { get; } public override MethodIL EmitIL() { ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); codeStream.Emit(ILOpcode.ldtoken, emit.NewToken(Method)); string helperName; if (Method.OwningType.HasInstantiation) { codeStream.Emit(ILOpcode.ldtoken, emit.NewToken(Method.OwningType)); helperName = "GetCurrentMethodGeneric"; } else helperName = "GetCurrentMethodNonGeneric"; MethodDesc classlibHelper = Context.GetHelperEntryPoint("ReflectionHelpers", helperName); codeStream.Emit(ILOpcode.call, emit.NewToken(classlibHelper)); codeStream.Emit(ILOpcode.ret); return emit.Link(this); } } internal sealed class MethodBaseGetCurrentMethodThunkCache { private Unifier _cache; public MethodBaseGetCurrentMethodThunkCache() { _cache = new Unifier(); } public MethodDesc GetHelper(MethodDesc currentMethod) { return _cache.GetOrCreateValue(currentMethod.GetTypicalMethodDefinition()); } private sealed class Unifier : LockFreeReaderHashtable { protected override int GetKeyHashCode(MethodDesc key) { return key.GetHashCode(); } protected override int GetValueHashCode(MethodBaseGetCurrentMethodThunk value) { return value.Method.GetHashCode(); } protected override bool CompareKeyToValue(MethodDesc key, MethodBaseGetCurrentMethodThunk value) { return key == value.Method; } protected override bool CompareValueToValue(MethodBaseGetCurrentMethodThunk value1, MethodBaseGetCurrentMethodThunk value2) { return value1.Method == value2.Method; } protected override MethodBaseGetCurrentMethodThunk CreateValueFromKey(MethodDesc key) { return new MethodBaseGetCurrentMethodThunk(key); } } } }