Wasm: enable stack trace exceptions, simple exceptions test, upgrade emscripten (#8319)

This commit is contained in:
yowl 2020-10-14 19:05:51 -05:00 коммит произвёл GitHub
Родитель b06c72e12f
Коммит 0d45438de0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 116 добавлений и 6 удалений

Просмотреть файл

@ -5,14 +5,14 @@ git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
rem checkout a known good version to avoid a random break when emscripten changes the top of tree.
git checkout c1f0ad9
git checkout def6e49
powershell -NoProfile -NoLogo -ExecutionPolicy ByPass -command "& """%~dp0update-machine-certs.ps1""" %*"
rem Use the python that is downloaded to native-tools explicitly as its not on the path
call "%1"\..\native-tools\bin\python3 emsdk.py install 2.0.0
call "%1"\..\native-tools\bin\python3 emsdk.py install 2.0.3
if %errorlevel% NEQ 0 goto fail
call emsdk activate 2.0.0
call emsdk activate 2.0.3
if %errorlevel% NEQ 0 goto fail
exit /b 0

Просмотреть файл

@ -4539,13 +4539,25 @@ namespace Internal.IL
void ThrowOrRethrow(StackEntry exceptionObject)
{
int offset = GetTotalParameterOffset() + GetTotalLocalOffset();
LLVMValueRef shadowStack = _builder.BuildGEP(_currentFunclet.GetParam(0),
new LLVMValueRef[] { LLVMValueRef.CreateConstInt(LLVMTypeRef.Int32, (uint)offset, false) },
String.Empty);
LLVMValueRef exSlot = _builder.BuildBitCast(shadowStack, LLVMTypeRef.CreatePointer(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), 0));
_builder.BuildStore(exceptionObject.ValueAsType(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), _builder), exSlot);
LLVMValueRef[] llvmArgs = new LLVMValueRef[] { shadowStack };
MetadataType helperType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "Exception");
MethodDesc helperMethod = helperType.GetKnownMethod("DispatchExWasm", null);
LLVMValueRef fn = LLVMFunctionForMethod(helperMethod, helperMethod, null, false, null, null, out bool hasHiddenParam, out LLVMValueRef dictPtrPtrStore, out LLVMValueRef fatFunctionPtr);
ExceptionRegion currentExceptionRegion = GetCurrentTryRegion();
_builder.BuildCall(fn, llvmArgs, string.Empty);
if (RhpThrowEx.Handle.Equals(IntPtr.Zero))
{
RhpThrowEx = Module.AddFunction("RhpThrowEx", LLVMTypeRef.CreateFunction(LLVMTypeRef.Void, new LLVMTypeRef[] { LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0) }, false));
}
LLVMValueRef[] args = new LLVMValueRef[] { exceptionObject.ValueAsType(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), _builder) };
ExceptionRegion currentExceptionRegion = GetCurrentTryRegion();
if (currentExceptionRegion == null)
{
_builder.BuildCall(RhpThrowEx, args, "");

Просмотреть файл

@ -239,6 +239,7 @@
<Compile Include="System\Delegate.DefaultParameters.cs" />
<Compile Include="System\RuntimeTypeHandle.cs" />
<Compile Include="System\Exception.CoreRT.cs" />
<Compile Include="System\Exception.CoreRT.Wasm.cs" Condition="'$(Platform)'=='wasm'"/>
<Compile Include="System\RuntimeExceptionHelpers.cs" />
<Compile Include="System\EETypePtr.cs" />
<Compile Include="System\Runtime\RuntimeImports.cs" />

Просмотреть файл

@ -22,10 +22,11 @@ namespace System.Diagnostics
// at S_P_CoreLib_System_Diagnostics_StackTrace__InitializeForCurrentThread (wasm-function[12314]:275)
// at S_P_CoreLib_System_Diagnostics_StackTrace___ctor_0(wasm-function[12724]:118)
skipFrames += 2; // METHODS_TO_SKIP is a constant so just change here
// at S_P_CoreLib_System_Exception__DispatchExWasm(wasm-function[2360]:39)
fixed (byte* curChar = backtraceBuffer)
{
callstackLen = emscripten_get_callstack(8 /* original source stack if source maps available, not tested */, curChar, backtraceBuffer.Length);
callstackLen = emscripten_get_callstack(0, curChar, backtraceBuffer.Length);
}
int _numOfFrames = 1;
int lineStartIx = 0;

Просмотреть файл

@ -0,0 +1,42 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace System
{
public partial class Exception
{
[DllImport("*")]
internal static extern void RhpThrowEx(object exception);
private static void DispatchExWasm(object exception)
{
AppendExceptionStackFrameWasm(exception, new StackTrace(1).ToString());
//RhpThrowEx(exception); can't as not handling the transition unmanaged->managed in the landing pads.
}
private static void AppendExceptionStackFrameWasm(object exceptionObj, string stackTraceString)
{
// This method is called by the runtime's EH dispatch code and is not allowed to leak exceptions
// back into the dispatcher.
try
{
Exception ex = exceptionObj as Exception;
if (ex == null)
Environment.FailFast("Exceptions must derive from the System.Exception class");
if (!RuntimeExceptionHelpers.SafeToPerformRichExceptionSupport)
return;
ex._stackTraceString = stackTraceString.Replace("__", ".").Replace("_", ".");
}
catch
{
// We may end up with a confusing stack trace or a confusing ETW trace log, but at least we
// can continue to dispatch this exception.
}
}
}
}

Просмотреть файл

@ -1,6 +1,12 @@
@echo off
setlocal
"%1\%2"
IF /i "%__Mode%"=="wasm" (
call %EMSDK_NODE% "%1\%2"
) ELSE (
"%1\%2"
)
set ErrorCode=%ERRORLEVEL%
IF "%ErrorCode%"=="100" (
echo %~n0: pass

Просмотреть файл

@ -3,6 +3,10 @@
using System;
using System.Text;
#if CODEGEN_WASM
using System.Runtime.InteropServices;
using Console=BringUpTest.Console;
#endif
public class BringUpTest
{
@ -53,7 +57,11 @@ public class BringUpTest
}
string stackTrace = e.StackTrace;
#if CODEGEN_WASM && !DEBUG //Wasm doesn't get useful names in release mode, e.g. it gets at wasm-function[10259]:0x4b5182
if (!stackTrace.Contains("wasm-function"))
#else
if (!stackTrace.Contains("BringUpTest.Main"))
#endif
{
Console.WriteLine("Unexpected stack trace: " + stackTrace);
return Fail;
@ -198,5 +206,45 @@ public class BringUpTest
CreateSomeGarbage();
return true;
}
#if CODEGEN_WASM
internal class Console
{
private static unsafe void PrintString(string s)
{
int length = s.Length;
fixed (char* curChar = s)
{
for (int i = 0; i < length; i++)
{
TwoByteStr curCharStr = new TwoByteStr();
curCharStr.first = (byte)(*(curChar + i));
printf((byte*)&curCharStr, null);
}
}
}
internal static void WriteLine(string s)
{
PrintString(s);
PrintString("\n");
}
internal static void WriteLine(string format, string p)
{
PrintString(string.Format(format, p));
PrintString("\n");
}
}
struct TwoByteStr
{
public byte first;
public byte second;
}
[DllImport("*")]
private static unsafe extern int printf(byte* str, byte* unused);
#endif
}

Просмотреть файл