Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Put default interfaces behind a define (#15358)
Browse files Browse the repository at this point in the history
This is needed so that we can turn default interfaces off in release branches.

I can't find a central location where the PRERELEASE flag could be defined because native and managed builds seem to be completely disconnected.

To limit the risk of only flipping the flag in one build type, I'm adding a test that verifies being able to load an interface with default methods matches what RuntimeFeature says.
  • Loading branch information
MichalStrehovsky committed Dec 5, 2017
1 parent d714acd commit 809b8f7
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 118 deletions.
7 changes: 7 additions & 0 deletions clr.defines.targets
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<!-- Features we're currently flighting, but don't intend to ship in officially supported releases -->
<PropertyGroup Condition="'$(IsPrerelease)' == 'true'">
<FeatureDefaultInterfaces>true</FeatureDefaultInterfaces>
</PropertyGroup>

<PropertyGroup>
<DefineConstants Condition="'$(FeatureAppX)' == 'true'">$(DefineConstants);FEATURE_APPX</DefineConstants>
<DefineConstants Condition="'$(FeatureArrayStubAsIL)' == 'true'">$(DefineConstants);FEATURE_ARRAYSTUB_AS_IL</DefineConstants>
Expand All @@ -17,6 +23,7 @@
<DefineConstants Condition="'$(FeatureXplatEventSource)' == 'true'">$(DefineConstants);FEATURE_EVENTSOURCE_XPLAT</DefineConstants>
<DefineConstants Condition="'$(FeatureUseLcid)' == 'true'">$(DefineConstants);FEATURE_USE_LCID</DefineConstants>
<DefineConstants Condition="'$(FeatureWin32Registry)' == 'true'">$(DefineConstants);FEATURE_WIN32_REGISTRY</DefineConstants>
<DefineConstants Condition="'$(FeatureDefaultInterfaces)' == 'true'">$(DefineConstants);FEATURE_DEFAULT_INTERFACES</DefineConstants>

<DefineConstants Condition="'$(ProfilingSupportedBuild)' == 'true'">$(DefineConstants);PROFILING_SUPPORTED</DefineConstants>

Expand Down
9 changes: 9 additions & 0 deletions clrdefinitions.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
include(clrfeatures.cmake)

# If set, indicates that this is not an officially supported release
# Keep in sync with IsPrerelease in dir.props
set(PRERELEASE 1)

# Features we're currently flighting, but don't intend to ship in officially supported releases
if (PRERELEASE)
add_definitions(-DFEATURE_DEFAULT_INTERFACES=1)
endif (PRERELEASE)

if (CLR_CMAKE_TARGET_ARCH_AMD64)
if (CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DDBG_TARGET_AMD64_UNIX)
Expand Down
5 changes: 5 additions & 0 deletions dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@
<PackageThirdPartyNoticesFile>$(ProjectDir)THIRD-PARTY-NOTICES.TXT</PackageThirdPartyNoticesFile>
<SyncInfoDirectory>$(BaseIntermediateOutputPath)</SyncInfoDirectory>

<!-- If true, indicates that this is not an officially supported release -->
<!-- It is important to flip this to false in official release branches -->
<!-- Keep it in sync with PRERELEASE in clrdefinitions.cmake -->
<IsPrerelease>true</IsPrerelease>

<!-- This should be kept in sync with package details in src/.nuget/init/project.json -->
<RuntimeIdGraphDefinitionVersion>1.0.2-beta-24224-02</RuntimeIdGraphDefinitionVersion>
<RuntimeIdGraphDefinitionFile>$(PackagesDir)/microsoft.netcore.platforms/$(RuntimeIdGraphDefinitionVersion)/runtime.json</RuntimeIdGraphDefinitionFile>
Expand Down
1 change: 0 additions & 1 deletion src/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,6 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredCompilation, W("EXPERIMENTAL_TieredCo
// TypeLoader
//
CONFIG_DWORD_INFO(INTERNAL_TypeLoader_InjectInterfaceDuplicates, W("INTERNAL_TypeLoader_InjectInterfaceDuplicates"), 0, "Injects duplicates in interface map for all types.")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TypeLoader_DefaultInterfaces, W("UNSUPPORTED_TypeLoader_DefaultInterfaces"), 0, "Enables support for default interfaces.")

//
// Virtual call stubs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ public static class RuntimeFeature
/// </summary>
public const string PortablePdb = nameof(PortablePdb);

#if FEATURE_DEFAULT_INTERFACES
/// <summary>
/// Indicates that this version of runtime supports default interface method implementations.
/// </summary>
public const string DefaultImplementationsOfInterfaces = nameof(DefaultImplementationsOfInterfaces);
#endif

/// <summary>
/// Checks whether a certain feature is supported by the Runtime.
Expand All @@ -23,7 +26,9 @@ public static bool IsSupported(string feature)
switch (feature)
{
case PortablePdb:
#if FEATURE_DEFAULT_INTERFACES
case DefaultImplementationsOfInterfaces:
#endif
return true;
}

Expand Down
6 changes: 4 additions & 2 deletions src/vm/classcompat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2612,25 +2612,27 @@ VOID MethodTableBuilder::EnumerateClassMethods()
}
}

