もっと知りたい、Rubyのしくみ VMベースのインタプリタ型言語処理系であるRubyがコードをどのように解釈し、どうやって実行するか、そのしくみを解説。
Rubyについての基礎知識がなくても、図版と短いコードの実験を多用した構成により、そのしくみについて理解することができます。
実務でRubyは使えるけれど、基礎知識について自信がない人や、学びたくてもまとまった時間がとれずに悩んでいる人などもっとRubyを活用するためにRubyを知りたい人に最適。
Rubyインタプリタを題材にプログラミング言語処理系の仕組みを解説するNo Starch Press社の“Ruby Under a Microscope” の翻訳発行です。
日本語版には、Rubyの開発者であるまつもとゆきひろ氏の序文とYARVの開発者である笹田耕一氏の付録が加筆されています。
日本語版序文 序文 謝辞 はじめに 対象読者 検証にRubyを使う どのRuby処理系なの? 本書の構成 第1章 字句解析と構文解析 字句解析:Rubyを構成する言葉 parser_yylex 関数 実験1-1:Ripperを使ってさまざまなRubyスクリプトを字句解析する 構文解析:Rubyはコードをどのように理解するか LALR 構文解析アルゴリズムを理解する 実際のRubyの文法規則をいくつか Bisonの文法規則を読む 実験1-2:Ripperを使ってさまざまなRubyスクリプトを構文解析する まとめ 第2章 コンパイル Ruby 1.8 にコンパイラはない Ruby 1.9 以降はコンパイラを導入する 単純なスクリプトをRubyはどうコンパイルするか ブロック呼び出しのコンパイル RubyはAST の中をどう反復していくか 実験2-1:YARV 命令を表示する ローカルテーブル オプション引数のコンパイル キーワード引数のコンパイル 実験2-2:ローカルテーブルを表示する まとめ 第3章 Rubyはどのようにコードを実行するか YARVの内部スタックとRubyのコールスタック Rubyが単純なスクリプトをどう実行するかを見ていく ブロック呼び出しの実行 YARV命令を間近に見てみる 実験3-1:Ruby 2.0/Ruby 1.9 とRuby 1.8 のベンチマーク比較 Ruby変数のローカルアクセスと動的アクセス ローカル変数アクセス メソッド引数はローカル変数とみなされる 動的変数アクセス Cの世界でEPのはしごを上る 実験3-2:特殊変数を調査する 特殊変数リストの決定版 まとめ 第4章 制御構造とメソッドディスパッチ Rubyがどうやってif 文を実行するか あるスコープから別のスコープへジャンプする 捕捉テーブル 捕捉テーブルの別の利用方法 実験4-1:Rubyがループを内部でどう実装しているかをテストする send 命令:Rubyで最も複雑な制御構造 メソッド探索とメソッドディスパッチ 11種類のメソッドタイプ 通常のメソッド呼び出し 通常のメソッド向け引数の準備 組み込みメソッド呼び出し attr_readerとattr_writerの呼び出し attr_readerとattr_writerにおけるメソッドディスパッチの最適化 実験4-2:Rubyがキーワード引数をどう実装しているかの調査 まとめ 第5章 オブジェクトとクラス Rubyオブジェクトの内側 klassとivptrの調査 クラスの2つのインスタンスの可視化 一般的なオブジェクト 単純なRubyの値は構造体を全く必要としない 一般的なオブジェクトはインスタンス変数を持つか RBasic構造体とRObject構造体の定義を読む Rubyは一般的なオブジェクト用のインスタンス変数をどこに保存するか? 実験5-1:新しいインスタンス変数を保存するのにどれくらい時間がかかるか? RClass 構造体の内側は何 継承 クラスインスタンス変数vs. クラス変数 クラス変数の取得と設定 定数 実際のRClass構造体 RClass構造体の定義を読む 実験5-2:Rubyはクラスメソッドをどこに保存する? まとめ 第6章 メソッド探索と定数探索 Rubyがモジュールをどう実装しているか モジュールはクラスである クラスにモジュールをインクルードする Rubyのメソッド探索アルゴリズム メソッド探索の例 実際のメソッド探索アルゴリズム Rubyにおける多重継承 グローバルメソッドキャッシュ インラインメソッドキャッシュ Rubyのメソッドキャッシュをクリアする あるクラスに2つのモジュールをインクルードする あるモジュールを別のモジュールにインクルードする Module#prependの例 RubyがModule#prepend をどう実装しているか 実験6-1:インクルードした後でモジュールを変更する クラスはモジュールのメソッドを後で確認する クラスはインクルードされたサブモジュールを後では確認しない インクルードされたクラスは元のモジュールとメソッドテーブルを共有する Rubyがモジュールをどうコピーしているかを詳しく見る 定数探索 スーパークラス内の定数を見つける Rubyはどうやって親の名前空間内の定数を見つけるか? Rubyにおけるレキシカルスコープ 新しいクラスやモジュール用に定数を生成する レキシカルスコープを使って親の名前空間内の定数を見つける Rubyの定数探索アルゴリズム 実験6-2:Rubyはどの定数をはじめに見つけるのか? Rubyの実際の定数探索アルゴリズム まとめ 第7章 ハッシュテーブル:Ruby内部の働き者 Rubyにおけるハッシュテーブル ハッシュテーブルに値を保存する ハッシュテーブルから値を取り出す 実験7-1:さまざまなサイズのハッシュテーブルから値を取り出す ハッシュテーブルを拡張して、より多くの値を格納する仕組み ハッシュの衝突 エントリの再ハッシュ Rubyはハッシュテーブル内のエントリをどう再ハッシュするか? 実験7-2:さまざまなサイズのハッシュに新しい要素を1つ追加する マジックナンバー57と67はどこからくるのか Rubyはハッシュ関数をどう実装しているか 実験7-3:ハッシュのキーとしてオブジェクトを使用する Ruby 2.0におけるハッシュ最適化 まとめ 第8章 Lisp から借用したアイデア ブロック:Rubyにおけるクロージャ Rubyのブロック呼び出しを一歩ずつ確認する 1975 年から借用したアイデア rb_block_tとrb_control_frame_t構造体 実験8-1:whileループとeachにブロックを渡すのとどちらが速いか ラムダとProc:関数を第一級市民として扱う スタックvs. ヒープメモリ Rubyが文字列の値をどう保存するかを詳しく見る Rubyはラムダをどう作るか Rubyはラムダをどう呼び出すか Proc オブジェクト 実験8-2:ラムダを呼び出した後でローカル変数を変更する 同じスコープでラムダを1回以上呼び出す まとめ 第9章 メタプログラミング メソッドを定義する別のやり方 通常のメソッド定義処理 オブジェクトのプレフィックスを使ってクラスメソッドを定義する 新しいレキシカルスコープを使ってクラスメソッドを定義する 特異クラスを使ってメソッドを定義する レキシカルスコープ内の特異クラスを使ってメソッドを定義する Refinementsを作成する Refinementsを使用する 実験9-1:わたしは誰? レキシカルスコープを使うとselfはどう変わるか トップレベルスコープでのself クラススコープでのself メタクラススコープでのself クラスメソッドの内側でのself メタプログラミングとクロージャ:eval、instance_eval、binding コードを生成するコード bindingと共にevalを呼び出す instance_evalを使う例 Rubyのクロージャにおけるもう1つの重要な側面 instance_evalはself をレシーバに変更する instance_evalは新しいレキシカルスコープ用に特異クラスを作成する ブロック用のレキシカルスコープをRubyはどう監視し続けるか 実験9-2:メソッドを定義するためにクロージャを使う define_methodを使う メソッドはクロージャとして機能する まとめ 第10章 JRuby:JVM上のRuby MRIとJRubyでプログラムを実行する JRubyはコードをどうパースし、コンパイルするか JRubyはコードをどう実行するか RubyクラスをJavaクラスを使って実装する 実験10-1:JRubyのJITコンパイラを観察する 実験コード -J-XX:+PrintCompilationオプションの使用 JITはJRubyプログラムを高速化するか JRubyとMRI における文字列 JRubyとMRI は文字列データをどう保存するか コピー・オン・ライト 実験10-2:コピー・オン・ライトの性能を計測する ユニークで共有されていない文字列の生成 実験コード コピー・オン・ライトの視覚化 共有文字列を編集することは速度を落とす まとめ 第11章 Rubinius:Rubyで実装されたRuby Rubiniusカーネルと仮想マシン 字句解析と構文解析 Rubyを使ってRubyをコンパイルする Rubiniusバイトコード命令列 RubyとC++とで一緒に動く RubyのオブジェクトをC++オブジェクトで実装する 実験11-1:MRIとRubiniusのバックトレースの比較 Rubiniusのバックトレース RubiniusとMRIの配列 MRIの配列の内側 RArray構造体の定義 Rubiniusの配列の内側 実験11-2:RubiniusのArray#shiftの実装を調査する Array#shiftを読む Array#shiftを変更する まとめ 第12章 MRI・JRuby・RubiniusにおけるGC ガベージコレクションは3つの問題を解決する MRIにおけるガベージコレクション:マークスイープ フリーリスト MRIの複数のフリーリストの用途 マーク MRIは生きているオブジェクトをどうマークするか スイープ 遅延スイープ RVALUE構造体 マークスイープのデメリット 実験12-1:MRIのガベージコレクションを実際に見ていく MRIの遅延スイープの様子を見る MRIのフルGCを見る GCのプロファイリングレポートを翻訳する JRubyとRubiniusにおけるGC コピーGC バンプ・アロケーション 半空間アルゴリズム Edenヒープ 世代別GC 弱い世代別仮説 新世代オブジェクト用に半空間アルゴリズムを使う オブジェクトを昇格する 旧世代オブジェクト用のガベージコレクション 世代間の参照 並行GC オブジェクトグラフが変わっている間にもマークする 三色マーキング JVMにおける3つのGC 実験12-2:JRubyのVerbose GCモードを使う メジャーGCを始動する 参考文献 まとめ 付録A さらにそのほかのRuby仮想マシン YARV:Yet Another RubyVM YARVの設計方針 YARVの開発までの経緯 さらにそのほかのRuby仮想マシン 訳者あとがき 著者・訳者について
まだレビューがありません