/// <summary> /// This thunk is used to lazily resolve Finalizer calls /// </summary> /// <param name="obj">Object to be finalized</param> private static void FinalizeThunk(object obj) { RuntimeTypeHandle rthType = RuntimeAugments.GetRuntimeTypeHandleFromObjectReference(obj); TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc type = context.ResolveRuntimeTypeHandle(rthType); MethodDesc finalizer = type.GetFinalizer(); IntPtr fnPtrFinalizer; if (!TryGetVTableCallableAddress(finalizer, out fnPtrFinalizer)) { Environment.FailFast("Method address lookup failed for: " + finalizer.ToString()); } TypeSystemContextFactory.Recycle(context); unsafe { rthType.ToEETypePtr()->FinalizerCode = fnPtrFinalizer; } // Call the finalizer directly. No need to play tricks with tail calling, as this is rare enough, it shouldn't happen much // Here we take advantage of the detail that the calling convention abi for a static function // that returns no values, and takes a single object parameter matches that of a // instance function that takes no parameters Intrinsics.Call(fnPtrFinalizer, obj); }
internal bool GetMethodFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { createdType = default(RuntimeTypeHandle); nameAndSignature = null; genericMethodTypeArgumentHandles = null; TypeSystemContext context = TypeSystemContextFactory.Create(); MethodDesc parsedMethod = TryParseNativeSignatureWorker(context, moduleHandle, ref parser, typeArgs, methodArgs, true) as MethodDesc; if (parsedMethod == null) return false; if (!EnsureTypeHandleForType(parsedMethod.OwningType)) return false; createdType = parsedMethod.OwningType.RuntimeTypeHandle; nameAndSignature = parsedMethod.NameAndSignature; if (!parsedMethod.IsMethodDefinition && parsedMethod.Instantiation.Length > 0) { genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedMethod.Instantiation.Length]; for (int i = 0; i < parsedMethod.Instantiation.Length; ++i) { if (!EnsureTypeHandleForType(parsedMethod.Instantiation[i])) return false; genericMethodTypeArgumentHandles[i] = parsedMethod.Instantiation[i].RuntimeTypeHandle; } } TypeSystemContextFactory.Recycle(context); return true; }
// // Parse a native layout signature pointed to by "signature" in the executable image, optionally using // "typeArgs" and "methodArgs" for generic type parameter substitution. The first field in "signature" // must be an encoded method but any data beyond that is user-defined and returned in "remainingSignature" // public bool GetMethodFromSignatureAndContext(IntPtr signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles, out IntPtr remainingSignature) { remainingSignature = signature; createdType = default(RuntimeTypeHandle); nameAndSignature = null; genericMethodTypeArgumentHandles = null; TypeSystemContext context = TypeSystemContextFactory.Create(); MethodDesc parsedMethod = TryParseNativeSignature(context, ref remainingSignature, typeArgs, methodArgs, true) as MethodDesc; if (parsedMethod == null) return false; if (!EnsureTypeHandleForType(parsedMethod.OwningType)) return false; createdType = parsedMethod.OwningType.RuntimeTypeHandle; nameAndSignature = parsedMethod.NameAndSignature; if (parsedMethod.Instantiation.Length > 0) { genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedMethod.Instantiation.Length]; for (int i = 0; i < parsedMethod.Instantiation.Length; ++i) { if (!EnsureTypeHandleForType(parsedMethod.Instantiation[i])) return false; genericMethodTypeArgumentHandles[i] = parsedMethod.Instantiation[i].RuntimeTypeHandle; } } TypeSystemContextFactory.Recycle(context); return true; }
public bool CanInstantiationsShareCode(RuntimeTypeHandle[] genericArgHandles1, RuntimeTypeHandle[] genericArgHandles2, CanonicalFormKind kind) { if (genericArgHandles1.Length != genericArgHandles2.Length) return false; bool match = true; TypeSystemContext context = TypeSystemContextFactory.Create(); for (int i = 0; i < genericArgHandles1.Length; i++) { TypeDesc genericArg1 = context.ResolveRuntimeTypeHandle(genericArgHandles1[i]); TypeDesc genericArg2 = context.ResolveRuntimeTypeHandle(genericArgHandles2[i]); if (context.ConvertToCanon(genericArg1, kind) != context.ConvertToCanon(genericArg2, kind)) { match = false; break; } } TypeSystemContextFactory.Recycle(context); return match; }
/// <summary> /// Attempt a virtual dispatch on a given instanceType based on the method found via a metadata token /// </summary> private static bool TryDispatchMethodOnTarget_Inner(NativeFormatModuleInfo module, int metadataToken, RuntimeTypeHandle targetInstanceType, out IntPtr methodAddress) { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING TypeSystemContext context = TypeSystemContextFactory.Create(); NativeFormatMetadataUnit metadataUnit = context.ResolveMetadataUnit(module); MethodDesc targetMethod = metadataUnit.GetMethod(metadataToken.AsHandle(), null); TypeDesc instanceType = context.ResolveRuntimeTypeHandle(targetInstanceType); MethodDesc realTargetMethod = targetMethod; // For non-interface methods we support the target method not being the exact target. (This allows // a canonical method to be passed in and work for any generic type instantiation.) if (!targetMethod.OwningType.IsInterface) { realTargetMethod = instanceType.FindMethodOnTypeWithMatchingTypicalMethod(targetMethod); } bool success = LazyVTableResolver.TryDispatchMethodOnTarget(instanceType, realTargetMethod, out methodAddress); TypeSystemContextFactory.Recycle(context); return(success); #else methodAddress = IntPtr.Zero; return(false); #endif }
public bool TryComputeHasInstantiationDeterminedSize(RuntimeTypeHandle typeHandle, out bool hasInstantiationDeterminedSize) { TypeSystemContext context = TypeSystemContextFactory.Create(); bool success = TryComputeHasInstantiationDeterminedSize(typeHandle, context, out hasInstantiationDeterminedSize); TypeSystemContextFactory.Recycle(context); return success; }
/// <summary> /// Attempt to convert the dispatch cell to a metadata token to a more efficient vtable dispatch or interface/slot dispatch. /// Failure to convert is not a correctness issue. We also support performing a dispatch based on metadata token alone. /// </summary> private static DispatchCellInfo ConvertDispatchCellInfo_Inner(NativeFormatModuleInfo module, DispatchCellInfo cellInfo) { Debug.Assert(cellInfo.CellType == DispatchCellType.MetadataToken); TypeSystemContext context = TypeSystemContextFactory.Create(); MethodDesc targetMethod = context.ResolveMetadataUnit(module).GetMethod(cellInfo.MetadataToken.AsHandle(), null); Debug.Assert(!targetMethod.HasInstantiation); // At this time we do not support generic virtuals through the dispatch mechanism Debug.Assert(targetMethod.IsVirtual); if (targetMethod.OwningType.IsInterface) { if (!LazyVTableResolver.TryGetInterfaceSlotNumberFromMethod(targetMethod, out cellInfo.InterfaceSlot)) { // Unable to resolve interface method. Fail, by not mutating cellInfo return cellInfo; } if (!targetMethod.OwningType.RetrieveRuntimeTypeHandleIfPossible()) { new TypeBuilder().BuildType(targetMethod.OwningType); } cellInfo.CellType = DispatchCellType.InterfaceAndSlot; cellInfo.InterfaceType = targetMethod.OwningType.RuntimeTypeHandle.ToIntPtr(); cellInfo.MetadataToken = 0; } else { // Virtual function case, attempt to resolve to a VTable slot offset. // If the offset is less than 4096 update the cellInfo #if DEBUG // The path of resolving a metadata token at dispatch time is relatively rare in practice. // Force it to occur in debug builds with much more regularity if ((s_ConvertDispatchCellInfoCounter % 16) == 0) { s_ConvertDispatchCellInfoCounter++; TypeSystemContextFactory.Recycle(context); return cellInfo; } s_ConvertDispatchCellInfoCounter++; #endif int slotIndexOfMethod = LazyVTableResolver.VirtualMethodToSlotIndex(targetMethod); int vtableOffset = -1; if (slotIndexOfMethod >= 0) vtableOffset = LazyVTableResolver.SlotIndexToEETypeVTableOffset(slotIndexOfMethod); if ((vtableOffset < 4096) && (vtableOffset != -1)) { cellInfo.CellType = DispatchCellType.VTableOffset; cellInfo.VTableOffset = checked((uint)vtableOffset); cellInfo.MetadataToken = 0; } // Otherwise, do nothing, and resolve with a metadata dispatch later } TypeSystemContextFactory.Recycle(context); return cellInfo; }
public int GetCanonicalHashCode(RuntimeTypeHandle typeHandle, CanonicalFormKind kind) { TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc type = context.ResolveRuntimeTypeHandle(typeHandle); int hashCode = type.ConvertToCanonForm(kind).GetHashCode(); TypeSystemContextFactory.Recycle(context); return hashCode; }
public bool ConversionToCanonFormIsAChange(RuntimeTypeHandle[] genericArgHandles, CanonicalFormKind kind) { // Todo: support for universal canon type? TypeSystemContext context = TypeSystemContextFactory.Create(); Instantiation genericArgs = context.ResolveRuntimeTypeHandles(genericArgHandles); bool result; context.ConvertInstantiationToCanonForm(genericArgs, kind, out result); TypeSystemContextFactory.Recycle(context); return result; }
private bool ResolveInterfaceGenericVirtualMethodSlot(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature) { 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(ResolveInterfaceGenericVirtualMethodSlot_Static(targetTypeHandle, ref declaringType, ref methodNameAndSignature)); } else { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING TypeSystemContext context = TypeSystemContextFactory.Create(); DefType targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle); // Method being called... MethodDesc targetVirtualMethod = ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(context, declaringType, methodNameAndSignature); 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(ResolveInterfaceGenericVirtualMethodSlot_Static(targetTypeHandle, ref declaringType, ref methodNameAndSignature)); } TypeDesc instanceDefTypeToExamine; MethodDesc newlyFoundVirtualMethod = LazyVTableResolver.ResolveInterfaceMethodToVirtualMethod(targetType, out instanceDefTypeToExamine, targetVirtualMethod); targetVirtualMethod = newlyFoundVirtualMethod; // The pregenerated base type must be the one that implements the interface method // Call into Redhawk to deal with this. if ((newlyFoundVirtualMethod == null) && (instanceDefTypeToExamine != null)) { TypeSystemContextFactory.Recycle(context); // If we can't find the method in the type system, the overload must be defined in the static environment. Search there instead. return(ResolveInterfaceGenericVirtualMethodSlot_Static(instanceDefTypeToExamine.GetRuntimeTypeHandle(), ref declaringType, ref methodNameAndSignature)); } declaringType = targetVirtualMethod.OwningType.GetRuntimeTypeHandle(); methodNameAndSignature = targetVirtualMethod.NameAndSignature; TypeSystemContextFactory.Recycle(context); return(true); #else Environment.FailFast("GVM Resolution for non template or pregenerated type"); return(false); #endif } }
/// <summary> /// Resolve a dispatch on an interface EEType/slot index pair to a function pointer /// </summary> private bool TryResolveTypeSlotDispatch_Inner(IntPtr targetTypeAsIntPtr, IntPtr interfaceTypeAsIntPtr, ushort slot, out IntPtr methodAddress) { methodAddress = IntPtr.Zero; #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc targetType; TypeDesc interfaceType; unsafe { targetType = context.ResolveRuntimeTypeHandle(((EEType *)targetTypeAsIntPtr.ToPointer())->ToRuntimeTypeHandle()); interfaceType = context.ResolveRuntimeTypeHandle(((EEType *)interfaceTypeAsIntPtr.ToPointer())->ToRuntimeTypeHandle()); } if (!(interfaceType.GetTypeDefinition() is MetadataType)) { // If the interface open type is not a metadata type, this must be an interface not known in the metadata world. // Use the redhawk resolver for this directly. TypeDesc pregeneratedType = LazyVTableResolver.GetMostDerivedPregeneratedOrTemplateLoadedType(targetType); pregeneratedType.RetrieveRuntimeTypeHandleIfPossible(); interfaceType.RetrieveRuntimeTypeHandleIfPossible(); methodAddress = RuntimeAugments.ResolveDispatchOnType(pregeneratedType.RuntimeTypeHandle, interfaceType.RuntimeTypeHandle, slot); } else { MethodDesc interfaceMethod; if (!LazyVTableResolver.TryGetMethodFromInterfaceSlot(interfaceType, slot, out interfaceMethod)) { return(false); } if (!LazyVTableResolver.TryDispatchMethodOnTarget(targetType, interfaceMethod, out methodAddress)) { return(false); } } TypeSystemContextFactory.Recycle(context); return(true); #else return(false); #endif }
internal bool GetTypeFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType) { createdType = default(RuntimeTypeHandle); TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc parsedType = TryParseNativeSignatureWorker(context, moduleHandle, ref parser, typeArgs, methodArgs, false) as TypeDesc; if (parsedType == null) return false; if (!EnsureTypeHandleForType(parsedType)) return false; createdType = parsedType.RuntimeTypeHandle; TypeSystemContextFactory.Recycle(context); return true; }
// // Parse a native layout signature pointed to by "signature" in the executable image, optionally using // "typeArgs" and "methodArgs" for generic type parameter substitution. The first field in "signature" // must be an encoded type but any data beyond that is user-defined and returned in "remainingSignature" // public bool GetTypeFromSignatureAndContext(IntPtr signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out IntPtr remainingSignature) { remainingSignature = signature; createdType = default(RuntimeTypeHandle); TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc parsedType = TryParseNativeSignature(context, ref remainingSignature, typeArgs, methodArgs, false) as TypeDesc; if (parsedType == null) return false; if (!EnsureTypeHandleForType(parsedType)) return false; createdType = parsedType.RuntimeTypeHandle; TypeSystemContextFactory.Recycle(context); return true; }
/// <summary> /// Try to look up field acccess info for given canon in metadata blobs for all available modules. /// </summary> /// <param name="metadataReader">Metadata reader for the declaring type</param> /// <param name="declaringTypeHandle">Declaring type for the method</param> /// <param name="fieldHandle">Field handle</param> /// <param name="canonFormKind">Canonical form to use</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> public static bool TryGetFieldAccessMetadata( MetadataReader metadataReader, RuntimeTypeHandle runtimeTypeHandle, FieldHandle fieldHandle, out FieldAccessMetadata fieldAccessMetadata) { fieldAccessMetadata = default(FieldAccessMetadata); if (TryGetFieldAccessMetadataFromFieldAccessMap( metadataReader, runtimeTypeHandle, fieldHandle, CanonicalFormKind.Specific, ref fieldAccessMetadata)) { return(true); } if (TryGetFieldAccessMetadataFromFieldAccessMap( metadataReader, runtimeTypeHandle, fieldHandle, CanonicalFormKind.Universal, ref fieldAccessMetadata)) { return(true); } TypeSystemContext context = TypeSystemContextFactory.Create(); bool success = TryGetFieldAccessMetadataFromNativeFormatMetadata( metadataReader, runtimeTypeHandle, fieldHandle, context, ref fieldAccessMetadata); TypeSystemContextFactory.Recycle(context); return(success); }
private RuntimeTypeHandle GetExternalTypeHandle(NativeFormatModuleInfo moduleHandle, uint typeIndex) { Debug.Assert(moduleHandle != null); RuntimeTypeHandle result; TypeSystemContext context = TypeSystemContextFactory.Create(); { NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); nativeLayoutContext._module = moduleHandle; nativeLayoutContext._typeSystemContext = context; TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex); result = type.RuntimeTypeHandle; } TypeSystemContextFactory.Recycle(context); Debug.Assert(!result.IsNull()); return(result); }
/// <summary> /// This function is called from the lazy vtable resolver thunks via the UniversalTransitionThunk to compute /// the correct resolution of a virtual dispatch. /// </summary> /// <param name="callerTransitionBlockParam">pointer to the arguments of the called function</param> /// <param name="eeTypePointerOffsetAsIntPtr">eeTypePointerOffsetAsIntPtr is the offset from the start of the EEType to the vtable slot</param> /// <returns>function pointer of correct override of virtual function</returns> unsafe private static IntPtr VTableResolveThunk(IntPtr callerTransitionBlockParam, IntPtr eeTypePointerOffsetAsIntPtr) { int eeTypePointerOffset = (int)eeTypePointerOffsetAsIntPtr; int vtableSlotIndex = EETypeVTableOffsetToSlotIndex(eeTypePointerOffset); Debug.Assert(eeTypePointerOffset == SlotIndexToEETypeVTableOffset(vtableSlotIndex)); // Assert that the round trip through the slot calculations is good EEType **thisPointer = *((EEType ***)(((byte *)callerTransitionBlockParam) + ArgIterator.GetThisOffset())); EEType * eeType = *thisPointer; RuntimeTypeHandle rth = eeType->ToRuntimeTypeHandle(); TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc type = context.ResolveRuntimeTypeHandle(rth); IntPtr functionPointer = ResolveVirtualVTableFunction(type, vtableSlotIndex); eeType->GetVTableStartAddress()[vtableSlotIndex] = functionPointer; TypeSystemContextFactory.Recycle(context); return(functionPointer); }
private RuntimeTypeHandle GetExternalTypeHandle(ref NativeParser parser, uint typeIndex) { IntPtr moduleHandle = RuntimeAugments.GetModuleFromPointer(parser.Reader.OffsetToAddress(parser.Offset)); Debug.Assert(moduleHandle != IntPtr.Zero); RuntimeTypeHandle result; TypeSystemContext context = TypeSystemContextFactory.Create(); { NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); nativeLayoutContext._moduleHandle = moduleHandle; nativeLayoutContext._typeSystemContext = context; TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex); result = type.RuntimeTypeHandle; } TypeSystemContextFactory.Recycle(context); Debug.Assert(!result.IsNull()); return(result); }
// // 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; } }
private static void HighLevelDebugFuncEvalHelper() { uint parameterBufferSize = RuntimeAugments.RhpGetFuncEvalParameterBufferSize(); IntPtr writeParameterCommandPointer; IntPtr debuggerBufferPointer; unsafe { byte *debuggerBufferRawPointer = stackalloc byte[(int)parameterBufferSize]; debuggerBufferPointer = new IntPtr(debuggerBufferRawPointer); WriteParameterCommand writeParameterCommand = new WriteParameterCommand { commandCode = 1, bufferAddress = debuggerBufferPointer.ToInt64() }; writeParameterCommandPointer = new IntPtr(&writeParameterCommand); RuntimeAugments.RhpSendCustomEventToDebugger(writeParameterCommandPointer, Unsafe.SizeOf <WriteParameterCommand>()); // .. debugger magic ... the debuggerBuffer will be filled with parameter data TypesAndValues typesAndValues = new TypesAndValues(); uint trash; uint parameterCount; uint parameterValue; uint eeTypeCount; ulong eeType; uint offset = 0; NativeReader reader = new NativeReader(debuggerBufferRawPointer, parameterBufferSize); offset = reader.DecodeUnsigned(offset, out trash); // The VertexSequence always generate a length, I don't really need it. offset = reader.DecodeUnsigned(offset, out parameterCount); typesAndValues.parameterValues = new int[parameterCount]; for (int i = 0; i < parameterCount; i++) { offset = reader.DecodeUnsigned(offset, out parameterValue); typesAndValues.parameterValues[i] = (int)parameterValue; } offset = reader.DecodeUnsigned(offset, out eeTypeCount); for (int i = 0; i < eeTypeCount; i++) { // TODO: Stuff these eeType values into the external reference table offset = reader.DecodeUnsignedLong(offset, out eeType); } TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create(); bool hasThis; TypeDesc[] parameters; bool[] parametersWithGenericDependentLayout; bool result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader); typesAndValues.types = new RuntimeTypeHandle[parameters.Length]; bool needToDynamicallyLoadTypes = false; for (int i = 0; i < typesAndValues.types.Length; i++) { if (!parameters[i].RetrieveRuntimeTypeHandleIfPossible()) { needToDynamicallyLoadTypes = true; break; } typesAndValues.types[i] = parameters[i].GetRuntimeTypeHandle(); } if (needToDynamicallyLoadTypes) { TypeLoaderEnvironment.Instance.RunUnderTypeLoaderLock(() => { typeSystemContext.FlushTypeBuilderStates(); GenericDictionaryCell[] cells = new GenericDictionaryCell[parameters.Length]; for (int i = 0; i < cells.Length; i++) { cells[i] = GenericDictionaryCell.CreateTypeHandleCell(parameters[i]); } IntPtr[] eetypePointers; TypeBuilder.ResolveMultipleCells(cells, out eetypePointers); for (int i = 0; i < parameters.Length; i++) { typesAndValues.types[i] = ((EEType *)eetypePointers[i])->ToRuntimeTypeHandle(); } }); } TypeSystemContextFactory.Recycle(typeSystemContext); LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { // TODO: What these false really means? Need to make sure our format contains those information argumentTypes[i] = new LocalVariableType(typesAndValues.types[i], false, false); } LocalVariableSet.SetupArbitraryLocalVariableSet <TypesAndValues>(HighLevelDebugFuncEvalHelperWithVariables, ref typesAndValues, argumentTypes); } }
private unsafe static void RegularFuncEval(byte *parameterBuffer, uint parameterBufferSize) { TypesAndValues typesAndValues = new TypesAndValues(); uint trash; uint parameterCount; uint parameterValueSize; uint eeTypeCount; ulong eeType; uint offset = 0; NativeReader reader = new NativeReader(parameterBuffer, parameterBufferSize); offset = reader.DecodeUnsigned(offset, out trash); // The VertexSequence always generate a length, I don't really need it. offset = reader.DecodeUnsigned(offset, out parameterCount); typesAndValues.parameterValues = new byte[parameterCount][]; for (int i = 0; i < parameterCount; i++) { offset = reader.DecodeUnsigned(offset, out parameterValueSize); byte[] parameterValue = new byte[parameterValueSize]; for (int j = 0; j < parameterValueSize; j++) { uint parameterByte; offset = reader.DecodeUnsigned(offset, out parameterByte); parameterValue[j] = (byte)parameterByte; } typesAndValues.parameterValues[i] = parameterValue; } offset = reader.DecodeUnsigned(offset, out eeTypeCount); ulong[] debuggerPreparedExternalReferences = new ulong[eeTypeCount]; for (int i = 0; i < eeTypeCount; i++) { offset = reader.DecodeUnsignedLong(offset, out eeType); debuggerPreparedExternalReferences[i] = eeType; } TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create(); bool hasThis; TypeDesc[] parameters; bool[] parametersWithGenericDependentLayout; bool result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader, debuggerPreparedExternalReferences); typesAndValues.types = new RuntimeTypeHandle[parameters.Length]; bool needToDynamicallyLoadTypes = false; for (int i = 0; i < typesAndValues.types.Length; i++) { if (!parameters[i].RetrieveRuntimeTypeHandleIfPossible()) { needToDynamicallyLoadTypes = true; break; } typesAndValues.types[i] = parameters[i].GetRuntimeTypeHandle(); } if (needToDynamicallyLoadTypes) { TypeLoaderEnvironment.Instance.RunUnderTypeLoaderLock(() => { typeSystemContext.FlushTypeBuilderStates(); GenericDictionaryCell[] cells = new GenericDictionaryCell[parameters.Length]; for (int i = 0; i < cells.Length; i++) { cells[i] = GenericDictionaryCell.CreateTypeHandleCell(parameters[i]); } IntPtr[] eetypePointers; TypeBuilder.ResolveMultipleCells(cells, out eetypePointers); for (int i = 0; i < parameters.Length; i++) { typesAndValues.types[i] = ((EEType *)eetypePointers[i])->ToRuntimeTypeHandle(); } }); } TypeSystemContextFactory.Recycle(typeSystemContext); LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { // TODO, FuncEval, what these false really means? Need to make sure our format contains those information argumentTypes[i] = new LocalVariableType(typesAndValues.types[i], false, false); } LocalVariableSet.SetupArbitraryLocalVariableSet <TypesAndValues>(HighLevelDebugFuncEvalHelperWithVariables, ref typesAndValues, argumentTypes); }
// This method computes the method pointer and dictionary pointer for a GVM. // Inputs: // - targetTypeHanlde: target type on which the GVM is implemented // - nameAndSignature: name and signature of the GVM method // - genericMethodArgumentHandles: GVM instantiation arguments // Outputs: // - methodPointer: pointer to the GVM's implementation // - dictionaryPointer: (if applicable) pointer to the dictionary to be used with the GVM call public bool TryGetGenericVirtualMethodPointer(RuntimeTypeHandle targetTypeHandle, MethodNameAndSignature nameAndSignature, RuntimeTypeHandle[] genericMethodArgumentHandles, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; TypeSystemContext context = TypeSystemContextFactory.Create(); DefType targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle); Instantiation methodInstantiation = context.ResolveRuntimeTypeHandles(genericMethodArgumentHandles); InstantiatedMethod method = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, targetType, nameAndSignature, methodInstantiation, IntPtr.Zero, false); if (!method.CanShareNormalGenericCode()) { // First see if we can find an exact method implementation for the GVM (avoid using USG implementations if we can, // because USG code is much slower). if (TryLookupExactMethodPointerForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out methodPointer)) { Debug.Assert(methodPointer != IntPtr.Zero); TypeSystemContextFactory.Recycle(context); return(true); } } // If we cannot find an exact method entry point, look for an equivalent template and compute the generic dictinoary TemplateLocator templateLocator = new TemplateLocator(); NativeLayoutInfo nativeLayoutInfo = new NativeLayoutInfo(); InstantiatedMethod templateMethod = templateLocator.TryGetGenericMethodTemplate(method, out nativeLayoutInfo.Module, out nativeLayoutInfo.Token); if (templateMethod == null) { return(false); } methodPointer = templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal) ? templateMethod.UsgFunctionPointer : templateMethod.FunctionPointer; if (!TryLookupGenericMethodDictionaryForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out dictionaryPointer)) { 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(); if (!TypeBuilder.TryBuildGenericMethod(method, out dictionaryPointer)) { return(false); } } } Debug.Assert(methodPointer != IntPtr.Zero && dictionaryPointer != IntPtr.Zero); if (templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal)) { // Check if we need to wrap the method pointer into a calling convention converter thunk if (!TypeLoaderEnvironment.Instance.MethodSignatureHasVarsNeedingCallingConventionConverter(context, nameAndSignature.Signature)) { TypeSystemContextFactory.Recycle(context); return(true); } RuntimeTypeHandle[] typeArgs = Array.Empty <RuntimeTypeHandle>(); if (RuntimeAugments.IsGenericType(targetTypeHandle)) { RuntimeAugments.GetGenericInstantiation(targetTypeHandle, out typeArgs); } // Create a CallingConventionConverter to call the method correctly IntPtr thunkPtr = CallConverterThunk.MakeThunk( CallConverterThunk.ThunkKind.StandardToGenericInstantiating, methodPointer, nameAndSignature.Signature, dictionaryPointer, typeArgs, genericMethodArgumentHandles); Debug.Assert(thunkPtr != IntPtr.Zero); methodPointer = thunkPtr; // Set dictionaryPointer to null so we don't make a fat function pointer around the whole thing. dictionaryPointer = IntPtr.Zero; // TODO! add a new call converter thunk that will pass the instantiating arg through and use a fat function pointer. // should allow us to make fewer thunks. } TypeSystemContextFactory.Recycle(context); return(true); }
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 } }