Skip to content

Commit

Permalink
Improved memory method so JIT compiler does not optimize it away
Browse files Browse the repository at this point in the history
  • Loading branch information
pardeike committed Jan 16, 2017
1 parent b9cab30 commit b875090
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 21 deletions.
12 changes: 1 addition & 11 deletions Harmony/Harmony.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
Expand Down Expand Up @@ -62,16 +62,6 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Traverse.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<Private>False</Private>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if exist "$(TargetDir)$(TargetName).pdb" "C:\Program Files (x86)\Mono\bin\mono.exe" "C:\Program Files (x86)\Mono\lib\mono\4.5\pdb2mdb.exe" "$(TargetPath)"</PostBuildEvent>
Expand Down
27 changes: 17 additions & 10 deletions Harmony/Platform.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;

namespace Harmony
{
Expand Down Expand Up @@ -99,6 +100,18 @@ public static unsafe long WriteLong(long memory, long value)
return memory + sizeof(long);
}

// purpose of this method is to "do some work" so the JIT compiler
// does not optimize our code away. since it is never called with 0
// it actually does nothing
public static void LongConsumer(long val)
{
if (val == 0) Console.WriteLine(val);
}

// the way we create rwx memory is by building a new method and making
// sure the JIT compiler does not optimize our code away. We force this
// by calling a second method. the loop runs an estimated times to make
// sure we have enough assembler code to cover our memory size
static int counter;
public static long GetMemory(int size)
{
Expand All @@ -110,21 +123,15 @@ public static long GetMemory(int size)
var methodName = "HarmonyMemoryMethod" + counter;
var methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, typeof(void), new Type[0]);
var il = methodBuilder.GetILGenerator();
// lets try to be clever enough that no optimization reduces our JIT code size
il.DeclareLocal(typeof(int));
il.Emit(OpCodes.Ldc_I4, 0);
for (int i = 1; i <= size / 2; i++) // size/2 is a rough estimate
for (var i = 1; i <= 1 + (size / 8); i++)
{
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldc_I8, 0x1000000000000000 + i);
il.Emit(OpCodes.Call, typeof(Platform).GetMethod("LongConsumer"));
}
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
var m = type.GetMethod(methodName);
m.Invoke(null, new object[] { });
m.Invoke(null, new object[] { }); // make sure it is JIT-compiled
return m.MethodHandle.GetFunctionPointer().ToInt64();
}
}
Expand Down

0 comments on commit b875090

Please sign in to comment.