IL Injection, class hierarchy and method calls

120 views
Skip to first unread message

Indiefreaks.com

unread,
Jul 12, 2011, 6:31:39 AM7/12/11
to mono-cecil
Hi,

Here is another issue I'm meeting with my game profiler.

As a quick reminder, my game profiler does inject two method calls to
each methods before and after the actual method body in a given
assembly to store profiled data in static fields that are also added
to the type during the build process.

everything works fine but I have a strange behavior.
Imagine the following solution:

Indiefreaks.Game.Framework Project (dll assembly)
--- Application class
------- Update virtual method
------- Draw virtual method
--- IUpdate interface
------- Update method
--- IDraw interface
------- Draw method
--- GameState class implements IUpdate & IDraw
------- IUpdate.Update method (explicit implementation)
------- Update virtual method (called by IUpdate.Update)

Commander game (exe assembly)
--- CommanderApplication class inherits from Application
------- Update method overrides Application.Update
------- Draw method overrides Application.Draw

My first problem is that when I inject my profiling code in both
assemblies, my CommanderApplication.Draw method does include the right
code (verified in Reflector):

protected override void Draw(GameTime gameTime)
{
__profilerAttribute132.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.Draw(gameTime);
__profilerAttribute132.ProfilingMethodEnd();
ProfilingManager.Update();
}

And here is the IL code:

