public static EcmaModule Create(TypeSystemContext context, PEReader peReader, PdbSymbolReader pdbReader) { MetadataReader metadataReader = CreateMetadataReader(context, peReader); if (metadataReader.IsAssembly) return new EcmaAssembly(context, peReader, metadataReader, pdbReader); else return new EcmaModule(context, peReader, metadataReader, pdbReader); }
/// <summary> /// Returns JIT helper entrypoint. JIT helpers can be either implemented by entrypoint with given mangled name or /// by a method in class library. /// </summary> public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, out string mangledName, out MethodDesc methodDesc) { mangledName = null; methodDesc = null; switch (id) { case ReadyToRunHelper.Throw: mangledName = "RhpThrowEx"; break; case ReadyToRunHelper.Rethrow: mangledName = "RhpRethrow"; break; case ReadyToRunHelper.Overflow: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowOverflowException"); break; case ReadyToRunHelper.RngChkFail: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowIndexOutOfRangeException"); break; case ReadyToRunHelper.FailFast: mangledName = "__fail_fast"; // TODO: Report stack buffer overrun break; case ReadyToRunHelper.ThrowNullRef: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowNullReferenceException"); break; case ReadyToRunHelper.ThrowDivZero: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowDivideByZeroException"); break; case ReadyToRunHelper.ThrowArgumentOutOfRange: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowArgumentOutOfRangeException"); break; case ReadyToRunHelper.ThrowArgument: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowArgumentException"); break; case ReadyToRunHelper.ThrowPlatformNotSupported: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException"); break; case ReadyToRunHelper.ThrowNotImplemented: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowNotImplementedException"); break; case ReadyToRunHelper.DebugBreak: mangledName = "RhDebugBreak"; break; case ReadyToRunHelper.WriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpAssignRefArm64" : "RhpAssignRef"; break; case ReadyToRunHelper.CheckedWriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpCheckedAssignRefArm64" : "RhpCheckedAssignRef"; break; case ReadyToRunHelper.ByRefWriteBarrier: mangledName = context.Target.Architecture == TargetArchitecture.ARM64 ? "RhpByRefAssignRefArm64" : "RhpByRefAssignRef"; break; case ReadyToRunHelper.WriteBarrier_EAX: mangledName = "RhpAssignRefEAX"; break; case ReadyToRunHelper.WriteBarrier_ECX: mangledName = "RhpAssignRefECX"; break; case ReadyToRunHelper.CheckedWriteBarrier_EAX: mangledName = "RhpCheckedAssignRefEAX"; break; case ReadyToRunHelper.CheckedWriteBarrier_ECX: mangledName = "RhpCheckedAssignRefECX"; break; case ReadyToRunHelper.Box: case ReadyToRunHelper.Box_Nullable: mangledName = "RhBox"; break; case ReadyToRunHelper.Unbox: mangledName = "RhUnbox2"; break; case ReadyToRunHelper.Unbox_Nullable: mangledName = "RhUnboxNullable"; break; case ReadyToRunHelper.NewMultiDimArr_NonVarArg: methodDesc = context.GetHelperEntryPoint("ArrayHelpers", "NewObjArray"); break; case ReadyToRunHelper.NewArray: mangledName = "RhNewArray"; break; case ReadyToRunHelper.NewObject: mangledName = "RhNewObject"; break; case ReadyToRunHelper.Stelem_Ref: mangledName = "RhpStelemRef"; break; case ReadyToRunHelper.Ldelema_Ref: mangledName = "RhpLdelemaRef"; break; case ReadyToRunHelper.MemCpy: mangledName = "memcpy"; // TODO: Null reference handling break; case ReadyToRunHelper.MemSet: mangledName = "memset"; // TODO: Null reference handling break; case ReadyToRunHelper.GetRuntimeTypeHandle: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeTypeHandle"); break; case ReadyToRunHelper.GetRuntimeType: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeType"); break; case ReadyToRunHelper.GetRuntimeMethodHandle: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeMethodHandle"); break; case ReadyToRunHelper.GetRuntimeFieldHandle: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeFieldHandle"); break; case ReadyToRunHelper.AreTypesEquivalent: mangledName = "RhTypeCast_AreTypesEquivalent"; break; case ReadyToRunHelper.Lng2Dbl: mangledName = "RhpLng2Dbl"; break; case ReadyToRunHelper.ULng2Dbl: mangledName = "RhpULng2Dbl"; break; case ReadyToRunHelper.Dbl2Lng: mangledName = "RhpDbl2Lng"; break; case ReadyToRunHelper.Dbl2ULng: mangledName = "RhpDbl2ULng"; break; case ReadyToRunHelper.Dbl2Int: mangledName = "RhpDbl2Int"; break; case ReadyToRunHelper.Dbl2UInt: mangledName = "RhpDbl2UInt"; break; case ReadyToRunHelper.Dbl2IntOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2IntOvf"); break; case ReadyToRunHelper.Dbl2UIntOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2UIntOvf"); break; case ReadyToRunHelper.Dbl2LngOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2LngOvf"); break; case ReadyToRunHelper.Dbl2ULngOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2ULngOvf"); break; case ReadyToRunHelper.DblRem: mangledName = "RhpDblRem"; break; case ReadyToRunHelper.FltRem: mangledName = "RhpFltRem"; break; case ReadyToRunHelper.DblRound: mangledName = "RhpDblRound"; break; case ReadyToRunHelper.FltRound: mangledName = "RhpFltRound"; break; case ReadyToRunHelper.LMul: mangledName = "RhpLMul"; break; case ReadyToRunHelper.LMulOfv: methodDesc = context.GetHelperEntryPoint("MathHelpers", "LMulOvf"); break; case ReadyToRunHelper.ULMulOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "ULMulOvf"); break; case ReadyToRunHelper.Mod: methodDesc = context.GetHelperEntryPoint("MathHelpers", "IMod"); break; case ReadyToRunHelper.UMod: methodDesc = context.GetHelperEntryPoint("MathHelpers", "UMod"); break; case ReadyToRunHelper.ULMod: methodDesc = context.GetHelperEntryPoint("MathHelpers", "ULMod"); break; case ReadyToRunHelper.LMod: methodDesc = context.GetHelperEntryPoint("MathHelpers", "LMod"); break; case ReadyToRunHelper.Div: methodDesc = context.GetHelperEntryPoint("MathHelpers", "IDiv"); break; case ReadyToRunHelper.UDiv: methodDesc = context.GetHelperEntryPoint("MathHelpers", "UDiv"); break; case ReadyToRunHelper.ULDiv: methodDesc = context.GetHelperEntryPoint("MathHelpers", "ULDiv"); break; case ReadyToRunHelper.LDiv: methodDesc = context.GetHelperEntryPoint("MathHelpers", "LDiv"); break; case ReadyToRunHelper.LRsz: mangledName = "RhpLRsz"; break; case ReadyToRunHelper.LRsh: mangledName = "RhpLRsh"; break; case ReadyToRunHelper.LLsh: mangledName = "RhpLLsh"; break; case ReadyToRunHelper.PInvokeBegin: mangledName = "RhpPInvoke"; break; case ReadyToRunHelper.PInvokeEnd: mangledName = "RhpPInvokeReturn"; break; case ReadyToRunHelper.ReversePInvokeEnter: mangledName = "RhpReversePInvoke2"; break; case ReadyToRunHelper.ReversePInvokeExit: mangledName = "RhpReversePInvokeReturn2"; break; case ReadyToRunHelper.CheckCastAny: mangledName = "RhTypeCast_CheckCast"; break; case ReadyToRunHelper.CheckInstanceAny: mangledName = "RhTypeCast_IsInstanceOf"; break; case ReadyToRunHelper.CheckCastInterface: mangledName = "RhTypeCast_CheckCastInterface"; break; case ReadyToRunHelper.CheckInstanceInterface: mangledName = "RhTypeCast_IsInstanceOfInterface"; break; case ReadyToRunHelper.CheckCastClass: mangledName = "RhTypeCast_CheckCastClass"; break; case ReadyToRunHelper.CheckInstanceClass: mangledName = "RhTypeCast_IsInstanceOfClass"; break; case ReadyToRunHelper.CheckCastArray: mangledName = "RhTypeCast_CheckCastArray"; break; case ReadyToRunHelper.CheckInstanceArray: mangledName = "RhTypeCast_IsInstanceOfArray"; break; case ReadyToRunHelper.MonitorEnter: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorEnter"); break; case ReadyToRunHelper.MonitorExit: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorExit"); break; case ReadyToRunHelper.MonitorEnterStatic: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorEnterStatic"); break; case ReadyToRunHelper.MonitorExitStatic: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorExitStatic"); break; case ReadyToRunHelper.GVMLookupForSlot: methodDesc = context.SystemModule.GetKnownType("System.Runtime", "TypeLoaderExports").GetKnownMethod("GVMLookupForSlot", null); break; case ReadyToRunHelper.TypeHandleToRuntimeType: methodDesc = context.GetHelperEntryPoint("TypedReferenceHelpers", "TypeHandleToRuntimeTypeMaybeNull"); break; case ReadyToRunHelper.GetRefAny: methodDesc = context.GetHelperEntryPoint("TypedReferenceHelpers", "GetRefAny"); break; case ReadyToRunHelper.TypeHandleToRuntimeTypeHandle: methodDesc = context.GetHelperEntryPoint("TypedReferenceHelpers", "TypeHandleToRuntimeTypeHandleMaybeNull"); break; default: throw new NotImplementedException(id.ToString()); } }
/// <summary> /// Returns JIT helper entrypoint. JIT helpers can be either implemented by entrypoint with given mangled name or /// by a method in class library. /// </summary> static public void GetEntryPoint(TypeSystemContext context, JitHelperId id, out string mangledName, out MethodDesc methodDesc) { mangledName = null; methodDesc = null; switch (id) { case JitHelperId.Throw: mangledName = "RhpThrowEx"; break; case JitHelperId.Rethrow: mangledName = "RhpRethrow"; break; case JitHelperId.Overflow: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowOverflowException"); break; case JitHelperId.RngChkFail: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowIndexOutOfRangeException"); break; case JitHelperId.FailFast: mangledName = "__fail_fast"; // TODO: Report stack buffer overrun break; case JitHelperId.ThrowNullRef: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowNullReferenceException"); break; case JitHelperId.ThrowDivZero: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowDivideByZeroException"); break; case JitHelperId.WriteBarrier: mangledName = "RhpAssignRef"; break; case JitHelperId.CheckedWriteBarrier: mangledName = "RhpCheckedAssignRef"; break; case JitHelperId.ByRefWriteBarrier: mangledName = "RhpByRefAssignRef"; break; case JitHelperId.NewMultiDimArr: mangledName = "RhNewMDArray"; break; case JitHelperId.Stelem_Ref: mangledName = "RhpStelemRef"; break; case JitHelperId.Ldelema_Ref: mangledName = "RhpLdelemaRef"; break; case JitHelperId.MemCpy: mangledName = "memcpy"; // TODO: Null reference handling break; case JitHelperId.MemSet: mangledName = "memset"; // TODO: Null reference handling break; case JitHelperId.GetRuntimeTypeHandle: // TODO: Reflection case JitHelperId.GetRuntimeMethodHandle: case JitHelperId.GetRuntimeFieldHandle: mangledName = "__fail_fast"; break; default: throw new NotImplementedException(id.ToString()); } }
public CustomCanonResolver(TypeSystemContext wrappedContext) { _canonModule = new CanonModule(wrappedContext); _canonModuleName = _canonModule.GetName(); _wrappedResolver = wrappedContext; }
/// <summary> /// Parse MIbcGroup method and return enumerable of MethodProfileData /// /// Like the AssemblyDictionary method, data is encoded via IL instructions. The format is /// /// ldtoken methodInProfileData /// Any series of instructions that does not include pop. Expansion data is encoded via ldstr "id" /// followed by a expansion specific sequence of il opcodes. /// pop /// {Repeat N times for N methods described} /// /// Extensions supported with current parser: /// /// ldstr "ExclusiveWeight" /// Any ldc.i4 or ldc.r4 or ldc.r8 instruction to indicate the exclusive weight /// /// ldstr "WeightedCallData" /// ldc.i4 <Count of methods called> /// Repeat <Count of methods called times> /// ldtoken <Method called from this method> /// ldc.i4 <Weight associated with calling the <Method called from this method>> /// /// This format is designed to be extensible to hold more data as we add new per method profile data without breaking existing parsers. /// </summary> static IEnumerable <MethodProfileData> ReadMIbcGroup(TypeSystemContext tsc, EcmaMethod method) { EcmaMethodIL ilBody = EcmaMethodIL.Create(method); MetadataLoaderForPgoData metadataLoader = new MetadataLoaderForPgoData(ilBody); ILReader ilReader = new ILReader(ilBody.GetILBytes()); object methodInProgress = null; object metadataNotResolvable = new object(); object metadataObject = null; MibcGroupParseState state = MibcGroupParseState.LookingForNextMethod; int intValue = 0; int weightedCallGraphSize = 0; int profileEntryFound = 0; double exclusiveWeight = 0; Dictionary <MethodDesc, int> weights = null; bool processIntValue = false; List <long> instrumentationDataLongs = null; PgoSchemaElem[] pgoSchemaData = null; while (ilReader.HasNext) { ILOpcode opcode = ilReader.ReadILOpcode(); processIntValue = false; switch (opcode) { case ILOpcode.ldtoken: { int token = ilReader.ReadILToken(); if (state == MibcGroupParseState.ProcessingInstrumentationData) { instrumentationDataLongs.Add(token); } else { metadataObject = null; try { metadataObject = ilBody.GetObject(token, NotFoundBehavior.ReturnNull); if (metadataObject == null) { metadataObject = metadataNotResolvable; } } catch (TypeSystemException) { // The method being referred to may be missing. In that situation, // use the metadataNotResolvable sentinel to indicate that this record should be ignored metadataObject = metadataNotResolvable; } switch (state) { case MibcGroupParseState.ProcessingCallgraphToken: state = MibcGroupParseState.ProcessingCallgraphWeight; break; case MibcGroupParseState.LookingForNextMethod: methodInProgress = metadataObject; state = MibcGroupParseState.LookingForOptionalData; break; default: state = MibcGroupParseState.LookingForOptionalData; break; } } } break; case ILOpcode.ldc_r4: { float fltValue = ilReader.ReadILFloat(); switch (state) { case MibcGroupParseState.ProcessingExclusiveWeight: exclusiveWeight = fltValue; state = MibcGroupParseState.LookingForOptionalData; break; default: state = MibcGroupParseState.LookingForOptionalData; break; } break; } case ILOpcode.ldc_r8: { double dblValue = ilReader.ReadILDouble(); switch (state) { case MibcGroupParseState.ProcessingExclusiveWeight: exclusiveWeight = dblValue; state = MibcGroupParseState.LookingForOptionalData; break; default: state = MibcGroupParseState.LookingForOptionalData; break; } break; } case ILOpcode.ldc_i4_0: intValue = 0; processIntValue = true; break; case ILOpcode.ldc_i4_1: intValue = 1; processIntValue = true; break; case ILOpcode.ldc_i4_2: intValue = 2; processIntValue = true; break; case ILOpcode.ldc_i4_3: intValue = 3; processIntValue = true; break; case ILOpcode.ldc_i4_4: intValue = 4; processIntValue = true; break; case ILOpcode.ldc_i4_5: intValue = 5; processIntValue = true; break; case ILOpcode.ldc_i4_6: intValue = 6; processIntValue = true; break; case ILOpcode.ldc_i4_7: intValue = 7; processIntValue = true; break; case ILOpcode.ldc_i4_8: intValue = 8; processIntValue = true; break; case ILOpcode.ldc_i4_m1: intValue = -1; processIntValue = true; break; case ILOpcode.ldc_i4_s: intValue = (sbyte)ilReader.ReadILByte(); processIntValue = true; break; case ILOpcode.ldc_i4: intValue = (int)ilReader.ReadILUInt32(); processIntValue = true; break; case ILOpcode.ldc_i8: if (state == MibcGroupParseState.ProcessingInstrumentationData) { instrumentationDataLongs.Add((long)ilReader.ReadILUInt64()); } break; case ILOpcode.ldstr: { int userStringToken = ilReader.ReadILToken(); string optionalDataName = (string)ilBody.GetObject(userStringToken); switch (optionalDataName) { case "ExclusiveWeight": state = MibcGroupParseState.ProcessingExclusiveWeight; break; case "WeightedCallData": state = MibcGroupParseState.ProcessingCallgraphCount; break; case "InstrumentationDataStart": state = MibcGroupParseState.ProcessingInstrumentationData; instrumentationDataLongs = new List <long>(); break; case "InstrumentationDataEnd": if (instrumentationDataLongs != null) { instrumentationDataLongs.Add(2); // MarshalMask 2 (Type) instrumentationDataLongs.Add(0); // PgoInstrumentationKind.Done (0) pgoSchemaData = PgoProcessor.ParsePgoData <TypeSystemEntityOrUnknown>(metadataLoader, instrumentationDataLongs, false).ToArray(); } state = MibcGroupParseState.LookingForOptionalData; break; default: state = MibcGroupParseState.LookingForOptionalData; break; } } break; case ILOpcode.pop: if (methodInProgress != metadataNotResolvable) { profileEntryFound++; if (exclusiveWeight == 0) { // If no exclusive weight is found assign a non zero value that assumes the order in the pgo file is significant. exclusiveWeight = Math.Min(1000000.0 - profileEntryFound, 0.0) / 1000000.0; } if (methodInProgress != null) { // If the method being loaded didn't have meaningful input, skip MethodProfileData mibcData = new MethodProfileData((MethodDesc)methodInProgress, MethodProfilingDataFlags.ReadMethodCode, exclusiveWeight, weights, 0xFFFFFFFF, pgoSchemaData); yield return(mibcData); } state = MibcGroupParseState.LookingForNextMethod; exclusiveWeight = 0; weights = null; instrumentationDataLongs = null; pgoSchemaData = null; } methodInProgress = null; break; default: state = MibcGroupParseState.LookingForOptionalData; ilReader.Skip(opcode); break; } if (processIntValue) { switch (state) { case MibcGroupParseState.ProcessingExclusiveWeight: exclusiveWeight = intValue; state = MibcGroupParseState.LookingForOptionalData; break; case MibcGroupParseState.ProcessingCallgraphCount: weightedCallGraphSize = intValue; weights = new Dictionary <MethodDesc, int>(); if (weightedCallGraphSize > 0) { state = MibcGroupParseState.ProcessingCallgraphToken; } else { state = MibcGroupParseState.LookingForOptionalData; } break; case MibcGroupParseState.ProcessingCallgraphWeight: if (metadataObject != metadataNotResolvable) { weights.Add((MethodDesc)metadataObject, intValue); } weightedCallGraphSize--; if (weightedCallGraphSize > 0) { state = MibcGroupParseState.ProcessingCallgraphToken; } else { state = MibcGroupParseState.LookingForOptionalData; } break; case MibcGroupParseState.ProcessingInstrumentationData: instrumentationDataLongs.Add(intValue); break; default: state = MibcGroupParseState.LookingForOptionalData; instrumentationDataLongs = null; break; } } } }
public static bool IsSpecialUnboxingThunkTargetMethod(this TypeSystemContext context, MethodDesc method) { return(false); }
private static TypeDesc GetTypeThatMeetsConstraints(GenericParameterDesc genericParam, bool allowCanon) { TypeSystemContext context = genericParam.Context; // Universal canon is the best option if it's supported if (allowCanon && context.SupportsUniversalCanon) { return(context.UniversalCanonType); } // Not nullable type is the only thing where we can't substitute reference types GenericConstraints constraints = genericParam.Constraints; if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0) { return(null); } // If canon is allowed, we can use that if (allowCanon && context.SupportsCanon) { foreach (var c in genericParam.TypeConstraints) { // Could be e.g. "where T : U" // We could try to dig into the U and solve it, but that just opens us up to // recursion and it's just not worth it. if (c.IsSignatureVariable) { return(null); } if (!c.IsGCPointer) { return(null); } } return(genericParam.Context.CanonType); } // If canon is not allowed, we're limited in our choices. TypeDesc constrainedType = null; foreach (var c in genericParam.TypeConstraints) { // Can't do multiple constraints if (constrainedType != null) { return(null); } // Could be e.g. "where T : IFoo<U>" or "where T : U" if (c.ContainsSignatureVariables()) { return(null); } // If there's unimplemented static abstract methods, this is not a suitable instantiation. // We shortcut to look for any static virtuals. It matches what Roslyn does for error CS8920. // Once TypeSystemConstraintsHelpers is updated to check constraints around static virtuals, // we could dispatch there instead. if (c.IsInterface) { if (HasStaticVirtualMethods(c)) { return(null); } foreach (DefType intface in c.RuntimeInterfaces) { if (HasStaticVirtualMethods(intface)) { return(null); } }
public EcmaAssembly(TypeSystemContext context, PEReader peReader, MetadataReader metadataReader) : base(context, peReader, metadataReader) { _assemblyDefinition = metadataReader.GetAssemblyDefinition(); }
public static bool IsSystemGuid(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System", "Guid")); }
public static bool IsSystemDecimal(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System", "Decimal")); }
public static bool IsStringBuilder(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System.Text", "StringBuilder")); }
public static bool IsSystemDateTime(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System", "DateTime")); }
public static bool IsHandleRef(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System.Runtime.InteropServices", "HandleRef")); }
public static bool IsCriticalHandle(TypeSystemContext context, TypeDesc type) { return(IsOrDerivesFromType(type, GetCriticalHandle(context))); }
public MultiFileSharedCompilationModuleGroup(TypeSystemContext context, IEnumerable <ModuleDesc> compilationModuleSet) : base(context, compilationModuleSet) { }
internal EcmaModule(TypeSystemContext context, PEReader peReader, MetadataReader metadataReader, PdbSymbolReader pdbReader) : this(context, peReader, metadataReader) { PdbReader = pdbReader; }
public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System", "ArgIterator")); }
/// <summary> /// Attempts to resolve constrained call to <paramref name="interfaceMethod"/> into a concrete non-unboxing /// method on <paramref name="constrainedType"/>. /// The ability to resolve constraint methods is affected by the degree of code sharing we are performing /// for generic code. /// </summary> /// <returns>The resolved method or null if the constraint couldn't be resolved.</returns> public static MethodDesc TryResolveConstraintMethodApprox(this TypeDesc constrainedType, TypeDesc interfaceType, MethodDesc interfaceMethod, out bool forceRuntimeLookup) { forceRuntimeLookup = false; bool isStaticVirtualMethod = interfaceMethod.Signature.IsStatic; // We can't resolve constraint calls effectively for reference types, and there's // not a lot of perf. benefit in doing it anyway. if (!constrainedType.IsValueType && (!isStaticVirtualMethod || constrainedType.IsCanonicalDefinitionType(CanonicalFormKind.Any))) { return(null); } // Interface method may or may not be fully canonicalized here. // It would be canonical on the CoreCLR side so canonicalize here to keep the algorithms similar. Instantiation methodInstantiation = interfaceMethod.Instantiation; interfaceMethod = interfaceMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); // 1. Find the (possibly generic) method that would implement the // constraint if we were making a call on a boxed value type. TypeDesc canonType = constrainedType.ConvertToCanonForm(CanonicalFormKind.Specific); TypeSystemContext context = constrainedType.Context; MethodDesc genInterfaceMethod = interfaceMethod.GetMethodDefinition(); MethodDesc method = null; if (genInterfaceMethod.OwningType.IsInterface) { // Sometimes (when compiling shared generic code) // we don't have enough exact type information at JIT time // even to decide whether we will be able to resolve to an unboxed entry point... // To cope with this case we always go via the helper function if there's any // chance of this happening by checking for all interfaces which might possibly // be compatible with the call (verification will have ensured that // at least one of them will be) // Enumerate all potential interface instantiations int potentialMatchingInterfaces = 0; foreach (DefType potentialInterfaceType in canonType.RuntimeInterfaces) { if (potentialInterfaceType.ConvertToCanonForm(CanonicalFormKind.Specific) == interfaceType.ConvertToCanonForm(CanonicalFormKind.Specific)) { potentialMatchingInterfaces++; MethodDesc potentialInterfaceMethod = genInterfaceMethod; if (potentialInterfaceMethod.OwningType != potentialInterfaceType) { potentialInterfaceMethod = context.GetMethodForInstantiatedType( potentialInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)potentialInterfaceType); } if (isStaticVirtualMethod) { method = canonType.ResolveVariantInterfaceMethodToStaticVirtualMethodOnType(potentialInterfaceMethod); } else { method = canonType.ResolveInterfaceMethodToVirtualMethodOnType(potentialInterfaceMethod); } // See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod if (!isStaticVirtualMethod && method != null && !method.OwningType.IsValueType) { // We explicitly wouldn't want to abort if we found a default implementation. // The above resolution doesn't consider the default methods. Debug.Assert(!method.OwningType.IsInterface); return(null); } } } Debug.Assert(potentialMatchingInterfaces != 0); if (potentialMatchingInterfaces > 1) { // We have more potentially matching interfaces Debug.Assert(interfaceType.HasInstantiation); bool isExactMethodResolved = false; if (!interfaceType.IsCanonicalSubtype(CanonicalFormKind.Any) && !interfaceType.IsGenericDefinition && !constrainedType.IsCanonicalSubtype(CanonicalFormKind.Any) && !constrainedType.IsGenericDefinition) { // We have exact interface and type instantiations (no generic variables and __Canon used // anywhere) if (constrainedType.CanCastTo(interfaceType)) { // We can resolve to exact method MethodDesc exactInterfaceMethod = context.GetMethodForInstantiatedType( genInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceType); if (isStaticVirtualMethod) { method = constrainedType.ResolveVariantInterfaceMethodToStaticVirtualMethodOnType(exactInterfaceMethod); } else { method = constrainedType.ResolveVariantInterfaceMethodToVirtualMethodOnType(exactInterfaceMethod); } isExactMethodResolved = method != null; } } if (!isExactMethodResolved) { // We couldn't resolve the interface statically // Notify the caller that it should use runtime lookup // Note that we can leave pMD incorrect, because we will use runtime lookup forceRuntimeLookup = true; } } else { // If we can resolve the interface exactly then do so (e.g. when doing the exact // lookup at runtime, or when not sharing generic code). if (constrainedType.CanCastTo(interfaceType)) { MethodDesc exactInterfaceMethod = genInterfaceMethod; if (genInterfaceMethod.OwningType != interfaceType) { exactInterfaceMethod = context.GetMethodForInstantiatedType( genInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceType); } if (isStaticVirtualMethod) { method = constrainedType.ResolveVariantInterfaceMethodToStaticVirtualMethodOnType(exactInterfaceMethod); } else { method = constrainedType.ResolveVariantInterfaceMethodToVirtualMethodOnType(exactInterfaceMethod); } } } } else if (genInterfaceMethod.IsVirtual) { MethodDesc targetMethod = interfaceType.FindMethodOnTypeWithMatchingTypicalMethod(genInterfaceMethod); method = constrainedType.FindVirtualFunctionTargetMethodOnObjectType(targetMethod); } else { // The method will be null if calling a non-virtual instance // methods on System.Object, i.e. when these are used as a constraint. method = null; } // Default implementation logic, which only kicks in for default implementations when looking up on an exact interface target if (isStaticVirtualMethod && method == null && !genInterfaceMethod.IsAbstract && !constrainedType.IsCanonicalSubtype(CanonicalFormKind.Any)) { MethodDesc exactInterfaceMethod = genInterfaceMethod; if (genInterfaceMethod.OwningType != interfaceType) { exactInterfaceMethod = context.GetMethodForInstantiatedType( genInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceType); } method = exactInterfaceMethod; } if (method == null) { // Fall back to VSD return(null); } //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod // Only return a method if the value type itself declares the method, // otherwise we might get a method from Object or System.ValueType if (!isStaticVirtualMethod && !method.OwningType.IsValueType) { // Fall back to VSD return(null); } // We've resolved the method, ignoring its generic method arguments // If the method is a generic method then go and get the instantiated descriptor if (methodInstantiation.Length != 0) { method = method.MakeInstantiatedMethod(methodInstantiation); } Debug.Assert(method != null); return(method); }
public LibraryInitializers(TypeSystemContext context, IEnumerable <ModuleDesc> librariesWithInitalizers) { _context = context; _librariesWithInitializers = new List <ModuleDesc>(librariesWithInitalizers); }
public static bool HasLazyStaticConstructor(this TypeSystemContext context, TypeDesc type) { return(type.HasStaticConstructor); }
public MrtProcessedImportAddressTableNode(string exportTableToImportSymbol, TypeSystemContext context) : base("_ImportTable_" + exportTableToImportSymbol, "_ImportTable_end_" + exportTableToImportSymbol) { ExportTableToImportSymbol = exportTableToImportSymbol; _pointerSize = context.Target.PointerSize; }
/// <summary> /// Parse an MIBC file for the methods that are interesting. /// The version bubble must be specified and will describe the restrict the set of methods parsed to those relevant to the compilation /// The onlyDefinedInAssembly parameter is used to restrict the set of types parsed to include only those which are defined in a specific module. Specify null to allow definitions from all modules. /// This limited parsing is not necessarily an exact set of prevention, so detailed algorithms that work at the individual method level are still necessary, but this allows avoiding excessive parsing. /// /// The format of the Mibc file is that of a .NET dll, with a global method named "AssemblyDictionary". Inside of that file are a series of references that are broken up by which assemblies define the individual methods. /// These references are encoded as IL code that represents the details. /// The format of these IL instruction is as follows. /// /// ldstr mibcGroupName /// ldtoken mibcGroupMethod /// pop /// {Repeat the above pattern N times, once per Mibc group} /// /// See comment above ReadMIbcGroup for details of the group format /// /// The mibcGroupName is in the following format "Assembly_{definingAssemblyName};{OtherAssemblyName};{OtherAssemblyName};...; (OtherAssemblyName is ; delimited) /// /// </summary> /// <returns></returns> public static ProfileData ParseMIbcFile(TypeSystemContext tsc, PEReader peReader, HashSet <string> assemblyNamesInVersionBubble, string onlyDefinedInAssembly) { var mibcModule = EcmaModule.Create(tsc, peReader, null, null, new CustomCanonResolver(tsc)); var assemblyDictionary = (EcmaMethod)mibcModule.GetGlobalModuleType().GetMethod("AssemblyDictionary", null); IEnumerable <MethodProfileData> loadedMethodProfileData = Enumerable.Empty <MethodProfileData>(); EcmaMethodIL ilBody = EcmaMethodIL.Create(assemblyDictionary); ILReader ilReader = new ILReader(ilBody.GetILBytes()); string mibcGroupName = ""; while (ilReader.HasNext) { ILOpcode opcode = ilReader.ReadILOpcode(); switch (opcode) { case ILOpcode.ldstr: int userStringToken = ilReader.ReadILToken(); Debug.Assert(mibcGroupName == ""); if (mibcGroupName == "") { mibcGroupName = (string)ilBody.GetObject(userStringToken); } break; case ILOpcode.ldtoken: int token = ilReader.ReadILToken(); if (String.IsNullOrEmpty(mibcGroupName)) { break; } string[] assembliesByName = mibcGroupName.Split(';'); bool hasMatchingDefinition = (onlyDefinedInAssembly == null) || assembliesByName[0].Equals(onlyDefinedInAssembly); if (!hasMatchingDefinition) { break; } if (assemblyNamesInVersionBubble != null) { bool areAllEntriesInVersionBubble = true; foreach (string s in assembliesByName) { if (string.IsNullOrEmpty(s)) { continue; } if (!assemblyNamesInVersionBubble.Contains(s)) { areAllEntriesInVersionBubble = false; break; } } if (!areAllEntriesInVersionBubble) { break; } } loadedMethodProfileData = loadedMethodProfileData.Concat(ReadMIbcGroup(tsc, (EcmaMethod)ilBody.GetObject(token))); break; case ILOpcode.pop: mibcGroupName = ""; break; default: ilReader.Skip(opcode); break; } } return(new IBCProfileData(false, loadedMethodProfileData)); }
/// <summary> /// Retrieves method whose runtime handle is suitable for use with GVMLookupForSlot. /// </summary> public MethodDesc GetTargetOfGenericVirtualMethodCall(MethodDesc calledMethod) { // Should be a generic virtual method Debug.Assert(calledMethod.HasInstantiation && calledMethod.IsVirtual); // Needs to be either a concrete method, or a runtime determined form. Debug.Assert(!calledMethod.IsCanonicalMethod(CanonicalFormKind.Specific)); MethodDesc targetMethod = calledMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); MethodDesc targetMethodDefinition = targetMethod.GetMethodDefinition(); MethodDesc slotNormalizedMethodDefinition = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(targetMethodDefinition); // If the method defines the slot, we can use that. if (slotNormalizedMethodDefinition == targetMethodDefinition) { return(calledMethod); } // Normalize to the slot defining method MethodDesc slotNormalizedMethod = TypeSystemContext.GetInstantiatedMethod( slotNormalizedMethodDefinition, targetMethod.Instantiation); // Since the slot normalization logic modified what method we're looking at, we need to compute the new target of lookup. // // If we could use virtual method resolution logic with runtime determined methods, we wouldn't need what we're going // to do below. MethodDesc runtimeDeterminedSlotNormalizedMethod; if (!slotNormalizedMethod.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) { // If the owning type is not generic, we can use it as-is, potentially only replacing the runtime-determined // method instantiation part. runtimeDeterminedSlotNormalizedMethod = slotNormalizedMethod.GetMethodDefinition(); } else { // If we need a runtime lookup but a normalization to the slot defining method happened above, we need to compute // the runtime lookup in terms of the base type that introduced the slot. // // To do that, we walk the base hierarchy of the runtime determined thing, looking for a type definition that matches // the slot-normalized virtual method. We then find the method on that type. TypeDesc runtimeDeterminedOwningType = calledMethod.OwningType; Debug.Assert(!runtimeDeterminedOwningType.IsInterface); while (!slotNormalizedMethod.OwningType.HasSameTypeDefinition(runtimeDeterminedOwningType)) { TypeDesc runtimeDeterminedBaseTypeDefinition = runtimeDeterminedOwningType.GetTypeDefinition().BaseType; if (runtimeDeterminedBaseTypeDefinition.HasInstantiation) { runtimeDeterminedOwningType = runtimeDeterminedBaseTypeDefinition.InstantiateSignature(runtimeDeterminedOwningType.Instantiation, default); } else { runtimeDeterminedOwningType = runtimeDeterminedBaseTypeDefinition; } } // Now get the method on the newly found type Debug.Assert(runtimeDeterminedOwningType.HasInstantiation); runtimeDeterminedSlotNormalizedMethod = TypeSystemContext.GetMethodForInstantiatedType( slotNormalizedMethod.GetTypicalMethodDefinition(), (InstantiatedType)runtimeDeterminedOwningType); } return(TypeSystemContext.GetInstantiatedMethod(runtimeDeterminedSlotNormalizedMethod, calledMethod.Instantiation)); }
public CanonModule(TypeSystemContext wrappedContext) : base(wrappedContext, null) { }
public NodeFactory(TypeSystemContext typeSystemContext) { _targetDetails = typeSystemContext.Target; _typeSystemContext = typeSystemContext; CreateNodeCaches(); }
private void CreateNodeCaches() { _typeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) => { if (_compilationModuleGroup.ContainsType(type)) { if (type.IsGenericDefinition) { return(new GenericDefinitionEETypeNode(this, type)); } else { return(new EETypeNode(this, type)); } } else { return(new ExternEETypeSymbolNode(this, type)); } }); _constructedTypeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) => { if (_compilationModuleGroup.ContainsType(type)) { return(new ConstructedEETypeNode(this, type)); } else { return(new ExternEETypeSymbolNode(this, type)); } }); _clonedTypeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) => { // Only types that reside in other binaries should be cloned Debug.Assert(_compilationModuleGroup.ShouldReferenceThroughImportTable(type)); return(new ClonedConstructedEETypeNode(this, type)); }); _nonGCStatics = new NodeCache <MetadataType, NonGCStaticsNode>((MetadataType type) => { return(new NonGCStaticsNode(type, this)); }); _GCStatics = new NodeCache <MetadataType, GCStaticsNode>((MetadataType type) => { return(new GCStaticsNode(type)); }); _GCStaticIndirectionNodes = new NodeCache <MetadataType, EmbeddedObjectNode>((MetadataType type) => { ISymbolNode gcStaticsNode = TypeGCStaticsSymbol(type); Debug.Assert(gcStaticsNode is GCStaticsNode); return(GCStaticsRegion.NewNode((GCStaticsNode)gcStaticsNode)); }); _threadStatics = new NodeCache <MetadataType, ThreadStaticsNode>((MetadataType type) => { return(new ThreadStaticsNode(type, this)); }); _GCStaticEETypes = new NodeCache <GCPointerMap, GCStaticEETypeNode>((GCPointerMap gcMap) => { return(new GCStaticEETypeNode(Target, gcMap)); }); _readOnlyDataBlobs = new NodeCache <Tuple <Utf8String, byte[], int>, BlobNode>((Tuple <Utf8String, byte[], int> key) => { return(new BlobNode(key.Item1, ObjectNodeSection.ReadOnlyDataSection, key.Item2, key.Item3)); }, new BlobTupleEqualityComparer()); _externSymbols = new NodeCache <string, ExternSymbolNode>((string name) => { return(new ExternSymbolNode(name)); }); _pInvokeModuleFixups = new NodeCache <string, PInvokeModuleFixupNode>((string name) => { return(new PInvokeModuleFixupNode(name)); }); _pInvokeMethodFixups = new NodeCache <Tuple <string, string>, PInvokeMethodFixupNode>((Tuple <string, string> key) => { return(new PInvokeMethodFixupNode(key.Item1, key.Item2)); }); _methodEntrypoints = new NodeCache <MethodDesc, IMethodNode>(CreateMethodEntrypointNode); _unboxingStubs = new NodeCache <MethodDesc, IMethodNode>(CreateUnboxingStubNode); _fatFunctionPointers = new NodeCache <MethodDesc, FatFunctionPointerNode>(method => { return(new FatFunctionPointerNode(method)); }); _shadowConcreteMethods = new NodeCache <MethodDesc, IMethodNode>(method => { return(new ShadowConcreteMethodNode <MethodCodeNode>(method, (MethodCodeNode)MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))); }); _runtimeDeterminedMethods = new NodeCache <MethodDesc, IMethodNode>(method => { return(new RuntimeDeterminedMethodNode(method, MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))); }); _virtMethods = new NodeCache <MethodDesc, VirtualMethodUseNode>((MethodDesc method) => { return(new VirtualMethodUseNode(method)); }); _readyToRunHelpers = new NodeCache <Tuple <ReadyToRunHelperId, Object>, ISymbolNode>(CreateReadyToRunHelperNode); _genericReadyToRunHelpersFromDict = new NodeCache <Tuple <ReadyToRunHelperId, object, TypeSystemEntity>, ISymbolNode>(data => { return(new ReadyToRunGenericLookupFromDictionaryNode(this, data.Item1, data.Item2, data.Item3)); }); _genericReadyToRunHelpersFromType = new NodeCache <Tuple <ReadyToRunHelperId, object, TypeSystemEntity>, ISymbolNode>(data => { return(new ReadyToRunGenericLookupFromTypeNode(this, data.Item1, data.Item2, data.Item3)); }); _indirectionNodes = new NodeCache <ISymbolNode, IndirectionNode>(symbol => { return(new IndirectionNode(symbol)); }); _frozenStringNodes = new NodeCache <string, FrozenStringNode>((string data) => { return(new FrozenStringNode(data, Target)); }); _interfaceDispatchCells = new NodeCache <MethodDesc, InterfaceDispatchCellNode>((MethodDesc method) => { return(new InterfaceDispatchCellNode(method)); }); _interfaceDispatchMaps = new NodeCache <TypeDesc, InterfaceDispatchMapNode>((TypeDesc type) => { return(new InterfaceDispatchMapNode(type)); }); _interfaceDispatchMapIndirectionNodes = new NodeCache <TypeDesc, EmbeddedObjectNode>((TypeDesc type) => { var dispatchMap = InterfaceDispatchMap(type); return(DispatchMapTable.NewNodeWithSymbol(dispatchMap, (indirectionNode) => { dispatchMap.SetDispatchMapIndex(this, DispatchMapTable.IndexOfEmbeddedObject(indirectionNode)); })); }); _genericCompositions = new NodeCache <GenericCompositionDetails, GenericCompositionNode>((GenericCompositionDetails details) => { return(new GenericCompositionNode(details)); }); _eagerCctorIndirectionNodes = new NodeCache <MethodDesc, EmbeddedObjectNode>((MethodDesc method) => { Debug.Assert(method.IsStaticConstructor); Debug.Assert(TypeSystemContext.HasEagerStaticConstructor((MetadataType)method.OwningType)); return(EagerCctorTable.NewNode(MethodEntrypoint(method))); }); _vTableNodes = new NodeCache <TypeDesc, VTableSliceNode>((TypeDesc type ) => { if (CompilationModuleGroup.ShouldProduceFullType(type)) { return(new EagerlyBuiltVTableSliceNode(type)); } else { return(new LazilyBuiltVTableSliceNode(type)); } }); _methodGenericDictionaries = new NodeCache <MethodDesc, GenericDictionaryNode>(method => { return(new MethodGenericDictionaryNode(method)); }); _typeGenericDictionaries = new NodeCache <TypeDesc, GenericDictionaryNode>(type => { return(new TypeGenericDictionaryNode(type)); }); _genericDictionaryLayouts = new NodeCache <TypeSystemEntity, DictionaryLayoutNode>(methodOrType => { return(new DictionaryLayoutNode(methodOrType)); }); _stringAllocators = new NodeCache <MethodDesc, IMethodNode>(constructor => { return(new StringAllocatorMethodNode(constructor)); }); }
private static bool ResolveType(string name, ModuleDesc callingModule, out TypeDesc type, out ModuleDesc referenceModule) { // This can do enough resolution to resolve "Foo" or "Foo, Assembly, PublicKeyToken=...". // The reflection resolution rules are complicated. This is only needed for a heuristic, // not for correctness, so this shortcut is okay. type = null; referenceModule = null; int i = 0; // Consume type name part StringBuilder typeName = new StringBuilder(); StringBuilder typeNamespace = new StringBuilder(); while (i < name.Length && (char.IsLetterOrDigit(name[i]) || name[i] == '.' || name[i] == '`')) { if (name[i] == '.') { if (typeNamespace.Length > 0) { typeNamespace.Append('.'); } typeNamespace.Append(typeName); typeName.Clear(); } else { typeName.Append(name[i]); } i++; } // Consume any comma or white space while (i < name.Length && (name[i] == ' ' || name[i] == ',')) { i++; } // Consume assembly name StringBuilder assemblyName = new StringBuilder(); while (i < name.Length && (char.IsLetterOrDigit(name[i]) || name[i] == '.')) { assemblyName.Append(name[i]); i++; } TypeSystemContext context = callingModule.Context; // If the name was assembly-qualified, resolve the assembly // If it wasn't qualified, we resolve in the calling assembly referenceModule = callingModule; if (assemblyName.Length > 0) { referenceModule = context.ResolveAssembly(new AssemblyName(assemblyName.ToString()), false); if (referenceModule == null) { return(false); } } // Resolve type in the assembly type = referenceModule.GetType(typeNamespace.ToString(), typeName.ToString(), false); // If it didn't resolve and wasn't assembly-qualified, we also try core library if (type == null && assemblyName.Length == 0) { referenceModule = context.SystemModule; type = referenceModule.GetType(typeNamespace.ToString(), typeName.ToString(), false); } return(type != null); }
/// <summary> /// Returns JIT helper entrypoint. JIT helpers can be either implemented by entrypoint with given mangled name or /// by a method in class library. /// </summary> public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, out string mangledName, out MethodDesc methodDesc) { mangledName = null; methodDesc = null; switch (id) { case ReadyToRunHelper.Throw: mangledName = "RhpThrowEx"; break; case ReadyToRunHelper.Rethrow: mangledName = "RhpRethrow"; break; case ReadyToRunHelper.Overflow: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowOverflowException"); break; case ReadyToRunHelper.RngChkFail: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowIndexOutOfRangeException"); break; case ReadyToRunHelper.FailFast: mangledName = "__fail_fast"; // TODO: Report stack buffer overrun break; case ReadyToRunHelper.ThrowNullRef: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowNullReferenceException"); break; case ReadyToRunHelper.ThrowDivZero: methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowDivideByZeroException"); break; case ReadyToRunHelper.DebugBreak: mangledName = "RhDebugBreak"; break; case ReadyToRunHelper.WriteBarrier: mangledName = "RhpAssignRef"; break; case ReadyToRunHelper.CheckedWriteBarrier: mangledName = "RhpCheckedAssignRef"; break; case ReadyToRunHelper.ByRefWriteBarrier: mangledName = "RhpByRefAssignRef"; break; case ReadyToRunHelper.Box: case ReadyToRunHelper.Box_Nullable: mangledName = "RhBox"; break; case ReadyToRunHelper.Unbox: mangledName = "RhUnbox2"; break; case ReadyToRunHelper.Unbox_Nullable: mangledName = "RhUnboxNullable"; break; case ReadyToRunHelper.NewMultiDimArr_NonVarArg: methodDesc = context.GetHelperEntryPoint("ArrayHelpers", "NewObjArray"); break; case ReadyToRunHelper.NewArray: mangledName = "RhNewArray"; break; case ReadyToRunHelper.NewObject: mangledName = "RhNewObject"; break; case ReadyToRunHelper.Stelem_Ref: mangledName = "RhpStelemRef"; break; case ReadyToRunHelper.Ldelema_Ref: mangledName = "RhpLdelemaRef"; break; case ReadyToRunHelper.MemCpy: mangledName = "memcpy"; // TODO: Null reference handling break; case ReadyToRunHelper.MemSet: mangledName = "memset"; // TODO: Null reference handling break; case ReadyToRunHelper.GetRuntimeTypeHandle: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeTypeHandle"); break; case ReadyToRunHelper.GetRuntimeMethodHandle: methodDesc = context.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeMethodHandle"); break; case ReadyToRunHelper.GetRuntimeFieldHandle: // TODO: Reflection mangledName = "__fail_fast"; break; case ReadyToRunHelper.Lng2Dbl: mangledName = "RhpLng2Dbl"; break; case ReadyToRunHelper.ULng2Dbl: mangledName = "RhpULng2Dbl"; break; case ReadyToRunHelper.Dbl2Lng: mangledName = "RhpDbl2Lng"; break; case ReadyToRunHelper.Dbl2ULng: mangledName = "RhpDbl2ULng"; break; case ReadyToRunHelper.Dbl2IntOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2IntOvf"); break; case ReadyToRunHelper.Dbl2UIntOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2UIntOvf"); break; case ReadyToRunHelper.Dbl2LngOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2LngOvf"); break; case ReadyToRunHelper.Dbl2ULngOvf: methodDesc = context.GetHelperEntryPoint("MathHelpers", "Dbl2ULngOvf"); break; case ReadyToRunHelper.DblRem: mangledName = "RhpDblRem"; break; case ReadyToRunHelper.FltRem: mangledName = "RhpFltRem"; break; case ReadyToRunHelper.PInvokeBegin: mangledName = "RhpPInvoke"; break; case ReadyToRunHelper.PInvokeEnd: mangledName = "RhpPInvokeReturn"; break; case ReadyToRunHelper.ReversePInvokeEnter: mangledName = "RhpReversePInvoke2"; break; case ReadyToRunHelper.ReversePInvokeExit: mangledName = "RhpReversePInvokeReturn2"; break; case ReadyToRunHelper.CheckCastAny: mangledName = "RhTypeCast_CheckCast2"; break; case ReadyToRunHelper.CheckInstanceAny: mangledName = "RhTypeCast_IsInstanceOf2"; break; case ReadyToRunHelper.MonitorEnter: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorEnter"); break; case ReadyToRunHelper.MonitorExit: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorExit"); break; case ReadyToRunHelper.MonitorEnterStatic: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorEnterStatic"); break; case ReadyToRunHelper.MonitorExitStatic: methodDesc = context.GetHelperEntryPoint("SynchronizedMethodHelpers", "MonitorExitStatic"); break; default: throw new NotImplementedException(id.ToString()); } }
private bool ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { if (IsPregeneratedOrTemplateRuntimeTypeHandle(targetTypeHandle)) { // If the target type isn't dynamic, or at least is template type generated, the static lookup logic is what we want. return(ResolveGenericVirtualMethodTarget_Static(targetTypeHandle, declaringTypeHandle, genericArguments, callingMethodNameAndSignature, out methodPointer, out dictionaryPointer)); } else { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING methodPointer = IntPtr.Zero; dictionaryPointer = IntPtr.Zero; TypeSystemContext context = TypeSystemContextFactory.Create(); DefType targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle); // Method being called... MethodDesc targetVirtualMethod = ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(context, declaringTypeHandle, callingMethodNameAndSignature); if (targetVirtualMethod == null) { // If we can't find the method in the type system, it must only be present in the static environment. Search there instead. TypeSystemContextFactory.Recycle(context); return(ResolveGenericVirtualMethodTarget_Static(targetTypeHandle, declaringTypeHandle, genericArguments, callingMethodNameAndSignature, out methodPointer, out dictionaryPointer)); } MethodDesc dispatchMethod = targetType.FindVirtualFunctionTargetMethodOnObjectType(targetVirtualMethod); if (dispatchMethod == null) { return(false); } Instantiation targetMethodInstantiation = context.ResolveRuntimeTypeHandles(genericArguments); MethodDesc instantiatedDispatchMethod = dispatchMethod.Context.ResolveGenericMethodInstantiation(dispatchMethod.OwningType.IsValueType /* get the unboxing stub */, dispatchMethod.OwningType.GetClosestDefType(), dispatchMethod.NameAndSignature, targetMethodInstantiation, IntPtr.Zero, false); GenericDictionaryCell cell = GenericDictionaryCell.CreateMethodCell(instantiatedDispatchMethod, false); using (LockHolder.Hold(_typeLoaderLock)) { // Now that we hold the lock, we may find that existing types can now find // their associated RuntimeTypeHandle. Flush the type builder states as a way // to force the reresolution of RuntimeTypeHandles which couldn't be found before. context.FlushTypeBuilderStates(); TypeBuilder.ResolveSingleCell(cell, out methodPointer); } TypeSystemContextFactory.Recycle(context); return(true); #else methodPointer = IntPtr.Zero; dictionaryPointer = IntPtr.Zero; Environment.FailFast("GVM Resolution for non template or pregenerated type"); return(false); #endif } }
// // Lazily parse the method signature, and construct the call converter data // private void EnsureCallConversionInfoLoaded() { if (_signatureParsed) { return; } lock (this) { // Check if race was won by another thread and the signature got parsed if (_signatureParsed) { return; } TypeSystemContext context = TypeSystemContextFactory.Create(); { Instantiation typeInstantiation = Instantiation.Empty; Instantiation methodInstantiation = Instantiation.Empty; if (_typeArgs != null && _typeArgs.Length > 0) { typeInstantiation = context.ResolveRuntimeTypeHandles(_typeArgs); } if (_methodArgs != null && _methodArgs.Length > 0) { methodInstantiation = context.ResolveRuntimeTypeHandles(_methodArgs); } bool hasThis; TypeDesc[] parameters; bool[] paramsByRefForced; if (!TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature(context, _methodSignature, typeInstantiation, methodInstantiation, out hasThis, out parameters, out paramsByRefForced)) { Debug.Assert(false); Environment.FailFast("Failed to get type handles for parameters in method signature"); } Debug.Assert(parameters != null && parameters.Length >= 1); bool[] byRefParameters = new bool[parameters.Length]; RuntimeTypeHandle[] parameterHandles = new RuntimeTypeHandle[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { ByRefType parameterAsByRefType = parameters[j] as ByRefType; if (parameterAsByRefType != null) { parameterAsByRefType.ParameterType.RetrieveRuntimeTypeHandleIfPossible(); parameterHandles[j] = parameterAsByRefType.ParameterType.RuntimeTypeHandle; byRefParameters[j] = true; } else { parameters[j].RetrieveRuntimeTypeHandleIfPossible(); parameterHandles[j] = parameters[j].RuntimeTypeHandle; byRefParameters[j] = false; } Debug.Assert(!parameterHandles[j].IsNull()); } // Build thunk data TypeHandle thReturnType = new TypeHandle(CallConverterThunk.GetByRefIndicatorAtIndex(0, byRefParameters), parameterHandles[0]); TypeHandle[] thParameters = null; if (parameters.Length > 1) { thParameters = new TypeHandle[parameters.Length - 1]; for (int i = 1; i < parameters.Length; i++) { thParameters[i - 1] = new TypeHandle(CallConverterThunk.GetByRefIndicatorAtIndex(i, byRefParameters), parameterHandles[i]); } } _argIteratorData = new ArgIteratorData(hasThis, false, thParameters, thReturnType); // StandardToStandard thunks don't actually need any parameters to change their ABI // so don't force any params to be adjusted if (!StandardToStandardThunk) { _paramsByRefForced = paramsByRefForced; } } TypeSystemContextFactory.Recycle(context); _signatureParsed = true; } }
public bool HasLazyStaticConstructor(TypeDesc type) { return(TypeSystemContext.HasLazyStaticConstructor(type)); }
public ModuleDesc(TypeSystemContext context) { Context = context; }
protected override void PrepareRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout) { // GC statics start with a pointer to the "MethodTable" that signals the size and GCDesc to the GC layout.GcStatics.Size = context.Target.LayoutPointerSize; layout.ThreadGcStatics.Size = context.Target.LayoutPointerSize; }
private void CreateNodeCaches() { _typeSymbols = new NodeCache <TypeDesc, IEETypeNode>(CreateNecessaryTypeNode); _constructedTypeSymbols = new NodeCache <TypeDesc, IEETypeNode>(CreateConstructedTypeNode); _clonedTypeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) => { // Only types that reside in other binaries should be cloned Debug.Assert(_compilationModuleGroup.ShouldReferenceThroughImportTable(type)); return(new ClonedConstructedEETypeNode(this, type)); }); _importedTypeSymbols = new NodeCache <TypeDesc, IEETypeNode>((TypeDesc type) => { Debug.Assert(_compilationModuleGroup.ShouldReferenceThroughImportTable(type)); return(_importedNodeProvider.ImportedEETypeNode(this, type)); }); _nonGCStatics = new NodeCache <MetadataType, ISortableSymbolNode>((MetadataType type) => { if (_compilationModuleGroup.ContainsType(type) && !_compilationModuleGroup.ShouldReferenceThroughImportTable(type)) { return(new NonGCStaticsNode(type, this)); } else { return(_importedNodeProvider.ImportedNonGCStaticNode(this, type)); } }); _GCStatics = new NodeCache <MetadataType, ISortableSymbolNode>((MetadataType type) => { if (_compilationModuleGroup.ContainsType(type) && !_compilationModuleGroup.ShouldReferenceThroughImportTable(type)) { return(new GCStaticsNode(type)); } else { return(_importedNodeProvider.ImportedGCStaticNode(this, type)); } }); _GCStaticsPreInitDataNodes = new NodeCache <MetadataType, GCStaticsPreInitDataNode>((MetadataType type) => { ISymbolNode gcStaticsNode = TypeGCStaticsSymbol(type); Debug.Assert(gcStaticsNode is GCStaticsNode); return(((GCStaticsNode)gcStaticsNode).NewPreInitDataNode()); }); _GCStaticIndirectionNodes = new NodeCache <MetadataType, EmbeddedObjectNode>((MetadataType type) => { ISymbolNode gcStaticsNode = TypeGCStaticsSymbol(type); Debug.Assert(gcStaticsNode is GCStaticsNode); return(GCStaticsRegion.NewNode((GCStaticsNode)gcStaticsNode)); }); _threadStatics = new NodeCache <MetadataType, ISymbolDefinitionNode>(CreateThreadStaticsNode); _typeThreadStaticIndices = new NodeCache <MetadataType, TypeThreadStaticIndexNode>(type => { return(new TypeThreadStaticIndexNode(type)); }); _GCStaticEETypes = new NodeCache <GCPointerMap, GCStaticEETypeNode>((GCPointerMap gcMap) => { return(new GCStaticEETypeNode(Target, gcMap)); }); _readOnlyDataBlobs = new NodeCache <ReadOnlyDataBlobKey, BlobNode>(key => { return(new BlobNode(key.Name, ObjectNodeSection.ReadOnlyDataSection, key.Data, key.Alignment)); }); _externSymbols = new NodeCache <string, ExternSymbolNode>((string name) => { return(new ExternSymbolNode(name)); }); _pInvokeModuleFixups = new NodeCache <PInvokeModuleData, PInvokeModuleFixupNode>((PInvokeModuleData moduleData) => { return(new PInvokeModuleFixupNode(moduleData)); }); _pInvokeMethodFixups = new NodeCache <Tuple <PInvokeModuleData, string, PInvokeFlags>, PInvokeMethodFixupNode>((Tuple <PInvokeModuleData, string, PInvokeFlags> key) => { return(new PInvokeMethodFixupNode(key.Item1, key.Item2, key.Item3)); }); _methodEntrypoints = new NodeCache <MethodDesc, IMethodNode>(CreateMethodEntrypointNode); _unboxingStubs = new NodeCache <MethodDesc, IMethodNode>(CreateUnboxingStubNode); _methodAssociatedData = new NodeCache <IMethodNode, MethodAssociatedDataNode>(methodNode => { return(new MethodAssociatedDataNode(methodNode)); }); _fatFunctionPointers = new NodeCache <MethodKey, FatFunctionPointerNode>(method => { return(new FatFunctionPointerNode(method.Method, method.IsUnboxingStub)); }); _gvmDependenciesNode = new NodeCache <MethodDesc, GVMDependenciesNode>(method => { return(new GVMDependenciesNode(method)); }); _gvmTableEntries = new NodeCache <TypeDesc, TypeGVMEntriesNode>(type => { return(new TypeGVMEntriesNode(type)); }); _reflectableMethods = new NodeCache <MethodDesc, ReflectableMethodNode>(method => { return(new ReflectableMethodNode(method)); }); _shadowConcreteMethods = new NodeCache <MethodKey, IMethodNode>(methodKey => { MethodDesc canonMethod = methodKey.Method.GetCanonMethodTarget(CanonicalFormKind.Specific); if (methodKey.IsUnboxingStub) { return(new ShadowConcreteUnboxingThunkNode(methodKey.Method, MethodEntrypoint(canonMethod, true))); } else { return(new ShadowConcreteMethodNode(methodKey.Method, MethodEntrypoint(canonMethod))); } }); _runtimeDeterminedMethods = new NodeCache <MethodDesc, IMethodNode>(method => { return(new RuntimeDeterminedMethodNode(method, MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))); }); _virtMethods = new NodeCache <MethodDesc, VirtualMethodUseNode>((MethodDesc method) => { // We don't need to track virtual method uses for types that have a vtable with a known layout. // It's a waste of CPU time and memory. Debug.Assert(!VTable(method.OwningType).HasFixedSlots); return(new VirtualMethodUseNode(method)); }); _readyToRunHelpers = new NodeCache <ReadyToRunHelperKey, ISymbolNode>(CreateReadyToRunHelperNode); _genericReadyToRunHelpersFromDict = new NodeCache <ReadyToRunGenericHelperKey, ISymbolNode>(CreateGenericLookupFromDictionaryNode); _genericReadyToRunHelpersFromType = new NodeCache <ReadyToRunGenericHelperKey, ISymbolNode>(CreateGenericLookupFromTypeNode); _indirectionNodes = new NodeCache <ISortableSymbolNode, ISymbolNode>(indirectedNode => { return(new IndirectionNode(Target, indirectedNode, 0)); }); _frozenStringNodes = new NodeCache <string, FrozenStringNode>((string data) => { return(new FrozenStringNode(data, Target)); }); _frozenArrayNodes = new NodeCache <PreInitFieldInfo, FrozenArrayNode>((PreInitFieldInfo fieldInfo) => { return(new FrozenArrayNode(fieldInfo)); }); _interfaceDispatchCells = new NodeCache <DispatchCellKey, InterfaceDispatchCellNode>(callSiteCell => { return(new InterfaceDispatchCellNode(callSiteCell.Target, callSiteCell.CallsiteId)); }); _interfaceDispatchMaps = new NodeCache <TypeDesc, InterfaceDispatchMapNode>((TypeDesc type) => { return(new InterfaceDispatchMapNode(this, type)); }); _sealedVtableNodes = new NodeCache <TypeDesc, SealedVTableNode>((TypeDesc type) => { return(new SealedVTableNode(type)); }); _runtimeMethodHandles = new NodeCache <MethodDesc, RuntimeMethodHandleNode>((MethodDesc method) => { return(new RuntimeMethodHandleNode(method)); }); _runtimeFieldHandles = new NodeCache <FieldDesc, RuntimeFieldHandleNode>((FieldDesc field) => { return(new RuntimeFieldHandleNode(field)); }); _interfaceDispatchMapIndirectionNodes = new NodeCache <TypeDesc, EmbeddedObjectNode>((TypeDesc type) => { return(DispatchMapTable.NewNodeWithSymbol(InterfaceDispatchMap(type))); }); _genericCompositions = new NodeCache <GenericCompositionDetails, GenericCompositionNode>((GenericCompositionDetails details) => { return(new GenericCompositionNode(details)); }); _eagerCctorIndirectionNodes = new NodeCache <MethodDesc, EmbeddedObjectNode>((MethodDesc method) => { Debug.Assert(method.IsStaticConstructor); Debug.Assert(TypeSystemContext.HasEagerStaticConstructor((MetadataType)method.OwningType)); return(EagerCctorTable.NewNode(MethodEntrypoint(method))); }); _namedJumpStubNodes = new NodeCache <Tuple <string, ISymbolNode>, NamedJumpStubNode>((Tuple <string, ISymbolNode> id) => { return(new NamedJumpStubNode(id.Item1, id.Item2)); }); _delegateMarshalingDataNodes = new NodeCache <DefType, DelegateMarshallingDataNode>(type => { return(new DelegateMarshallingDataNode(type)); }); _structMarshalingDataNodes = new NodeCache <DefType, StructMarshallingDataNode>(type => { return(new StructMarshallingDataNode(type)); }); _vTableNodes = new NodeCache <TypeDesc, VTableSliceNode>((TypeDesc type ) => { if (CompilationModuleGroup.ShouldProduceFullVTable(type)) { return(new EagerlyBuiltVTableSliceNode(type)); } else { return(_vtableSliceProvider.GetSlice(type)); } }); _methodGenericDictionaries = new NodeCache <MethodDesc, ISortableSymbolNode>(method => { if (CompilationModuleGroup.ContainsMethodDictionary(method)) { return(new MethodGenericDictionaryNode(method, this)); } else { return(_importedNodeProvider.ImportedMethodDictionaryNode(this, method)); } }); _typeGenericDictionaries = new NodeCache <TypeDesc, ISortableSymbolNode>(type => { if (CompilationModuleGroup.ContainsTypeDictionary(type)) { Debug.Assert(!this.LazyGenericsPolicy.UsesLazyGenerics(type)); return(new TypeGenericDictionaryNode(type, this)); } else { return(_importedNodeProvider.ImportedTypeDictionaryNode(this, type)); } }); _typesWithMetadata = new NodeCache <MetadataType, TypeMetadataNode>(type => { return(new TypeMetadataNode(type)); }); _methodsWithMetadata = new NodeCache <MethodDesc, MethodMetadataNode>(method => { return(new MethodMetadataNode(method)); }); _fieldsWithMetadata = new NodeCache <FieldDesc, FieldMetadataNode>(field => { return(new FieldMetadataNode(field)); }); _modulesWithMetadata = new NodeCache <ModuleDesc, ModuleMetadataNode>(module => { return(new ModuleMetadataNode(module)); }); _genericDictionaryLayouts = new NodeCache <TypeSystemEntity, DictionaryLayoutNode>(_dictionaryLayoutProvider.GetLayout); _stringAllocators = new NodeCache <MethodDesc, IMethodNode>(constructor => { return(new StringAllocatorMethodNode(constructor)); }); NativeLayout = new NativeLayoutHelper(this); WindowsDebugData = new WindowsDebugDataHelper(this); }
internal EcmaAssembly(TypeSystemContext context, PEReader peReader, MetadataReader metadataReader, PdbSymbolReader pdbReader) : base(context, peReader, metadataReader, pdbReader) { _assemblyDefinition = metadataReader.GetAssemblyDefinition(); }