From 6b4e52febbd69cc6b25735c96d89910d41e09d93 Mon Sep 17 00:00:00 2001 From: ZaneYork Date: Wed, 3 Jun 2020 10:56:31 +0800 Subject: [PATCH] Parallel exception aggregate fix --- .../ModLoading/Framework/RecursiveRewriter.cs | 109 ++++++++++-------- 1 file changed, 62 insertions(+), 47 deletions(-) diff --git a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs index c774c038..c03376d6 100644 --- a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs +++ b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs @@ -57,60 +57,75 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework /// Returns whether the module was modified. public bool RewriteModule() { - bool anyRewritten = false; - - foreach (TypeDefinition type in this.Module.GetTypes()) - { - if (type.BaseType == null) - continue; // special type like - - anyRewritten |= this.RewriteCustomAttributes(type.CustomAttributes); - anyRewritten |= this.RewriteGenericParameters(type.GenericParameters); - - foreach (InterfaceImplementation @interface in type.Interfaces) - anyRewritten |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType); - - if (type.BaseType.FullName != "System.Object") - anyRewritten |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType); - - foreach (MethodDefinition method in type.Methods) + Tuple aggregateResult = this.Module.GetTypes() + .AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism) + .Select(type => { - anyRewritten |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType); - anyRewritten |= this.RewriteGenericParameters(method.GenericParameters); - anyRewritten |= this.RewriteCustomAttributes(method.CustomAttributes); - - foreach (ParameterDefinition parameter in method.Parameters) - anyRewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType); - - foreach (var methodOverride in method.Overrides) - anyRewritten |= this.RewriteMethodReference(methodOverride); - - if (method.HasBody) + try { - foreach (VariableDefinition variable in method.Body.Variables) - anyRewritten |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType); + bool anyRewritten = false; + if (type.BaseType == null) + return new Tuple(anyRewritten, null); // special type like - // check CIL instructions - ILProcessor cil = method.Body.GetILProcessor(); - Collection instructions = cil.Body.Instructions; - for (int i = 0; i < instructions.Count; i++) + anyRewritten |= this.RewriteCustomAttributes(type.CustomAttributes); + anyRewritten |= this.RewriteGenericParameters(type.GenericParameters); + + foreach (InterfaceImplementation @interface in type.Interfaces) + anyRewritten |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType); + + if (type.BaseType.FullName != "System.Object") + anyRewritten |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType); + + foreach (MethodDefinition method in type.Methods) { - var instruction = instructions[i]; - if (instruction.OpCode.Code == Code.Nop) - continue; + anyRewritten |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType); + anyRewritten |= this.RewriteGenericParameters(method.GenericParameters); + anyRewritten |= this.RewriteCustomAttributes(method.CustomAttributes); - anyRewritten |= this.RewriteInstruction(instruction, cil, newInstruction => + foreach (ParameterDefinition parameter in method.Parameters) + anyRewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType); + + foreach (var methodOverride in method.Overrides) + anyRewritten |= this.RewriteMethodReference(methodOverride); + + if (method.HasBody) { - anyRewritten = true; - cil.Replace(instruction, newInstruction); - instruction = newInstruction; - }); - } - } - } - } + foreach (VariableDefinition variable in method.Body.Variables) + anyRewritten |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType); - return anyRewritten; + // check CIL instructions + ILProcessor cil = method.Body.GetILProcessor(); + Collection instructions = cil.Body.Instructions; + for (int i = 0; i < instructions.Count; i++) + { + var instruction = instructions[i]; + if (instruction.OpCode.Code == Code.Nop) + continue; + + anyRewritten |= this.RewriteInstruction(instruction, cil, newInstruction => + { + anyRewritten = true; + cil.Replace(instruction, newInstruction); + instruction = newInstruction; + }); + } + } + } + + return new Tuple(anyRewritten, null); + } + catch (Exception e) + { + return new Tuple(false, e.InnerException ?? e); + } + }) + .TakeWhile(tuple => tuple.Item2 == null) // Stop on any exception occurs + .Aggregate((tupleA, tupleB) => new Tuple(tupleA.Item1 | tupleB.Item1, tupleA.Item2 ?? tupleB.Item2)); // Aggregate result and exception + if (aggregateResult.Item2 != null) + { + throw aggregateResult.Item2; // rethrow inner Exception + } + return aggregateResult.Item1; }