private RemoveAction GetAction(MethodDesc method) { TypeDesc owningType = method.OwningType; if ((_removedFeature & RemovedFeature.Etw) != 0) { if (!method.Signature.IsStatic) { if (IsEventSourceType(owningType)) { if (method.IsConstructor) { return(RemoveAction.ConvertToStub); } if (method.Name == "IsEnabled" || method.IsFinalizer || method.Name == "Dispose") { return(RemoveAction.ConvertToStub); } return(RemoveAction.ConvertToThrow); } else if (IsEventSourceImplementation(owningType)) { if (method.IsFinalizer) { return(RemoveAction.ConvertToStub); } if (method.IsConstructor) { return(RemoveAction.ConvertToStub); } if (method.HasCustomAttribute("System.Diagnostics.Tracing", "NonEventAttribute")) { return(RemoveAction.Nothing); } return(RemoveAction.ConvertToThrow); } } } if ((_removedFeature & RemovedFeature.FrameworkResources) != 0) { if (method.Signature.IsStatic && owningType is Internal.TypeSystem.Ecma.EcmaType mdType && mdType.Name == "SR" && mdType.Namespace == "System" && FrameworkStringResourceBlockingPolicy.IsFrameworkAssembly(mdType.EcmaModule)) { if (method.Name == "UsingResourceKeys") { return(RemoveAction.ConvertToTrueStub); } else if (method.Name == "GetResourceString" && method.Signature.Length == 2) { return(RemoveAction.ConvertToGetResourceStringStub); } return(RemoveAction.Nothing); } } return(RemoveAction.Nothing); }
private TypeDesc MarshalArgument(TypeDesc type) { if (IsBlittableType(type)) { return(type.UnderlyingType); } if (type.IsSzArray) { var arrayType = (ArrayType)type; if (IsBlittableType(arrayType.ParameterType)) { return(EmitArrayMarshalling(arrayType)); } if (arrayType.ParameterType == _context.GetWellKnownType(WellKnownType.Char)) { if (GetCharSet() == PInvokeAttributes.CharSetUnicode) { return(EmitArrayMarshalling(arrayType)); } } } if (type.IsByRef) { var byRefType = (ByRefType)type; if (IsBlittableType(byRefType.ParameterType)) { return(EmitByRefMarshalling(byRefType)); } if (byRefType.ParameterType == _context.GetWellKnownType(WellKnownType.Char)) { if (GetCharSet() == PInvokeAttributes.CharSetUnicode) { return(EmitByRefMarshalling(byRefType)); } } } if (type.IsString) { return(EmitStringMarshalling()); } if (type.Category == TypeFlags.Boolean) { return(EmitBooleanMarshalling()); } if (type is MetadataType) { var metadataType = (MetadataType)type; if (metadataType.Module == _context.SystemModule) { var nameSpace = metadataType.Namespace; var name = metadataType.Name; if (name == "StringBuilder" && nameSpace == "System.Text") { return(EmitStringBuilderMarshalling()); } } } if (IsSafeHandle(type)) { return(EmitSafeHandleMarshalling(type)); } throw new NotSupportedException(); }
public GenericDefinitionEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, type) { Debug.Assert(type.IsGenericDefinition); }
public static TypeDesc MergeTypesToCommonParent(TypeDesc ta, TypeDesc tb) { if (ta == tb) { return(ta); } // Handle the array case if (ta.IsArray) { if (tb.IsArray) { return(MergeArrayTypesToCommonParent((ArrayType)ta, (ArrayType)tb)); } else if (tb.IsInterface) { // Check to see if we can merge the array to a common interface (such as Derived[] and IList<Base>) if (ta.CanCastTo(tb)) { return(tb); } } // keep merging from here ta = ta.Context.GetWellKnownType(WellKnownType.Array); } else if (tb.IsArray) { if (ta.IsInterface && tb.CanCastTo(ta)) { return(ta); } tb = tb.Context.GetWellKnownType(WellKnownType.Array); } Debug.Assert(ta.IsDefType); Debug.Assert(tb.IsDefType); if (tb.IsInterface) { if (ta.IsInterface) { // // Both classes are interfaces. Check that if one // interface extends the other. // // Does tb extend ta ? // if (tb.ImplementsEquivalentInterface(ta)) { return(ta); } // // Does tb extend ta ? // if (ta.ImplementsEquivalentInterface(tb)) { return(tb); } // No compatible merge found - using Object return(ta.Context.GetWellKnownType(WellKnownType.Object)); } else { return(MergeClassWithInterface(ta, tb)); } } else if (ta.IsInterface) { return(MergeClassWithInterface(tb, ta)); } int aDepth = 0; int bDepth = 0; // find the depth in the class hierarchy for each class for (TypeDesc searchType = ta; searchType != null; searchType = searchType.BaseType) { aDepth++; } for (TypeDesc searchType = tb; searchType != null; searchType = searchType.BaseType) { bDepth++; } // for whichever class is lower down in the hierarchy, walk up the superclass chain // to the same level as the other class while (aDepth > bDepth) { ta = ta.BaseType; aDepth--; } while (bDepth > aDepth) { tb = tb.BaseType; bDepth--; } while (ta != tb) { ta = ta.BaseType; tb = tb.BaseType; } // If no compatible merge is found, we end up using Object Debug.Assert(ta != null); return(ta); }
private ulong BuildBuckets(double timeScale, double maxAge) { ReadNewLog log = liveObjectTable.readNewLog; bool useMarkers = markersRadioButton.Checked; if (this.useMarkers != useMarkers) { this.useMarkers = useMarkers; bucketTable = null; } int bucketCount; if (useMarkers) { for (bucketCount = 0; bucketCount < log.commentEventList.count; bucketCount++) if (log.commentEventList.eventTickIndex[bucketCount] >= liveObjectTable.lastTickIndex) break; bucketCount++; } else { bucketCount = (int)Math.Ceiling(maxAge/timeScale); if (bucketCount == 0) bucketCount = 1; } if (bucketTable == null || bucketTable.Length != bucketCount) { bucketTable = new Bucket[bucketCount]; double nowTime = log.TickIndexToTime(liveObjectTable.lastTickIndex); double age = 0; for (int i = 0; i < bucketTable.Length; i++) { bucketTable[i].totalSize = 0; bucketTable[i].typeDescToSizeCount = new Dictionary<TypeDesc, SizeCount>(); bucketTable[i].minAge = age; if (useMarkers) { int markerIndex = bucketTable.Length - i - 1; if (i > 0) bucketTable[i].minComment = log.commentEventList.eventString[markerIndex]; age = nowTime; if (markerIndex > 0) { bucketTable[i].maxComment = log.commentEventList.eventString[markerIndex-1]; age -= log.TickIndexToTime(log.commentEventList.eventTickIndex[markerIndex-1]); } } else { age += timeScale; } bucketTable[i].maxAge = age; } if (typeIndexToTypeDesc == null || typeIndexToTypeDesc.Length < log.typeName.Length) typeIndexToTypeDesc = new TypeDesc[log.typeName.Length]; else { foreach (TypeDesc t in typeIndexToTypeDesc) { if (t != null) t.totalSize = 0; } } LiveObjectTable.LiveObject o; for (liveObjectTable.GetNextObject(0, ulong.MaxValue, out o); o.id < ulong.MaxValue; liveObjectTable.GetNextObject(o.id + o.size, ulong.MaxValue, out o)) { int bucketIndex; double allocTime = log.TickIndexToTime(o.allocTickIndex); age = nowTime - allocTime; bucketIndex = (int)(age/timeScale); if (bucketIndex >= bucketTable.Length) bucketIndex = bucketTable.Length - 1; else if (bucketIndex < 0) bucketIndex = 0; while (bucketIndex < bucketTable.Length - 1 && age >= bucketTable[bucketIndex].maxAge) bucketIndex++; while (bucketIndex > 0 && age < bucketTable[bucketIndex].minAge) bucketIndex--; bucketTable[bucketIndex].totalSize += o.size; TypeDesc t = typeIndexToTypeDesc[o.typeIndex]; if (t == null) { t = new TypeDesc(log.typeName[o.typeIndex]); typeIndexToTypeDesc[o.typeIndex] = t; } t.totalSize += o.size; SizeCount sizeCount; if (!bucketTable[bucketIndex].typeDescToSizeCount.TryGetValue(t, out sizeCount)) { sizeCount = new SizeCount(); bucketTable[bucketIndex].typeDescToSizeCount[t] = sizeCount; } sizeCount.size += o.size; sizeCount.count += 1; } } ulong maxBucketSize = 0; foreach (Bucket b in bucketTable) { if (maxBucketSize < b.totalSize) maxBucketSize = b.totalSize; } totalSize = 0; sortedTypeTable = new ArrayList(); foreach (TypeDesc t in typeIndexToTypeDesc) { if (t != null) { sortedTypeTable.Add(t); totalSize += t.totalSize; } } sortedTypeTable.Sort(); return maxBucketSize; }
void BuildAddressRangesTypeTable() { rangeList = null; rangeCount = 0; if (typeIndexToTypeDesc == null || typeIndexToTypeDesc.Length < typeName.Length) typeIndexToTypeDesc = new TypeDesc[typeName.Length]; else { foreach (TypeDesc t in typeIndexToTypeDesc) { if (t != null) { t.totalSize = 0; t.selectedSize = 0; } } } ulong totalAllocated = 0; ulong totalSelected = 0; LiveObjectTable.LiveObject o; bool prevLOH = false; for (liveObjectTable.GetNextObject(0, ulong.MaxValue, out o); o.id < ulong.MaxValue; liveObjectTable.GetNextObject(o.id + o.size, ulong.MaxValue, out o)) { int gen = liveObjectTable.GenerationOfObject(ref o); if (gen > generations-1) gen = generations-1; bool thisLOH = gen == generations-1; // Check whether we can fit this object into the last range we created. // We assume the liveObjectList is sorted, so the object can only attach // at the end of this range. if (rangeList != null && o.id - rangeList.hiAddr <= allowableGap && prevLOH == thisLOH) { Debug.Assert(o.id >= rangeList.hiAddr); rangeList.hiAddr = o.id + o.size; } else { rangeList = new AddressRange(o.id, o.id + o.size, rangeList, rangeCount++); } prevLOH = thisLOH; TypeDesc t = typeIndexToTypeDesc[o.typeIndex]; if (t == null) { t = new TypeDesc(o.typeIndex, typeName[o.typeIndex]); typeIndexToTypeDesc[o.typeIndex] = t; } t.totalSize += o.size; totalAllocated += o.size; if (InsideSelection(o.id) != 0) { t.selectedSize += o.size; totalSelected += o.size; } if (rangeList.genLoAddr[gen] > o.id) rangeList.genLoAddr[gen] = o.id; if (rangeList.genHiAddr[gen] < o.id + o.size) rangeList.genHiAddr[gen] = o.id + o.size; } sortedTypeTable = new ArrayList(); foreach (TypeDesc t in typeIndexToTypeDesc) if (t != null) sortedTypeTable.Add(t); sortedTypeTable.Sort(); foreach (TypeDesc t in sortedTypeTable) { t.percentage = 0.0; if (totalAllocated > 0) t.percentage = 100.0*t.totalSize/totalAllocated; t.selectedPercentage = 0.0; if (totalSelected > 0) t.selectedPercentage = 100*t.selectedSize/totalSelected; } }
public static bool IsSystemGuid(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System", "Guid")); }
private void AddToTypeTable(int typeIndex, int lifeTime) { TypeDesc t = typeIndexToTypeDesc[typeIndex]; if (t == null) { t = new TypeDesc(typeName[typeIndex]); typeIndexToTypeDesc[typeIndex] = t; } t.totalSize += lifeTime; }
public static bool IsStringBuilder(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System.Text", "StringBuilder")); }
public static bool IsSystemDecimal(TypeSystemContext context, TypeDesc type) { return(IsCoreNamedType(context, type, "System", "Decimal")); }
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 PropertySignature(bool isStatic, TypeDesc[] parameters, TypeDesc returnType) { IsStatic = isStatic; _parameters = parameters; ReturnType = returnType; }
public void AddCompilationRoot(TypeDesc type, string reason) { _rootAdder(_factory.ConstructedTypeSymbol(type), reason); }
void BuildSizeRangesAndTypeTable(int[] typeSizeStacktraceToCount) { BuildBuckets(); totalSize = 0; totalCount = 0; if (typeIndexToTypeDesc == null) typeIndexToTypeDesc = new TypeDesc[histogram.readNewLog.typeName.Length]; else { foreach (TypeDesc t in typeIndexToTypeDesc) { if (t != null) { t.totalSize = 0; t.count = 0; } } } for (int i = 0; i < typeSizeStacktraceToCount.Length; i++) { int count = typeSizeStacktraceToCount[i]; if (count == 0) continue; int[] stacktrace = histogram.readNewLog.stacktraceTable.IndexToStacktrace(i); int typeIndex = stacktrace[0]; int size = stacktrace[1]; TypeDesc t = (TypeDesc)typeIndexToTypeDesc[typeIndex]; if (t == null) { t = new TypeDesc(typeName[typeIndex]); typeIndexToTypeDesc[typeIndex] = t; } t.totalSize += (ulong)size*(ulong)count; t.count += count; totalSize += (ulong)size * (ulong)count; totalCount += count; AddToBuckets(t, size, count); } if (totalSize == 0) totalSize = 1; if (totalCount == 0) totalCount = 1; TrimEmptyBuckets(); sortedTypeTable = new ArrayList(); foreach (TypeDesc t in typeIndexToTypeDesc) if (t != null) sortedTypeTable.Add(t); sortedTypeTable.Sort(); }
internal bool IsInheritanceChainLayoutFixedInCurrentVersionBubble(TypeDesc type) { // TODO: implement return(true); }
internal ByRefType(TypeDesc parameter) : base(parameter) { }
public bool IsEffectivelySealed(TypeDesc type) { return(_devirtualizationManager.IsEffectivelySealed(type)); }
private void RedrawType(TypeDesc t) { DrawTypeDescription(typeLegendPanel.CreateGraphics(), t); Graphics g = graphPanel.CreateGraphics(); DrawLiveObjects(g, t, 0, ulong.MaxValue); Pen pen = new Pen(Color.Black); DrawSelectionHorizontalLine(g, pen, selectedHighAddr); DrawSelectionHorizontalLine(g, pen, selectedLowAddr); }
public MethodDesc ResolveVirtualMethod(MethodDesc declMethod, TypeDesc implType) { return(_devirtualizationManager.ResolveVirtualMethod(declMethod, implType)); }
public void AddCompilationRoot(TypeDesc type, string reason) { _graph.AddRoot(_factory.MaximallyConstructableType(type), reason); }
public bool IsVectorOfT(TypeDesc type) { return(IsSimdType(type) && ((MetadataType)type).Name == "Vector`1" && ((MetadataType)type).Namespace == "System.Numerics"); }
/// <summary> /// Wrapper helper function around the IsCanonicalDefinitionType API on the TypeSystemContext /// </summary> public static bool IsCanonicalDefinitionType(this TypeDesc type, CanonicalFormKind kind) { return(type.Context.IsCanonicalDefinitionType(type, kind)); }
private Object ResolveMemberReference(MemberReferenceHandle handle) { MemberReference memberReference = _metadataReader.GetMemberReference(handle); Object parent = GetObject(memberReference.Parent, NotFoundBehavior.ReturnResolutionFailure); if (parent is ResolutionFailure) { return(parent); } TypeDesc parentTypeDesc = parent as TypeDesc; if (parentTypeDesc != null) { BlobReader signatureReader = _metadataReader.GetBlobReader(memberReference.Signature); EcmaSignatureParser parser = new EcmaSignatureParser(this, signatureReader, NotFoundBehavior.ReturnResolutionFailure); string name = _metadataReader.GetString(memberReference.Name); if (parser.IsFieldSignature) { FieldDesc field = parentTypeDesc.GetField(name); if (field != null) { return(field); } return(ResolutionFailure.GetMissingFieldFailure(parentTypeDesc, name)); } else { MethodSignature sig = parser.ParseMethodSignature(); if (sig == null) { return(parser.ResolutionFailure); } TypeDesc typeDescToInspect = parentTypeDesc; Instantiation substitution = default(Instantiation); // Try to resolve the name and signature in the current type, or any of the base types. do { MethodDesc method = typeDescToInspect.GetMethod(name, sig, substitution); if (method != null) { // If this resolved to one of the base types, make sure it's not a constructor. // Instance constructors are not inherited. if (typeDescToInspect != parentTypeDesc && method.IsConstructor) { break; } return(method); } var baseType = typeDescToInspect.BaseType; if (baseType != null) { if (!baseType.HasInstantiation) { substitution = default(Instantiation); } else { // If the base type is generic, any signature match for methods on the base type with the generic details from // the deriving type Instantiation newSubstitution = typeDescToInspect.GetTypeDefinition().BaseType.Instantiation; if (!substitution.IsNull) { TypeDesc[] newSubstitutionTypes = new TypeDesc[newSubstitution.Length]; for (int i = 0; i < newSubstitution.Length; i++) { newSubstitutionTypes[i] = newSubstitution[i].InstantiateSignature(substitution, default(Instantiation)); } newSubstitution = new Instantiation(newSubstitutionTypes); } substitution = newSubstitution; } } typeDescToInspect = baseType; } while (typeDescToInspect != null); return(ResolutionFailure.GetMissingMethodFailure(parentTypeDesc, name, sig)); } } else if (parent is MethodDesc) { ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramVararg, (MethodDesc)parent); } else if (parent is ModuleDesc) { throw new NotImplementedException("MemberRef to a global function or variable."); } ThrowHelper.ThrowBadImageFormatException(); return(null); }
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); } constrainedType = c; } return(constrainedType ?? genericParam.Context.GetWellKnownType(WellKnownType.Object)); }
public bool HasFixedSlotVTable(TypeDesc type) { return(true); }
/// <summary> /// Provides method bodies for intrinsics recognized by the compiler that /// are specialized per instantiation. It can return null if the intrinsic /// is not recognized. /// </summary> private MethodIL TryGetPerInstantiationIntrinsicMethodIL(MethodDesc method) { Debug.Assert(method.IsIntrinsic); MetadataType owningType = method.OwningType.GetTypeDefinition() as MetadataType; if (owningType == null) { return(null); } string methodName = method.Name; switch (owningType.Name) { case "RuntimeHelpers": { if ((methodName == "IsReferenceOrContainsReferences" || methodName == "IsReference") && owningType.Namespace == "System.Runtime.CompilerServices") { TypeDesc elementType = method.Instantiation[0]; // Fallback to non-intrinsic implementation for universal generics if (elementType.IsCanonicalSubtype(CanonicalFormKind.Universal)) { return(null); } bool result = elementType.IsGCPointer; if (methodName == "IsReferenceOrContainsReferences") { result |= (elementType.IsDefType ? ((DefType)elementType).ContainsGCPointers : false); } return(new ILStubMethodIL(method, new byte[] { result ? (byte)ILOpcode.ldc_i4_1 : (byte)ILOpcode.ldc_i4_0, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null)); } } break; case "Comparer`1": { if (methodName == "Create" && owningType.Namespace == "System.Collections.Generic") { return(ComparerIntrinsics.EmitComparerCreate(method)); } } break; case "EqualityComparer`1": { if (methodName == "Create" && owningType.Namespace == "System.Collections.Generic") { return(ComparerIntrinsics.EmitEqualityComparerCreate(method)); } } break; case "EqualityComparerHelpers": { if (owningType.Namespace != "Internal.IntrinsicSupport") { return(null); } if (methodName == "EnumOnlyEquals") { // EnumOnlyEquals would basically like to do this: // static bool EnumOnlyEquals<T>(T x, T y) where T: struct => x == y; // This is not legal though. // We don't want to do this: // static bool EnumOnlyEquals<T>(T x, T y) where T: struct => x.Equals(y); // Because it would box y. // So we resort to some per-instantiation magic. TypeDesc elementType = method.Instantiation[0]; if (!elementType.IsEnum) { return(null); } ILOpcode convInstruction; if (((DefType)elementType).InstanceFieldSize.AsInt <= 4) { convInstruction = ILOpcode.conv_i4; } else { Debug.Assert(((DefType)elementType).InstanceFieldSize.AsInt == 8); convInstruction = ILOpcode.conv_i8; } return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldarg_0, (byte)convInstruction, (byte)ILOpcode.ldarg_1, (byte)convInstruction, (byte)ILOpcode.prefix1, unchecked ((byte)ILOpcode.ceq), (byte)ILOpcode.ret, }, Array.Empty <LocalVariableDefinition>(), null)); } else if (methodName == "GetComparerForReferenceTypesOnly") { TypeDesc elementType = method.Instantiation[0]; if (!elementType.IsRuntimeDeterminedSubtype && !elementType.IsCanonicalSubtype(CanonicalFormKind.Any) && !elementType.IsGCPointer) { return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null)); } } else if (methodName == "StructOnlyEquals") { TypeDesc elementType = method.Instantiation[0]; if (!elementType.IsRuntimeDeterminedSubtype && !elementType.IsCanonicalSubtype(CanonicalFormKind.Any) && !elementType.IsGCPointer) { Debug.Assert(elementType.IsValueType); TypeSystemContext context = elementType.Context; MetadataType helperType = context.SystemModule.GetKnownType("Internal.IntrinsicSupport", "EqualityComparerHelpers"); MethodDesc methodToCall = null; if (elementType.IsEnum) { methodToCall = helperType.GetKnownMethod("EnumOnlyEquals", null).MakeInstantiatedMethod(elementType); } else if (elementType.IsNullable && ComparerIntrinsics.ImplementsIEquatable(elementType.Instantiation[0])) { methodToCall = helperType.GetKnownMethod("StructOnlyEqualsNullable", null).MakeInstantiatedMethod(elementType.Instantiation[0]); } else if (ComparerIntrinsics.ImplementsIEquatable(elementType)) { methodToCall = helperType.GetKnownMethod("StructOnlyEqualsIEquatable", null).MakeInstantiatedMethod(elementType); } if (methodToCall != null) { return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldarg_0, (byte)ILOpcode.ldarg_1, (byte)ILOpcode.call, 1, 0, 0, 0, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), new object[] { methodToCall })); } } } } break; } return(null); }
public DelegateCreationInfo GetDelegateCtor(TypeDesc delegateType, MethodDesc target, bool followVirtualDispatch) { return(DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch)); }
public MethodIL EmitIL() { MethodSignature targetMethodSignature = _targetMethod.Signature; // We have 4 code streams: // - _marshallingCodeStream is used to convert each argument into a native type and // store that into the local // - callsiteSetupCodeStream is used to used to load each previously generated local // and call the actual target native method. // - _returnValueMarshallingCodeStream is used to convert the native return value // to managed one. // - _unmarshallingCodestream is used to propagate [out] native arguments values to // managed ones. _emitter = new ILEmitter(); ILCodeStream fnptrLoadStream = _emitter.NewCodeStream(); _marshallingCodeStream = _emitter.NewCodeStream(); ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream(); _returnValueMarshallingCodeStream = _emitter.NewCodeStream(); _unmarshallingCodestream = _emitter.NewCodeStream(); TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length]; // // Parameter marshalling // // // Convert each argument to something we can pass to native and store it in a local. // Then load the local in the second code stream. // for (int i = 0; i < targetMethodSignature.Length; i++) { // TODO: throw if there's custom marshalling _marshallingCodeStream.EmitLdArg(i); TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]); nativeParameterTypes[i] = nativeType; ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType); _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp); callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp); } // // Return value marshalling // // TODO: throw if SetLastError is true // TODO: throw if there's custom marshalling TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType); if (UseLazyResolution(_targetMethod, _importMetadata.Module)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, _emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, _emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(_importMetadata.Attributes); MethodSignature nativeCalliSig = new MethodSignature( targetMethodSignature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = _emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, _emitter.NewToken(nativeCalliSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Attributes); MethodSignature nativeSig = new MethodSignature( targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata); callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod)); } _unmarshallingCodestream.Emit(ILOpcode.ret); return(_emitter.Link(_targetMethod)); }
public bool HasLazyStaticConstructor(TypeDesc type) { return(type.HasStaticConstructor); }
void AddToBuckets(TypeDesc t, int size, int count) { for (int i = 0; i < buckets.Length; i++) { if (buckets[i].minSize <= size && size <= buckets[i].maxSize) { ulong totalSize = (ulong)size*(ulong)count; buckets[i].totalSize += totalSize; SizeCount sizeCount; if (!buckets[i].typeDescToSizeCount.TryGetValue(t, out sizeCount)) { sizeCount = new SizeCount(); buckets[i].typeDescToSizeCount[t] = sizeCount; } sizeCount.size += totalSize; sizeCount.count += count; break; } } }
public override MethodDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation) { MethodDesc method = this; TypeDesc owningType = method.OwningType; TypeDesc instantiatedOwningType = owningType.InstantiateSignature(typeInstantiation, methodInstantiation); if (owningType != instantiatedOwningType) method = instantiatedOwningType.Context.ResolveRuntimeMethod(UnboxingStub, (DefType)instantiatedOwningType, _nameAndSignature, IntPtr.Zero, false); Instantiation instantiation = method.Instantiation; TypeDesc[] clone = null; for (int i = 0; i < instantiation.Length; i++) { TypeDesc uninst = instantiation[i]; TypeDesc inst = uninst.InstantiateSignature(typeInstantiation, methodInstantiation); if (inst != uninst) { if (clone == null) { clone = new TypeDesc[instantiation.Length]; for (int j = 0; j < clone.Length; j++) { clone[j] = instantiation[j]; } } clone[i] = inst; } } return (clone == null) ? method : method.Context.GetInstantiatedMethod(method.GetMethodDefinition(), new Instantiation(clone)); }
public DelegateCreationInfo GetDelegateCtor(TypeDesc delegateType, MethodDesc target) { return(DelegateCreationInfo.Create(delegateType, target, NodeFactory)); }
public LocalVariableDefinition(TypeDesc type, bool isPinned) { IsPinned = isPinned; Type = type; }
public bool HasLazyStaticConstructor(TypeDesc type) { return(TypeSystemContext.HasLazyStaticConstructor(type)); }
internal PointerType(TypeDesc parameterType) : base(parameterType) { }
internal abstract VTableSliceNode GetSlice(TypeDesc type);
private void DrawTypeDescription(Graphics g, TypeDesc t) { int dotOffset = (font.Height - dotSize)/2; g.FillRectangle(t.brushes[t.selected], t.rect.Left, t.rect.Top+dotOffset, dotSize, dotSize); g.DrawString(t.typeName, font, blackBrush, t.rect.Left + dotSize*2, t.rect.Top); string s = string.Format(" ({0:n0} bytes, {1:f2}% - {2:n0} bytes, {3:f2}% selected)", t.totalSize, t.percentage, t.selectedSize, t.selectedPercentage); g.DrawString(s, font, blackBrush, t.rect.Left + dotSize*2, t.rect.Top + font.Height); }
internal override VTableSliceNode GetSlice(TypeDesc type) { return(new LazilyBuiltVTableSliceNode(type)); }
private string ComputeObjectsDescription(TypeDesc selectedType, ulong selectedLowAddr, ulong selectedHighAddr) { string description = ""; if (selectedType != null) description += selectedType.typeName + " "; description += "objects "; if (selectedLowAddr > 0) description += string.Format("between {0} and {1}", FormatAddress(selectedLowAddr), FormatAddress(selectedHighAddr)); return description; }
public AppContextInitializerMethod(TypeDesc owningType, IEnumerable <string> switches) { _owningType = owningType; _switches = new List <string>(switches); }
private void DrawLiveObjects(Graphics g, TypeDesc selectedType, ulong lowAddr, ulong highAddr) { Pen freePen = new Pen(Color.White); RectangleF clipRect = g.VisibleClipBounds; for (AddressRange r = rangeList; r != null; r = r.next) { // figure out base x for this range int x1 = leftMargin + r.index*(heapWidth + gap); int x2 = x1 + heapWidth; if (x2 < clipRect.Left || clipRect.Right < x1) continue; ulong visibleStartAddr = VisibleYToAddress(r, outerGraphPanel.Size.Height); ulong visibleEndAddr = VisibleYToAddress(r, 0); if (clipRect.Height < outerGraphPanel.Size.Height) { visibleStartAddr = VisibleYToAddress(r, (int)clipRect.Bottom + graphPanel.Top + 1); visibleEndAddr = VisibleYToAddress(r, (int)clipRect.Top + graphPanel.Top - 1); } IntersectIntervals(lowAddr, highAddr, ref visibleStartAddr, ref visibleEndAddr); IntersectIntervals(r.loAddr, r.hiAddr, ref visibleStartAddr, ref visibleEndAddr); LiveObjectTable.LiveObject o; ulong addr = liveObjectTable.FindObjectBackward(visibleStartAddr); liveObjectTable.GetNextObject(addr, visibleStartAddr, out o); if (o.id + o.size + align - 1 < visibleStartAddr) addr = visibleStartAddr; visibleEndAddr += align - 1; for (liveObjectTable.GetNextObject(addr, visibleEndAddr, out o); o.id < visibleEndAddr; liveObjectTable.GetNextObject(addr, visibleEndAddr, out o)) { // fill any space between this object and the end of the previous one // (or the start of the range, as the case may be) in white if (addr + align - 1 < o.id) { FillSpace(g, r, freePen, addr, o.id); } LiveObjectTable.LiveObject oo; for (addr = o.id + o.size; addr < visibleEndAddr; ) { // extend this range if oo is adjacent, of the same type, and still in the range liveObjectTable.GetNextObject(addr, visibleEndAddr, out oo); if (oo.id < visibleEndAddr && addr + align - 1 >= oo.id && oo.typeIndex == o.typeIndex) { addr = oo.id + oo.size; } else break; } // figure out what type the object is TypeDesc t = typeIndexToTypeDesc[o.typeIndex]; // fill the space in the type's color FillSpace(g, r, t.pens[t.selected], o.id, addr); } if (addr + align - 1 < visibleEndAddr) { FillSpace(g, r, freePen, addr, visibleEndAddr); } } }
/// <summary> /// Compute the RuntimeInterfaces for a TypeDesc, is permitted to depend on /// RuntimeInterfaces of base type, but must not depend on any other /// details of the base type. /// </summary> public abstract DefType[] ComputeRuntimeInterfaces(TypeDesc type);