System.Stringのコンストラクタを許すな
String のコンストラクタ、ありえてはいけない存在だよな
— ウィンドウズ青山 (@azyobuzin) 2016年8月2日
ということは、コンストラクタを FCall にするとあり得ない型のインスタンスをお返しすることができるわけですね!!
— ウィンドウズ青山 (@azyobuzin) 2016年8月2日
というわけで始まりました深夜の CoreCLR ソースコードリーディングのお時間。司会は早くこの記事を書き終えてアニメを見たいazyobuzinがお送りいたします。
普通のコンストラクタ
コンストラクタは、名前「.ctor」、戻り値の型 void で定義されるインスタンスメソッドと考えることができます。そしてオペコード newobj でコンストラクタが指定されると、そのクラスのインスタンスが作成され、第0引数に入れられコンストラクタが呼び出されます。つまり、「メモリ確保 → コンストラクタ呼び出し」という順番になります。
String のコンストラクタ
mscorlib の String クラスのコンストラクタは、すべて [MethodImplAttribute(MethodImplOptions.InternalCall)]
が付与されていています(ILでは internalcall 属性, 通称 FCall)。 FCall は ecalllist.h でマッピングされた関数を呼び出します。
マネージドメソッドとして定義されたコンストラクタ
では、 String のコンストラクタを呼び出した時に、実際に呼び出される関数を見ていきましょう。まずは FCDynamicSig
で定義されているこの5つ。
FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayStartLengthManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrStartLengthManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_Char_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharCountManaged)
https://github.com/dotnet/coreclr/blob/release/1.0.0/src/vm/ecalllist.h#L214-L218
これらは最後に「Managed」がついてることからわかるように、マネージドメソッドを呼び出します。最初の「CtorCharArrayManaged」に対応するメソッドを探すと String クラスに CtorCharArray メソッドがありました。(ecall.h, ecall.cpp を読むと、 String 型のメンバーを舐めているのがわかります。)
CtorCharArray はインスタンスメソッドで、 String を返します。……は?とりあえず、この戻り値が newobj の実行結果となるようです。
アンマネージドのほう
C++で書かれたメソッドを呼び出すものは FCFuncElementSig
で定義されています。
FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_RetVoid, COMString::StringInitCharPtr) FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_Int_Int_RetVoid, COMString::StringInitCharPtrPartial)
https://github.com/dotnet/coreclr/blob/v1.0.0/src/vm/ecalllist.h#L219-L220
COMString クラスのメンバーの実装は stringnative.cpp にあります。
StringInitCharPtr を見てみると
_ASSERTE(stringThis == 0); // This is the constructor
なんてコードがありますね。つまり this として null が渡されているようです。ということはマネージドのほうも this は null なのだと思われます。
戻り値はオブジェクトの参照、つまり String です。
Decimal のコンストラクタ
他にもコンストラクタが internalcall なものはないかと探していたら Decimal の float, double を引数にとるコンストラクタが internalcall でした。 decimal.cpp の InitSingle と InitDouble が呼び出されるメソッドです。今度は戻り値が void ですね。値型だと戻り値は不要のようです。そもそも値型のコンストラクタは newobj のほかに、普通に call で呼び出すこともあります(コンパイラ依存案件)し、そういうものなのでしょうか。よくわからん。
Unicode正規化を実装する (4) クイックチェック
バックナンバー
- Unicode正規化を実装する (1) UCDにふれる - アジョブジ星通信
- Unicode正規化を実装する (2) 正規分解・互換分解 - アジョブジ星通信
- Unicode正規化を実装する (3) 正規合成 - アジョブジ星通信
本当は正規化の高速化全般について書きたかったのですが、 UAX #15 に「トライ木使うといいんじゃね?」とか書いてあるんですけど、どういう木構造にしたらいいのかさっぱりわからず無事死亡しました。強い方、よろしくお願いします。
というわけで今回は、クイックチェックプロパティを使った、正規化済み判定と合成の高速化について説明していこうと思います。
続きを読むUnicode正規化を実装する (3) 正規合成
バックナンバー
PCの死亡を言い訳に3ヶ月空いてしまいましたが、その間に Unicode 9.0.0 がリリースされたようです。サンプルリポジトリに入っている UCD のコピーを 9.0.0 にアップデートしました。 NormalizationTest.txt のテストケースは前回のサンプルコードのまま問題なくクリアしています。
さて、今回は合成です。合成は分解テーブルのキーと値が逆のテーブルを作って、ひたすらルックアップしていく作業になります。ただし、合成できる文字には細かい規定があるので気をつけましょう。
前回同様、サンプルと見比べながら読み進めてもらえると良いです。結構ファイルが分散しているので、「定義へ移動」が使える Visual Studio を使うと読みやすいかと思います。
続きを読むツイートの新構造対応のメモ
これです。
CoreTweet 0.6.3 で API の変更には対応したのでその使い方について説明を書いておこうと思います。
1. とりあえず tweet_mode=extended をつけておく
新構造のデータを受信するには tweet_mode=extended
を指定する必要があります。 CoreTweet でこれをやるには、各 API 呼び出しで、 tweet_mode
引数に TweetMode.extended
を指定します。
サンプルコード
t.Statuses.HomeTimeline(tweet_mode: TweetMode.extended); // TweetMode 列挙体を使用 t.Statuses.HomeTimeline(tweet_mode => "extended"); // string で
で、このパラメータを指定すると、 text ではなく full_text フィールドにツイートの中身が入ってくるようになります。 CoreTweet では FullText プロパティになっています。
Unicode正規化を実装する (2) 正規分解・互換分解
前回: Unicode正規化を実装する (1) UCDにふれる - アジョブジ星通信
さて、前回 UnicodeData.txt の読み方をやりましたので、これを使って実際に正規分解・互換分解を実装してみましょう。
サンプルコードと見比べながら説明を読んでいただければと思います。
続きを読むルータを新調した
買いました。
- 出版社/メーカー: バッファロー
- 発売日: 2015/12/24
- メディア: Personal Computers
- この商品を含むブログ (1件) を見る
前のルータの無線が 11g で、 torne でアニメ見てると動きの多いシーンでフリーズしていました。
参考:
こういう状況なんですよ pic.twitter.com/HEYvnqklch
— 櫻井桃華 (@azyobuzin) 2016年3月20日
で、新調した結果ですが・・・変わりませんでした!だって PS3 が 11g しか対応してない上、 11g の速度はそんなに変わらなかったんだもん!
というわけでスマホだけ高速化しましたとさ、おしまい。
ここで終わらないのが今日の僕(と父)。テレビに有線で LAN ケーブルがつながってるので、それを前のルータにつなぎ変えて、テレビとPS3に有線で接続で接続することで、 PS3 の通信速度が 60Mbps になりました。めでたしめでたし。