From a80a6cff59891951f97f3eb1af23aa87a579a4ba Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 23 Dec 2022 13:12:04 +0500 Subject: [PATCH 1/4] Fix broken catch leaving in ctors --- .../ImplementInitializablePatternTask.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs b/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs index 9be4a2742c..9d4644d150 100644 --- a/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs +++ b/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs @@ -1,6 +1,6 @@ -// Copyright (C) 2013 Xtensive LLC. -// All rights reserved. -// For conditions of distribution and use, see license. +// Copyright (C) 2013-2022 Xtensive LLC. +// This code is distributed under MIT license terms. +// See the License.txt file in the project root for more information. // Created by: Denis Krjuchkov // Created: 2013.08.19 @@ -20,6 +20,8 @@ public override ActionResult Execute(ProcessorContext context) { var body = constructor.Body; var il = body.GetILProcessor(); + var originalLastRet = body.Instructions.Reverse().First(i => i != null && i.OpCode.Code == Code.Ret); + var leavePlaceholder = il.Create(OpCodes.Nop); var initializeCall = EmitInitializeCall(context, il); @@ -36,6 +38,11 @@ public override ActionResult Execute(ProcessorContext context) var ret = il.Create(OpCodes.Ret); il.Append(ret); il.Replace(leavePlaceholder, il.Create(OpCodes.Leave, ret)); + if (body.ExceptionHandlers.Count != 0) { + foreach (var eHandler in body.ExceptionHandlers) { + FixCatchLeave(eHandler.HandlerStart, eHandler.HandlerEnd, originalLastRet, initializeCall); + } + } body.InitLocals = true; var handler = new ExceptionHandler(ExceptionHandlerType.Catch) { @@ -61,6 +68,19 @@ private void ReplaceRetWithBr(ILProcessor il, Instruction start, Instruction end } } + private void FixCatchLeave(Instruction start, Instruction end, Instruction oldRetTarget, Instruction newTarget) + { + var current = start; + while (current != end) { + var next = current.Next; + var code = current.OpCode.Code; + if ((code == Code.Leave || code == Code.Leave_S) && current.Operand == oldRetTarget) { + current.Operand = newTarget; + } + current = next; + } + } + private Instruction GetStartInstruction(ILProcessor il) { var instructions = constructor.Body.Instructions; From b1049a46bd6d1d2d771acf0cc77c203a1a4ab30d Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Fri, 23 Dec 2022 18:49:01 +0500 Subject: [PATCH 2/4] Fix issues - not every ctor has ret at the end - not every catch block has leave-to-ret structure --- .../Tasks/ImplementInitializablePatternTask.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs b/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs index 9d4644d150..5f04315e19 100644 --- a/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs +++ b/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs @@ -20,8 +20,7 @@ public override ActionResult Execute(ProcessorContext context) { var body = constructor.Body; var il = body.GetILProcessor(); - var originalLastRet = body.Instructions.Reverse().First(i => i != null && i.OpCode.Code == Code.Ret); - + var originalLastRet = body.Instructions.Reverse().FirstOrDefault(i => i != null && i.OpCode.Code == Code.Ret); var leavePlaceholder = il.Create(OpCodes.Nop); var initializeCall = EmitInitializeCall(context, il); @@ -71,7 +70,7 @@ private void ReplaceRetWithBr(ILProcessor il, Instruction start, Instruction end private void FixCatchLeave(Instruction start, Instruction end, Instruction oldRetTarget, Instruction newTarget) { var current = start; - while (current != end) { + while (current != end && current != null) { var next = current.Next; var code = current.OpCode.Code; if ((code == Code.Leave || code == Code.Leave_S) && current.Operand == oldRetTarget) { From 089ea26a2be7b80997798aeef626789bc2171eb7 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 25 Dec 2022 15:51:23 +0500 Subject: [PATCH 3/4] Fixing hanlders only when there is last il ret call --- .../Tasks/ImplementInitializablePatternTask.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs b/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs index 5f04315e19..0c09c43994 100644 --- a/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs +++ b/Weaver/Xtensive.Orm.Weaver/Tasks/ImplementInitializablePatternTask.cs @@ -38,9 +38,10 @@ public override ActionResult Execute(ProcessorContext context) il.Append(ret); il.Replace(leavePlaceholder, il.Create(OpCodes.Leave, ret)); if (body.ExceptionHandlers.Count != 0) { - foreach (var eHandler in body.ExceptionHandlers) { - FixCatchLeave(eHandler.HandlerStart, eHandler.HandlerEnd, originalLastRet, initializeCall); - } + if (originalLastRet != null) + foreach (var eHandler in body.ExceptionHandlers) { + FixCatchLeave(eHandler.HandlerStart, eHandler.HandlerEnd, originalLastRet, initializeCall); + } } body.InitLocals = true; From 43274fa23e8faacdb93cd9997b52324f534393be Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 25 Dec 2022 16:24:26 +0500 Subject: [PATCH 4/4] Improve changelog --- ChangeLog/6.0.11_dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog/6.0.11_dev.txt b/ChangeLog/6.0.11_dev.txt index e69de29bb2..a6fd4174d6 100644 --- a/ChangeLog/6.0.11_dev.txt +++ b/ChangeLog/6.0.11_dev.txt @@ -0,0 +1 @@ +[weaver] Fixed ctor processing with try...catch where there was broken catch section leaving \ No newline at end of file