Today アクセスカウンター Yesterday アクセスカウンター

ホワット・ア・ワンダフル・ワールド

私は知識に何ものかを付け加え,また他の人々がより多くのものを付け加える手助けをした --- G.H.ハーディ

全記事一覧 << 2008/07 12345678910111213141516171819202122232425262728293031 2008/09 >>

プロフィール

あろは (alohakun)

  • Author:あろは (alohakun)
  • 若槻俊宏 (WAKATSUKI toshihiro)

    連絡先 : alohakun ___at___ gmail.com
    mixi : http://mixi.jp/show_friend.pl?id=182927
    twitter : http://twitter.com/alohakun

    abstract

    プログラミングという人間の知的行為を体系化し,単なる職人芸ではなく,サイエンスにするための研究をしています.

    具体的には,等価変換計算モデルに基づいた,仕様記述からのプログラム合成の研究をしています.

    もっと噛み砕くと,プログラムの正しさをどのように定式化し,どのような枠組みで,どのように変換を進めていけば,正しさを保証したまま,効率的なプログラムを手に入れることができるのか,ということについて研究しています.

    キーワード : equivalent transformation, computation model, programming paradigm, formal specification, program synthesis













    あわせて読みたい


    この日記のはてなブックマーク数


    スカウター : ホワット・ア・ワンダフル・ワールド


    Map









    FC2 BLOG RANKING

FC2カウンター

ブロとも申請フォーム

この人とブロともになる

Vx32: Lightweight, User-level Sandboxing on the x86

2008/07/16(水) 08:00:51

面白そう.

Plan9日記 2008-06-28 ■[9fans] 9vx

9vxはPlan9カーネルをユーザランドに移植したもので、その上でPlan9の実行バイナリを無変更で実行できるというもの。対応しているホストOSはLinux、MacOS X、FreeBSD。実行速度はQEMUはもちろんVMWareよりも高速。9vxを実装するために、vx32というIA32用のsandboxingライブラリを使っている。sandboxを作る手法はいろいろあるけど、vx32はデータをsandboxするためにセグメンテーション、コードをsandboxするために動的コード変換を使っている。vx32のサンプルプログラムには9vxの他にもLinuxのシステムコールをトラップしてjail化するものとか含まれているので、Plan9ネタに限定せず,興味がある人はいるのでは?

ちなみにvx32の作者であるBryan Ford氏、どこかで見た名前だなと思ったら、OSKitの人だった。

これですね.

Vx32: portable, efficient, safe execution of untrusted x86 code

普通のサンドボックス技術では,例えば VMWare みたいにシステム丸ごとエミュレートするか,JVM (CLR) みたいに仮想機械で抽象機械語を実行,という形になるので,オーバーヘッドが大きい.

