return constrainedType ?? genericParam.Context.GetWellKnownType(WellKnownType.Object);
}
+
+ /// <summary>
+ /// Return true when the type in question is marked with the NonVersionable attribute.
+ /// </summary>
+ /// <param name="type">Type to check</param>
+ /// <returns>True when the type is marked with the non-versionable custom attribute, false otherwise.</returns>
+ public static bool IsNonVersionable(this MetadataType type)
+ {
+ return type.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
+ }
}
}
continue;
}
+ if (!factory.CompilationModuleGroup.VersionsWithMethodBody(inlinee))
+ {
+ // We cannot record inlining info across version bubble as cross-bubble assemblies
+ // are not guaranteed to preserve token values. Only non-versionable methods may be
+ // inlined across the version bubble.
+ Debug.Assert(inlinee.IsNonVersionable());
+ continue;
+ }
+
if (!inlineeToInliners.TryGetValue(ecmaInlineeDefinition, out HashSet<EcmaMethod> inliners))
{
inliners = new HashSet<EcmaMethod>();
case TypeFlags.ValueType:
case TypeFlags.Nullable:
case TypeFlags.Enum:
+ if (typeDesc.IsWellKnownType(WellKnownType.TypedReference))
+ {
+ EmitElementType(CorElementType.ELEMENT_TYPE_TYPEDBYREF);
+ return;
+ }
+
{
ModuleToken token = context.GetModuleTokenForType((EcmaType)typeDesc);
EmitModuleOverride(token.Module, context);
EmitModuleOverride(targetModule, context);
EmitElementType(CorElementType.ELEMENT_TYPE_GENERICINST);
EmitTypeSignature(type.GetTypeDefinition(), context.InnerContext(targetModule));
+ SignatureContext outerContext = context.OuterContext;
EmitUInt((uint)type.Instantiation.Length);
for (int paramIndex = 0; paramIndex < type.Instantiation.Length; paramIndex++)
{
- EmitTypeSignature(type.Instantiation[paramIndex], context);
+ EmitTypeSignature(type.Instantiation[paramIndex], outerContext);
}
}
{
Instantiation instantiation = method.Method.Instantiation;
EmitUInt((uint)instantiation.Length);
+ SignatureContext outerContext = context.OuterContext;
for (int typeParamIndex = 0; typeParamIndex < instantiation.Length; typeParamIndex++)
{
- EmitTypeSignature(instantiation[typeParamIndex], context);
+ EmitTypeSignature(instantiation[typeParamIndex], outerContext);
}
}
}
{
EmitByte((byte)(fixupKind | ReadyToRunFixupKind.ModuleOverride));
EmitUInt((uint)factory.ManifestMetadataTable.ModuleToIndex(targetModule));
- return outerContext.InnerContext(targetModule);
+ return new SignatureContext(targetModule, outerContext.Resolver);
}
}
}
/// </summary>
public readonly ModuleTokenResolver Resolver;
+ public SignatureContext OuterContext => new SignatureContext(GlobalContext, Resolver);
+
public SignatureContext(EcmaModule context, ModuleTokenResolver resolver)
{
GlobalContext = context;
public EcmaModule GetTargetModule(TypeDesc type)
{
- if (type.IsPrimitive || type.IsString || type.IsObject)
+ if (type.IsPrimitive || type.IsString || type.IsObject || type.IsWellKnownType(WellKnownType.TypedReference))
{
return LocalContext;
}
return method.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute");
}
+
+ /// <summary>
+ /// Return true when the method is marked as non-versionable. Non-versionable methods
+ /// may be freely inlined into ReadyToRun images even when they don't reside in the
+ /// same version bubble as the module being compiled.
+ /// </summary>
+ /// <param name="method">Method to check</param>
+ /// <returns>True when the method is marked as non-versionable, false otherwise.</returns>
+ public static bool IsNonVersionable(this MethodDesc method)
+ {
+ return method.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
+ }
}
}
// (because otherwise we may not be able to encode its tokens)
// and if the callee is either in the same version bubble or is marked as non-versionable.
bool canInline = VersionsWithMethodBody(callerMethod) &&
- (VersionsWithMethodBody(calleeMethod) ||
- calleeMethod.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute"));
+ (VersionsWithMethodBody(calleeMethod) || calleeMethod.IsNonVersionable());
return canInline;
}
}
// Valuetypes with non-versionable attribute are candidates for fixed layout. Reject the rest.
- return type is MetadataType metadataType && metadataType.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute");
+ return type is MetadataType metadataType && metadataType.IsNonVersionable();
}
return true;
public string[] CodegenOptions { get; set; }
+ public bool CompositeOrInputBubble => Composite || InputBubble;
+
public static Command RootCommand()
{
// For some reason, arity caps at 255 by default
if (_commandLineOptions.CompileBubbleGenerics)
{
- if (!_commandLineOptions.InputBubble)
+ if (!_commandLineOptions.CompositeOrInputBubble)
{
Console.WriteLine(SR.WarningIgnoringBubbleGenerics);
_commandLineOptions.CompileBubbleGenerics = false;
rootingModules.Add(module);
versionBubbleModulesHash.Add(module);
- if (!_commandLineOptions.InputBubble)
+ if (!_commandLineOptions.CompositeOrInputBubble)
{
break;
}
// For non-single-method compilations add compilation roots.
foreach (var module in rootingModules)
{
- compilationRoots.Add(new ReadyToRunRootProvider(module, profileDataManager, _commandLineOptions.Partial));
+ compilationRoots.Add(new ReadyToRunRootProvider(
+ module,
+ profileDataManager,
+ profileDrivenPartialNGen: _commandLineOptions.Partial));
- if (!_commandLineOptions.InputBubble)
+ if (!_commandLineOptions.CompositeOrInputBubble)
{
break;
}