From de42b92b75364a93f5710a25f6813978b2bf7dad Mon Sep 17 00:00:00 2001 From: spouliot Date: Mon, 5 Jan 2009 13:39:32 +0000 Subject: [PATCH] 2009-01-05 Sebastien Pouliot * CodeReader.cs: Do not call VisitVariableDefinitionCollection unless LocalVarToken is different from zero. * CodeWriter.cs: Use HasVariables and HasExceptionHandlers. Write zero, not TokenType.Signature, for LocalVarToken if no variable is defined. That should fix the problem with unsign * Mono.Cecil.Cil/MethodBody.cs: Add HasExceptionHandlers, HasVariables and HasScopes to avoid creating empty collections inside Cecil. There is no HasInstruction because there's always something if MethodDefinition.HasBody is true (i.e. a MethodBody exists). [re-apply r1222198] git-svn-id: svn+ssh://mono-cvs.ximian.com/source/trunk/mcs@122458 e3ebcda4-bce8-0310-ba0a-eca2169e7518 --- class/Mono.Cecil/ChangeLog | 13 +++++++ class/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs | 3 +- class/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs | 13 ++++--- class/Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs | 56 ++++++++++++++++++++------- 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/class/Mono.Cecil/ChangeLog b/class/Mono.Cecil/ChangeLog index ef41984d46..de80a8f648 100644 --- a/class/Mono.Cecil/ChangeLog +++ b/class/Mono.Cecil/ChangeLog @@ -1,3 +1,16 @@ +2009-01-05 Sebastien Pouliot + + * CodeReader.cs: Do not call VisitVariableDefinitionCollection + unless LocalVarToken is different from zero. + * CodeWriter.cs: Use HasVariables and HasExceptionHandlers. + Write zero, not TokenType.Signature, for LocalVarToken if no + variable is defined. That should fix the problem with unsign + * Mono.Cecil.Cil/MethodBody.cs: Add HasExceptionHandlers, + HasVariables and HasScopes to avoid creating empty collections + inside Cecil. There is no HasInstruction because there's always + something if MethodDefinition.HasBody is true (i.e. a MethodBody + exists). [re-apply r1222198] + 2008-12-29 Sebastien Pouliot * Mono.Cecil/MethodReturnType.cs: Override ToString so we can, by diff --git a/class/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs b/class/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs index 0c1d7c3fb7..9fe965f556 100644 --- a/class/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs +++ b/class/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs @@ -71,7 +71,8 @@ namespace Mono.Cecil.Cil { methBody.CodeSize = br.ReadInt32 (); methBody.LocalVarToken = br.ReadInt32 (); body.InitLocals = (fatflags & (int) MethodHeader.InitLocals) != 0; - VisitVariableDefinitionCollection (methBody.Variables); + if (methBody.LocalVarToken != 0) + VisitVariableDefinitionCollection (methBody.Variables); ReadCilBody (methBody, br); if ((fatflags & (int) MethodHeader.MoreSects) != 0) ReadSection (methBody, br); diff --git a/class/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs b/class/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs index dd42cd2c1c..f6abc5029f 100644 --- a/class/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs +++ b/class/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs @@ -368,22 +368,25 @@ namespace Mono.Cecil.Cil { { long pos = m_binaryWriter.BaseStream.Position; - if (body.Variables.Count > 0 || body.ExceptionHandlers.Count > 0 + if (body.HasVariables || body.HasExceptionHandlers || m_codeWriter.BaseStream.Length >= 64 || body.MaxStack > 8) { MethodHeader header = MethodHeader.FatFormat; if (body.InitLocals) header |= MethodHeader.InitLocals; - if (body.ExceptionHandlers.Count > 0) + if (body.HasExceptionHandlers) header |= MethodHeader.MoreSects; m_binaryWriter.Write ((byte) header); m_binaryWriter.Write ((byte) 0x30); // (header size / 4) << 4 m_binaryWriter.Write ((short) body.MaxStack); m_binaryWriter.Write ((int) m_codeWriter.BaseStream.Length); - m_binaryWriter.Write (((int) TokenType.Signature | body.LocalVarToken)); + // the token should be zero if there are no variables + int token = body.HasVariables ? ((int) TokenType.Signature | body.LocalVarToken) : 0; + m_binaryWriter.Write (token); - WriteExceptionHandlerCollection (body.ExceptionHandlers); + if (body.HasExceptionHandlers) + WriteExceptionHandlerCollection (body.ExceptionHandlers); } else m_binaryWriter.Write ((byte) ((byte) MethodHeader.TinyFormat | m_codeWriter.BaseStream.Length << 2)); @@ -556,7 +559,7 @@ namespace Mono.Cecil.Cil { break; IMethodSignature method = (IMethodSignature) instruction.Operand; - int count = method.Parameters.Count; + int count = method.HasParameters ? method.Parameters.Count : 0; if (method.HasThis && code != OpCodes.Newobj) ++count; diff --git a/class/Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs b/class/Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs index c76b4aba6a..71539070a6 100644 --- a/class/Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs +++ b/class/Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs @@ -82,25 +82,47 @@ namespace Mono.Cecil.Cil { get { return m_instructions; } } + public bool HasExceptionHandlers { + get { return m_exceptions != null && m_exceptions.Count > 0; } + } + public ExceptionHandlerCollection ExceptionHandlers { - get { return m_exceptions; } + get { + if (m_exceptions == null) + m_exceptions = new ExceptionHandlerCollection (this); + return m_exceptions; + } + } + + public bool HasVariables { + get { return m_variables != null && m_variables.Count > 0; } } public VariableDefinitionCollection Variables { - get { return m_variables; } + get { + if (m_variables == null) + m_variables = new VariableDefinitionCollection (this); + return m_variables; + } + } + + public bool HasScopes { + get { return m_scopes != null && m_scopes.Count > 0; } } public ScopeCollection Scopes { - get { return m_scopes; } + get { + if (m_scopes == null) + m_scopes = new ScopeCollection (this); + return m_scopes; + } } public MethodBody (MethodDefinition meth) { m_method = meth; + // there is always a RET instruction (if a body is present) m_instructions = new InstructionCollection (this); - m_exceptions = new ExceptionHandlerCollection (this); - m_variables = new VariableDefinitionCollection (this); - m_scopes = new ScopeCollection (this); } internal static Instruction GetInstruction (MethodBody oldBody, MethodBody newBody, Instruction i) @@ -121,10 +143,12 @@ namespace Mono.Cecil.Cil { CilWorker worker = nb.CilWorker; - foreach (VariableDefinition var in body.Variables) - nb.Variables.Add (new VariableDefinition ( - var.Name, var.Index, parent, - context.Import (var.VariableType))); + if (body.HasVariables) { + foreach (VariableDefinition var in body.Variables) + nb.Variables.Add (new VariableDefinition ( + var.Name, var.Index, parent, + context.Import (var.VariableType))); + } foreach (Instruction instr in body.Instructions) { Instruction ni = new Instruction (instr.OpCode); @@ -189,6 +213,9 @@ namespace Mono.Cecil.Cil { instr.Operand = GetInstruction (body, nb, (Instruction) oldi.Operand); } + if (!body.HasExceptionHandlers) + return nb; + foreach (ExceptionHandler eh in body.ExceptionHandlers) { ExceptionHandler neh = new ExceptionHandler (eh.Type); neh.TryStart = GetInstruction (body, nb, eh.TryStart); @@ -582,10 +609,13 @@ namespace Mono.Cecil.Cil { public void Accept (ICodeVisitor visitor) { visitor.VisitMethodBody (this); - m_variables.Accept (visitor); + if (HasVariables) + m_variables.Accept (visitor); m_instructions.Accept (visitor); - m_exceptions.Accept (visitor); - m_scopes.Accept (visitor); + if (HasExceptionHandlers) + m_exceptions.Accept (visitor); + if (HasScopes) + m_scopes.Accept (visitor); visitor.TerminateMethodBody (this); } -- 2.11.4.GIT