読者です 読者をやめる 読者になる 読者になる

ソースを読める歓び (或いは DLR と Orcas について)

.NET

IronPythonIronRubyソースコードには DLR のソースコードも含まれているのですが,それらを漁っていると,"Orcas" や "CLR V2 SP1" といったおもしろい単語に出くわします.目下ソース探検中の方はぜひ実際に grep してみて下さい.

Orcas における DynamicMethod の新機能 - Anonymous Assembly

たとえば AssemblyGen.cs を見てみると,CLR 2.0 SP1 で,DynamicMethod クラスに新しいコンストラクタが追加されることがコメントから読み取れます.
このヒントに従って調べてみると,確かにコンストラクタが増えていました.

// CLR 2.0
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility);
public DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility);
public DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility);
// CLR 2.0 SP1
public DynamicMethod(string name, Type returnType, Type[] parameterTypes);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility);
public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility);
public DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility);
public DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility);

実際追加されたメソッドのドキュメントを読んでみると,どうやら Orcas で anonymous assembly という概念が追加される予定らしきことが分かります.

The dynamic method that is created by this constructor is associated with an anonymous assembly instead of an existing type or module. The anonymous assembly exists only to provide a sandbox environment for dynamic methods, that is, to isolate them from other code. This environment makes it safe for the dynamic method to be emitted and executed by partially trusted code.

This constructor specifies that just-in-time (JIT) visibility checks will be enforced. That is, the code in the dynamic method has access to public methods of public classes. Exceptions are thrown if the method tries to access types or members that are private, protected, or internal (Friend in Visual Basic). To create a dynamic method that has restricted ability to skip JIT visibility checks, use the DynamicMethodNew(String, Type, Type(), Boolean) constructor.

When an anonymously hosted dynamic method is constructed, the call stack of the emitting assembly is included. When the method is invoked, the permissions of the emitting assembly are used instead of the permissions of the actual caller. Thus, the dynamic method cannot execute at a higher level of privilege than that of the assembly that emitted it, even if it is passed to and executed by an assembly that has a higher trust level.

This constructor specifies the method attributes MethodAttributes.Public and MethodAttributes.Static, and the calling convention CallingConventions.Standard.

おそらく DLR を意図しての CLR 側のピンポイントな改良ということでしょう.Lightweight Code Gen (LCG) と Code Access Security (CAS) の組み合わせのややこしさについてご存じの方であれば,上のドキュメントの抜粋で何となく察しはつくのではないでしょうか?

Orcas における GC の新機能 - GCCollectionMode と GCLatencyMode

また,AssemblyTypeNames.cs にもおもしろいものがあります.ここでは .NET Framework に付属するアセンブリと,そのアセンブリに含まれるクラス名の対応表がハードコード (というか自動コード生成) されているのですが,そこに Orcas の文字があります.
具体的には,既存のアセンブリに Orcas で追加される型名がリストアップされています.せっかくなので抜き出してみました.

  • mscorlib.dll
    • System.DateTimeOffset
    • System.GCCollectionMode
    • System.Runtime.GCLatencyMode
  • System.dll
    • System.ComponentModel.Design.Serialization.IDesignerLoaderHost2
    • System.ComponentModel.INotifyPropertyChanging
    • System.ComponentModel.PropertyChangingEventArgs
    • System.ComponentModel.PropertyChangingEventHandler
    • System.Configuration.IdnElement
    • System.Configuration.IriParsingElement
    • System.Configuration.UriSection
    • System.Net.Sockets.SendPacketsElement
    • System.Net.Sockets.SocketAsyncEventArgs
    • System.Net.Sockets.SocketAsyncOperation
    • System.UriIdnScope
  • System.Drawing.dll
    • なし
  • System.Windows.Forms.dll
    • System.Windows.Forms.FileDialogCustomPlace
    • System.Windows.Forms.FileDialogCustomPlacesCollection
  • System.Xml.dll
    • System.Xml.Serialization.Configuration.RootedPathValidator