一方 vx32 は,バイナリにライブラリとしてリンクするだけで,普通に x86 コードを安全にネイティブ実行できるというモノ (アプリケーションレベル仮想機械) なのでオーバーヘッドが圧倒的に少なく (VMWare などとの違い),任意のプログラミング言語が使える (Java や C# との違い),ということらしい.たぶん.

試しに Ubuntu binaries を落としてみたんだけど,よくわからんでした.


$ ls /opt/vx32/bin/
vx32-addr2line vx32-cpp vx32-gcov vx32-objdump vx32-strings
vx32-ar vx32-gcc vx32-ld vx32-ranlib vx32-strip
vx32-as vx32-gcc-4.1.2 vx32-nm vx32-readelf
vx32-c++filt vx32-gccbug vx32-objcopy vx32-size

$ /opt/vx32/bin/vx32-gcc -v
Using built-in specs.
Target: vx32
コンフィグオプション: ./configure --target=vx32 --prefix=/opt/vx32
スレッドモデル: single
gcc バージョン 4.1.2

$ /opt/vx32/bin/vx32-gcc test.c
test.c:1:18: error: stdio.h: そのようなファイルやディレクトリはありません
test.c: In function 'main':
test.c:2: 警告: incompatible implicit declaration of built-in function 'printf'

$ /opt/vx32/bin/vx32-gcc test.c
test.c: In function 'main':
test.c:1: 警告: incompatible implicit declaration of built-in function 'printf'
/opt/vx32/lib/gcc/vx32/4.1.2/../../../../vx32/bin/ld: crt0.o: No such file: その ようなファイルやディレクトリはありません
collect2: ld はステータス 1 で終了しました


なんか根本的に間違ってる予感 (また後で)

安全で,OS に依存しない実行環境を作れるので,plan9 など他の OS のバイナリをそのまま安全に実行できるようにしたり (安全っていう点が,WINE などの互換 API ライブラリとは異なる ?),カーネルやバイナリ無変更で Linux system call jail を実現したりできるらしい.

Vx32: Lightweight, User-level Sandboxing on the x86

パッと見た欠点は,Windows では使えなさそうな点と,IA-32e モード (AMD 64 モード) を使うバイナリは実効できない点なのかな.
vx32 は,x86 のコードセグメンテーション機能を活用しているので,x86 以外の CPU には対応できないアーキテクチャということらしい.

wikipedia : VX32
C 言語/コンパイラ/BinaryHacksTB:0CM:0 このエントリーを含むはてなブックマーク | livedoorクリップ livedoorクリップ BuzzurlにブックマークBuzzurlにブックマーク newsing it!

call とか ret は無くてもなんとかなる

2008/07/11(金) 01:02:33

Linux Kernel の include/asm-i386/system.h の switch_to() マクロとかで使われていたりして,わりと有名なテクニックなのかもしれませんが,

call foo

とかは,機械的に

pushl $1f
jmp foo
1:

みたいに,スタックの頭に戻り番地をプッシュして,関数にジャンプする感じに書き換えられるのではないかと思いました.

ret もまぁ,

pop %ecx
jmp *%ecx

みたいに,適当に壊しても良いレジスタに戻り値を pop して間接ジャンプすれば大丈夫な気がします.

もちろん,本来一命令で済むものを,わざわざメモリ触った挙句命令数増やすのはバカバカしいので,実用性は無いわけですが.

アセンブラとか,x86 命令レベルのクロック数とか μOP (マイクロオペレーション) レベルの話とか全然わからない子なので,大きな勘違いをしている恐れがあります (ツッコミ期待)

最近の x86 は,インタフェースだけは x86 のままでも,中身は全然別物らしいです.一個の x86 的 CISC 命令が複数の μOP に分解されて実行されたり,逆に複数の命令が一個の μOP で実行できたり.

x86 レベルではレジスタは 8 つしかありませんが,たとえば Pentium 4 は,物理レジスタは 128 本あるそうです.なので μOP レベルでは,x86 命令からさらにレジスタ割付みたいなことが行われて,レジスタリネーミングとかいう最適化技術が使われていたりも.

アセンブリのレベルの見た目と,実際の速度が全然異なるようです.なので,よく 「高級言語なんて当てにするな,アセンブリリスト出して見ろ」 とか言う古いプログラマの人がいたりするようですが,最近の CPU はアセンブリ自体がある種の高級言語で,x86 命令が内部的には μOP に JIT されて,命令が分解されたりまとめられたり実行順序が勝手に変更されたり同時実行されたりレジスタリネーミングされてものすごいパイプライニングされたり,わけわからんことになってみたいなので,アセンブリ見ても本当に早いのかどうかはわからない気がします.

なんかとりとめなくなってしまいましたが,要するに niha さんとかが最近アセンブリプログラミングについて書いてるみたいなので,僕もなんとなく思いついたことを書いてみたくなっただけなのでした.

CPU って,ガチガチのハードウェアみたいに思われてますけど,現在の x86 CPU は,IA-32 っていう高級な CISC 命令セットを実行するための仮想機械 (VM) なんですよね.本当にガチのハードウェアは,μOP っていう,もっと細かいオペレーションを実行する,レジスタがいっぱいある RISC プロセッサです.そういう非常に複雑な二重構造になっているのに,あれだけの性能が出ているという奇跡.すごいなぁと思います.

# icc の最適化がすごくて,gcc とかは一生かなわないってのも,ある意味当たり前です.インテル社だけが,μOP の仕様や,それへの変換アルゴリズムなど,もろもろの内部の秘密テクノロジを知っているのですから,他のコンパイラベンダは,ベンチマークの結果から内部を推測して,最適化ルーチンを作るしかありません.そりゃ,一生追いつけませんよ

ということは,実は x86 命令セットに限らず,ppc とか sparc とか arm とか,他のプロセッサの命令セットもハードレベルで JIT して実行できるポテンシャルはあるのでは ? と.

インテルが μOP の仕様を公開してくれれば,それの上の LLVM みたいなフレームワークを被せて,ハードウェアとソフトウェアが協調して,高速に低レベル命令を実行する VM フレームワークみたいなのが作れて良いのになぁ,とか妄想したりも.




んでまぁ,ここまで巨大なブラックボックスの上で世界が動いているという現状を考えると,やっぱりフォーマルメソッドには一定の限界があるのかなぁ,とか思うわけです.

原理的には,全てをロジックで記述し尽くして,プロファイルとか泥臭いことしなくても,(実時間の許す範囲で) 可能な限りの最適化とか可能だと思うんですけど.企業が秘密を握っている限り,それは不可能.実験と計測の世界のままです.

やっぱり,プロセッサアーキテクチャもオープンになって欲しいというか,やはり究極的には,FPGA とかで,全て明確な世界に持ってくる必要があるのだと思います.アプリケーションの仕様に合わせて,逆算的に命令セットや,最適なハードウェアをロジカルに生成すると.まぁ,今のところは夢物語ですが.




あー,分岐予測か.確かに.call/ret の組が無いと,どこからどこまでが関数なのかわからないとか,そういう話なのかな ?

http://d.hatena.ne.jp/scinfaxi/20080711/1215724490

そういえば JVM とかも,手書きで作った変なパターンのバイトコードに対しては,あんまり JIT が効かないので,javac とかはむしろほとんど最適化しない,素直な構造のコードを吐くようになってるとかいう話があったような.つくづく x86 って,ハードウェアというよりは VM に近いよなぁ.




追記

敬愛している id:shinichiro_h さんと id:w_o さんに同時に dis られるという快挙を達成しましたので,大満足です!書いたかいがあるというもので,非常にうれしい.天にも昇る気分です (ドM)

http://d.hatena.ne.jp/shinichiro_h/20080711#1215786569
http://morihyphen.hp.infoseek.co.jp/log2/200807.html#07110
C 言語/コンパイラ/BinaryHacksTB:0CM:8 このエントリーを含むはてなブックマーク | livedoorクリップ livedoorクリップ BuzzurlにブックマークBuzzurlにブックマーク newsing it!

C の構文の変態さ

2008/04/05(土) 16:28:58

そもそも C に文字列型なんてありません.文字列みたいなアレは,文字の配列型です.

ポインタと配列型は,全く違うものです.そもそも typeof (GCC 拡張) で取れる型が違う,sizeof で取れるオブジェクトサイズも違う.

まぁ,文字列リテラルが存在していて,唯一複合型なのに静的 (static) 領域に初期化して置いとくことができたりして,いろいろややこしいのですが.

あと,配列の要素アクセスは,常にポインタ演算経由で行われるのも,ややこしいところですね.配列とポインタを同一視してしまうというもっともありがちな混乱は,ここに由来するのだと思います.アセンブリ言語のレベルでは,配列なんていう高級な概念は存在しなくて,メモリと番地しかありません.ポインタは番地を入れる変数 (メモリやレジスタ)

そんなこんなで,もともとアセンブリに由来する C は同じことを表現する方法が非常にたくさんあることで有名ですが,似ているようで違うものもたくさんあります.それが諸悪の根源ですね.

C99 で複合リテラルが入ったので,さらに変態的な書き方がいろいろ可能になってます.

どれが同じ意味で,どれが違うのか,全部ちゃんとわかってますか ?


#include <stdio.h>

int main() {

  char a[] = "abcdefghi";
  puts(a);
  printf("%d\n", sizeof(a));
  putchar(a[1]);
  putchar('\n');
  putchar(*(a + 1));
  putchar('\n');
  putchar(1[a]);
  putchar('\n');
  a[1] = 'z';
  puts(a);
  // a++;         ******* error: lvalue required as increment operand ******
  // puts(a);
  
  char *p1 = (char[]){'a','b','c','d','e','f','g','h','i','\0'};
  puts(p1);
  printf("%d\n", sizeof(p1));
  p1[1] = 'z';
  puts(p1);
  p1++;
  puts(p1);
  
  char *p2 = (char[]){"abcdefghi"};
  puts(p2);
  printf("%d\n", sizeof(p2));
  p2[1] = 'z';
  puts(p2);
  p2++;
  puts(p2);

  char* const p3 = (char[]){'a','b','c','d','e','f','g','h','i','\0'};
  puts(p3);
  printf("%d\n", sizeof(p3));
  p3[1] = 'z';
  puts(p3);
  // p3++;        ****** error: increment of read-only variable 'p3' ******
  // puts(p3);
  
  const char* p4 = (char[]){'a','b','c','d','e','f','g','h','i','\0'};
  puts(p4);
  printf("%d\n", sizeof(p4));
  // p4[1] = 'z'; ****** error: assignment of read-only location ******
  // puts(p4);
  p4++;
  puts(p4);

  char *p5 = "abcdefghi";
  puts(p5);
  printf("%d\n", sizeof(p5));
  // p5[1] = 'z'; ******  セグメンテーション違反です ******
  // puts(p5);
  p5++;
  puts(p5);

  const char* const p6 = (char[]){'a','b','c','d','e','f','g','h','i','\0'};
  puts(p6);
  printf("%d\n", sizeof(p6));
  // p6[1] = 'z'; ****** error: assignment of read-only location ******
  // puts(p6);
  // p6++;        ****** error: increment of read-only variable 'p6' ******
  // puts(p6);
  
  const char p7[] = "abcdefghi";
  puts(p7);
  printf("%d\n", sizeof(p7));
  // p7[1] = 'z'; ****** error: assignment of read-only location ******
  // puts(p7);
  // p7++;        ****** error: lvalue required as increment operand ******
  // puts(p7);

  /* error: initializer element is not constant */
  // static const char* p8 = (char[]){'a','b','c','d','e','f','g','h','i','\0'};

  char (*p9)[10] = (char (*) [10])&"0123456789abcdefghi";
  puts(*p9);
  printf("%d\n", sizeof(*p9));
  p9++; // 10 バイト進む
  puts(*p9);

  return 0;
}


最後の例の意味がちゃんとわかれば,ポインタを理解できていると思って良いかもしれません.

配列の要素アクセス a[10] は *(a + 10) のシンタックスシュガーだから,*(10 + a) と同じ,すなわち 10[a] と書いても同じ意味,とかはわりと有名な話ですが.a に 10 を足したとき,アドレスがいくつ進むのか ? とかが,a の型の大きさによって決まるのです.

要するに sizeof(*a) ぶん増えます.char だったら 1 (バイト),4 バイト整数だったら 4, 文字の要素数10の配列型 (sizeof は 10) だったら,10 増えます.

追記

同じ意味でも,最適化が絡んでくるとびみょーに違ったりする場合もあります.

参考 : const char* const p = "ABC"; と const char q[] = "ABC"; はどちらがよいか、みたいな与太
C 言語/コンパイラ/BinaryHacksTB:0CM:0 このエントリーを含むはてなブックマーク | livedoorクリップ livedoorクリップ BuzzurlにブックマークBuzzurlにブックマーク newsing it!

stack overflow

2007/12/02(日) 03:07:20

たった 2 KB で溢れちゃうの ? と思ったら,組込み環境の話だったのか.

日記を書く[・ _ゝ・]はやみずさん2007-11-27 ■ double x[1024];

そういえば昔,オート変数で 10 万要素ぐらいの配列を宣言して SEGV ってて困ってた人がいたなぁ.GA とか NN とかでゲノム解析のアルゴリズム研究とかやってる人は,もともとが生物屋とかで,そんなに計算機に詳しくなかったりすることが多い.そして,最初は Perl とかで書いてるんだけど,だんだん速度が足りなくなってきて C で書き直したりするケースはよくあることのように思う.同じアルゴリズムだから,たかだか定数倍の速度差とはいえ,30 時間かかる計算が 10 時間になったら非常にうれしい.そして,小さい問題ではちゃんと動いたから,いざ同じプログラムのデータの大きさの部分だけ変更して実行すると,とたんにうまく動かなくなって嵌まったりする.

ちなみに,一般的な Linux 環境の Stack Size リミットは 8 MB らしい.

$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
max nice (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) unlimited
max rt priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

テキトーに,こういうコードを gcc でコンパイルして実行すると.


main() {
double a[1024 * 1024];
a[0] = 1.2345;
}


SEGV る.らめぇぇぇ溢れちゃうぅう

$ gcc maxstack.c ; ./a.out
セグメンテーション違反です

root になって,ulimit で stack size を拡張すれば,どんなに大きくても大丈夫 (適当に倍の16 MBぐらいに)

# su
# ulimit -s 16000
# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
max nice (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) unlimited
max rt priority (-r) 0
stack size (kbytes, -s) 16000
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
# gcc maxstack.c ; ./a.out

たぶん (あまり自信は無いので,有識者の反応を期待) stack size を unlimited にすれば,とりあえずは HDD (仮想記憶) を喰い尽くすまでは計算ができるのではないだろうか (ユーザのディスク使用量に制限が無い限り).

そうなれば,スタックとヒープを区別する必要は無くなるので,「再帰的関数定義はスタックオーバーフローの怖れがあって,セキュリティ的にまずいからあまり使わない方が良い」 というような,スクリプト言語使いが良く言うような C を dis る発言はナンセンスなものとなる.とはいえ,うっかり無限再帰になるようなプログラムを走らせると,ディスクが喰い尽くされてもっとえらいことになるけど.スクリプト言語なら,GC が途中で走り初めて,どうしようも無くなったら OutOfMemory ナンチャラとかが投げられて強制終了してくれると思う.いや,仮想記憶がある限り,メモリは (最近のディスクの大容量化を考えると) 永遠に尽きないからそれは無いのかな ? なんらかの上限はありそうだけど.malloc が失敗するとか,コンストラクタが OutOfMemory 吐くとかって,近代 OS では本当にあるのかなぁ… 結局,GC ってのも,効率化のための一手段に過ぎないわけだ.近代の実行環境では,メモリは無限にあると考えて問題ない.ただし,仮想記憶が動くと劇的に遅くなりますよ,というだけの話.

ガーベッジコレクション (なるべく遅すぎるディスクに触らないで,メモリの上だけでなんとかする) ってのは,レジスタアロケーション (なるべく遅い主メモリに触らないで,レジスタの上だけでなんとかしようとする) とか,キャッシュメモリの最適化 (なるべく遅い主メモリに触らないで,比較的早いキャッシュの上だけでなんとかする) とかと,本質的には変わりない,最適化の一手段に過ぎない.ある意味では,重要なのは速度だけとも言える.遅くても良い (無限に高速なメモリがある状況) ならば,C でもスクリプト言語でも,なんでも開発効率は変わらない.速度をあげるために,手動で最適化をしないといけないから,C とかは面倒,というだけの話.そこを履き違えて,「C はスタックが溢れたりして危険だし,GC も無い開発効率が悪い言語.○○言語サイコー」,とかいう言及は,本質が見えてないと思ったりするのであった.
C 言語/コンパイラ/BinaryHacksTB:0CM:2 このエントリーを含むはてなブックマーク | livedoorクリップ livedoorクリップ BuzzurlにブックマークBuzzurlにブックマーク newsing it!

Optimizing direct threaded code by selective inlining

2007/11/21(水) 14:43:31

東大さんで今,mini-python のインタプリタを作るという演習をやっているそうな.

んで,今 twitter の柱の hayamizu 氏を筆頭に,空前の VM (仮想マシン) ブームが起きている感じ.

ちなみに,仮想マシンの本で僕が読んで良かったのは,Java 仮想マシン仕様の第二版と,コンパイラとバーチャルマシンって本かなぁ (そんなに詳しくない).

ところで,仮想マシンの構造ってのは,ナイーブには単純で,ひたすら switch 文で命令を引いて実行するだけ

なので,switch 文をテーブルに展開して,直接命令のコードの場所に goto したりする最適化が非常に効く.というのがこの論文.

Optimizing direct threaded code by selective inlining (PDF)

# 追記 : あ,ACM ポータルの論文は,北大ドメインからじゃないとダウンロードできないのか… いつも普通に落としてたので,気がつかなかった.

毎朝 5 時から朝 hack しているらしい hayamizu 氏も,GCC が switch をジャンプに展開するのを期待していたようですが,僕が寝ている間にいろいろ一悶着あったみたいです (twitter のログをテキトーに加工して tac で逆順にしたもの).GCC の最適化はそんなにがんばってないので有名ですが,馬鹿の子呼ばわりはひどい!

hayamizu switchのアセンブリコードをみて驚いているところ
yuki_neko_nyan あ、素人な私はswitchのasmすら知らない
hayamizu 驚いたというより, こうするしかないのかぁ, と思った.
yuki_neko_nyan いまの作業が済んだら見てみる。
natsutan 上手くジャンプのテーブル乗ってますか? > switch文
hayamizu switch分は cmpl, je, cmpl, je, cmpl, je, cmpl, je, cmpl, je, ....
yuki_neko_nyan テーブル表現がどうなるのかを知らないのじゃよぉ。いや、本当にテー ブルつくってlogic計算なのかな、とか ...
natsutan caseが、 0,1,2,3,4とか、等差数列になっていれば、テーブルで一発飛んでく れますよ。
hayamizu なるほど。0, 1, 100 でやってみたところです。enumでやってみよう。
yuki_neko_nyan gcc compiler hack入門編[Switch]ただいま開催中
yuki_neko_nyan でもcmpl,jmpだとifと全然かわらない気がする
hayamizu あれ、enumでも cmpl, jp, cmpl, jp, cmpl, jp, cmpl, jp になるぞ。もしか してgccってバカの子なんじゃ、、、
yuki_neko_nyan -O2とかは効く?
natsutan -mno-tablejump があるくらいなので、テーブルにしてくれそうなのですが、条件がたりないのかな。
natsutan @hayamizu 最適化おぷしょんが入ってないとか
yuki_neko_nyan つけないと最適化しないとするなら、私の常識が崩壊か。
hayamizu 0, 1, 2, 3 とそのまま書いても cmpl, je, cmpl, je (°∀°) cmpl, je, cmpl, je
hayamizu jpってなんだよjpって。
hayamizu なるほど、 最適化オプション
natsutan @alohakunの光臨を待つか・・
hayamizu 最適化オプションをつけると、 -O2からコードの形はかわるものの、 cmplが1 回減ったくらいでテーブルを作っている気配がない。
yuki_neko_nyan -O2してもcmpl jeだねぇ
yuki_neko_nyan なぞ。というか騙されてきたのでなければ、どういう条件でよばれるの だろうか
natsutan @hayamizu default:ラベルを抜いてみるとか
natsutan @hayamizu 今、長門プロンプト立ち上げた。長門に聞いてみる
hayamizu .@natsutanの長門キター / ちなみにdefaultは書いてないです
yuki_neko_nyan 長門キターー。彼女ならなんとかしてくれる。というかなんでもしてく れる
yuki_neko_nyan わたしはdefaultを書いた組でしたが同じだたーよ
yuki_neko_nyan 朝からgcc -Sまつり
natsutan できたよ
natsutan natsutan http://homepage3.nifty.com/~Natsutan/tmp/t.c
YUKI.N>gcc -c -O3 -S t.c でこれ。http://homepage3.nifty.com/~Natsutan/tmp/t.s
yuki_neko_nyan ひょっとしてcaseの数によって最適化がちがう??
hayamizu うおお、見事に最適化されているっぽい。
natsutan 2のべきじょうじゃないと、テーブルがややこしくなる。
hayamizu それだ! > caseの数
hayamizu おー最適化された。caseの数がすくないとそのままなのか。
yuki_neko_nyan とりあえずcaseを8個にしたら手元のでもTableになった
yuki_neko_nyan -Oつけなくてもtableになりそう
yuki_neko_nyan defaultありcaseが5つ最適化なしでtableになった
hayamizu 今Gaucheのvm.o を逆アセンブルしてcmplの数を数えたら、メインループの鬼のようなcase祭り(case 183個)もcmplが28個しかなかった。 ...
yuki_neko_nyan うひゃ、それすげーvm.c
hayamizu お騒がせしました。おかげさまで飯田橋6時半着なのに授業に遅刻できそうです(・∀・) 朝ハックはたのしい。 ...
yuki_neko_nyan caseが4まではtableにならない。jmp2回ってのがコストになるのかな
@hayamizu @natsutan 凄い勉強になった。感謝
yuki_neko_nyan 早起きするといいことあるねぇ〜
yuki_neko_nyan defaultラベルの存在は関係なさそう。純粋にcaseが5つ以上で最適化 。
natsutan 全ては長門のおかげです
hayamizu 授業にまにあったのも長門のおかげ。感謝感謝
hayamizu しかし、テーブルを作るならgaucheのvm.cはもっと効率よく最適化されそうな 気もする
yuki_neko_nyan caseのnestもあるし、fall throughもあるからvm.cは意外とすごいこと になってる。
yuki_neko_nyan gccの最適化に@hayamizuがその名を刻むのはこれからしばらくたって のことであった。

gcc の optimizer のどこで最適化されてるのかってのは,また後で (光臨しても結局役たたずの alohakun)

linux kernel とか device driver が,default 文を一番上に書く書き方をしてるのって,もしかしてここらへん関係なのかな ? 今は default あっても関係無いみたいだけど,昔の gcc では意味があったとか,古い gcc に対する対策とかの慣習なのかもしれないし.関数の引数を fast call するために 3 つ以内にするとかと同様に,switch の case 文の数まで考えてコードが書かれているのかもしれない.gcc が吐くコードを見ながら,kernel のコードの書き方を修正しているような GNU の変態どもなら有り得る.ハードウェア/コンパイラ/オペレーティングシステムは三位一体で,お互いがお互いにフィードバックをあたえる MAGI SYSTEM.全部知らないと理由がわからないことが多く,奥が深い世界である.




追記

masa_edw 丁度落ちてる時間に発言して更新されてないぽいな
masa_edw もう一度→gaucheのvm.cはgccの場合labels as valueを使ったgotoに展開されるということを見落としてない?
hayamizu @masa_edw dispatch_tableってやつ?
hayamizu @masa_edw なるほど. GCCじゃないとただのswitchになるのか.
hayamizu わざわざSWITCHとCASEのマクロがあるのはこのせいだったのか

本筋とは関係無いけど,これが論文や記事でも触れられていた,移植性と可搬性のトレードオフの例ですな.

他にも,例えば関数論理型言語マーキュリーのコンパイラが生成するCコードは,gcc の場合は labels as values 使った threaded code に展開されて,それ以外のCコンパイラの場合は普通のCコードに展開されるようなコードを,ifdef 使って吐いている.




natsutan さんにせっかく光臨を期待されたので,論文書きつつ必死で gcc のコード追ってたのに,先に書かれてしまいましたよ \(^o^)/

はじめてのにき 2007-11-21 _ switchの展開

素晴らしすぎて全俺が泣いた.natsutan さんは,これからは shinh さんの光臨を期待した方が良いと思います.わいはいらんこやなぁ.

あと,このネタはよくまとまってますし,表に書かれた方が良いのではないですかね.とか.いや,兼雑記見てる人のほとんどはにきもも見てるとは思いますけど.
C 言語/コンパイラ/BinaryHacksTB:1CM:8 このエントリーを含むはてなブックマーク | livedoorクリップ livedoorクリップ BuzzurlにブックマークBuzzurlにブックマーク newsing it!

最近のコメント

リンク

このブログをリンクに追加する

最近のトラックバック

人生の残り日数

日本人男性の平均寿命は 28700日.

RSSフィード

カテゴリー