/// <summary> /// Try to resolve a virtual call to targetMethod to its implementation on instanceType. /// </summary> /// <param name="instanceType">non-interface type</param> /// <param name="targetMethod">non-generic virtual or interface method</param> /// <param name="methodAddress">function pointer resolved</param> /// <returns>true if successful</returns> public static bool TryDispatchMethodOnTarget(TypeDesc instanceType, MethodDesc targetMethod, out IntPtr methodAddress) { methodAddress = IntPtr.Zero; if (targetMethod == null) { return(false); } if (IsPregeneratedOrTemplateTypeLoaded(instanceType)) { if (targetMethod.OwningType.IsInterface) { ushort interfaceSlot; if (!TryGetInterfaceSlotNumberFromMethod(targetMethod, out interfaceSlot)) { return(false); } methodAddress = RuntimeAugments.ResolveDispatchOnType(instanceType.GetRuntimeTypeHandle(), targetMethod.OwningType.GetRuntimeTypeHandle(), interfaceSlot); Debug.Assert(methodAddress != IntPtr.Zero); // TODO! This should happen for ICastable dispatch... return(true); } else { unsafe { int vtableSlotIndex = LazyVTableResolver.VirtualMethodToSlotIndex(targetMethod); EEType *eeType = instanceType.GetRuntimeTypeHandle().ToEETypePtr(); IntPtr *vtableStart = (IntPtr *)(((byte *)eeType) + sizeof(EEType)); methodAddress = vtableStart[vtableSlotIndex]; return(true); } } } MethodDesc targetVirtualMethod = targetMethod; DefType instanceDefType = instanceType.GetClosestDefType(); // For interface resolution, its a two step process, first get the virtual slot if (targetVirtualMethod.OwningType.IsInterface) { TypeDesc instanceDefTypeToExamine; MethodDesc newlyFoundVirtualMethod = ResolveInterfaceMethodToVirtualMethod(instanceType, out instanceDefTypeToExamine, targetVirtualMethod); targetVirtualMethod = newlyFoundVirtualMethod; // The pregenerated type must be the one that implements the interface method // Call into Redhawk to deal with this. if ((newlyFoundVirtualMethod == null) && (instanceDefTypeToExamine != null)) { ushort interfaceSlot; if (!TryGetInterfaceSlotNumberFromMethod(targetMethod, out interfaceSlot)) { return(false); } methodAddress = RuntimeAugments.ResolveDispatchOnType(instanceDefTypeToExamine.GetRuntimeTypeHandle(), targetMethod.OwningType.GetRuntimeTypeHandle(), interfaceSlot); Debug.Assert(methodAddress != IntPtr.Zero); // TODO! This should happen for ICastable dispatch... return(true); } } // VirtualSlot can be null if the interface method isn't really implemented. This should never happen, but since our // type loader doesn't check all interface overloads at load time, it could happen if (targetVirtualMethod == null) { return(false); } // Resolve virtual method to exact method MethodDesc dispatchMethod = instanceDefType.FindVirtualFunctionTargetMethodOnObjectType(targetVirtualMethod); return(TryGetVTableCallableAddress(dispatchMethod, out methodAddress)); }
private static unsafe IntPtr ResolveCallOnValueType(IntPtr unused, IntPtr callDescIntPtr) #endif { NonGenericConstrainedCallDesc *callDesc = (NonGenericConstrainedCallDesc *)callDescIntPtr; IntPtr exactTarget = IntPtr.Zero; IntPtr targetOnTypeVtable = RuntimeAugments.ResolveDispatchOnType(callDesc->_constraintType, callDesc->_constrainedMethodType, callDesc->_constrainedMethodSlot); bool decodeUnboxing = true; if (!RuntimeAugments.IsInterface(callDesc->_constrainedMethodType)) { // Non-interface constrained call on a valuetype to a method that isn't GetHashCode/Equals/ToString?!?! if (callDesc->_constrainedMethodSlot > s_MaxObjectVTableSlot) { throw new NotSupportedException(); } RuntimeTypeHandle baseTypeHandle; bool gotBaseType = RuntimeAugments.TryGetBaseType(callDesc->_constraintType, out baseTypeHandle); Debug.Assert(gotBaseType); if (targetOnTypeVtable == RuntimeAugments.ResolveDispatchOnType(baseTypeHandle, callDesc->_constrainedMethodType, callDesc->_constrainedMethodSlot)) { // In this case, the valuetype does not override the base types implementation of ToString(), GetHashCode(), or Equals(object) decodeUnboxing = false; } } if (decodeUnboxing) { exactTarget = TypeLoaderEnvironment.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(targetOnTypeVtable, callDesc->_constraintType); } else { // Create a fat function pointer, where the instantiation argument is ConstraintType, and the target is BoxAndToString, BoxAndGetHashCode, or BoxAndEquals IntPtr realTarget; switch (callDesc->_constrainedMethodSlot) { case s_ToStringSlot: realTarget = s_boxAndToStringFuncPtr; break; case s_GetHashCodeSlot: realTarget = s_boxAndGetHashCodeFuncPtr; break; case s_EqualsSlot: realTarget = s_boxAndEqualsFuncPtr; break; default: throw new NotSupportedException(); } exactTarget = FunctionPointerOps.GetGenericMethodFunctionPointer(realTarget, callDesc->_constraintType.ToIntPtr()); } // Ensure that all threads will have their function pointers completely published before updating callDesc. // as the ExactTarget is read from callDesc by binder generated code without a barrier, we need a barrier here // to ensure that the new function pointer data is valid on all threads Interlocked.MemoryBarrier(); // Its possible for multiple threads to race to set exact target. Check to see we always set the same value if (callDesc->_exactTarget != IntPtr.Zero) { Debug.Assert(callDesc->_exactTarget == exactTarget); } callDesc->_exactTarget = exactTarget; return(exactTarget); }
protected sealed override Object GetFieldBypassCctor() { IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset); return(RuntimeAugments.LoadReferenceTypeField(fieldAddress)); }
// // 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(); { NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); if (_methodSignature.IsNativeLayoutSignature) { nativeLayoutContext._moduleHandle = RuntimeAugments.GetModuleFromPointer(_methodSignature.NativeLayoutSignature); } else { nativeLayoutContext._moduleHandle = _methodSignature.ModuleHandle; } nativeLayoutContext._typeSystemContext = context; nativeLayoutContext._typeArgumentHandles = Instantiation.Empty; nativeLayoutContext._methodArgumentHandles = Instantiation.Empty; if (_typeArgs != null && _typeArgs.Length > 0) { nativeLayoutContext._typeArgumentHandles = context.ResolveRuntimeTypeHandles(_typeArgs); } if (_methodArgs != null && _methodArgs.Length > 0) { nativeLayoutContext._methodArgumentHandles = context.ResolveRuntimeTypeHandles(_methodArgs); } bool hasThis; TypeDesc[] parameters; bool[] paramsByRefForced; if (!TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature(context, _methodSignature, nativeLayoutContext, 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; } }
/// <summary> /// Register all modules which were added (Registered) to the runtime and are not already registered with the TypeLoader. /// </summary> /// <param name="moduleType">Type to assign to all new modules.</param> public void RegisterNewModules(ModuleType moduleType) { // prevent multiple threads from registering modules concurrently using (LockHolder.Hold(_moduleRegistrationLock)) { // Fetch modules that have already been registered with the runtime int loadedModuleCount = RuntimeAugments.GetLoadedModules(null); TypeManagerHandle[] loadedModuleHandles = new TypeManagerHandle[loadedModuleCount]; int loadedModuleCountUpdated = RuntimeAugments.GetLoadedModules(loadedModuleHandles); Debug.Assert(loadedModuleCount == loadedModuleCountUpdated); LowLevelList <TypeManagerHandle> newModuleHandles = new LowLevelList <TypeManagerHandle>(loadedModuleHandles.Length); foreach (TypeManagerHandle moduleHandle in loadedModuleHandles) { // Skip already registered modules. int oldModuleIndex; if (_loadedModuleMap.HandleToModuleIndex.TryGetValue(moduleHandle, out oldModuleIndex)) { continue; } newModuleHandles.Add(moduleHandle); } // Copy existing modules to new dictionary int oldModuleCount = _loadedModuleMap.Modules.Length; ModuleInfo[] updatedModules = new ModuleInfo[oldModuleCount + newModuleHandles.Count]; if (oldModuleCount > 0) { Array.Copy(_loadedModuleMap.Modules, 0, updatedModules, 0, oldModuleCount); } for (int newModuleIndex = 0; newModuleIndex < newModuleHandles.Count; newModuleIndex++) { ModuleInfo newModuleInfo; unsafe { byte *pBlob; uint cbBlob; if (RuntimeAugments.FindBlob(newModuleHandles[newModuleIndex], (int)ReflectionMapBlob.EmbeddedMetadata, new IntPtr(&pBlob), new IntPtr(&cbBlob))) { newModuleInfo = new NativeFormatModuleInfo(newModuleHandles[newModuleIndex], moduleType, (IntPtr)pBlob, (int)cbBlob); } else { newModuleInfo = new ModuleInfo(newModuleHandles[newModuleIndex], moduleType); } } updatedModules[oldModuleCount + newModuleIndex] = newModuleInfo; if (_moduleRegistrationCallbacks != null) { _moduleRegistrationCallbacks(newModuleInfo); } } // Atomically update the module map _loadedModuleMap = new ModuleMap(updatedModules); } }
protected override bool IsValueTypeImpl() { return(RuntimeAugments.IsValueType(_typeHandle)); }
public override Type GetElementType() { if (RuntimeAugments.IsArrayType(_typeHandle) || RuntimeAugments.IsUnmanagedPointerType(_typeHandle) || RuntimeAugments.IsByRefType(_typeHandle)) { return(GetRuntimeTypeInfo(RuntimeAugments.GetRelatedParameterTypeHandle(_typeHandle))); } return(null); }
partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, ref AssemblyBindResult result, ref Exception exception, ref bool foundMatch) { lock (s_ecmaLoadedAssemblies) { for (int i = 0; i < s_ecmaLoadedAssemblies.Count; i++) { PEInfo info = s_ecmaLoadedAssemblies[i]; if (AssemblyNameMatches(refName, info.Name)) { if (foundMatch) { exception = new AmbiguousMatchException(); return; } result.EcmaMetadataReader = info.Reader; foundMatch = result.EcmaMetadataReader != null; // For failed matches, we will never be able to succeed, so return now if (!foundMatch) { return; } } } if (!foundMatch) { try { // Not found in already loaded list, attempt to source assembly from disk foreach (string filePath in FilePathsForAssembly(refName)) { FileStream ownedFileStream = null; PEReader ownedPEReader = null; try { if (!RuntimeAugments.FileExists(filePath)) { continue; } try { ownedFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); } catch (System.IO.IOException) { // Failure to open a file is not fundamentally an assembly load error, but it does indicate this file cannot be used continue; } ownedPEReader = new PEReader(ownedFileStream); // FileStream ownership transferred to ownedPEReader ownedFileStream = null; if (!ownedPEReader.HasMetadata) { continue; } MetadataReader reader = ownedPEReader.GetMetadataReader(); // Create AssemblyName from MetadataReader RuntimeAssemblyName runtimeAssemblyName = reader.GetAssemblyDefinition().ToRuntimeAssemblyName(reader).CanonicalizePublicKeyToken(); // If assembly name doesn't match, it isn't the one we're looking for. Continue to look for more assemblies if (!AssemblyNameMatches(refName, runtimeAssemblyName)) { continue; } // This is the one we are looking for, add it to the list of loaded assemblies PEInfo peinfo = new PEInfo(runtimeAssemblyName, reader, ownedPEReader); s_ecmaLoadedAssemblies.Add(peinfo); // At this point the PE reader is no longer owned by this code, but is owned by the s_ecmaLoadedAssemblies list PEReader pe = ownedPEReader; ownedPEReader = null; ModuleList moduleList = ModuleList.Instance; ModuleInfo newModuleInfo = new EcmaModuleInfo(moduleList.SystemModule.Handle, pe, reader); moduleList.RegisterModule(newModuleInfo); foundMatch = true; result.EcmaMetadataReader = peinfo.Reader; break; } finally { if (ownedFileStream != null) { ownedFileStream.Dispose(); } if (ownedPEReader != null) { ownedPEReader.Dispose(); } } } } catch (System.IO.IOException) { } catch (System.ArgumentException) { } catch (System.BadImageFormatException badImageFormat) { exception = badImageFormat; } // Cache missed lookups if (!foundMatch) { PEInfo peinfo = new PEInfo(refName, null, null); s_ecmaLoadedAssemblies.Add(peinfo); } } } }
protected sealed override Object UncheckedGetField(Object obj) { return(RuntimeAugments.LoadReferenceTypeField(obj, _offset)); }
public unsafe static IntPtr AllocateThunk(IntPtr commonStubAddress) { lock (s_Lock) { LowLevelList <ThunksTemplateMap> mappings; if (!s_ThunkMaps.TryGetValue(commonStubAddress, out mappings)) { s_ThunkMaps[commonStubAddress] = mappings = new LowLevelList <ThunksTemplateMap>(); } IntPtr thunkStub = GetThunkFromAllocatedPool(mappings, commonStubAddress); if (thunkStub == IntPtr.Zero) { // No available thunks, so we need a new mapping of the thunks template page IntPtr thunkBase = AsmCode.GetThunksBase(); Debug.Assert(thunkBase != IntPtr.Zero); IntPtr moduleHandle = RuntimeAugments.GetModuleFromTypeHandle(typeof(ThunkPool).TypeHandle); Debug.Assert(moduleHandle != IntPtr.Zero); int templateRva = (int)((long)thunkBase - (long)moduleHandle); Debug.Assert(templateRva % ALLOCATION_GRANULARITY == 0); IntPtr thunkMap = IntPtr.Zero; if (s_ThunksTemplate == IntPtr.Zero) { // First, we use the thunks directly from the thunks template sections in the module until all // thunks in that template are used up. thunkMap = moduleHandle + templateRva; s_ThunksTemplate = thunkMap; } else { // We've already used the thunks tempate in the module for some previous thunks, and we // cannot reuse it here. Now we need to create a new mapping of the thunks section in order to have // more thunks thunkMap = RuntimeImports.RhAllocateThunksFromTemplate(moduleHandle, templateRva, NUM_THUNK_BLOCKS * PAGE_SIZE * 2); if (thunkMap == IntPtr.Zero) { // We either ran out of memory and can't do anymore mappings of the thunks templates sections, // or we are using the managed runtime services fallback, which doesn't provide the // file mapping feature (ex: older version of mrt100.dll, or no mrt100.dll at all). // The only option is for the caller to attempt and recycle unused thunks to be able to // find some free entries. return(IntPtr.Zero); } } Debug.Assert(thunkMap != IntPtr.Zero && (long)thunkMap % ALLOCATION_GRANULARITY == 0); // Each mapping consists of multiple blocks of thunk stubs/data pairs. Keep track of those // so that we do not create a new mapping until all blocks in the sections we just mapped are consumed for (int i = 0; i < NUM_THUNK_BLOCKS; i++) { s_RecentlyMappedThunksBlock[i] = thunkMap + (PAGE_SIZE * i * 2); } s_RecentlyMappedThunksBlockIndex = 1; thunkStub = AllocateThunksTemplateMapFromMapping(thunkMap, commonStubAddress, mappings); } return(SetThumbBit(thunkStub)); } }
// Eager initialization called from LibraryInitializer for the assembly. internal static void Initialize() { Instance = new TypeLoaderEnvironment(); RuntimeAugments.InitializeLookups(new Callbacks()); NoStaticsData = (IntPtr)1; }
/// <summary> /// Locate and lazily load debug info for the native app module overlapping given /// virtual address. /// </summary> /// <param name="ip">Instruction pointer address (code address for the lookup)</param> /// <param name="rva">Output VA relative to module base</param> private static IDiaSession GetDiaSession(IntPtr ip, out int rva) { if (ip == IntPtr.Zero) { rva = -1; return(null); } IntPtr moduleBase = RuntimeAugments.GetModuleFromPointer(ip); if (moduleBase == IntPtr.Zero) { rva = -1; return(null); } rva = (int)(ip.ToInt64() - moduleBase.ToInt64()); if (s_loadedModules == null) { // Lazily create the parallel arrays s_loadedModules and s_perModuleDebugInfo int moduleCount = RuntimeAugments.GetLoadedModules(null); s_loadedModules = new IntPtr[moduleCount]; s_perModuleDebugInfo = new IDiaSession[moduleCount]; // Actually read the module addresses into the array RuntimeAugments.GetLoadedModules(s_loadedModules); } // Locate module index based on base address int moduleIndex = s_loadedModules.Length; do { if (--moduleIndex < 0) { return(null); } }while(s_loadedModules[moduleIndex] != moduleBase); IDiaSession diaSession = s_perModuleDebugInfo[moduleIndex]; if (diaSession != null) { return(diaSession); } string modulePath = RuntimeAugments.TryGetFullPathToApplicationModule(moduleBase); if (modulePath == null) { return(null); } int indexOfLastDot = modulePath.LastIndexOf('.'); if (indexOfLastDot == -1) { return(null); } IDiaDataSource diaDataSource = GetDiaDataSource(); if (diaDataSource == null) { return(null); } // Look for .pdb next to .exe / dll - if it's not there, bail. String pdbPath = modulePath.Substring(0, indexOfLastDot) + ".pdb"; int hr = diaDataSource.LoadDataFromPdb(pdbPath); if (hr != S_OK) { return(null); } hr = diaDataSource.OpenSession(out diaSession); if (hr != S_OK) { return(null); } s_perModuleDebugInfo[moduleIndex] = diaSession; return(diaSession); }
private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle); int hashCode = openCallingTypeHandle.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode(); #if GVM_RESOLUTION_TRACE Debug.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name); #endif foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(module, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader)) { continue; } NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(module, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) { continue; } NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(module); var lookup = gvmHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle)) { continue; } RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle)) { continue; } uint parsedCallingNameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature)) { continue; } uint parsedTargetMethodNameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); if (!TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer)) { var sb = new System.Text.StringBuilder(); sb.AppendLine("Generic virtual method pointer lookup failure."); sb.AppendLine(); sb.AppendLine("Declaring type handle: " + declaringType.LowLevelToStringRawEETypeAddress()); sb.AppendLine("Target type handle: " + targetTypeHandle.LowLevelToStringRawEETypeAddress()); sb.AppendLine("Method name: " + targetMethodNameAndSignature.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < genericArguments.Length; i++) { sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + genericArguments[i].LowLevelToStringRawEETypeAddress()); } Environment.FailFast(sb.ToString()); } return(true); } } return(false); }
public static object CreateInstance( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type, BindingFlags bindingAttr, Binder binder, object?[]?args, CultureInfo?culture, object?[]?activationAttributes) { if (type == null) { throw new ArgumentNullException(nameof(type)); } // If they didn't specify a lookup, then we will provide the default lookup. const BindingFlags LookupMask = (BindingFlags)0x000000FF; if ((bindingAttr & LookupMask) == 0) { bindingAttr |= BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance; } if (activationAttributes != null && activationAttributes.Length > 0) { throw new PlatformNotSupportedException(SR.NotSupported_ActivAttr); } type = type.UnderlyingSystemType; CreateInstanceCheckType(type); args ??= Array.Empty <object>(); int numArgs = args.Length; Type?[] argTypes = new Type[numArgs]; for (int i = 0; i < numArgs; i++) { argTypes[i] = args[i]?.GetType(); } ConstructorInfo[] candidates = type.GetConstructors(bindingAttr); ListBuilder <MethodBase> matches = new ListBuilder <MethodBase>(candidates.Length); for (int i = 0; i < candidates.Length; i++) { if (candidates[i].QualifiesBasedOnParameterCount(bindingAttr, CallingConventions.Any, argTypes)) { matches.Add(candidates[i]); } } if (matches.Count == 0) { if (numArgs == 0 && type.IsValueType) { return(RuntimeAugments.NewObject(type.TypeHandle)); } throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, type)); } binder ??= Type.DefaultBinder; MethodBase invokeMethod = binder.BindToMethod(bindingAttr, matches.ToArray(), ref args, null, culture, null, out object?state); if (invokeMethod.GetParametersNoCopy().Length == 0) { if (args.Length != 0) { Debug.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs); throw new NotSupportedException(SR.NotSupported_CallToVarArg); } // Desktop compat: CoreClr invokes a "fast-path" here (call Activator.CreateInstance(type, true)) that also // bypasses the binder.ReorderArgumentArray() call. That "fast-path" isn't a fast-path for us so we won't do that // but we'll still null out the "state" variable to bypass the Reorder call. // // The only time this matters at all is if (1) a third party binder is being used and (2) it actually reordered the array // which it shouldn't have done because (a) we didn't request it to bind arguments by name, and (b) it's kinda hard to // reorder a zero-length args array. But who knows what a third party binder will do if we make a call to it that we didn't // used to do, so we'll preserve the CoreClr order of calls just to be safe. state = null; } object result = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); if (state != null) { binder.ReorderArgumentArray(ref args, state); } return(result); }
protected override bool IsPointerImpl() { return(RuntimeAugments.IsUnmanagedPointerType(_typeHandle)); }
protected sealed override void UncheckedSetField(Object obj, Object value) { RuntimeAugments.StoreReferenceTypeField(obj, _offset, value); }
protected override bool IsPrimitiveImpl() { return(RuntimeAugments.IsPrimitive(_typeHandle)); }
private bool ResolveInterfaceGenericVirtualMethodSlot_Static(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature) { // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle; RuntimeTypeHandle[] targetTypeInstantiation; openTargetTypeHandle = GetOpenTypeDefinition(targetTypeHandle, out targetTypeInstantiation); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader)) { continue; } NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) { continue; } NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode()); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!openCallingTypeHandle.Equals(interfaceTypeHandle)) { continue; } uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken); if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature)) { continue; } // For each of the possible GVM slot targets for the current interface call, we will do the following: // // Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look // for ones that match the target object's type. // // Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target // provides an implementation for // // Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument // substitution (in case of a generic interface), and check if this interface signature is assignable from the // calling interface signature (from the name and sig input). if there is an exact match based on // interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface // type is compatible with the initial slots interface by means of variance. // This is done by calling the TypeLoaderEnvironment helper function. // // Example: // public interface IFoo<out T, out U> // { // string M1<V>(); // } // public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U> // { // string IFoo<T, U>.M1<V>() { ... } // public virtual string M1<V>() { ... } // } // public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T> // { // string IFoo<U, T>.M1<V>() { ... } // } // // GVM Table layout for IFoo<T, U>.M1<V>: // { // InterfaceTypeHandle = IFoo<T, U> // InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) } // GVMTargetSlots[] = // { // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo2<T, U> // ImplementingTypes = { // ImplementingTypeHandle = Foo2<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) } // } // }, // } // } // uint currentOffset = entryParser.Offset; // Non-variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false)) { return(true); } entryParser.Offset = currentOffset; // Variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true)) { return(true); } } } return(false); }
public override string ToString() { return(RuntimeAugments.GetLastResortString(_typeHandle)); }
private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle); int hashCode = openCallingTypeHandle.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode(); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader)) { continue; } NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) { continue; } NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle)) { continue; } RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle)) { continue; } uint parsedCallingNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature)) { continue; } uint parsedTargetMethodNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); return(TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer)); } } return(false); }
public TypeDesc ResolveRuntimeTypeHandle(RuntimeTypeHandle rtth) { TypeDesc returnedType; if (_runtimeTypeHandleResolutionCache.TryGetValue(rtth, out returnedType)) { return(returnedType); } if (rtth.Equals(CanonType.RuntimeTypeHandle)) { returnedType = CanonType; } else if (rtth.Equals(UniversalCanonType.RuntimeTypeHandle)) { returnedType = UniversalCanonType; } else if (RuntimeAugments.IsGenericTypeDefinition(rtth)) { returnedType = TryGetMetadataBasedTypeFromRuntimeTypeHandle_Uncached(rtth); if (returnedType == null) { unsafe { TypeDesc[] genericParameters = new TypeDesc[rtth.ToEETypePtr()->GenericArgumentCount]; for (int i = 0; i < genericParameters.Length; i++) { genericParameters[i] = GetSignatureVariable(i, false); } returnedType = new NoMetadataType(this, rtth, null, new Instantiation(genericParameters), rtth.GetHashCode()); } } } else if (RuntimeAugments.IsGenericType(rtth)) { RuntimeTypeHandle typeDefRuntimeTypeHandle; RuntimeTypeHandle[] genericArgRuntimeTypeHandles; typeDefRuntimeTypeHandle = RuntimeAugments.GetGenericInstantiation(rtth, out genericArgRuntimeTypeHandles); DefType typeDef = (DefType)ResolveRuntimeTypeHandle(typeDefRuntimeTypeHandle); Instantiation genericArgs = ResolveRuntimeTypeHandles(genericArgRuntimeTypeHandles); returnedType = ResolveGenericInstantiation(typeDef, genericArgs); } else if (RuntimeAugments.IsArrayType(rtth)) { RuntimeTypeHandle elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth); TypeDesc elementType = ResolveRuntimeTypeHandle(elementTypeHandle); unsafe { if (rtth.ToEETypePtr()->IsSzArray) { returnedType = GetArrayType(elementType); } else { returnedType = GetArrayType(elementType, rtth.ToEETypePtr()->ArrayRank); } } } else if (RuntimeAugments.IsUnmanagedPointerType(rtth)) { RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth); TypeDesc targetType = ResolveRuntimeTypeHandle(targetTypeHandle); returnedType = GetPointerType(targetType); } else if (RuntimeAugments.IsByRefType(rtth)) { RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth); TypeDesc targetType = ResolveRuntimeTypeHandle(targetTypeHandle); returnedType = GetByRefType(targetType); } else { returnedType = TryGetMetadataBasedTypeFromRuntimeTypeHandle_Uncached(rtth); if (returnedType == null) { returnedType = new NoMetadataType(this, rtth, null, Instantiation.Empty, rtth.GetHashCode()); } } // We either retrieved an existing DefType that is already registered with the runtime // or one that is not associated with an EEType yet. If it's not associated, associate it. if (returnedType.RuntimeTypeHandle.IsNull()) { TypeBuilderState state = returnedType.GetTypeBuilderStateIfExist(); bool skipStoringRuntimeTypeHandle = false; // If we've already attempted to lookup and failed to retrieve this type handle, we // may have already decided to create a new one. In that case, do not attempt to abort // that creation process as it may have already begun the process of type creation if (state != null && state.AttemptedAndFailedToRetrieveTypeHandle) { skipStoringRuntimeTypeHandle = true; } if (!skipStoringRuntimeTypeHandle) { returnedType.SetRuntimeTypeHandleUnsafe(rtth); } } _runtimeTypeHandleResolutionCache.Add(rtth, returnedType); return(returnedType.WithDebugName()); }
private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch) { uint numTargetImplementations = entryParser.GetUnsigned(); for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken); RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle)) { // Skip over signatures data for (uint l = 0; l < numIfaceSigs; l++) { entryParser.GetUnsigned(); } continue; } for (uint l = 0; l < numIfaceSigs; l++) { RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle); NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned())); IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr)) { Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller declaringType = targetTypeHandle; methodNameAndSignature = targetMethodNameAndSignature; return(true); } } } } } return(false); }
/// <summary> /// Register initially (eagerly) loaded modules. /// </summary> internal ModuleList() { _loadedModuleMap = new ModuleMap(new ModuleInfo[0]); _moduleRegistrationCallbacks = default(Action <ModuleInfo>); _moduleRegistrationLock = new Lock(); RegisterNewModules(ModuleType.Eager); TypeManagerHandle systemObjectModule = RuntimeAugments.GetModuleFromTypeHandle(RuntimeAugments.RuntimeTypeHandleOf <object>()); foreach (ModuleInfo m in _loadedModuleMap.Modules) { if (m.Handle == systemObjectModule) { _systemModule = m; break; } } }
protected override bool HasElementTypeImpl() { return(RuntimeAugments.IsArrayType(_typeHandle) || RuntimeAugments.IsUnmanagedPointerType(_typeHandle) || RuntimeAugments.IsByRefType(_typeHandle)); }
public static unsafe IntPtr Get(RuntimeTypeHandle constraintType, RuntimeTypeHandle constrainedMethodType, int constrainedMethodSlot, bool directConstrainedCall = false) { LowLevelDictionary <RuntimeTypeHandle, LowLevelList <IntPtr> > nonGenericConstrainedCallDescsDirect = directConstrainedCall ? s_nonGenericConstrainedCallDescsDirect : s_nonGenericConstrainedCallDescs; lock (nonGenericConstrainedCallDescsDirect) { // Get list of constrained call descs associated with a given type LowLevelList <IntPtr> associatedCallDescs; if (!nonGenericConstrainedCallDescsDirect.TryGetValue(constraintType, out associatedCallDescs)) { associatedCallDescs = new LowLevelList <IntPtr>(); nonGenericConstrainedCallDescsDirect.Add(constraintType, associatedCallDescs); } // Perform linear scan of associated call descs to see if one matches for (int i = 0; i < associatedCallDescs.Count; i++) { NonGenericConstrainedCallDesc *callDesc = (NonGenericConstrainedCallDesc *)associatedCallDescs[i]; Debug.Assert(constraintType.Equals(callDesc->_constraintType)); if (callDesc->_constrainedMethodSlot != constrainedMethodSlot) { continue; } if (!callDesc->_constrainedMethodType.Equals(constrainedMethodType)) { continue; } // Found matching entry. return(associatedCallDescs[i]); } // Did not find match, allocate a new one and add it to the lookup list IntPtr newCallDescPtr = MemoryHelpers.AllocateMemory(sizeof(NonGenericConstrainedCallDesc)); NonGenericConstrainedCallDesc *newCallDesc = (NonGenericConstrainedCallDesc *)newCallDescPtr; newCallDesc->_exactTarget = IntPtr.Zero; if (directConstrainedCall) { newCallDesc->_lookupFunc = RuntimeAugments.GetUniversalTransitionThunk(); } else { if (RuntimeAugments.IsValueType(constraintType)) { newCallDesc->_lookupFunc = s_resolveCallOnValueTypeFuncPtr; } else { newCallDesc->_lookupFunc = s_resolveCallOnReferenceTypeFuncPtr; } } newCallDesc->_constraintType = constraintType; newCallDesc->_constrainedMethodSlot = constrainedMethodSlot; newCallDesc->_constrainedMethodType = constrainedMethodType; associatedCallDescs.Add(newCallDescPtr); return(newCallDescPtr); } }
protected override bool IsArrayImpl() { return(RuntimeAugments.IsArrayType(_typeHandle)); }
/// <summary> /// Eager startup initialization of stack trace metadata support creates /// the per-module method name resolver hashtable and registers the runtime augment /// for metadata-based stack trace resolution. /// </summary> internal static void Initialize() { _perModuleMethodNameResolverHashtable = new PerModuleMethodNameResolverHashtable(); RuntimeAugments.InitializeStackTraceMetadataSupport(new StackTraceMetadataCallbacksImpl()); }
protected override bool IsByRefImpl() { return(RuntimeAugments.IsByRefType(_typeHandle)); }
protected sealed override void UncheckedSetFieldBypassCctor(Object value) { IntPtr fieldAddress = RuntimeAugments.GetThreadStaticFieldAddress(DeclaringTypeHandle, ThreadStaticsBlockOffset, FieldOffset); RuntimeAugments.StoreReferenceTypeField(fieldAddress, value); }
public static bool TryGetPointerTypeTargetType(RuntimeTypeHandle pointerTypeHandle, out RuntimeTypeHandle targetTypeHandle) { targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(pointerTypeHandle); return(true); }