[インデックス 12085] ファイルの概要
このコミットは、Goコンパイラのバックエンド(5g, 6g, 8g)におけるグローバル変数の扱いに関する重要な修正を導入しています。具体的には、グローバル変数がレジスタにキャッシュされた後に変更された場合の一貫性を保証するための変更です。
コミット
commit 8998835543c0055b66c034fbca53d7c294f3956e
Author: Russ Cox <rsc@golang.org>
Date: Mon Feb 20 13:41:44 2012 -0500
5g, 6g, 8g: flush modified globals aggressively
The alternative is to record enough information that the
trap handler know which registers contain cached globals
and can flush the registers back to their original locations.
That's significantly more work.
This only affects globals that have been written to.
Code that reads from a global should continue to registerize
as well as before.
Fixes #1304.
R=ken2
CC=golang-dev
https://golang.org/cl/5687046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8998835543c0055b66c034fbca53d7c294f3956e
元コミット内容
このコミットの目的は、Goコンパイラのバックエンドである5g
(ARM), 6g
(x86-64), 8g
(x86) において、変更されたグローバル変数を積極的にメモリにフラッシュすることです。
コミットメッセージによると、この変更の背景には、グローバル変数がCPUレジスタにキャッシュされた状態で変更された際に発生する可能性のある問題があります。本来であれば、トラップハンドラがどのレジスタにキャッシュされたグローバル変数が含まれているかを認識し、それらを元のメモリ位置にフラッシュするような、より複雑なメカニズムを実装することも考えられます。しかし、それは「著しく多くの作業」を伴うため、このコミットではよりシンプルなアプローチ、すなわち「積極的にフラッシュする」方法が採用されました。
この修正は、書き込みが行われたグローバル変数にのみ影響します。グローバル変数からの読み取りを行うコードは、以前と同様にレジスタ化(registerize
)され続けるべきであり、その最適化は維持されます。
このコミットは、GoのIssue #1304を修正するために行われました。
変更の背景
この変更の背景には、コンパイラ最適化と実行時の一貫性のバランスという、低レベルプログラミングにおける一般的な課題があります。
Goコンパイラは、パフォーマンス向上のために、頻繁にアクセスされる変数をCPUのレジスタにキャッシュする「レジスタ割り当て(register allocation)」という最適化を行います。これは、メモリへのアクセスよりもレジスタへのアクセスの方がはるかに高速であるため、プログラムの実行速度を大幅に向上させることができます。
しかし、グローバル変数の場合、複数のゴルーチン(Goの軽量スレッド)や、あるいはシグナルハンドラのような非同期イベントによって、その値が予期せず変更される可能性があります。もしグローバル変数の値がレジスタにキャッシュされている間にメモリ上の値が変更された場合、レジスタ内の古い値が使用され続けることで、プログラムの動作に不整合が生じる可能性があります。
Issue #1304は、まさにこの問題、すなわちグローバル変数がレジスタにキャッシュされている状態で、その変数が変更された場合に、その変更が即座に反映されないというバグを報告していたと考えられます。特に、Goのランタイムやガベージコレクタのような低レベルのコードでは、グローバル変数の値の一貫性が極めて重要になります。
このコミットは、より複雑なレジスタ追跡メカニズムを実装する代わりに、変更されたグローバル変数を各命令の前に強制的にメモリにフラッシュするという、より保守的で安全なアプローチを選択しました。これにより、レジスタとメモリ間の不整合を防ぎ、プログラムの正確性を保証します。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念を理解しておく必要があります。
-
コンパイラバックエンド (5g, 6g, 8g):
- Goコンパイラは、ソースコードを機械語に変換する過程で、複数のステージを経ます。バックエンドは、中間表現を特定のCPUアーキテクチャ(例: ARM, x86, x86-64)の機械語に変換する部分を担当します。
5g
はARMアーキテクチャ向け、6g
はx86-64アーキテクチャ向け、8g
はx86アーキテクチャ向けのGoコンパイラバックエンドを指します。これらのバックエンドは、それぞれ異なる命令セットとレジスタセットを持つCPUに対応しています。
-
グローバル変数:
- プログラム全体からアクセス可能な変数です。通常、プログラムのデータセグメントに格納されます。
- 複数の関数やゴルーチンから読み書きされる可能性があるため、その値の一貫性を保つことが重要です。
-
CPUレジスタ:
- CPU内部にある高速な記憶領域です。CPUは、メモリからデータを読み書きするよりも、レジスタからデータを読み書きする方がはるかに高速です。
- コンパイラは、プログラムの実行速度を向上させるために、頻繁にアクセスされる変数の値をレジスタに一時的に格納(キャッシュ)します。これを「レジスタ割り当て(register allocation)」または「レジスタ化(registerize)」と呼びます。
-
トラップハンドラ (Trap Handler):
- CPUが特定の例外(トラップ)を検出したときに実行される特別なコードです。
- 例えば、ページフォルト、ゼロ除算、不正な命令などがトラップを引き起こします。
- この文脈では、グローバル変数の値がレジスタとメモリで不整合になった場合に、それを検知して修正するようなメカニズムを指している可能性があります。しかし、コミットメッセージでは、そのような複雑なトラップハンドラの実装は「著しく多くの作業」であると述べられています。
-
積極的なフラッシュ (Aggressive Flushing):
- レジスタにキャッシュされた変数の値を、頻繁に(この場合は各命令の前に)対応するメモリ位置に書き戻す(フラッシュする)ことです。
- これにより、レジスタとメモリ間のデータの一貫性が保証されますが、レジスタの高速性を十分に活用できないため、パフォーマンスにわずかな影響を与える可能性があります。しかし、正確性を優先する場合には有効な戦略です。
-
Issue #1304:
- Goプロジェクトのバグトラッカーで報告された特定のバグを指します。コミットメッセージに「Fixes #1304」とある場合、このコミットがそのバグを修正したことを意味します。
- このバグは、グローバル変数のレジスタキャッシュとメモリの一貫性に関する問題であったと推測されます。
技術的詳細
このコミットの技術的詳細は、Goコンパイラのレジスタ割り当てとデータフロー解析の内部に深く関わっています。
Goコンパイラのバックエンド(5g
, 6g
, 8g
)は、コード生成の過程で、変数がどのレジスタに割り当てられるか、そしてそのレジスタの値がいつメモリに書き戻されるかを決定します。このプロセスは、reg.c
ファイル群で定義されているレジスタ割り当てアルゴリズムによって制御されます。
コミットメッセージにある「prop
」関数は、おそらくレジスタのプロパゲーション(伝播)またはデータフロー解析の一部であり、レジスタの状態(どの変数がどのレジスタにあるか、レジスタの値が有効かなど)を追跡する役割を担っています。
変更点を見ると、prop
関数内のswitch
文のdefault
ケースに新しいコードが追加されています。これは、特定の最適化パスや命令の種類に特化しない、一般的なケース(おそらくすべての命令の処理前)に適用されるロジックであることを示唆しています。
追加されたコードは以下の通りです。
// Work around for issue 1304:
// flush modified globals before each instruction.
for(z=0; z<BITS; z++)
cal.b[z] |= externs.b[z];
ここで重要なのは以下の点です。
externs.b[z]
:これは、グローバル変数(外部変数)のビットマップであると推測されます。BITS
はビットマップのサイズを示し、z
はそのインデックスです。このビットマップは、どのグローバル変数が存在するか、あるいはどのグローバル変数が変更されたかを示すために使用される可能性があります。cal.b[z] |= externs.b[z]
:cal
はおそらく「call-clobbered」レジスタ、または「caller-saved」レジスタ、あるいは単に「callee-saved」レジスタに関連するビットマップである可能性があります。しかし、この文脈では、cal
が「callee-saved」レジスタのビットマップであると仮定すると、cal.b[z] |= externs.b[z]
は、グローバル変数がレジスタにキャッシュされている場合、そのレジスタを「汚染された(dirty)」状態としてマークし、次の命令の実行前にメモリにフラッシュする必要があることをコンパイラに指示していると考えられます。- コメント「
flush modified globals before each instruction.
」:このコメントが示すように、このコードは、変更されたグローバル変数を各命令の実行前にメモリにフラッシュするメカニズムを実装しています。これは、レジスタにキャッシュされたグローバル変数の値が、メモリ上の最新の値と常に同期されるようにするための「積極的なフラッシュ」戦略です。
このアプローチは、レジスタ割り当ての複雑さを増すことなく、グローバル変数のデータ一貫性問題を解決するための実用的なワークアラウンドです。パフォーマンスへの影響は最小限に抑えつつ、正確性を保証します。
コアとなるコードの変更箇所
変更は、Goコンパイラのバックエンドであるsrc/cmd/5g/reg.c
, src/cmd/6g/reg.c
, src/cmd/8g/reg.c
の3つのファイルにわたって行われています。これらのファイルは、それぞれARM, x86-64, x86アーキテクチャ向けのレジスタ割り当てとコード生成ロジックを含んでいます。
各ファイルにおいて、prop
関数内のswitch
文のdefault
ケースに以下の7行が追加されています。
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -1029,6 +1029,13 @@ prop(Reg *r, Bits ref, Bits cal)
break;
+
+ default:
+ // Work around for issue 1304:
+ // flush modified globals before each instruction.
+ for(z=0; z<BITS; z++)
+ cal.b[z] |= externs.b[z];
+ break;
}
for(z=0; z<BITS; z++) {
ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
この変更は、3つのアーキテクチャすべてに共通して適用されており、グローバル変数の扱いに関する一般的な問題に対する修正であることを示しています。
コアとなるコードの解説
追加されたコードは、prop
関数内で、特定の命令タイプに特化しない一般的な処理パス(default
ケース)において実行されます。
// Work around for issue 1304:
// flush modified globals before each instruction.
for(z=0; z<BITS; z++)
cal.b[z] |= externs.b[z];
// Work around for issue 1304:
: このコメントは、これがIssue #1304に対する修正であることを明確に示しています。// flush modified globals before each instruction.
: このコメントは、このコードの主要な目的を説明しています。すなわち、変更されたグローバル変数を各命令の実行前にメモリにフラッシュすることです。for(z=0; z<BITS; z++)
: このループは、BITS
で定義されたサイズのビットマップをイテレートします。BITS
は、レジスタセットやグローバル変数の状態をビット単位で表現するために使用されるビットマップのワード数またはサイズであると考えられます。cal.b[z] |= externs.b[z];
:externs.b[z]
:これは、現在レジスタにキャッシュされている可能性のあるグローバル変数、または変更されたグローバル変数を示すビットマップの一部です。cal.b[z]
:これは、レジスタの状態を追跡する別のビットマップの一部です。このビットマップは、特定のレジスタが「汚染されている」(つまり、メモリに書き戻す必要がある)ことを示すために使用される可能性があります。|=
(ビット単位OR代入):この演算子は、externs.b[z]
のビットをcal.b[z]
に設定します。これにより、externs
ビットマップで示されるグローバル変数が、cal
ビットマップで「フラッシュが必要」とマークされます。
このコードの論理的な流れは以下のようになります。
- コンパイラが命令を処理する際、
prop
関数が呼び出されます。 prop
関数内のswitch
文のdefault
ケースに到達します。これは、特定の最適化ルールが適用されない一般的な命令に対して発生します。- ループが
externs
ビットマップを走査し、レジスタにキャッシュされている可能性のあるグローバル変数(または変更されたグローバル変数)を特定します。 - 特定されたグローバル変数に対応するビットが
cal
ビットマップに設定されます。これにより、これらのグローバル変数が「汚染された」状態としてマークされ、次の命令の実行前にメモリにフラッシュされるべきであることがコンパイラに伝えられます。
この「積極的なフラッシュ」戦略は、レジスタとメモリ間のデータ一貫性を保証するためのシンプルかつ効果的な方法であり、特にマルチスレッド環境や非同期イベントが存在するシステムにおいて、グローバル変数の正確な動作を維持するために重要です。
関連リンク
- Go Issue #1304: https://github.com/golang/go/issues/1304 (このコミットが修正したバグの報告)
- Go CL 5687046: https://golang.org/cl/5687046 (このコミットに対応するGerritの変更リスト)
参考にした情報源リンク
- Goコンパイラのソースコード (特に
src/cmd/5g/reg.c
,src/cmd/6g/reg.c
,src/cmd/8g/reg.c
) - Go Issue Tracker (Issue #1304の議論)
- コンパイラ設計に関する一般的な知識(レジスタ割り当て、データフロー解析、グローバル変数の扱い)
- CPUアーキテクチャに関する一般的な知識(ARM, x86, x86-64のレジスタとメモリモデル)
[インデックス 12085] ファイルの概要
このコミットは、Goコンパイラのバックエンド(5g, 6g, 8g)におけるグローバル変数の扱いに関する重要な修正を導入しています。具体的には、グローバル変数がレジスタにキャッシュされた後に変更された場合の一貫性を保証するための変更です。
コミット
commit 8998835543c0055b66c034fbca53d7c294f3956e
Author: Russ Cox <rsc@golang.org>
Date: Mon Feb 20 13:41:44 2012 -0500
5g, 6g, 8g: flush modified globals aggressively
The alternative is to record enough information that the
trap handler know which registers contain cached globals
and can flush the registers back to their original locations.
That's significantly more work.
This only affects globals that have been written to.
Code that reads from a global should continue to registerize
as well as before.
Fixes #1304.
R=ken2
CC=golang-dev
https://golang.org/cl/5687046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8998835543c0055b66c034fbca53d7c294f3956e
元コミット内容
このコミットの目的は、Goコンパイラのバックエンドである5g
(ARM), 6g
(x86-64), 8g
(x86) において、変更されたグローバル変数を積極的にメモリにフラッシュすることです。
コミットメッセージによると、この変更の背景には、グローバル変数がCPUレジスタにキャッシュされた状態で変更された際に発生する可能性のある問題があります。本来であれば、トラップハンドラがどのレジスタにキャッシュされたグローバル変数が含まれているかを認識し、それらを元のメモリ位置にフラッシュするような、より複雑なメカニズムを実装することも考えられます。しかし、それは「著しく多くの作業」を伴うため、このコミットではよりシンプルなアプローチ、すなわち「積極的にフラッシュする」方法が採用されました。
この修正は、書き込みが行われたグローバル変数にのみ影響します。グローバル変数からの読み取りを行うコードは、以前と同様にレジスタ化(registerize
)され続けるべきであり、その最適化は維持されます。
このコミットは、GoのIssue #1304を修正するために行われました。
変更の背景
この変更の背景には、コンパイラ最適化と実行時の一貫性のバランスという、低レベルプログラミングにおける一般的な課題があります。
Goコンパイラは、パフォーマンス向上のために、頻繁にアクセスされる変数をCPUのレジスタにキャッシュする「レジスタ割り当て(register allocation)」という最適化を行います。これは、メモリへのアクセスよりもレジスタへのアクセスの方がはるかに高速であるため、プログラムの実行速度を大幅に向上させることができます。
しかし、グローバル変数の場合、複数のゴルーチン(Goの軽量スレッド)や、あるいはシグナルハンドラのような非同期イベントによって、その値が予期せず変更される可能性があります。もしグローバル変数の値がレジスタにキャッシュされている間にメモリ上の値が変更された場合、レジスタ内の古い値が使用され続けることで、プログラムの動作に不整合が生じる可能性があります。
Issue #1304は、まさにこの問題、すなわちグローバル変数がレジスタにキャッシュされている状態で、その変数が変更された場合に、その変更が即座に反映されないというバグを報告していたと考えられます。特に、Goのランタイムやガベージコレクタのような低レベルのコードでは、グローバル変数の値の一貫性が極めて重要になります。
このコミットは、より複雑なレジスタ追跡メカニズムを実装する代わりに、変更されたグローバル変数を各命令の前に強制的にメモリにフラッシュするという、より保守的で安全なアプローチを選択しました。これにより、レジスタとメモリ間の不整合を防ぎ、プログラムの正確性を保証します。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念を理解しておく必要があります。
-
コンパイラバックエンド (5g, 6g, 8g):
- Goコンパイラは、ソースコードを機械語に変換する過程で、複数のステージを経ます。バックエンドは、中間表現を特定のCPUアーキテクチャ(例: ARM, x86, x86-64)の機械語に変換する部分を担当します。
5g
はARMアーキテクチャ向け、6g
はx86-64アーキテクチャ向け、8g
はx86アーキテクチャ向けのGoコンパイラバックエンドを指します。これらのバックエンドは、それぞれ異なる命令セットとレジスタセットを持つCPUに対応しています。
-
グローバル変数:
- プログラム全体からアクセス可能な変数です。通常、プログラムのデータセグメントに格納されます。
- 複数の関数やゴルーチンから読み書きされる可能性があるため、その値の一貫性を保つことが重要です。
-
CPUレジスタ:
- CPU内部にある高速な記憶領域です。CPUは、メモリからデータを読み書きするよりも、レジスタからデータを読み書きする方がはるかに高速です。
- コンパイラは、プログラムの実行速度を向上させるために、頻繁にアクセスされる変数の値をレジスタに一時的に格納(キャッシュ)します。これを「レジスタ割り当て(register allocation)」または「レジスタ化(registerize)」と呼びます。
-
トラップハンドラ (Trap Handler):
- CPUが特定の例外(トラップ)を検出したときに実行される特別なコードです。
- 例えば、ページフォルト、ゼロ除算、不正な命令などがトラップを引き起こします。
- この文脈では、グローバル変数の値がレジスタとメモリで不整合になった場合に、それを検知して修正するようなメカニズムを指している可能性があります。しかし、コミットメッセージでは、そのような複雑なトラップハンドラの実装は「著しく多くの作業」であると述べられています。
-
積極的なフラッシュ (Aggressive Flushing):
- レジスタにキャッシュされた変数の値を、頻繁に(この場合は各命令の前に)対応するメモリ位置に書き戻す(フラッシュする)ことです。
- これにより、レジスタとメモリ間のデータの一貫性が保証されますが、レジスタの高速性を十分に活用できないため、パフォーマンスにわずかな影響を与える可能性があります。しかし、正確性を優先する場合には有効な戦略です。
-
Issue #1304:
- Goプロジェクトのバグトラッカーで報告された特定のバグを指します。コミットメッセージに「Fixes #1304」とある場合、このコミットがそのバグを修正したことを意味します。
- このバグは、グローバル変数のレジスタキャッシュとメモリの一貫性に関する問題であったと推測されます。
技術的詳細
このコミットの技術的詳細は、Goコンパイラのレジスタ割り当てとデータフロー解析の内部に深く関わっています。
Goコンパイラのバックエンド(5g
, 6g
, 8g
)は、コード生成の過程で、変数がどのレジスタに割り当てられるか、そしてそのレジスタの値がいつメモリに書き戻されるかを決定します。このプロセスは、reg.c
ファイル群で定義されているレジスタ割り当てアルゴリズムによって制御されます。
コミットメッセージにある「prop
」関数は、おそらくレジスタのプロパゲーション(伝播)またはデータフロー解析の一部であり、レジスタの状態(どの変数がどのレジスタにあるか、レジスタの値が有効かなど)を追跡する役割を担っています。
変更点を見ると、prop
関数内のswitch
文のdefault
ケースに新しいコードが追加されています。これは、特定の最適化パスや命令の種類に特化しない、一般的なケース(おそらくすべての命令の処理前)に適用されるロジックであることを示唆しています。
追加されたコードは以下の通りです。
// Work around for issue 1304:
// flush modified globals before each instruction.
for(z=0; z<BITS; z++)
cal.b[z] |= externs.b[z];
ここで重要なのは以下の点です。
externs.b[z]
:これは、グローバル変数(外部変数)のビットマップであると推測されます。BITS
はビットマップのサイズを示し、z
はそのインデックスです。このビットマップは、どのグローバル変数が存在するか、あるいはどのグローバル変数が変更されたかを示すために使用される可能性があります。cal.b[z] |= externs.b[z]
:cal
はおそらく「call-clobbered」レジスタ、または「caller-saved」レジスタ、あるいは単に「callee-saved」レジスタに関連するビットマップである可能性があります。しかし、この文脈では、cal
が「callee-saved」レジスタのビットマップであると仮定すると、cal.b[z] |= externs.b[z]
は、グローバル変数がレジスタにキャッシュされている場合、そのレジスタを「汚染された(dirty)」状態としてマークし、次の命令の実行前にメモリにフラッシュする必要があることをコンパイラに指示していると考えられます。- コメント「
flush modified globals before each instruction.
」:このコメントが示すように、このコードは、変更されたグローバル変数を各命令の実行前にメモリにフラッシュするメカニズムを実装しています。これは、レジスタにキャッシュされたグローバル変数の値が、メモリ上の最新の値と常に同期されるようにするための「積極的なフラッシュ」戦略です。
このアプローチは、レジスタ割り当ての複雑さを増すことなく、グローバル変数のデータ一貫性問題を解決するための実用的なワークアラウンドです。パフォーマンスへの影響は最小限に抑えつつ、正確性を保証します。
コアとなるコードの変更箇所
変更は、Goコンパイラのバックエンドであるsrc/cmd/5g/reg.c
, src/cmd/6g/reg.c
, src/cmd/8g/reg.c
の3つのファイルにわたって行われています。これらのファイルは、それぞれARM, x86-64, x86アーキテクチャ向けのレジスタ割り当てとコード生成ロジックを含んでいます。
各ファイルにおいて、prop
関数内のswitch
文のdefault
ケースに以下の7行が追加されています。
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -1029,6 +1029,13 @@ prop(Reg *r, Bits ref, Bits cal)
break;
+
+ default:
+ // Work around for issue 1304:
+ // flush modified globals before each instruction.
+ for(z=0; z<BITS; z++)
+ cal.b[z] |= externs.b[z];
+ break;
}
for(z=0; z<BITS; z++) {
ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
この変更は、3つのアーキテクチャすべてに共通して適用されており、グローバル変数の扱いに関する一般的な問題に対する修正であることを示しています。
コアとなるコードの解説
追加されたコードは、prop
関数内で、特定の命令タイプに特化しない一般的な処理パス(default
ケース)において実行されます。
// Work around for issue 1304:
// flush modified globals before each instruction.
for(z=0; z<BITS; z++)
cal.b[z] |= externs.b[z];
// Work around for issue 1304:
: このコメントは、これがIssue #1304に対する修正であることを明確に示しています。// flush modified globals before each instruction.
: このコメントは、このコードの主要な目的を説明しています。すなわち、変更されたグローバル変数を各命令の実行前にメモリにフラッシュすることです。for(z=0; z<BITS; z++)
: このループは、BITS
で定義されたサイズのビットマップをイテレートします。BITS
は、レジスタセットやグローバル変数の状態をビット単位で表現するために使用されるビットマップのワード数またはサイズであると考えられます。cal.b[z] |= externs.b[z];
:externs.b[z]
:これは、現在レジスタにキャッシュされている可能性のあるグローバル変数、または変更されたグローバル変数を示すビットマップの一部です。cal.b[z]
:これは、レジスタの状態を追跡する別のビットマップの一部です。このビットマップは、特定のレジスタが「汚染されている」(つまり、メモリに書き戻す必要がある)ことを示すために使用される可能性があります。|=
(ビット単位OR代入):この演算子は、externs.b[z]
のビットをcal.b[z]
に設定します。これにより、externs
ビットマップで示されるグローバル変数が、cal
ビットマップで「フラッシュが必要」とマークされます。
このコードの論理的な流れは以下のようになります。
- コンパイラが命令を処理する際、
prop
関数が呼び出されます。 prop
関数内のswitch
文のdefault
ケースに到達します。これは、特定の最適化ルールが適用されない一般的な命令に対して発生します。- ループが
externs
ビットマップを走査し、レジスタにキャッシュされている可能性のあるグローバル変数(または変更されたグローバル変数)を特定します。 - 特定されたグローバル変数に対応するビットが
cal
ビットマップに設定されます。これにより、これらのグローバル変数が「汚染された」状態としてマークされ、次の命令の実行前にメモリにフラッシュされるべきであることがコンパイラに伝えられます。
この「積極的なフラッシュ」戦略は、レジスタとメモリ間のデータ一貫性を保証するためのシンプルかつ効果的な方法であり、特にマルチスレッド環境や非同期イベントが存在するシステムにおいて、グローバル変数の正確な動作を維持するために重要です。
関連リンク
- Go Issue #1304 (Gerrit Change List): https://golang.org/cl/5687046
- このGerrit Change Listのページには、関連するGo Issueへのリンクが含まれている場合があります。
参考にした情報源リンク
- Goコンパイラのソースコード (特に
src/cmd/5g/reg.c
,src/cmd/6g/reg.c
,src/cmd/8g/reg.c
) - Go Gerrit Code Review: https://golang.org/cl/5687046
- コンパイラ設計に関する一般的な知識(レジスタ割り当て、データフロー解析、グローバル変数の扱い)
- CPUアーキテクチャに関する一般的な知識(ARM, x86, x86-64のレジスタとメモリモデル)