-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Workflow
Build the runtime like
./build.sh -bl -os browser -c Debug -subset clr.runtime+libs
That should install the emsdk, build the runtime and the libs.
To test the runtime startup I usually use these steps
-
remove
artifacts/obj/coreclr/browser.wasm.Debug/hosts/corewasmrun(this is because libs were not available at the time when corewasmrun was linked. this is temporary issue and will not happen once we have proper assembly loading) -
build
simple-serverlike this./dotnet.sh build -c Release src/mono/sample/wasm/simple-server
-
build
corewasmrunand run it in the browser. For quicker roundtrip, I run this command insrc/coreclr(source "../mono/browser/emsdk/emsdk_env.sh" && cd ../../artifacts/obj/coreclr/browser.wasm.Debug/; make corewasmrun -j12) && (cp hosts/corewasmrun/index.html ../../artifacts/obj/coreclr/browser.wasm.Debug/hosts/corewasmrun/;cd ../../artifacts/obj/coreclr/browser.wasm.Debug/hosts/corewasmrun/; ~/git/runtime-main/src/mono/sample/wasm/simple-server/bin/Release/net8.0/HttpServer)
It builds the corewasmrun, opens index.html in the default browser and runs the runtime initialization. It should also forward the browser console output to the terminal. (if chrome is not your default browser, you can just copy the URL in chrome)
On windows it should work in similar way, you might need to run ninja instead of make though.
Debugging
For debugging I use chrome browser with "C/C++ DevTools Support (DWARF)" extension. It is not perfect, but works most of the time. It can step through C code, set breakpoints, inspect wasm linear memory.
Next steps
These are the areas to work on to progress with the runtime initialization and improve code in the main branch.
-
helper calls opcodes - [wasm coreclr] helper call opcodes #119000
-
pinvoke / Qcalls - [wasm coreclr] pinvoke / Qcalls #119001
-
stackwalking - this is the current breaking point, need to find out how to handle it on wasm
-
compare the wasm startup with desktop startup - it is possible we are already hitting managed exception somewhere
Current state
On main branch it gets to the point, where it compiles and runs 6 managed methods, before it breaks. The filtered (|grep Compiled) terminal output should look like this:
log: stdout: Compiled method: .System.AppContext:Setup(ptr,ptr,int)
log: stdout: Compiled method: .System.Diagnostics.Debug:Assert(bool,System.String)
log: stdout: Compiled method: .System.Diagnostics.Debug:Assert(bool,System.String,System.String)
log: stdout: Compiled method: .System.Collections.Generic.Dictionary`2[System.__Canon,System.__Canon]:.ctor(int)
log: stdout: Compiled method: .System.Collections.Generic.Dictionary`2[System.__Canon,System.__Canon]:.ctor(int,System.Collections.Generic.IEqualityComparer`1[System.__Canon])
log: stdout: Compiled method: .System.Object:.ctor()
With proof of concept code it compiles/runs 60 methods/native functions before it breaks. The code is in https://github.com/radekdoulik/runtime/tree/clr-interp-qcall-and-helper-call-poc branch. Filtered output looks like this:
log: stdout: Compiled method: .System.AppContext:Setup(ptr,ptr,int)
log: stdout: Compiled method: .System.Diagnostics.Debug:Assert(bool,System.String)
log: stdout: Compiled method: .System.Diagnostics.Debug:Assert(bool,System.String,System.String)
log: stdout: Compiled method: .System.Collections.Generic.Dictionary`2[System.__Canon,System.__Canon]:.ctor(int)
log: stdout: Compiled method: .System.Collections.Generic.Dictionary`2[System.__Canon,System.__Canon]:.ctor(int,System.Collections.Generic.IEqualityComparer`1[System.__Canon])
log: stdout: Compiled method: .System.Object:.ctor()
log: stdout: Compiled method: .System.RuntimeTypeHandle:GetRuntimeTypeFromHandle(nint)
log: stdout: Compiled method: .System.Runtime.CompilerServices.TypeHandle:.ctor(ptr)
log: stdout: Compiled method: .System.Runtime.CompilerServices.TypeHandle:get_IsTypeDesc()
log: stdout: Compiled method: .System.Runtime.CompilerServices.TypeHandle:AsMethodTable()
log: stdout: Compiled method: .System.Runtime.CompilerServices.MethodTableAuxiliaryData:get_ExposedClassObject()
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:AsPointer[nint](byref)
log: stdout: Compiled method: .System.RuntimeTypeHandle:GetRuntimeTypeFromHandleSlow(nint)
log: stdout: Compiled method: .System.Runtime.CompilerServices.ObjectHandleOnStack:Create[System.__Canon](byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:AsPointer[System.__Canon](byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.ObjectHandleOnStack:.ctor(ptr)
log: stdout: InvokeCompiledMethod: System.RuntimeTypeHandle.GetRuntimeTypeFromHandleSlow --> RuntimeTypeHandle_GetRuntimeTypeFromHandleSlow [entrypoint]
log: stdout: Compiled method: .System.Type:GetTypeFromHandle(System.RuntimeTypeHandle)
log: stdout: Compiled method: .System.Type:get_IsValueType()
log: stdout: Compiled method: .System.RuntimeType:IsValueTypeImpl()
log: stdout: Compiled method: .System.RuntimeType:GetNativeTypeHandle()
log: stdout: Compiled method: .System.Runtime.CompilerServices.MethodTable:get_IsValueType()
log: stdout: Compiled method: .System.GC:KeepAlive(System.Object)
log: stdout: Compiled method: .System.Collections.Generic.EqualityComparer`1[System.__Canon]:get_Default()
log: stdout: Compiled method: .System.Runtime.CompilerServices.StaticsHelpers:GetGCStaticBase(ptr)
log: stdout: Compiled method: .System.Runtime.CompilerServices.MethodTableAuxiliaryData:GetDynamicStaticsInfo()
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:As[System.Runtime.CompilerServices.MethodTableAuxiliaryData,System.Runtime.CompilerServices.DynamicStaticsInfo](byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:Subtract[System.Runtime.CompilerServices.DynamicStaticsInfo](byref,int)
log: stdout: Compiled method: .System.Runtime.CompilerServices.StaticsHelpers:VolatileReadAsByref(byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:AsPointer[byte](byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.StaticsHelpers:GetGCStaticBaseSlow(ptr)
log: stdout: Compiled method: .System.Runtime.CompilerServices.InitHelpers:InitClassSlow(ptr)
log: stdout: InvokeCompiledMethod: System.Runtime.CompilerServices.InitHelpers.InitClassHelper --> InitClassHelper [entrypoint]
log: stdout: Compiled method: .System.Collections.Generic.EqualityComparer`1[System.__Canon]:.cctor()
log: stdout: Compiled method: .System.Collections.Generic.ComparerHelpers:CreateDefaultEqualityComparer(System.Type)
log: stdout: Compiled method: .System.Type:op_Inequality(System.Type,System.Type)
log: stdout: Compiled method: .System.Type:op_Equality(System.Type,System.Type)
log: stdout: Compiled method: .System.Runtime.CompilerServices.CastHelpers:IsInstanceOfClass(ptr,System.Object)
log: stdout: Compiled method: .System.Diagnostics.Debug:Fail(System.String,System.String)
log: stdout: Compiled method: .System.Runtime.CompilerServices.InitHelpers:InitClass(ptr)
log: stdout: Compiled method: .System.Runtime.CompilerServices.MethodTableAuxiliaryData:get_IsClassInited()
log: stdout: Compiled method: .System.Threading.Volatile:Read(byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:AsRef[uint](byref)
log: stdout: Compiled method: .System.Runtime.CompilerServices.Unsafe:As[uint,System.Threading.Volatile+VolatileUInt32](byref)
log: stdout: InvokeCompiledMethod: System.Runtime.CompilerServices.InitHelpers.InitClassHelper --> InitClassHelper [entrypoint]
log: stdout: Compiled method: .System.Diagnostics.Debug:.cctor()
log: stdout: Compiled method: .System.Diagnostics.DebugProvider:.ctor()
log: stdout: InvokeCompiledMethod: System.Runtime.CompilerServices.InitHelpers.InitClassHelper --> InitClassHelper [entrypoint]
log: stdout: InvokeCompiledMethod: System.Runtime.CompilerServices.InitHelpers.InitClassHelper --> InitClassHelper [entrypoint]
log: stdout: Compiled method: .System.Diagnostics.DebugProvider:Fail(System.String,System.String)
log: stdout: Compiled method: .System.Diagnostics.StackTrace:.ctor(int,bool)
log: stdout: Compiled method: .System.ArgumentOutOfRangeException:ThrowIfNegative[int](int,System.String)
log: stdout: Compiled method: .System.Int32:IsNegative(int)
log: stdout: Compiled method: .System.Diagnostics.StackTrace:InitializeForCurrentThread(int,bool)
log: stdout: Compiled method: .System.Diagnostics.StackTrace:CaptureStackTrace(int,bool,System.Exception)
log: stdout: Compiled method: .System.Diagnostics.StackFrameHelper:.ctor()
log: stdout: Compiled method: .System.Diagnostics.StackFrameHelper:InitializeSourceInfo(bool,System.Exception)
log: stdout: Compiled method: .System.Diagnostics.StackTrace:GetStackFramesInternal(System.Diagnostics.StackFrameHelper,bool,System.Exception)
log: stdout: Compiled method: .System.Diagnostics.StackTrace:GetStackFramesInternal(System.Runtime.CompilerServices.ObjectHandleOnStack,bool,System.Runtime.CompilerServices.ObjectHandleOnStack)
log: stdout: InvokeCompiledMethod: System.Diagnostics.StackTrace.<GetStackFramesInternal>g____PInvoke|0_0 --> StackTrace_GetStackFramesInternal [entrypoint]