.method family hidebysig virtual instance void Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
gameTime) cil managed
{
.maxstack 8
L_0000: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
L_0005: ldarg.0
L_0006: call class [mscorlib]System.Reflection.MethodBase
[mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
L_000b: castclass [mscorlib]System.Reflection.MethodInfo
L_0010: callvirt instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodStart(object,
class [mscorlib]System.Reflection.MethodInfo)
L_0015: ldarg.0
L_0016: ldarg.1
L_0017: call instance void
[Indiefreaks.Game.Framework]Indiefreaks.Xna.Core.Application::Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_001c: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
L_0021: call instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodEnd()
L_0026: call void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilingManager::Update()
L_002b: ret
}

However, the __profilerAttribute132.ProfilingMethodEnd(); method never
gets called while ProfilingManager.Update(); does get called.

I don't understand why. Any clue?
Note that the Application.Draw class calls internally an
((IDraw)ActiveGameState).Draw(gameTime); method.
Here is the Application.Draw code (modified with my injected code):

protected override void Draw(GameTime gameTime)
{
__profilerAttribute464.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.GraphicsDevice.Clear(Color.Black);
if (((this._loadingGameState != null) &&
this._loadingGameState.IsLoadingComplete) && !
this._loadingGameState.ShouldRenderLoadedGameState)
{
((IDraw) this._loadingGameState).Draw(gameTime);
}
else if ((this.ActiveGameState != null) &&
this.ActiveGameState.IsLoadingComplete)
{
((IDraw) this.ActiveGameState).Draw(gameTime);
}
if ((this._transitionColor.A != 0f) || (this._transitionColor.A !=
1f))
{
this._transitionRenderer.Begin(SpriteSortMode.Immediate,
BlendState.AlphaBlend);
this._transitionRenderer.Draw(this._transitionTexture,
base.GraphicsDevice.Viewport.Bounds, this._transitionColor);
this._transitionRenderer.End();
}
base.Draw(gameTime);
__profilerAttribute464.ProfilingMethodEnd();
}

My second problem may be related to the 1st one but I'm not sure:

The CommanderApplication.Update normally calls the Application.Update
method (using base.Update()) which in turns calls the internal
((IUpdate)ActiveGameState.Update(gameTime); method.

Here is the code with the profiled injection code:

protected override void Update(GameTime gameTime)
{
__profilerAttribute463.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
if ((SunBurn.Editor != null) && SunBurn.Editor.EditorAttached)
{
Input.Enabled = false;
}
else
{
Input.Enabled = true;
}
base.Update(gameTime);
this.Threads.Update();
Interpolator.Update((float)
gameTime.ElapsedGameTime.TotalSeconds);
Timer.Update((float) gameTime.ElapsedGameTime.TotalSeconds);
if (((this.ActiveGameState != null) &&
this.ActiveGameState.IsLoadingComplete) && ((this._loadingGameState ==
null) || this._loadingGameState.ShouldRenderLoadedGameState))
{
((IUpdate) this.ActiveGameState).Update(gameTime);
}
if (((this._loadingGameState != null) &&
this._loadingGameState.IsLoadingComplete) && !
this._loadingGameState.ShouldRenderLoadedGameState)
{
((IUpdate) this._loadingGameState).Update(gameTime);
}
__profilerAttribute463.ProfilingMethodEnd();
}

What is strange is that the _profilerAttributeXXX.ProfilingEnd()
methods in CommanderApplication and Application Update methods get
called before the GameState.Update() one:

Commander.exe Information: 0 : Started Profiling
CommanderApplication.Update
Commander.exe Information: 0 : Started Profiling
Application.Update
Commander.exe Information: 0 : Ended Profiling Application.Update
Commander.exe Information: 0 : Ended Profiling
CommanderApplication.Update
Commander.exe Information: 0 : Started Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
...
Commander.exe Information: 0 : Ended Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update

I was expecting to get the methods called this way instead (that's the
way they actually are run by the game):

Commander.exe Information: 0 : Started Profiling
CommanderApplication.Update
Commander.exe Information: 0 : Started Profiling
Application.Update
Commander.exe Information: 0 : Started Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
...
Commander.exe Information: 0 : Ended Profiling
GameState.Indiefreaks.Xna.Core.IUpdate.Update
Commander.exe Information: 0 : Ended Profiling Application.Update
Commander.exe Information: 0 : Ended Profiling
CommanderApplication.Update

I hope you can help me understand these behaviors and how I could
solve them.
Thanks

Indiefreaks.com

unread,
Jul 12, 2011, 9:56:26 AM7/12/11
to mono-cecil
I have been trying to find out why my injected code doesn't run in
vain. I wanted to share some IL code resulting from my game profiler
to see if anyone could help identify the issue.

As a reminder, CommanderApplication inherits from Application which
holds an instance of a GameState class.
The following methods get called
CommanderApplication.Update()
{_profilerAttributeXXX.StartProfilingMethod()},
Application.Update(){_profilerAttributeXXX.StartProfilingMethod()},
Application.Update(){_profilerAttributeXXX.EndProfilingMethod()},
CommanderApplication.Draw()
{_profilerAttributeXXX.StartProfilingMethod()},
Application.Draw(){_profilerAttributeXXX.StartProfilingMethod()}
Application.Draw(){_profilerAttributeXXX.EndProfilingMethod()}

but these don't:
CommanderApplication.Update()
{_profilerAttributeXXX.EndProfilingMethod()},
CommanderApplication.Draw()
{_profilerAttributeXXX.EndProfilingMethod()},

CommanderApplication Update:
C#
protected override void Update(GameTime gameTime)
{
__profilerAttribute131.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.Update(gameTime);
__profilerAttribute131.ProfilingMethodEnd();
}

IL
.method family hidebysig virtual instance void Update(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
gameTime) cil managed
{
.maxstack 8
L_0000: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Commander.CommanderApplication::__profilerAttribute131
L_0005: ldarg.0
L_0006: call class [mscorlib]System.Reflection.MethodBase
[mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
L_000b: castclass [mscorlib]System.Reflection.MethodInfo
L_0010: callvirt instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodStart(object,
class [mscorlib]System.Reflection.MethodInfo)
L_0015: ldarg.0
L_0016: ldarg.1
L_0017: call instance void
[Indiefreaks.Game.Framework]Indiefreaks.Xna.Core.Application::Update(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_001c: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Commander.CommanderApplication::__profilerAttribute131
L_0021: call instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodEnd()
L_0026: ret
}

CommanderApplication Draw:
C#
protected override void Draw(GameTime gameTime)
{
__profilerAttribute132.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.Draw(gameTime);
__profilerAttribute132.ProfilingMethodEnd();
ProfilingManager.Update();
}

IL
Application Update:
C#
protected override void Update(GameTime gameTime)
{
__profilerAttribute463.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
if ((SunBurn.Editor != null) && SunBurn.Editor.EditorAttached)
{
Input.Enabled = false;
}
else
{
Input.Enabled = true;
}
base.Update(gameTime);
this.Threads.Update();
Interpolator.Update((float)
gameTime.ElapsedGameTime.TotalSeconds);
Timer.Update((float) gameTime.ElapsedGameTime.TotalSeconds);
if (((this.ActiveGameState != null) &&
this.ActiveGameState.IsLoadingComplete) && ((this._loadingGameState ==
null) || this._loadingGameState.ShouldRenderLoadedGameState))
{
((IUpdate) this.ActiveGameState).Update(gameTime);
}
if (((this._loadingGameState != null) &&
this._loadingGameState.IsLoadingComplete) && !
this._loadingGameState.ShouldRenderLoadedGameState)
{
((IUpdate) this._loadingGameState).Update(gameTime);
}
__profilerAttribute463.ProfilingMethodEnd();
}

IL
.method family hidebysig virtual instance void Update(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
gameTime) cil managed
{
.maxstack 3
.locals init (
[0] valuetype [mscorlib]System.TimeSpan CS$0$0000,
[1] valuetype [mscorlib]System.TimeSpan CS$0$0001)
L_0000: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Xna.Core.Application::__profilerAttribute463
L_0005: ldarg.0
L_0006: call class [mscorlib]System.Reflection.MethodBase
[mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
L_000b: castclass [mscorlib]System.Reflection.MethodInfo
L_0010: callvirt instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodStart(object,
class [mscorlib]System.Reflection.MethodInfo)
L_0015: call class [SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Core.SceneInterface
Indiefreaks.Xna.Core.Application::get_SunBurn()
L_001a: callvirt instance class [SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Editor.LightingSystemEditor
[SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Core.SceneInterface::get_Editor()
L_001f: brfalse.s L_003f
L_0021: call class [SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Core.SceneInterface
Indiefreaks.Xna.Core.Application::get_SunBurn()
L_0026: callvirt instance class [SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Editor.LightingSystemEditor
[SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Core.SceneInterface::get_Editor()
L_002b: callvirt instance bool [SynapseGaming-SunBurn-
Pro]SynapseGaming.LightingSystem.Editor.LightingSystemEditor::get_EditorAttached()
L_0030: brfalse.s L_003f
L_0032: call class Indiefreaks.Xna.Input.InputManager
Indiefreaks.Xna.Core.Application::get_Input()
L_0037: ldc.i4.0
L_0038: callvirt instance void
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameComponent::set_Enabled(bool)
L_003d: br.s L_004a
L_003f: call class Indiefreaks.Xna.Input.InputManager
Indiefreaks.Xna.Core.Application::get_Input()
L_0044: ldc.i4.1
L_0045: callvirt instance void
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameComponent::set_Enabled(bool)
L_004a: ldarg.0
L_004b: ldarg.1
L_004c: call instance void
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.Game::Update(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_0051: ldarg.0
L_0052: call instance class Indiefreaks.Xna.Threading.ThreadPool
Indiefreaks.Xna.Core.Application::get_Threads()
L_0057: callvirt instance void
Indiefreaks.Xna.Threading.ThreadPool::Update()
L_005c: ldarg.1
L_005d: callvirt instance valuetype [mscorlib]System.TimeSpan
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime::get_ElapsedGameTime()
L_0062: stloc.0
L_0063: ldloca.s CS$0$0000
L_0065: call instance float64
[mscorlib]System.TimeSpan::get_TotalSeconds()
L_006a: conv.r4
L_006b: call void
Indiefreaks.Xna.Core.Interpolator::Update(float32)
L_0070: ldarg.1
L_0071: callvirt instance valuetype [mscorlib]System.TimeSpan
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime::get_ElapsedGameTime()
L_0076: stloc.1
L_0077: ldloca.s CS$0$0001
L_0079: call instance float64
[mscorlib]System.TimeSpan::get_TotalSeconds()
L_007e: conv.r4
L_007f: call void Indiefreaks.Xna.Core.Timer::Update(float32)
L_0084: ldarg.0
L_0085: call instance class Indiefreaks.Xna.Core.GameState
Indiefreaks.Xna.Core.Application::get_ActiveGameState()
L_008a: brfalse.s L_00ba
L_008c: ldarg.0
L_008d: call instance class Indiefreaks.Xna.Core.GameState
Indiefreaks.Xna.Core.Application::get_ActiveGameState()
L_0092: callvirt instance bool
Indiefreaks.Xna.Core.GameState::get_IsLoadingComplete()
L_0097: brfalse.s L_00ba
L_0099: ldarg.0
L_009a: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_009f: brfalse.s L_00ae
L_00a1: ldarg.0
L_00a2: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_00a7: callvirt instance bool
Indiefreaks.Xna.Core.LoadingGameState::get_ShouldRenderLoadedGameState()
L_00ac: brfalse.s L_00ba
L_00ae: ldarg.0
L_00af: call instance class Indiefreaks.Xna.Core.GameState
Indiefreaks.Xna.Core.Application::get_ActiveGameState()
L_00b4: ldarg.1
L_00b5: callvirt instance void
Indiefreaks.Xna.Core.IUpdate::Update(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_00ba: ldarg.0
L_00bb: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_00c0: brfalse.s L_00e8
L_00c2: ldarg.0
L_00c3: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_00c8: callvirt instance bool
Indiefreaks.Xna.Core.GameState::get_IsLoadingComplete()
L_00cd: brfalse.s L_00e8
L_00cf: ldarg.0
L_00d0: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_00d5: callvirt instance bool
Indiefreaks.Xna.Core.LoadingGameState::get_ShouldRenderLoadedGameState()
L_00da: brtrue.s L_00e8
L_00dc: ldarg.0
L_00dd: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_00e2: ldarg.1
L_00e3: callvirt instance void
Indiefreaks.Xna.Core.IUpdate::Update(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_00e8: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Xna.Core.Application::__profilerAttribute463
L_00ed: call instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodEnd()
L_00f2: ret
}

Application Draw:
C#
protected override void Draw(GameTime gameTime)
{
__profilerAttribute464.ProfilingMethodStart(this, (MethodInfo)
MethodBase.GetCurrentMethod());
base.GraphicsDevice.Clear(Color.Black);
if (((this._loadingGameState != null) &&
this._loadingGameState.IsLoadingComplete) && !
this._loadingGameState.ShouldRenderLoadedGameState)
{
((IDraw) this._loadingGameState).Draw(gameTime);
}
else if ((this.ActiveGameState != null) &&
this.ActiveGameState.IsLoadingComplete)
{
((IDraw) this.ActiveGameState).Draw(gameTime);
}
if ((this._transitionColor.A != 0f) || (this._transitionColor.A !=
1f))
{
this._transitionRenderer.Begin(SpriteSortMode.Immediate,
BlendState.AlphaBlend);
this._transitionRenderer.Draw(this._transitionTexture,
base.GraphicsDevice.Viewport.Bounds, this._transitionColor);
this._transitionRenderer.End();
}
base.Draw(gameTime);
__profilerAttribute464.ProfilingMethodEnd();
}

IL
.method family hidebysig virtual instance void Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
gameTime) cil managed
{
.maxstack 4
.locals init (
[0] valuetype
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.Viewport
CS$0$0000)
L_0000: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Xna.Core.Application::__profilerAttribute464
L_0005: ldarg.0
L_0006: call class [mscorlib]System.Reflection.MethodBase
[mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
L_000b: castclass [mscorlib]System.Reflection.MethodInfo
L_0010: callvirt instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodStart(object,
class [mscorlib]System.Reflection.MethodInfo)
L_0015: ldarg.0
L_0016: call instance class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.GraphicsDevice
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.Game::get_GraphicsDevice()
L_001b: call valuetype
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color::get_Black()
L_0020: callvirt instance void
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.GraphicsDevice::Clear(valuetype
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color)
L_0025: ldarg.0
L_0026: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_002b: brfalse.s L_0055
L_002d: ldarg.0
L_002e: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_0033: callvirt instance bool
Indiefreaks.Xna.Core.GameState::get_IsLoadingComplete()
L_0038: brfalse.s L_0055
L_003a: ldarg.0
L_003b: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_0040: callvirt instance bool
Indiefreaks.Xna.Core.LoadingGameState::get_ShouldRenderLoadedGameState()
L_0045: brtrue.s L_0055
L_0047: ldarg.0
L_0048: ldfld class Indiefreaks.Xna.Core.LoadingGameState
Indiefreaks.Xna.Core.Application::_loadingGameState
L_004d: ldarg.1
L_004e: callvirt instance void
Indiefreaks.Xna.Core.IDraw::Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_0053: br.s L_0076
L_0055: ldarg.0
L_0056: call instance class Indiefreaks.Xna.Core.GameState
Indiefreaks.Xna.Core.Application::get_ActiveGameState()
L_005b: brfalse.s L_0076
L_005d: ldarg.0
L_005e: call instance class Indiefreaks.Xna.Core.GameState
Indiefreaks.Xna.Core.Application::get_ActiveGameState()
L_0063: callvirt instance bool
Indiefreaks.Xna.Core.GameState::get_IsLoadingComplete()
L_0068: brfalse.s L_0076
L_006a: ldarg.0
L_006b: call instance class Indiefreaks.Xna.Core.GameState
Indiefreaks.Xna.Core.Application::get_ActiveGameState()
L_0070: ldarg.1
L_0071: callvirt instance void
Indiefreaks.Xna.Core.IDraw::Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_0076: ldarg.0
L_0077: ldflda valuetype
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color
Indiefreaks.Xna.Core.Application::_transitionColor
L_007c: call instance uint8
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color::get_A()
L_0081: conv.r4
L_0082: ldc.r4 0
L_0087: bne.un.s L_009c
L_0089: ldarg.0
L_008a: ldflda valuetype
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color
Indiefreaks.Xna.Core.Application::_transitionColor
L_008f: call instance uint8
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color::get_A()
L_0094: conv.r4
L_0095: ldc.r4 1
L_009a: beq.s L_00e2
L_009c: ldarg.0
L_009d: ldfld class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteBatch
Indiefreaks.Xna.Core.Application::_transitionRenderer
L_00a2: ldc.i4.1
L_00a3: ldsfld class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.BlendState
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.BlendState::AlphaBlend
L_00a8: callvirt instance void
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteBatch::Begin(valuetype
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteSortMode,
class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.BlendState)
L_00ad: ldarg.0
L_00ae: ldfld class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteBatch
Indiefreaks.Xna.Core.Application::_transitionRenderer
L_00b3: ldarg.0
L_00b4: ldfld class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.Texture2D
Indiefreaks.Xna.Core.Application::_transitionTexture
L_00b9: ldarg.0
L_00ba: call instance class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.GraphicsDevice
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.Game::get_GraphicsDevice()
L_00bf: callvirt instance valuetype
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.Viewport
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.GraphicsDevice::get_Viewport()
L_00c4: stloc.0
L_00c5: ldloca.s CS$0$0000
L_00c7: call instance valuetype
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Rectangle
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.Viewport::get_Bounds()
L_00cc: ldarg.0
L_00cd: ldfld valuetype
[Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color
Indiefreaks.Xna.Core.Application::_transitionColor
L_00d2: callvirt instance void
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteBatch::Draw(class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.Texture2D,
valuetype [Microsoft.Xna.Framework]Microsoft.Xna.Framework.Rectangle,
valuetype [Microsoft.Xna.Framework]Microsoft.Xna.Framework.Color)
L_00d7: ldarg.0
L_00d8: ldfld class
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteBatch
Indiefreaks.Xna.Core.Application::_transitionRenderer
L_00dd: callvirt instance void
[Microsoft.Xna.Framework.Graphics]Microsoft.Xna.Framework.Graphics.SpriteBatch::End()
L_00e2: ldarg.0
L_00e3: ldarg.1
L_00e4: call instance void
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.Game::Draw(class
[Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
L_00e9: ldsfld class
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
Indiefreaks.Xna.Core.Application::__profilerAttribute464
L_00ee: call instance void
[Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::ProfilingMethodEnd()
L_00f3: ret
}


Thanks

On 12 juil, 12:31, "Indiefreaks.com" <webmas...@indiefreaks.com>
wrote:
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodStart(object,
> class [mscorlib]System.Reflection.MethodInfo)
>     L_0015: ldarg.0
>     L_0016: ldarg.1
>     L_0017: call instance void
> [Indiefreaks.Game.Framework]Indiefreaks.Xna.Core.Application::Draw(class
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
>     L_001c: ldsfld class
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
> Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
>     L_0021: call instance void
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodEnd()
>     L_0026: call void
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilingManager::Update­()

Indiefreaks.com

unread,
Jul 13, 2011, 10:45:38 AM7/13/11
to mono-cecil
Ok, since I'm not getting answers, I believe this is a really
localized problem to my own R&D.

Just a simple question: what the MethodDefinition.NoInlining and
MethodDefinition.NoOptimization properties do when saving the
Assembly?

Thanks

On Jul 12, 3:56 pm, "Indiefreaks.com" <webmas...@indiefreaks.com>
wrote:
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodStart(object,
> class [mscorlib]System.Reflection.MethodInfo)
>     L_0015: ldarg.0
>     L_0016: ldarg.1
>     L_0017: call instance void
> [Indiefreaks.Game.Framework]Indiefreaks.Xna.Core.Application::Update(class
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
>     L_001c: ldsfld class
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
> Indiefreaks.Commander.CommanderApplication::__profilerAttribute131
>     L_0021: call instance void
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodEnd()
>     L_0026: ret
>
> }
>
> CommanderApplication Draw:
> C#
> protected override void Draw(GameTime gameTime)
> {
>     __profilerAttribute132.ProfilingMethodStart(this, (MethodInfo)
> MethodBase.GetCurrentMethod());
>     base.Draw(gameTime);
>     __profilerAttribute132.ProfilingMethodEnd();
>     ProfilingManager.Update();
>
> }
>
> IL
> .method family hidebysig virtual instance void Draw(class
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
> gameTime) cil managed
> {
>     .maxstack 8
>     L_0000: ldsfld class
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
> Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
>     L_0005: ldarg.0
>     L_0006: call class [mscorlib]System.Reflection.MethodBase
> [mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
>     L_000b: castclass [mscorlib]System.Reflection.MethodInfo
>     L_0010: callvirt instance void
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodStart(object,
> class [mscorlib]System.Reflection.MethodInfo)
>     L_0015: ldarg.0
>     L_0016: ldarg.1
>     L_0017: call instance void
> [Indiefreaks.Game.Framework]Indiefreaks.Xna.Core.Application::Draw(class
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
>     L_001c: ldsfld class
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
> Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
>     L_0021: call instance void
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodEnd()
>     L_0026: call void
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilingManager::Update­()
>     L_002b: ret
>
> }
>
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute::Profi­lingMethodStart(object,
> class [mscorlib]System.Reflection.MethodInfo)
>     L_0015: call class [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Core.SceneInterface
> Indiefreaks.Xna.Core.Application::get_SunBurn()
>     L_001a: callvirt instance class [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Editor.LightingSystemEditor
> [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Core.SceneInterface::get_Editor()
>     L_001f: brfalse.s L_003f
>     L_0021: call class [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Core.SceneInterface
> Indiefreaks.Xna.Core.Application::get_SunBurn()
>     L_0026: callvirt instance class [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Editor.LightingSystemEditor
> [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Core.SceneInterface::get_Editor()
>     L_002b: callvirt instance bool [SynapseGaming-SunBurn-
> Pro]SynapseGaming.LightingSystem.Editor.LightingSystemEditor::get_EditorAtt­ached()
>     L_0030: brfalse.s L_003f
>     L_0032: call class Indiefreaks.Xna.Input.InputManager
> Indiefreaks.Xna.Core.Application::get_Input()
>     L_0037: ldc.i4.0
>     L_0038: callvirt instance void
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameComponent::set_En­abled(bool)
>     L_003d: br.s L_004a
>     L_003f: call class Indiefreaks.Xna.Input.InputManager
> Indiefreaks.Xna.Core.Application::get_Input()
>     L_0044: ldc.i4.1
>     L_0045: callvirt instance void
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameComponent::set_En­abled(bool)
>     L_004a: ldarg.0
>     L_004b: ldarg.1
>     L_004c: call instance void
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.Game::Update(class
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
>     L_0051: ldarg.0
>     L_0052: call instance class Indiefreaks.Xna.Threading.ThreadPool
> Indiefreaks.Xna.Core.Application::get_Threads()
>     L_0057: callvirt instance void
> Indiefreaks.Xna.Threading.ThreadPool::Update()
>     L_005c: ldarg.1
>     L_005d: callvirt instance valuetype [mscorlib]System.TimeSpan
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime::get_Elapsed­GameTime()
>     L_0062: stloc.0
>     L_0063: ldloca.s CS$0$0000
>     L_0065: call instance float64
> [mscorlib]System.TimeSpan::get_TotalSeconds()
>     L_006a: conv.r4
>     L_006b: call void
> Indiefreaks.Xna.Core.Interpolator::Update(float32)
>     L_0070: ldarg.1
>     L_0071: callvirt instance valuetype [mscorlib]System.TimeSpan
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime::get_Elapsed­GameTime()
>     L_00bb: ldfld class...
>
> read more »

Gábor Kozár

unread,
Jul 13, 2011, 11:52:04 AM7/13/11
to mono-...@googlegroups.com
You might want to shorten down your e-mails, because they're waaay for too long for a busy man to read. :)

As for your question, as far as I know, it does nothing compile-time, only comes into play during the runtime, in which it signals the CLR that the method should not be inlined or optimized.
In C#, you can specify this using the MethodImplAttribute (or maybe MethodImplOptionsAttribute? I can't quite remember).

2011/7/13 Indiefreaks.com <webm...@indiefreaks.com>
--
--
mono-cecil

Jb Evain

unread,
Jul 13, 2011, 12:35:52 PM7/13/11
to mono-...@googlegroups.com
On Tue, Jul 12, 2011 at 12:31 PM, Indiefreaks.com
<webm...@indiefreaks.com> wrote:
> .method family hidebysig virtual instance void Draw(class
> [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime
> gameTime) cil managed
> {
>    .maxstack 8
>    L_0000: ldsfld class
> [Indiefreaks.AOP.Profiler]Indiefreaks.AOP.Profiler.ProfilerAttribute
> Indiefreaks.Commander.CommanderApplication::__profilerAttribute132
>    L_0005: ldarg.0
>    L_0006: call class [mscorlib]System.Reflection.MethodBase
> [mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
>    L_000b: castclass [mscorlib]System.Reflection.MethodInfo

Gotta love being lectured about performance of method calls (sigh)
just to see this.

For information, you can do:

ldtoken drawMethodDefinition
call MethodBase::GetMethodFromHandle(System.RuntimeMethodHandle)

Bang!

On my machine, calling GetCurrentMethod a million times takes 2.6s.
Doing the GetMethodFromHandle trick a million times takes 0.5s.

Here, I just saved you enough time to call a few methods.

Jb

Indiefreaks.com

unread,
Jul 13, 2011, 1:31:42 PM7/13/11
to mono-cecil
Thanks for the tip, I'll implement it as soon as I get it working on
all cases ;)

Any idea why the method doesn't get called?
Until I found out, I'm currently cloning the method, clearing the
current one and adding my profiling stuff there but that really sounds
like a hack to me :(

Thanks

On Jul 13, 6:35 pm, Jb Evain <jbev...@gmail.com> wrote:
> On Tue, Jul 12, 2011 at 12:31 PM, Indiefreaks.com
>

Rodrigo B. de Oliveira

unread,
Jul 13, 2011, 2:36:56 PM7/13/11
to mono-...@googlegroups.com
On Wed, Jul 13, 2011 at 2:31 PM, Indiefreaks.com
<webm...@indiefreaks.com> wrote:
> ...

> Until I found out, I'm currently cloning the method, clearing the
> current one and adding my profiling stuff there but that really sounds
> like a hack to me :(
>

Any kind of il post processing is technically a hack. True story :)

Jb Evain

unread,
Jul 13, 2011, 7:03:18 PM7/13/11
to mono-...@googlegroups.com
On Wed, Jul 13, 2011 at 7:31 PM, Indiefreaks.com
<webm...@indiefreaks.com> wrote:
> Any idea why the method doesn't get called?

Nope.

But if the IL code is correct, it could be anything from methods
getting inlined and messing with your expectations, to you not
interpreting the results correctly.

Jb

Indiefreaks.com

unread,
Jul 14, 2011, 5:26:31 PM7/14/11
to mono-cecil
So, do you see how I can know what is going wrong and why the code I
inject passes PEVerifier on both IL and MD, seems well interpreted by
Reflector (C#) but still doesn't get called and worse gets jumped as
the next method call is invoked correctly?

Any other tool or debug tip for me to investigate with?

Thanks

On Jul 14, 1:03 am, Jb Evain <jbev...@gmail.com> wrote:
> On Wed, Jul 13, 2011 at 7:31 PM, Indiefreaks.com
>
Reply all
Reply to author
Forward
0 new messages