Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.

Wasm enable shared generics and generic virtual methods#7897

Merged
MichalStrehovsky merged 104 commits intodotnet:masterfrom
yowl:RunReferenceTypeShared-fails
Jan 2, 2020
Merged

Wasm enable shared generics and generic virtual methods#7897
MichalStrehovsky merged 104 commits intodotnet:masterfrom
yowl:RunReferenceTypeShared-fails

Conversation

@yowl
Copy link
Contributor

@yowl yowl commented Dec 1, 2019

Mostly taken from the cpp backend, this enables shared generics and generic virtual methods for the Wasm backend. Have tried to keep the logic as clean as I could, but maybe there's some obvious enhancements/reductions in code that I missed.

Size of HelloWasm.bc (LLVM bitcode) before 43,950KB, and after 37,593KB (these aren't exact as the after includes more tests, so actual saving is probably fractionally better) . HelloWasm before this change didn't have much in the way of generics so this mostly reflects the framework and runtime generics.

Enables the Simple/Generics tests for wasm which have the almost same coverage as cpp (Wasm includes an additional test) in terms of what is #if'ed out.

WIP as depends on #7893 and #7891

Fixes #7248

yowl added 30 commits April 20, 2019 12:42
…r at least might as well do that now rather than work around the lack of it.
# Conflicts:
#	tests/src/Simple/HelloWasm/Program.cs
add call for generic context
need to add the hidden param where necessary.
Still have to  do generic lookup functions and delegate thunks are undefined
Correct call for checking cctor to match cpp.  Return the value - but its not used yet
passes compilation.
Calling stub instead of signal()
exception thrown: RuntimeError: index out of bounds,__ZN6EEType18get_OptionalFieldsEv@http://localhost:6931/HelloWasm.wasm:wasm-function[19519]:0xc24eb3
__ZN6EEType13get_RareFlagsEv@http://localhost:6931/HelloWasm.wasm:wasm-function[19529]:0xc257d1
__ZN6EEType14RequiresAlign8Ev@http://localhost:6931/HelloWasm.wasm:wasm-function[19615]:0xc2a3d7
_RhpNewArray@http://localhost:6931/HelloWasm.wasm:wasm-function[19617]:0xc2a523
_S_P_TypeLoader_System_Collections_Generic_LowLevelDictionary_2_System___Canon__IntPtr___Clear@http://localhost:6931/HelloWasm.wasm:wasm-function[2237]:0x2f3c6f
_S_P_TypeLoader_System_Collections_Generic_LowLevelDictionary_2_System___Canon__IntPtr____ctor_0@http://localhost:6931/HelloWasm.wasm:wasm-function[1733]:0x29d8b4
_S_P_TypeLoader_System_Collections_Generic_LowLevelDictionary_2_System___Canon__IntPtr____ctor@http://localhost:6931/HelloWasm.wasm:wasm-function[1164]:0x256ca5
_S_P_TypeLoader_Internal_Runtime_TypeLoader_TypeLoaderEnvironment___ctor@http://localhost:6931/HelloWasm.wasm:wasm-function[861]:0x22fcff
_S_P_TypeLoader_Internal_Runtime_TypeLoader_TypeLoaderEnvironment__Initialize@http://localhost:6931/HelloWasm.wasm:wasm-function[470]:0x202c0b
_S_P_TypeLoader_Internal_Runtime_CompilerHelpers_LibraryInitializer__InitializeLibrary@http://localhost:6931/HelloWasm.wasm:wasm-function[400]:0x1fc3c6
_StartupCodeMain@http://localhost:6931/HelloWasm.wasm:wasm-function[396]:0x1fc2fe
___managed__Main@http://localhost:6931/HelloWasm.wasm:wasm-function[17784]:0xb875ad
_main@http://localhost:6931/HelloWasm.wasm:wasm-function[19766]:0xc31ced
Module._main@http://localhost:6931/HelloWasm.js:6592:33
callMain@http://localhost:6931/HelloWasm.js:7044:22
doRun@http://localhost:6931/HelloWasm.js:7102:49
Problem now seems to be that class statics are not initialised
now fails with

_S_P_CoreLib_System_Diagnostics_Debug__Fail_0@http://localhost:6931/HelloWasm.wasm:wasm-function[702]:0x21d82e
_S_P_CoreLib_System_Diagnostics_Debug__Assert_1@http://localhost:6931/HelloWasm.wasm:wasm-function[597]:0x20ff8a
_S_P_CoreLib_System_Diagnostics_Debug__Assert@http://localhost:6931/HelloWasm.wasm:wasm-function[337]:0x1f7a56
_S_P_CoreLib_System_Threading_ManagedThreadId__AllocateId@http://localhost:6931/HelloWasm.wasm:wasm-function[2330]:0x2fb83b
_S_P_CoreLib_System_Threading_ManagedThreadId___ctor@http://localhost:6931/HelloWasm.wasm:wasm-function[1682]:0x298e63
_S_P_CoreLib_System_Threading_ManagedThreadId__MakeForCurrentThread@http://localhost:6931/HelloWasm.wasm:wasm-function[1217]:0x25ae5b
_S_P_CoreLib_System_Threading_ManagedThreadId__get_Current@http://localhost:6931/HelloWasm.wasm:wasm-function[810]:0x22b6ce
_S_P_CoreLib_System_Runtime_CompilerServices_ClassConstructorRunner__get_CurrentManagedThreadId@http://localhost:6931/HelloWasm.wasm:wasm-function[484]:0x2050c7
_S_P_CoreLib_System_Runtime_CompilerServices_ClassConstructorRunner__EnsureClassConstructorRun@http://localhost:6931/HelloWasm.wasm:wasm-function[391]:0x1fbf2d
for the generic dict, try to remove the +1 pointer as otherwise the index lookup is one off - this maybe the wrong way to fix this.
Fails as InternalGetResourceString throws.
Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started looking but I haven't looked at the two files with the biggest changes yet. I hope I'll get to those soon. Sorry for the delays.

@@ -1,7 +1,15 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all changes to this file can be backed out.


<ProjectReference Include="ILHelpers.ilproj" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="-r:$(IntermediateOutputPath)\ILHelpers.dll" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="--usesharedgenerics" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be needed since shared genercis are now the default for wasm too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having a problem with this. If its not here, how does it get into the .rsp?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't reading

SharedGenericsMode genericsMode = _useSharedGenerics || !_isWasmCodegen ?
SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;
correctly. Once Wasm enables shared generics, this will always be true, so how far should I go with this logic, just set useSharedGenerics to default true with a comment "all current backends require shared generics" and warn if the command line arg is set false, or completely remove the option to turn off shared generics, the command line arg, and the SharedGenericsMode enum?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

yowl added 5 commits December 14, 2019 10:37
_S_P_CoreLib_System_Diagnostics_Debug__Assert@http://localhost:6931/Generics.wasm:wasm-function[375]:0x21682b
_S_P_TypeLoader_Internal_TypeSystem_TypeDesc__SetRuntimeTypeHandleUnsafe@http://localhost:6931/Generics.wasm:wasm-function[11211]:0x78026a
_S_P_TypeLoader_Internal_TypeSystem_CanonType__Initialize@http://localhost:6931/Generics.wasm:wasm-function[13993]:0x8fedfe
_S_P_TypeLoader_Internal_TypeSystem_CanonType___ctor@http://localhost:6931/Generics.wasm:wasm-function[13024]:0x88a3cf
_S_P_TypeLoader_Internal_TypeSystem_TypeSystemContext__get_CanonType@http://localhost:6931/Generics.wasm:wasm-function[11209]:0x78010c
_S_P_TypeLoader_Internal_TypeSystem_TypeSystemContext__ResolveRuntimeTypeHandle@http://localhost:6931/Generics.wasm:wasm-function[10335]:0x71
…red-fails

# Conflicts:
#	src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
#	tests/src/Simple/HelloWasm/Program.cs
@yowl
Copy link
Contributor Author

yowl commented Dec 14, 2019

Thanks, have made the adjustment for the fat function offset

@yowl
Copy link
Contributor Author

yowl commented Dec 15, 2019

Oh dear, I seem to have broken something, let me look at that.

yowl added 2 commits December 16, 2019 09:26
…red-fails

# Conflicts:
#	src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
#	tests/src/Simple/HelloWasm/Program.cs
@yowl yowl changed the title WIP: Wasm enable shared generics and generic virtual methods Wasm enable shared generics and generic virtual methods Dec 26, 2019
@yowl
Copy link
Contributor Author

yowl commented Dec 26, 2019

Remove WIP as dependencies now merged

@yowl
Copy link
Contributor Author

yowl commented Dec 27, 2019

Noticed a problem:
With this IL

  IL_005B:  constrained valuetype TKey_System.Collections.Generic.KeyValuePair`2<class System.__Canon, class System.__Canon>
  IL_0061:  callvirt    instance int32 System.Object::GetHashCode()

Which is from the method

// [S.P.CoreLib]System.Collections.Generic.Dictionary`2<TKey_System.Collections.Generic.KeyValuePair`2<System.__Canon,System.__Canon>,TValue_System.__Canon>.FindValue(KeyValuePair`2<__Canon,__Canon>)
.method instance class TValue_System.__Canon& FindValue(valuetype TKey_System.Collections.Generic.KeyValuePair`2<class System.__Canon, class System.__Canon>) cil managed

When getting the constrained type we use

        private void ImportConstrainedPrefix(int token)
        {
            _constrainedType = (TypeDesc)_methodIL.GetObject(token);
        }

Which results in _constrainedType being a RuntimeDeterminedType. This is a problem in the callvirt as we attempt to get the target method using

targetMethod = constrainedType.TryResolveConstraintMethodApprox(canonMethod.OwningType, canonMethod, out _);

which expects a MetadataType at

return FindVirtualFunctionTargetMethodOnObjectType(targetMethod, (MetadataType)objectType);
.

Where have I gone wrong here, should I even be creating code for TKey, if that's a value type, then shouldn't it be the actual type?

@MichalStrehovsky
Copy link
Member

Which results in _constrainedType being a RuntimeDeterminedType. This is a problem in the callvirt as we attempt to get the target method using

I would just do what the IL scanner is doing: grab the canonical form of the constrained type:

TypeDesc constrained = _constrained;
if (constrained.IsRuntimeDeterminedSubtype)
constrained = constrained.ConvertToCanonForm(CanonicalFormKind.Specific);

The scanner keeps both canonical and runtime determined form of the method, and uses the canonical for things like this (TryResolveConstraintMethodApprox is called with canonical method and canonical constraint). The runtime determined form is only needed if we will have to do a generic lookup, but constrained calls don't end up needing that because they acquire the generic context from this.

Note that the scanner still uses the runtime determined form of the constraint in case we need to box.

@yowl yowl changed the title Wasm enable shared generics and generic virtual methods WIP:Wasm enable shared generics and generic virtual methods Dec 28, 2019
@yowl
Copy link
Contributor Author

yowl commented Dec 28, 2019

Moving back to WIP as

        var dict = new Dictionary<KeyValuePair<string, string>, string>();
        var notContainsKey = dict.ContainsKey(new KeyValuePair<string, string>("", ""));
        dict.Add(new KeyValuePair<string, string>("", ""), "");
        var containsKey = dict.ContainsKey(new KeyValuePair<string, string>("", ""));

is failing on the Add with

exception thrown: RuntimeError: index out of bounds,_S_P_CoreLib_Internal_Runtime_EEType__get_Kind@http://localhost:6931/HelloWasm.wasm:wasm-function[632]:0x204237
_S_P_CoreLib_Internal_Runtime_EEType__get_IsParameterizedType@http://localhost:6931/HelloWasm.wasm:wasm-function[266]:0x1e65f6
_S_P_CoreLib_Internal_Runtime_EEType__get_IsPointerType@http://localhost:6931/HelloWasm.wasm:wasm-function[1424]:0x262ed0
_S_P_CoreLib_System_EETypePtr__get_IsPointer@http://localhost:6931/HelloWasm.wasm:wasm-function[1025]:0x2324e7
_S_P_CoreLib_System_ValueType__RegularGetValueTypeHashCode@http://localhost:6931/HelloWasm.wasm:wasm-function[3190]:0x33b9eb
_S_P_CoreLib_System_ValueType__GetHashCodeImpl@http://localhost:6931/HelloWasm.wasm:wasm-function[2267]:0x2c0903
_S_P_CoreLib_System_ValueType__GetHashCode@http://localhost:6931/HelloWasm.wasm:wasm-function[2266]:0x2c0774
_S_P_CoreLib_System_Collections_Generic_Dictionary_2_S_P_CoreLib_System_Collections_Generic_KeyValuePair_2_System___Canon__System___Canon___System___Canon___TryInsert@http://localhost:6931/HelloWasm.wasm:wasm-function[2011]:0x2a62fb
_S_P_CoreLib_System_Collections_Generic_Dictionary_2_S_P_CoreLib_System_Collections_Generic_KeyValuePair_2_System___Canon__System___Canon___System___Canon___Add@http://localhost:6931/HelloWasm.wasm:wasm-function[1050]:0x233e4d
_HelloWasm_Program__TestConstrainedValueTypeCallVirt@http://localhost:6931/HelloWasm.wasm:wasm-function[980]:0x22adca

@yowl
Copy link
Contributor Author

yowl commented Dec 29, 2019

Thanks for the constrained info. For the ValueType.GetHashCode problem, I think I have the special unboxing thunks ok as this code is fine

    private static void TestCallValueTypeGetHashCodeFromGeneric()
    {
        var x = new GenStruct<string>("").GetHashCode();
    }

    public struct GenStruct<TKey>
    {
        private TKey key; 

        public GenStruct(TKey key)
        {
            this.key = key;
        }
    }

However when the GetHashCode is called from within a generic method :

    private static void TestCallValueTypeGetHashCodeFromGeneric()
    {
        new GetHashCodeCaller<GenStruct<string>, string>().CallValueTypeGetHashCodeFromGeneric(new GenStruct<string>(""));
    }

    public class GetHashCodeCaller<TKey, TValue>
    {
        public void CallValueTypeGetHashCodeFromGeneric(TKey k)
        {
            k.GetHashCode();
        }
    }

Then I get this error, or rather as I'm not using Dict<,> anymore:

RuntimeError: index out of bounds,
___GenericLookupFromDict_S_P_CoreLib_System_EETypePtr__EETypePtrOf_System___Canon__TypeHandle_T_System___Canon@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[502]:0x1f84eb
_S_P_CoreLib_System_EETypePtr__EETypePtrOf_System___Canon_@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[417]:0x1f13f1
_HelloWasm_Program_GenStruct_1_System___Canon_____GetFieldHelper@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[3863]:0x35f5db
__Boxed_HelloWasm_Program_GenStruct_1_System___Canon____unbox_HelloWasm_Program_GenStruct_1____GetFieldHelper@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[3862]:0x35f57d
_S_P_CoreLib_System_ValueType__RegularGetValueTypeHashCode@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[3187]:0x338a7c
_S_P_CoreLib_System_ValueType__GetHashCodeImpl@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[2263]:0x2bd9b3
_S_P_CoreLib_System_ValueType__GetHashCode@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[2262]:0x2bd824
_HelloWasm_Program_GetHashCodeCaller_2_HelloWasm_Program_GenStruct_1_System___Canon___System___Canon___CallValueTypeGetHashCodeFromGeneric@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[1050]:0x233c89
_HelloWasm_Program__TestCallValueTypeGetHashCodeFromGeneric@file:///E:/GitHub/corert/tests/src/Simple/HelloWasm/bin/Debug/wasm/native/HelloWasm.wasm:wasm-function[981]:0x22adde

I want to ask if I have the RhBox correct. For the working first case, the RhBox is called with the concrete type, __EEType_HelloWasm_Program_GenStruct_1<String>___SYMBOL, but when called from the generic method, the type passed to RhBox is __EEType_HelloWasm_Program_GenStruct_1<System___Canon>___SYMBOL because the logic for doing a generic dict lookup is

            TypeDesc type = (TypeDesc)_methodIL.GetObject(token);
...
            if (type.IsRuntimeDeterminedSubtype)

And that is false. Is this wrong?

@yowl
Copy link
Contributor Author

yowl commented Dec 30, 2019

My mistake, was looking the the ILOpcode box, not the callvirt where I didn't have the lookup code. Its in now along with a test. Removing WIP. Sorry about the back and forth on this. I have the standard tests working, but then move on to trying the Uno Platform where more errors are uncovered.

@yowl yowl changed the title WIP:Wasm enable shared generics and generic virtual methods Wasm enable shared generics and generic virtual methods Dec 30, 2019
Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Once this feedback is addressed, we can check this in.

Append(gvmSlotVarName);
Append(" & ");
Append(FatFunctionPointerConstants.Offset.ToString());
Append(method.Context.Target.FatFunctionPointerOffset.ToString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit (also elsewhere):

Suggested change
Append(method.Context.Target.FatFunctionPointerOffset.ToString());
Append(_typeSystemContext.Target.FatFunctionPointerOffset.ToString());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -0,0 +1,34 @@
using System;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add copyright header?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: is this used?


SharedGenericsMode genericsMode = _useSharedGenerics || !_isWasmCodegen ?
SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;
SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_useSharedGenerics is now unused. Let's delete the command line option and field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TestReflectionInvoke.Run();
TestFieldAccess.Run();
TestDevirtualization.Run();
TestGenericInlining.Run();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this lost in a rebase?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, reinstated.

/// Offset by which fat function pointers are shifted to distinguish them
/// from real function pointers. Keep in line with FatFunctionPointerConstants
/// </summary>
internal const uint FatFunctionPointerOffset = (uint)1 << 31;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you switch this to the one obtained from Context.Target?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Moved a helper function from static to instance to get access.

//TODO refactor argument creation with else below
arguments = new StackEntry[]
{
new ExpressionEntry(StackValueKind.ValueType, "eeType", CallGenericHelper(ReadyToRunHelperId.TypeHandle, type),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would probably fix the TestNullableCasting test in the Simple\Generics test:

Suggested change
new ExpressionEntry(StackValueKind.ValueType, "eeType", CallGenericHelper(ReadyToRunHelperId.TypeHandle, type),
new ExpressionEntry(StackValueKind.ValueType, "eeType", CallGenericHelper(ReadyToRunHelperId.TypeHandleForCasting, type),

If it doesn't fix it, then leave this as-is for now. Let's not add more scope to this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately hits

Debug.Assert(factory.GenericLookup.Type((TypeDesc)target) != factory.GenericLookup.UnwrapNullableType((TypeDesc)target));
with target {[S.P.CoreLib]System.Collections.Generic.ICollection1<T_System.__Canon>}` Have opened #7934

HandleCall(null, methodSignature, ILOpcode.calli, calliTarget: ((ExpressionEntry)_stack.Pop()).ValueAsType(LLVM.PointerType(GetLLVMSignatureForMethod(methodSignature), 0), _builder));
MethodSignature methodSignature = (MethodSignature)_canonMethodIL.GetObject(token);

if (_method.ToString().Contains("InvokeRet"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!

}
else
{
if (ConstructedEETypeNode.CreationAllowed(typeDesc))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this if check? If we call GetEETypePointerForTypeDesc with true below, it should do the right thing wrt dependency tracking.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, works with it removed.

if (node == null)
continue;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: undo white space change (same below).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

@yowl yowl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for checking

/// </summary>
#if WASM
// WebAssembly uses index tables, not addresses for function pointers. This is going to be contentious it is baked into Ilc and hence an Ilc for x64 will not be able to compile Wasm and vice versa. Alternative ways round this?.
public const int Offset = 1 << 31;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was mentioned #7248 (comment) that there might be other better solutions available for Wasm.


<ProjectReference Include="ILHelpers.ilproj" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="-r:$(IntermediateOutputPath)\ILHelpers.dll" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="--usesharedgenerics" />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having a problem with this. If its not here, how does it get into the .rsp?


<ProjectReference Include="ILHelpers.ilproj" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="-r:$(IntermediateOutputPath)\ILHelpers.dll" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="--usesharedgenerics" />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't reading

SharedGenericsMode genericsMode = _useSharedGenerics || !_isWasmCodegen ?
SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;
correctly. Once Wasm enables shared generics, this will always be true, so how far should I go with this logic, just set useSharedGenerics to default true with a comment "all current backends require shared generics" and warn if the command line arg is set false, or completely remove the option to turn off shared generics, the command line arg, and the SharedGenericsMode enum?

//TODO refactor argument creation with else below
arguments = new StackEntry[]
{
new ExpressionEntry(StackValueKind.ValueType, "eeType", CallGenericHelper(ReadyToRunHelperId.TypeHandle, type),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately hits

Debug.Assert(factory.GenericLookup.Type((TypeDesc)target) != factory.GenericLookup.UnwrapNullableType((TypeDesc)target));
with target {[S.P.CoreLib]System.Collections.Generic.ICollection1<T_System.__Canon>}` Have opened #7934

@@ -0,0 +1,34 @@
using System;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


SharedGenericsMode genericsMode = _useSharedGenerics || !_isWasmCodegen ?
SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;
SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TestReflectionInvoke.Run();
TestFieldAccess.Run();
TestDevirtualization.Run();
TestGenericInlining.Run();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, reinstated.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="*.cs" />
<IlcArg Include="--usesharedgenerics" />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.


<ProjectReference Include="ILHelpers.ilproj" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="-r:$(IntermediateOutputPath)\ILHelpers.dll" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="--usesharedgenerics" />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience on this!

@MichalStrehovsky MichalStrehovsky merged commit f52a8e5 into dotnet:master Jan 2, 2020
@yowl yowl deleted the RunReferenceTypeShared-fails branch January 3, 2020 19:50
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wasm: support Generic Virtual Method Calls & Shared Generics (was: some linq methods fail to compile)

2 participants