#ifndef FEATURE_DEFAULT_INTERFACES
// Some interface checks.
if (fIsClassInterface)
{
if (IsMdVirtual(dwMemberAttrs))
{
if (!IsMdAbstract(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
if (!IsMdAbstract(dwMemberAttrs))
{
BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
}
}
else
{
// Instance field/method
if (!IsMdStatic(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
if (!IsMdStatic(dwMemberAttrs))
{
BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
}
}
}
#endif

// No synchronized methods in ValueTypes
if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
Expand Down
6 changes: 4 additions & 2 deletions src/vm/methodtablebuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2900,25 +2900,27 @@ MethodTableBuilder::EnumerateClassMethods()
}
}

#ifndef FEATURE_DEFAULT_INTERFACES
// Some interface checks.
if (fIsClassInterface)
{
if (IsMdVirtual(dwMemberAttrs))
{
if (!IsMdAbstract(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
if (!IsMdAbstract(dwMemberAttrs))
{
BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
}
}
else
{
// Instance field/method
if (!IsMdStatic(dwMemberAttrs) && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TypeLoader_DefaultInterfaces) == 0))
if (!IsMdStatic(dwMemberAttrs))
{
BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
}
}
}
#endif

// No synchronized methods in ValueTypes
if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,7 @@
<ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

<CLRTestPriority>0</CLRTestPriority>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
<!-- Use ILAsm that we just built for the new fixes required in default interface methods -->
<UseCustomILAsm>True</UseCustomILAsm>

<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</CLRTestBatchPreCommands>
<BashCLRTestPreCommands>
<![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_UNSUPPORTED_TypeLoader_DefaultInterfaces=1
]]>
</BashCLRTestPreCommands>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//
// Verifies that RuntimeFeature::IsSupported("DefaultImplementationsOfInterfaces") matches reality.
// This needs to succeed no matter whether default interfaces are supported.
//

.assembly extern System.Runtime{}
.assembly DefaultImplementationsOfInterfaces{}

.class interface private abstract auto ansi DefaultInterface
{
.method public hidebysig newslot virtual
instance void Method() cil managed
{
.maxstack 8
ret
}
}

.method private hidebysig static void TryLoadDefaultInterface() cil managed noinlining
{
.maxstack 8
ldtoken DefaultInterface
call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
callvirt instance string [System.Runtime]System.Object::ToString()
pop
ret
}

.method private hidebysig static bool SupportsDefaultInterfaces() cil managed
{
.maxstack 1
.try
{
call void TryLoadDefaultInterface()
leave.s Supports

}
catch [System.Runtime]System.TypeLoadException
{
pop
leave.s DoesNotSupport

}
Supports:
ldc.i4.1
ret

DoesNotSupport:
ldc.i4.0
ret
}

.method private hidebysig static int32
Main() cil managed
{
.entrypoint
.maxstack 2
ldstr "DefaultImplementationsOfInterfaces"
call bool [System.Runtime]System.Runtime.CompilerServices.RuntimeFeature::IsSupported(string)
call bool SupportsDefaultInterfaces()
beq Good

ldc.i4.m1
ret

Good:
ldc.i4 100
ret
}
Loading

0 comments on commit 809b8f7

Please sign in to comment.