最近全然ですが,一応ゲームプログラミングを嗜む身としては目を引く型が含まれています.そう,リアルタイムゲームと微妙な関係,GC の新機能です.
以前から .NET 3.5 では GC 周りにチューンが入るという話は公開されていたのですが,具体的にピンポイントの型名が分かったことで記事を見つけることができました.Chris Lyon's WebLog より以下の 3 つです.

このうち最も興味深いのは GC Latency Modes で,プロセス実行中に GC のモードを動的に切り替えることができるという機能です.これによって,レスポンスタイムが重要な時間帯は低レイテンシモードを使用し,時間に余裕があるときには通常モードに戻すといったことが可能になると.
まあ XNA に関してはその前に Xbox 360 CLR を何とかしてという話がありますが……
それでも XNA によって,CLR チームにとっても“リアル”なゲーム系ベンチマークの材料が増えてきたのはいいことでしょうね.

まとめというかオチ

さて,文体を変えてオチと.
今回のネタはひとえに DLR のソースが公開されていたからこそ見つけられた話,ということで arton さんのエントリにつながるわけですな.

学習するときに必要なことってなんだ?

良いお手本とフィードバックだ。フィードバックはプログラミングについて言えば簡単で、作って動かして結果を見れば良い。だから、自分ってやつを用意すればとりあえずはOK。UIとか言い出したら別の話だけど、プログラミングって言ってんだから、そいつはどうでも良い、多分。

良いお手本とはなんだろう?

もちろんソースだ。

ちなみに arton さんのところの話は最初に学ぶべき言語が何であるか? というもので,うちのエントリは DLR とかまだ見ぬ Orcas の話なわけで,引用時点で思いっきり脱線していることにご用心 *1
んで,何で引用してみたかというと,そういえば C# のコードを読んでいて「すげー」感を味わったことってほとんどないよなぁ,とふと思ったと.これは別にすごくないコードばかり読まされているという理由ではなくて,そもそも本気で読み漁ろうという規模だったり意義をもったりした C# のコードって,世に出てないことが多いのです.
SDK に付いてくる C# のサンプルコードやサンプルアプリケーションは,愛が感じられない書き方のものばっかりだし,うちの日記でよく取り上げるようなコード片は愛どころか暗黒面に落ちたものばっかりだし.
そんな中,最近読んでいて脳が多少なりとも活性化した C# のコードを挙げろと言われると,やはりこいつらがトップ 3 に入るわけです.

あまりにも楽しいものだから,例えば ReSharper の誇る "Navigate From Here" で飛び回ってみたり,クラスダイアグラムを描かせてみたり (はあんまり興味が無くてしてないのですが),partial class や nullable や yield return や ?? 演算子が何回使われているか数えてみたり,string.Empty の代わりに "" 使っている理由を考えてみたり,IList<T> と List<T> の比率を計算したり,TODO をひとつひとつ見て回ったりしてみると.今回の記事に書いたような発見はむしろおまけみたいなものです.
RubyPython という二大言語の処理系が,フルビルドをかけても (多分) 10 秒以内に動き出すというスピード感こそ,本来 C# が持っていた魅力なのかなと思うわけですよ.
(といいつつ MatzRuby のソースコンパイルも試してみたのですが,コア部分だけなら十分速いですね.そういえば C は (C++ に比べれば) コンパイルが速くて良かったんだった.昔 C++ でゲーム作っていたときの嫌な印象が不当に C 言語の印象も下げちゃってたのかも.なんせフルビルドの間にお風呂入れましたし.)

*1:ちなみに私の最初の言語は N88BASIC で,お手本はベーマガ投稿ゲームと友人のコードというありきたりパターン.でもまあ今の人たちは,それ自体複雑で変なルールの固まりの Windows とか,20 世紀最大のキメラ HTML & JavaScript コンビとかを先にさわっていることが多いんじゃなかろうか,とか.一方で昔よくあった Tree のたとえにディレクトリなんてのは,人々の啓蒙で滅ぶことが決定付けられてそうな今日この頃.あーでも世界を雲のように覆う HTML は木か.