Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/design/coreclr/botr/clr-abi.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ When a funclet finishes execution, and the VM returns execution to the function

Any register value changes made in the funclet are lost. If a funclet wants to make a variable change known to the main function (or the funclet that contains the "try" region), that variable change needs to be made to the shared main function stack frame. This not a fundamental limitation. If necessary, the runtime can be updated to preserve non-volatile register changes made in funclets.

Funclets are not required to preserve non-volatile registers.
Funclets are not required to preserve non-volatile registers that are saved by main method body.
Comment thread
jkotas marked this conversation as resolved.

Comment on lines 386 to 389
# EH Info, GC Info, and Hot & Cold Splitting

Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.S
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,21 @@ NESTED_ENTRY RhpCallFinallyFunclet, _TEXT, NoHandler

ALTERNATE_ENTRY RhpCallFinallyFunclet2

mov rsi, [rsp + locArg1] // rsi <- regdisplay

mov rax, [rsi + OFFSETOF__REGDISPLAY__pRbx]
mov [rax] , rbx
mov rax, [rsi + OFFSETOF__REGDISPLAY__pRbp]
mov [rax] , rbp
mov rax, [rsi + OFFSETOF__REGDISPLAY__pR12]
mov [rax] , r12
mov rax, [rsi + OFFSETOF__REGDISPLAY__pR13]
mov [rax] , r13
mov rax, [rsi + OFFSETOF__REGDISPLAY__pR14]
mov [rax] , r14
mov rax, [rsi + OFFSETOF__REGDISPLAY__pR15]
mov [rax] , r15

mov rax, [rsp + locThread] // rax <- Thread*
lock or dword ptr [rax + OFFSETOF__Thread__m_ThreadStateFlags], TSF_DoNotTriggerGc

Expand Down
21 changes: 21 additions & 0 deletions src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,27 @@ NESTED_ENTRY RhpCallFinallyFunclet, _TEXT

ALTERNATE_ENTRY RhpCallFinallyFunclet2

mov rdx, [rsp + rsp_offsetof_arguments + 8h] ;; rdx <- regdisplay

mov rax, [rdx + OFFSETOF__REGDISPLAY__pRbx]
mov [rax] , rbx
mov rax, [rdx + OFFSETOF__REGDISPLAY__pRbp]
mov [rax] , rbp
mov rax, [rdx + OFFSETOF__REGDISPLAY__pRsi]
mov [rax] , rsi
mov rax, [rdx + OFFSETOF__REGDISPLAY__pRdi]
mov [rax] , rdi
mov rax, [rdx + OFFSETOF__REGDISPLAY__pR12]
mov [rax] , r12
mov rax, [rdx + OFFSETOF__REGDISPLAY__pR13]
mov [rax] , r13
mov rax, [rdx + OFFSETOF__REGDISPLAY__pR14]
mov [rax] , r14
mov rax, [rdx + OFFSETOF__REGDISPLAY__pR15]
mov [rax] , r15

;; XMM6-15 do not need copy-back into REGDISPLAY (no GC adjustment required).

mov rax, [rsp + rsp_offsetof_thread] ;; rax <- Thread*
lock or dword ptr [rax + OFFSETOF__Thread__m_ThreadStateFlags], TSF_DoNotTriggerGc

Expand Down
11 changes: 11 additions & 0 deletions src/tests/Regressions/coreclr/GitHub_129010/Test129010.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<CLRTestPriority>1</CLRTestPriority>
</PropertyGroup>
<ItemGroup>
<Compile Include="test129010.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(TestLibraryProjectPath)" />
</ItemGroup>
</Project>
104 changes: 104 additions & 0 deletions src/tests/Regressions/coreclr/GitHub_129010/test129010.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using Xunit;

public class Program
{
static Exception ex = new Exception();
static byte[] data = null;
static int count = 0;

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Alloc()
{
data = new byte[65536];
if (count % 16 == 0)
{
// Force compacting GC
GC.Collect(2, GCCollectionMode.Forced, true, true);
}
Comment thread
janvorli marked this conversation as resolved.
count++;
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void Test()
{
try
{
throw ex;
}
catch (Exception)
{
throw;
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static object Dummy(object a)
{
return a;
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void Finally(object a)
{
// This puts object a into the first nonvolatile register
object b = Dummy(a);
Alloc();
Dummy(b);
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void Test2(object a)
{
try
{
try
{
Test();
}
finally
{
Finally(a);
}
}
catch (Exception)
{
}
}


[MethodImpl(MethodImplOptions.NoInlining)]
private static object Foo(int x)
{
return x.ToString();
}

static int sum = 0;
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Verify(object a)
{
sum += ((string)a).Length;
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void Test3()
{
// This puts object a into the first nonvolatile register
object a = Foo(5);
Test2(a);
Verify(a);
}

[Fact]
public static void TestEntryPoint()
{
for (int i = 0; i < 100; i++)
{
Test3();
}
}
}