そこで私はちょっとメソッド実装属性そして私は出会ったメソッド実装オプション.AggressiveInlining次のように説明されます:
可能であれば、メソッドをインライン化する必要があります。
ああ、面白そうだな、と私は思いました。コンパイラよりも賢いふりをして、邪悪な意志の力といくつかの角括弧だけを使って、コードを強制的にインライン化できるのです、ハハハ...
そこで、Visual Studio 2013 を起動し、コンソール アプリケーションを作成し、.NET バージョンを 4.5.1 に設定して、すべてのプログラムを終了するプログラムを作成しました (Release
もちろん、モードでコンパイルしました)。
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
public static class SoHelpful
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetSomeValueProbablyTwelve()
{
return 12;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static int GetSomeValueLikelyThirteen()
{
return 13;
}
public static int GetSomeValueMaybeItIsTwentyEight()
{
return 29;
}
}
class Program
{
static void Main()
{
int twelve = SoHelpful.GetSomeValueProbablyTwelve();
int thirteen = SoHelpful.GetSomeValueLikelyThirteen();
int twentyNine = SoHelpful.GetSomeValueMaybeItIsTwentyEight();
Console.WriteLine((twelve + thirteen + twentyNine));
}
}
}
さて、Swift ildasm を実行すると、次のようになります。
.class public abstract auto ansi sealed beforefieldinit ConsoleApplication1.SoHelpful
extends [mscorlib]System.Object
{
.method public hidebysig static int32 GetSomeValueProbablyTwelve() cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.s 12
IL_0002: ret
} // end of method SoHelpful::GetSomeValueProbablyTwelve
.method public hidebysig static int32 GetSomeValueLikelyThirteen() cil managed noinlining
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.s 13
IL_0002: ret
} // end of method SoHelpful::GetSomeValueLikelyThirteen
.method public hidebysig static int32 GetSomeValueMaybeItIsTwentyEight() cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.s 29
IL_0002: ret
} // end of method SoHelpful::GetSomeValueMaybeItIsTwentyEight
} // end of class ConsoleApplication1.SoHelpful
.class private auto ansi beforefieldinit ConsoleApplication1.Program
extends [mscorlib]System.Object
{
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 2
.locals init ([0] int32 twelve,
[1] int32 thirteen,
[2] int32 twentyNine)
IL_0000: call int32 ConsoleApplication1.SoHelpful::GetSomeValueProbablyTwelve()
IL_0005: stloc.0
IL_0006: call int32 ConsoleApplication1.SoHelpful::GetSomeValueLikelyThirteen()
IL_000b: stloc.1
IL_000c: call int32 ConsoleApplication1.SoHelpful::GetSomeValueMaybeItIsTwentyEight()
IL_0011: stloc.2
IL_0012: ldloc.0
IL_0013: ldloc.1
IL_0014: add
IL_0015: ldloc.2
IL_0016: add
IL_0017: call void [mscorlib]System.Console::WriteLine(int32)
IL_001c: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class ConsoleApplication1.Program
興味深いことに、次の 3 つのメソッドが定義されています。
.method public hidebysig static int32 GetSomeValueLikelyThirteen() cil managed noinlining
.method public hidebysig static int32 GetSomeValueProbablyTwelve() cil managed
.method public hidebysig static int32 GetSomeValueMaybeItIsTwentyEight() cil managed
したがって、積極的なインライン化属性が失われているように見えます。
わかりますnoinlining
がGetSomeValueLikelyThirteen
、GetSomeValueProbablyTwelve
と はGetSomeValueMaybeItIsTwentyEight
同じです。
それで何が起こったのでしょうか? いくつかの可能性があると思います:
- C# コンパイラは、
GetSomeValueProbablyTwelve
インライン化できないことを認識しているので、私の愚かな属性の愚かさで JIT に問題を引き起こすことはありません。 - C# コンパイラは、
GetSomeValueMaybeItIsTwentyEight
インライン化できることを認識しており、これが IL 内で同じである理由ですGetSomeValueProbablyTwelve
(したがって、この場合も、私の属性付けはほとんど無意味かつ愚かなものでした)。 - 属性が認識されるようにするには、コンパイル設定などを微調整する必要があります。
- 全く実装されていません
C#
。 - バグを発見しました
- その他
それで、それがどれか誰か知っていますか?
ベストアンサー1
MethodImplAttributes.AggressiveInlining
フラグにコンパイルされます実装フラグの列メソッド定義メタデータ テーブル (ECMA-335 パーティション II §22.26)。この属性の値は、パーティション II §23.1.11 に記載されていますが、AggressiveInlining
文書化されていません (0x0100 のテーブルに値が存在しません)。
コンパイルプロセス中に、コンパイラはメタデータから属性自体を削除します。逆アセンブラは、0x0100ビットが設定されている場合、属性を再度追加するための特別なロジックを実装する必要があります。実装フラグ方法については。