Browse Source

Optimized the generation of C# by not splitting any strings.

Our indention of lines in blocks was inadequate so we used to split strings by new lines, indent each line and put it back together. Creation of new strings is incredibly slow so this bogged our code generation down. I have now fixed indention properly and we no longer need to split already written blocks to indent them.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1129/head
Dimitar Dobrev 7 years ago committed by João Matos
parent
commit
d243780e67
  1. 2
      src/Generator/Generators/CLI/CLIMarshal.cs
  2. 22
      src/Generator/Generators/CLI/CLISources.cs
  3. 9
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  4. 73
      src/Generator/Generators/CSharp/CSharpSources.cs
  5. 15
      src/Generator/Generators/Marshal.cs
  6. 4
      src/Generator/Types/Std/Stdlib.cs
  7. 14
      src/Generator/Utils/BlockGenerator.cs
  8. 19
      src/Generator/Utils/TextGenerator.cs
  9. 21
      src/Generator/Utils/Utils.cs

2
src/Generator/Generators/CLI/CLIMarshal.cs

@ -775,7 +775,7 @@ namespace CppSharp.Generators.CLI @@ -775,7 +775,7 @@ namespace CppSharp.Generators.CLI
var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name,
property.Name);
var marshalCtx = new MarshalContext(Context.Context)
var marshalCtx = new MarshalContext(Context.Context, Context.Indent)
{
ArgName = fieldRef,
ParameterIndex = Context.ParameterIndex++,

22
src/Generator/Generators/CLI/CLISources.cs

@ -396,7 +396,7 @@ namespace CppSharp.Generators.CLI @@ -396,7 +396,7 @@ namespace CppSharp.Generators.CLI
else
variable = $"((::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}";
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
Parameter = param,
ArgName = param.Name,
@ -408,7 +408,7 @@ namespace CppSharp.Generators.CLI @@ -408,7 +408,7 @@ namespace CppSharp.Generators.CLI
if (isIndexer)
{
var ctx2 = new MarshalContext(Context)
var ctx2 = new MarshalContext(Context, CurrentIndent)
{
Parameter = indexParameter,
ArgName = indexParameter.Name
@ -483,7 +483,7 @@ namespace CppSharp.Generators.CLI @@ -483,7 +483,7 @@ namespace CppSharp.Generators.CLI
variable = string.Format("((::{0}*)NativePtr)->{1}",
@class.QualifiedOriginalName, decl.OriginalName);
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
Declaration = decl,
ArgName = decl.Name,
@ -592,7 +592,7 @@ namespace CppSharp.Generators.CLI @@ -592,7 +592,7 @@ namespace CppSharp.Generators.CLI
var returns = new List<string>();
foreach (var param in @event.Parameters)
{
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
ReturnVarName = param.Name,
ReturnType = param.QualifiedType
@ -686,7 +686,7 @@ namespace CppSharp.Generators.CLI @@ -686,7 +686,7 @@ namespace CppSharp.Generators.CLI
var nativeField = string.Format("{0}{1}",
nativeVar, property.Field.OriginalName);
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
ArgName = property.Name,
ReturnVarName = nativeField,
@ -834,7 +834,7 @@ namespace CppSharp.Generators.CLI @@ -834,7 +834,7 @@ namespace CppSharp.Generators.CLI
var paramIndex = 0;
foreach (var param in method.Parameters)
{
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
Function = method,
Parameter = param,
@ -870,7 +870,7 @@ namespace CppSharp.Generators.CLI @@ -870,7 +870,7 @@ namespace CppSharp.Generators.CLI
var varName = string.Format("_native.{0}", property.Field.OriginalName);
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
ReturnVarName = varName,
ReturnType = property.QualifiedType
@ -946,7 +946,7 @@ namespace CppSharp.Generators.CLI @@ -946,7 +946,7 @@ namespace CppSharp.Generators.CLI
WriteLine("auto {0} = ::{1}();", valueMarshalName, @class.QualifiedOriginalName);
var param = new Parameter { Name = "(*this)" , Namespace = function.Namespace };
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
MarshalVarPrefix = valueMarshalName,
Parameter = param
@ -1021,7 +1021,7 @@ namespace CppSharp.Generators.CLI @@ -1021,7 +1021,7 @@ namespace CppSharp.Generators.CLI
var nativeVarName = paramInfo.Name;
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
ArgName = nativeVarName,
ReturnVarName = nativeVarName,
@ -1054,7 +1054,7 @@ namespace CppSharp.Generators.CLI @@ -1054,7 +1054,7 @@ namespace CppSharp.Generators.CLI
isIntPtr ? "System::IntPtr()" : "nullptr");
}
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
ArgName = returnIdentifier,
ReturnVarName = returnIdentifier,
@ -1167,7 +1167,7 @@ namespace CppSharp.Generators.CLI @@ -1167,7 +1167,7 @@ namespace CppSharp.Generators.CLI
QualifiedType = new QualifiedType(paramType)
};
var ctx = new MarshalContext(Context)
var ctx = new MarshalContext(Context, CurrentIndent)
{
Parameter = effectiveParam,
ParameterIndex = paramIndex,

9
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CppSharp.AST;
@ -10,11 +11,13 @@ namespace CppSharp.Generators.CSharp @@ -10,11 +11,13 @@ namespace CppSharp.Generators.CSharp
{
public class CSharpMarshalContext : MarshalContext
{
public CSharpMarshalContext(BindingContext context)
: base(context)
public CSharpMarshalContext(BindingContext context, Stack<uint> indent)
: base(context, indent)
{
ArgumentPrefix = new TextGenerator();
indent.PushTo(ArgumentPrefix.CurrentIndent);
Cleanup = new TextGenerator();
indent.PushTo(Cleanup.CurrentIndent);
}
public TextGenerator ArgumentPrefix { get; private set; }
@ -335,7 +338,7 @@ namespace CppSharp.Generators.CSharp @@ -335,7 +338,7 @@ namespace CppSharp.Generators.CSharp
if (parameter.Usage == ParameterUsage.Unknown || parameter.IsIn)
return base.VisitParameterDecl(parameter);
var ctx = new CSharpMarshalContext(Context.Context)
var ctx = new CSharpMarshalContext(Context.Context, Context.Indent)
{
ReturnType = Context.ReturnType,
ReturnVarName = Context.ReturnVarName

73
src/Generator/Generators/CSharp/CSharpSources.cs

@ -820,7 +820,7 @@ namespace CppSharp.Generators.CSharp @@ -820,7 +820,7 @@ namespace CppSharp.Generators.CSharp
QualifiedType = var.QualifiedType
};
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
Parameter = param,
ArgName = param.Name,
@ -880,38 +880,40 @@ namespace CppSharp.Generators.CSharp @@ -880,38 +880,40 @@ namespace CppSharp.Generators.CSharp
private void GenerateFieldSetter(Field field, Class @class, QualifiedType fieldType)
{
string returnVar;
Type type = field.Type.Desugar();
var arrayType = type as ArrayType;
if (arrayType != null && @class.IsValueType)
{
returnVar = HandleValueArray(arrayType, field);
}
else
{
var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name;
var identifier = SafeIdentifier(name);
if (@class.IsValueType)
returnVar = $"{Helpers.InstanceField}.{identifier}";
else
returnVar = $"(({TypePrinter.PrintNative(@class)}*){Helpers.InstanceIdentifier})->{identifier}";
}
var param = new Parameter
{
Name = "value",
QualifiedType = field.QualifiedType
};
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
Parameter = param,
ArgName = param.Name,
ReturnVarName = returnVar
};
ctx.PushMarshalKind(MarshalKind.NativeField);
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
ctx.Declaration = field;
Type type = field.Type.Desugar();
var arrayType = type as ArrayType;
if (arrayType != null && @class.IsValueType)
{
ctx.ReturnVarName = HandleValueArray(arrayType, field);
}
else
{
var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name;
var identifier = SafeIdentifier(name);
if (@class.IsValueType)
ctx.ReturnVarName = $"{Helpers.InstanceField}.{identifier}";
else
ctx.ReturnVarName = $"(({TypePrinter.PrintNative(@class)}*){Helpers.InstanceIdentifier})->{identifier}";
}
param.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
@ -987,7 +989,7 @@ namespace CppSharp.Generators.CSharp @@ -987,7 +989,7 @@ namespace CppSharp.Generators.CSharp
function.OriginalReturnType.Type.IsPointerTo(out type);
var @internal = TypePrinter.PrintNative(function.Namespace);
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
Parameter = new Parameter
{
@ -1108,7 +1110,7 @@ namespace CppSharp.Generators.CSharp @@ -1108,7 +1110,7 @@ namespace CppSharp.Generators.CSharp
TypePrinter.PopContext();
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
ArgName = var.Name,
ReturnType = new QualifiedType(var.Type)
@ -1171,12 +1173,18 @@ namespace CppSharp.Generators.CSharp @@ -1171,12 +1173,18 @@ namespace CppSharp.Generators.CSharp
private void GenerateFieldGetter(Field field, Class @class, QualifiedType returnType)
{
var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name;
String returnVar;
string returnVar;
var arrayType = field.Type.Desugar() as ArrayType;
if (@class.IsValueType)
returnVar = $@"{Helpers.InstanceField}.{SafeIdentifier(name)}";
{
if (arrayType != null)
returnVar = HandleValueArray(arrayType, field);
else
returnVar = $"{Helpers.InstanceField}.{SafeIdentifier(name)}";
}
else
{
returnVar = $@"(({TypePrinter.PrintNative(@class)}*) {Helpers.InstanceIdentifier})->{SafeIdentifier(name)}";
returnVar = $"(({TypePrinter.PrintNative(@class)}*) {Helpers.InstanceIdentifier})->{SafeIdentifier(name)}";
// Class field getter should return a reference object instead of a copy. Wrapping `returnVar` in
// IntPtr ensures that non-copying object constructor is invoked.
Class typeClass;
@ -1185,7 +1193,7 @@ namespace CppSharp.Generators.CSharp @@ -1185,7 +1193,7 @@ namespace CppSharp.Generators.CSharp
returnVar = $"new {CSharpTypePrinter.IntPtrType}(&{returnVar})";
}
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
ArgName = field.Name,
Declaration = field,
@ -1194,11 +1202,6 @@ namespace CppSharp.Generators.CSharp @@ -1194,11 +1202,6 @@ namespace CppSharp.Generators.CSharp
};
ctx.PushMarshalKind(MarshalKind.NativeField);
var arrayType = field.Type.Desugar() as ArrayType;
if (arrayType != null && @class.IsValueType)
ctx.ReturnVarName = HandleValueArray(arrayType, field);
var marshal = new CSharpMarshalNativeToManagedPrinter(ctx);
field.QualifiedType.Visit(marshal);
@ -1666,7 +1669,7 @@ namespace CppSharp.Generators.CSharp @@ -1666,7 +1669,7 @@ namespace CppSharp.Generators.CSharp
if (param.Kind == ParameterKind.IndirectReturnType)
continue;
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
ReturnType = param.QualifiedType,
ReturnVarName = param.Name,
@ -1723,7 +1726,7 @@ namespace CppSharp.Generators.CSharp @@ -1723,7 +1726,7 @@ namespace CppSharp.Generators.CSharp
};
// Marshal the managed result to native
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
ArgName = Helpers.ReturnIdentifier,
Parameter = param,
@ -1901,7 +1904,7 @@ namespace CppSharp.Generators.CSharp @@ -1901,7 +1904,7 @@ namespace CppSharp.Generators.CSharp
var returns = new List<string>();
foreach (var param in @event.Parameters)
{
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
ReturnVarName = param.Name,
ReturnType = param.QualifiedType
@ -2853,7 +2856,7 @@ namespace CppSharp.Generators.CSharp @@ -2853,7 +2856,7 @@ namespace CppSharp.Generators.CSharp
if (needsReturn)
{
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
ArgName = Helpers.ReturnIdentifier,
ReturnVarName = Helpers.ReturnIdentifier,
@ -2944,7 +2947,7 @@ namespace CppSharp.Generators.CSharp @@ -2944,7 +2947,7 @@ namespace CppSharp.Generators.CSharp
var nativeVarName = paramInfo.Name;
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
Parameter = param,
ArgName = nativeVarName,
@ -3012,7 +3015,7 @@ namespace CppSharp.Generators.CSharp @@ -3012,7 +3015,7 @@ namespace CppSharp.Generators.CSharp
}
}
var ctx = new CSharpMarshalContext(Context)
var ctx = new CSharpMarshalContext(Context, CurrentIndent)
{
Parameter = param,
ParameterIndex = paramIndex,

15
src/Generator/Generators/Marshal.cs

@ -1,23 +1,27 @@ @@ -1,23 +1,27 @@
using CppSharp.AST;
using System.Collections.Generic;
namespace CppSharp.Generators
{
public class MarshalContext : TypePrinter
{
public MarshalContext(BindingContext context)
public MarshalContext(BindingContext context, Stack<uint> indent)
{
Context = context;
Before = new TextGenerator();
indent.PushTo(Before.CurrentIndent);
Return = new TextGenerator();
indent.PushTo(Return.CurrentIndent);
MarshalVarPrefix = string.Empty;
this.Indent = indent;
}
public BindingContext Context { get; private set; }
public BindingContext Context { get; }
public MarshalPrinter<MarshalContext> MarshalToNative;
public TextGenerator Before { get; private set; }
public TextGenerator Return { get; private set; }
public TextGenerator Before { get; }
public TextGenerator Return { get; }
public string ReturnVarName { get; set; }
public QualifiedType ReturnType { get; set; }
@ -27,11 +31,12 @@ namespace CppSharp.Generators @@ -27,11 +31,12 @@ namespace CppSharp.Generators
public Function Function { get; set; }
public string MarshalVarPrefix { get; set; }
public Stack<uint> Indent { get; }
}
public abstract class MarshalPrinter<T> : AstVisitor where T : MarshalContext
{
public T Context { get; private set; }
public T Context { get; }
protected MarshalPrinter(T ctx)
{

4
src/Generator/Types/Std/Stdlib.cs

@ -235,7 +235,7 @@ namespace CppSharp.Types.Std @@ -235,7 +235,7 @@ namespace CppSharp.Types.Std
QualifiedType = type
};
var elementCtx = new MarshalContext(ctx.Context)
var elementCtx = new MarshalContext(ctx.Context, ctx.Indent)
{
Parameter = param,
ArgName = param.Name,
@ -280,7 +280,7 @@ namespace CppSharp.Types.Std @@ -280,7 +280,7 @@ namespace CppSharp.Types.Std
ctx.ReturnVarName);
ctx.Before.WriteStartBraceIndent();
{
var elementCtx = new MarshalContext(ctx.Context)
var elementCtx = new MarshalContext(ctx.Context, ctx.Indent)
{
ReturnVarName = "_element",
ReturnType = type

14
src/Generator/Utils/BlockGenerator.cs

@ -176,8 +176,6 @@ namespace CppSharp @@ -176,8 +176,6 @@ namespace CppSharp
#region ITextGenerator implementation
public uint Indent { get { return Text.Indent; } }
public void Write(string msg, params object[] args)
{
Text.Write(msg, args);
@ -240,8 +238,9 @@ namespace CppSharp @@ -240,8 +238,9 @@ namespace CppSharp
public abstract class BlockGenerator : ITextGenerator
{
public Block RootBlock { get; private set; }
public Block RootBlock { get; }
public Block ActiveBlock { get; private set; }
public Stack<uint> CurrentIndent => ActiveBlock.Text.CurrentIndent;
protected BlockGenerator()
{
@ -264,12 +263,7 @@ namespace CppSharp @@ -264,12 +263,7 @@ namespace CppSharp
public void PushBlock(BlockKind kind = BlockKind.Unknown, object obj = null)
{
var block = new Block { Kind = kind, Object = obj };
var array = new uint[ActiveBlock.Text.CurrentIndent.Count];
ActiveBlock.Text.CurrentIndent.CopyTo(array, 0);
foreach (var indent in array.Reverse())
{
block.Text.CurrentIndent.Push(indent);
}
CurrentIndent.PushTo(block.Text.CurrentIndent);
block.Text.IsStartOfLine = ActiveBlock.Text.IsStartOfLine;
block.Text.NeedsNewLine = ActiveBlock.Text.NeedsNewLine;
PushBlock(block);
@ -306,8 +300,6 @@ namespace CppSharp @@ -306,8 +300,6 @@ namespace CppSharp
#region ITextGenerator implementation
public uint Indent { get { return ActiveBlock.Indent; } }
public void Write(string msg, params object[] args)
{
ActiveBlock.Write(msg, args);

19
src/Generator/Utils/TextGenerator.cs

@ -7,7 +7,6 @@ namespace CppSharp @@ -7,7 +7,6 @@ namespace CppSharp
{
public interface ITextGenerator
{
uint Indent { get; }
void Write(string msg, params object[] args);
void WriteLine(string msg, params object[] args);
void WriteLineIndent(string msg, params object[] args);
@ -30,11 +29,6 @@ namespace CppSharp @@ -30,11 +29,6 @@ namespace CppSharp
public bool NeedsNewLine { get; set; }
public Stack<uint> CurrentIndent { get; } = new Stack<uint>();
public uint Indent
{
get { return (uint)CurrentIndent.Sum(u => (int)u); }
}
public TextGenerator()
{
}
@ -60,16 +54,13 @@ namespace CppSharp @@ -60,16 +54,13 @@ namespace CppSharp
if (args.Length > 0)
msg = string.Format(msg, args);
foreach(var line in msg.SplitAndKeep(Environment.NewLine))
{
if (IsStartOfLine && !string.IsNullOrWhiteSpace(line))
StringBuilder.Append(new string(' ', (int) CurrentIndent.Sum(u => u)));
if (IsStartOfLine && !string.IsNullOrWhiteSpace(msg))
StringBuilder.Append(new string(' ', (int) CurrentIndent.Sum(u => u)));
if (line.Length > 0)
IsStartOfLine = line.EndsWith(Environment.NewLine);
if (msg.Length > 0)
IsStartOfLine = msg.EndsWith(Environment.NewLine);
StringBuilder.Append(line);
}
StringBuilder.Append(msg);
}
public void WriteLine(string msg, params object[] args)

21
src/Generator/Utils/Utils.cs

@ -49,13 +49,6 @@ namespace CppSharp @@ -49,13 +49,6 @@ namespace CppSharp
return str.Trim().Split();
}
public static IEnumerable<string> SplitAndKeep(this string s, string seperator)
{
string[] obj = s.Split(new[] { seperator }, StringSplitOptions.None);
return obj.Select((t, i) => i == obj.Length - 1 ? t : t + seperator);
}
public static string Capitalize(string s)
{
// Check for empty string.
@ -134,6 +127,18 @@ namespace CppSharp @@ -134,6 +127,18 @@ namespace CppSharp
return uri1.MakeRelativeUri(uri2).ToString();
}
}
public static class CollectionExtensions
{
public static void PushTo<T>(this Stack<T> source, Stack<T> destination)
{
var array = new T[source.Count];
source.CopyTo(array, 0);
foreach (var indent in array.Reverse())
{
destination.Push(indent);
}
}
}
}

Loading…
Cancel
Save