Skip to content

Commit

Permalink
Improved Method Inlining (#639)
Browse files Browse the repository at this point in the history
 - Improved Method Inlining
    * Skips emitting methods for methods that were inlined
    * Uses the final inline variation code
  • Loading branch information
tgiphil authored Jun 22, 2019
1 parent 12ca2ec commit 474997e
Show file tree
Hide file tree
Showing 72 changed files with 1,274 additions and 551 deletions.
8 changes: 8 additions & 0 deletions Source/Inno-Setup-Script/Mosa-Installer.iss
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ Source: "..\..\bin\MOSA Project\packages.config"; DestDir: "{userdocs}\Visual St
Source: "..\..\bin\MOSA Project\Program.cs"; DestDir: "{userdocs}\Visual Studio 2017\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\__TemplateIcon.ico"; DestDir: "{userdocs}\Visual Studio 2017\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\Mosa.Tool.Bootstrap.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\app.config"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\Boot.cs"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\Mosa.Starter.x86.csproj"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\MyTemplate.vstemplate"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\packages.config"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\Program.cs"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion
Source: "..\..\bin\MOSA Project\__TemplateIcon.ico"; DestDir: "{userdocs}\Visual Studio 2019\Templates\ProjectTemplates\Mosa Project"; Flags: ignoreversion


[ThirdParty]
UseRelativePaths=True
2 changes: 1 addition & 1 deletion Source/Mosa.ClassLib/Mosa.ClassLib.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
<tags>MOSA Compiler</tags>
</metadata>
<files>
<file src="..\..\bin\Mosa.ClassLib.dll" target="lib\net45" />
<file src="..\..\bin\Mosa.ClassLib.dll" target="lib\net472" />
</files>
</package>
2 changes: 1 addition & 1 deletion Source/Mosa.Compiler.Extension.Dwarf/DwarfCompilerStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ private void EmitDebugLineTypes(EndianAwareBinaryWriter wr)
if (symbol.VirtualAddress == 0)
continue;

var methodData = Compiler.CompilerData.GetMethodData(method);
var methodData = Compiler.GetMethodData(method);
if (methodData == null)
continue;

Expand Down
6 changes: 1 addition & 5 deletions Source/Mosa.Compiler.Framework/BaseCodeEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public override string ToString()
/// <param name="methodName">Name of the method.</param>
/// <param name="linker">The linker.</param>
/// <param name="codeStream">The stream the machine code is written to.</param>
public void Initialize(string methodName, Linker.MosaLinker linker, Stream codeStream)
public void Initialize(string methodName, MosaLinker linker, Stream codeStream)
{
Debug.Assert(codeStream != null);
Debug.Assert(linker != null);
Expand All @@ -114,10 +114,6 @@ public void Initialize(string methodName, Linker.MosaLinker linker, Stream codeS
Linker = linker;
CodeStream = codeStream;

// only necessary if method is being recompiled (due to inline optimization, for example)
var symbol = linker.GetSymbol(MethodName);
symbol.RemovePatches();

Labels = new Dictionary<int, int>();

OpcodeEncoder = new OpcodeEncoder(this);
Expand Down
9 changes: 3 additions & 6 deletions Source/Mosa.Compiler.Framework/BaseMethodCompilerStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,20 +165,17 @@ public abstract class BaseMethodCompilerStage : ITraceFactory
/// <summary>
/// Gets the stack frame.
/// </summary>
protected Operand StackFrame { get { return MethodCompiler.StackFrame; } }
protected Operand StackFrame { get { return MethodCompiler.Compiler.StackFrame; } }

/// <summary>
/// Gets the stack pointer.
/// </summary>
protected Operand StackPointer { get { return MethodCompiler.StackPointer; } }
protected Operand StackPointer { get { return MethodCompiler.Compiler.StackPointer; } }

/// <summary>
/// Gets a value indicating whether this instance has protected regions.
/// </summary>
/// <value>
/// <c>true</c> if this instance has protected regions; otherwise, <c>false</c>.
/// </value>
protected bool HasProtectedRegions { get { return Method.ExceptionHandlers.Count != 0; } }
protected bool HasProtectedRegions { get { return MethodCompiler.HasProtectedRegions; } }

/// <summary>
/// Gets a value indicating whether this instance has code.
Expand Down
28 changes: 25 additions & 3 deletions Source/Mosa.Compiler.Framework/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,26 @@ public sealed class Compiler
/// </summary>
public bool IsStopped { get; private set; }

/// <summary>
/// The stack frame
/// </summary>
internal Operand StackFrame { get; }

/// <summary>
/// The stack frame
/// </summary>
internal Operand StackPointer { get; }

#endregion Properties

#region Static Methods

private static List<BaseCompilerStage> GetDefaultCompilerPipeline(CompilerOptions compilerOptions)
{
return new List<BaseCompilerStage> {
new UnitTestStage(),
new TypeInitializerStage(),
new DevirtualizationStage(),
new StaticFieldStage(),
new MethodTableStage(),
new ExceptionTableStage(),
Expand All @@ -141,8 +153,10 @@ private static List<BaseMethodCompilerStage> GetDefaultMethodPipeline(CompilerOp
new ExceptionStage(),
new CILStaticAllocationResolutionStage(),
new CILTransformationStage(),
new DevirtualizeCallStage(),
new PlugStage(),
new UnboxValueTypeStage(),
new LowerIRStage(),
(compilerOptions.EnableInlinedMethods) ? new InlineStage() : null,
(compilerOptions.EnableInlinedMethods) ? new BlockMergeStage() : null,
(compilerOptions.EnableInlinedMethods) ? new DeadBlockStage() : null,
Expand All @@ -152,12 +166,12 @@ private static List<BaseMethodCompilerStage> GetDefaultMethodPipeline(CompilerOp
(compilerOptions.EnableSSA) ? new EnterSSAStage() : null,

//(compilerOptions.EnableBitTracker) ? new BitTrackerStage() : null,

(compilerOptions.EnableValueNumbering && compilerOptions.EnableSSA) ? new ValueNumberingStage() : null,
(compilerOptions.EnableLoopInvariantCodeMotion && compilerOptions.EnableSSA) ? new LoopInvariantCodeMotionStage() : null,
(compilerOptions.EnableSparseConditionalConstantPropagation && compilerOptions.EnableSSA) ? new SparseConditionalConstantPropagationStage() : null,
(compilerOptions.EnableIROptimizations) ? new IROptimizationStage() : null,
(compilerOptions.EnableIRLongExpansion && compilerOptions.Architecture.NativePointerSize == 4) ? new IRLongDecompositionStage() : null,
new LowerIRStage(),
(compilerOptions.EnableBitTracker) ? new BitTrackerStage() : null,
(compilerOptions.TwoPassOptimizations && compilerOptions.EnableValueNumbering && compilerOptions.EnableSSA) ? new ValueNumberingStage() : null,
(compilerOptions.TwoPassOptimizations && compilerOptions.EnableLoopInvariantCodeMotion && compilerOptions.EnableSSA) ? new LoopInvariantCodeMotionStage() : null,
Expand All @@ -167,10 +181,11 @@ private static List<BaseMethodCompilerStage> GetDefaultMethodPipeline(CompilerOp
new DeadBlockStage(),
new BlockMergeStage(),
new IRCleanupStage(),
new NewObjectIRStage(),
(compilerOptions.EnableInlinedMethods) ? new InlineEvaluationStage() : null,

//new StopStage(),
new DevirtualizeCallStage(),

new CallStage(),
new PlatformIntrinsicStage(),
new PlatformEdgeSplitStage(),
Expand All @@ -183,7 +198,6 @@ private static List<BaseMethodCompilerStage> GetDefaultMethodPipeline(CompilerOp
//new PreciseGCStage(),

new CodeGenerationStage(compilerOptions.EmitBinary),

(compilerOptions.EmitBinary) ? new ProtectedRegionLayoutStage() : null,
};
}
Expand All @@ -201,6 +215,9 @@ public Compiler(MosaCompiler mosaCompiler)
CompilerTrace = mosaCompiler.CompilerTrace;
Architecture = CompilerOptions.Architecture;

StackFrame = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackFrameRegister);
StackPointer = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackPointerRegister);

PostCompilerTraceEvent(CompilerEvent.CompilerStart);

CompilerExtensions.AddRange(mosaCompiler.CompilerExtensions);
Expand Down Expand Up @@ -575,6 +592,11 @@ private MosaType GeInternalRuntimeType()
return TypeSystem.GetTypeByName("Mosa.Runtime", "Internal");
}

public MethodData GetMethodData(MosaMethod method)
{
return CompilerData.GetMethodData(method);
}

#endregion Helper Methods

#region Type Methods
Expand Down
22 changes: 11 additions & 11 deletions Source/Mosa.Compiler.Framework/CompilerData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,23 @@ public MethodData GetMethodData(MosaMethod method)
{
lock (methods)
{
if (!methods.TryGetValue(method, out MethodData compilerMethod))
if (!methods.TryGetValue(method, out MethodData methodData))
{
compilerMethod = new MethodData(method);
methods.Add(method, compilerMethod);
methodData = new MethodData(method)
{
HasProtectedRegions = method.ExceptionHandlers.Count != 0,
IsLinkerGenerated = method.IsCompilerGenerated,
HasDoNotInlineAttribute = method.IsNoInlining,
HasAggressiveInliningAttribute = method.IsAggressiveInlining
};

methods.Add(method, methodData);
}

return compilerMethod;
return methodData;
}
}

public bool IsMethodInlined(MosaMethod method)
{
var methodData = GetMethodData(method);

return methodData.Inlined;
}

#endregion Methods
}
}
6 changes: 6 additions & 0 deletions Source/Mosa.Compiler.Framework/CompilerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public class CompilerOptions
/// </summary>
public bool EnableMethodScanner { get; set; }

/// <summary>
/// Gets or sets a value indicating whether [emit inline methods].
/// </summary>
public bool EmitInlinedMethods { get; set; }

/// <summary>
/// Adds additional sections to the Elf-File.
/// </summary>
Expand Down Expand Up @@ -334,6 +339,7 @@ public CompilerOptions()
EnablePlatformOptimizations = true;
EnableMethodScanner = false;
EnableBitTracker = true;
EmitInlinedMethods = false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private void EmitMethods()
continue;

var symbol = Linker.GetSymbol(method.FullName);
var methodData = Compiler.CompilerData.GetMethodData(method);
var methodData = Compiler.GetMethodData(method);

writer.WriteLine(
"{0}\t{1:x8}\t{2}\t{3:x8}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using Mosa.Compiler.Framework.IR;
using Mosa.Compiler.Framework.Trace;
using Mosa.Compiler.MosaTypeSystem;

namespace Mosa.Compiler.Framework.CompilerStages
{
/// <summary>
/// Devirtualization Stage
/// </remarks>
/// <seealso cref="Mosa.Compiler.Framework.BaseCompilerStage" />
public sealed class DevirtualizationStage : BaseCompilerStage
{
private Counter DevirtualizedMethodsCount = new Counter("DevirtualizationStage.DevirtualizedMethodsCount");

#region Overrides

protected override void Setup()
{
foreach (var type in TypeSystem.AllTypes)
{
// If type has an interface - don't consider either type for devirtualization
// FUTURE: be more specific and check each method
if (HasInterface(type))
continue;

foreach (var method in type.Methods)
{
if (method.IsStatic || !method.IsVirtual)
continue;

if (!method.HasImplementation && method.IsAbstract)
continue;

if (TypeLayout.IsMethodOverridden(method))
continue;

var methodData = Compiler.GetMethodData(method);

methodData.IsDevirtualized = true;
DevirtualizedMethodsCount++;
}
}
}

protected override void Finalization()
{
if (CompilerOptions.EnableStatistics)
{
//var log = new TraceLog(TraceType.MethodCounters, null, string.Empty);
//log.Log(MethodData.Counters.Export());
//CompilerTrace.PostTraceLog(log);
}
}

#endregion Overrides

private bool HasInterface(MosaType type)
{
var baseType = type;

while (baseType != null)
{
foreach (var interfaceType in baseType.Interfaces)
{
return true;
}

baseType = baseType.BaseType;
}

return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ protected override void Finalization()
protected void CreateMethodExceptionLookupTable()
{
// Emit assembly list
var methodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
var writer = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness);
var exceptionMethodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
var writer = new EndianAwareBinaryWriter(exceptionMethodLookupTable.Stream, Architecture.Endianness);

// 1. Number of methods
int count = 0;
Expand All @@ -55,25 +55,24 @@ protected void CreateMethodExceptionLookupTable()

foreach (var method in methodList)
{
if ((!method.HasImplementation && method.IsAbstract) || method.HasOpenGenericParams || method.DeclaringType.HasOpenGenericParams)
continue;
var targetMethodData = GetTargetMethodData(method);

if (method.ExceptionHandlers.Count == 0)
if (!targetMethodData.HasCode)
continue;

if (!Compiler.MethodScanner.IsMethodInvoked(method))
if (!targetMethodData.HasProtectedRegions)
continue;

// 1. Pointer to Method
Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0);
Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0);
writer.WriteZeroBytes(TypeLayout.NativePointerSize);

// 2. Size of Method
Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0);
Linker.Link(LinkType.Size, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0);
writer.WriteZeroBytes(TypeLayout.NativePointerSize);

// 3. Pointer to Method Definition
Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0);
Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0);
writer.WriteZeroBytes(TypeLayout.NativePointerSize);

count++;
Expand All @@ -87,5 +86,15 @@ protected void CreateMethodExceptionLookupTable()
// emit null entry (FUTURE)
//writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3);
}

private MethodData GetTargetMethodData(MosaMethod method)
{
var methodData = Compiler.GetMethodData(method);

if (methodData.ReplacedBy == null)
return methodData;

return Compiler.GetMethodData(methodData.ReplacedBy);
}
}
}
Loading

0 comments on commit 474997e

Please sign in to comment.