[インデックス 17974] ファイルの概要
このコミットは、Go言語のテストスイートにおいて、gccgo
コンパイラに特有の大きな型やスタックフレームに関するテストの挙動を調整するものです。具体的には、test/fixedbugs/bug385_32.go
とtest/fixedbugs/bug385_64.go
という2つのテストファイル内で、コンパイラエラーを期待するコメントの記述をERROR
からGC_ERROR
に変更しています。これにより、gccgo
がこれらのテストでエラーを報告しない場合でも、標準のGoコンパイラ(gc
)がエラーを報告することを期待するテストとして適切に扱われるようになります。
コミット
commit 3ddd2eaebc6bfb3ef05612a354cbd4273378d18b
Author: Ian Lance Taylor <iant@golang.org>
Date: Thu Dec 12 17:13:46 2013 -0800
test: disable large type/stack frame tests for gccgo
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/40370052
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3ddd2eaebc6bfb3ef05612a354cbd4273378d18b
元コミット内容
test: disable large type/stack frame tests for gccgo
このコミットは、gccgo
コンパイラに対して、大きな型やスタックフレームに関するテストを無効化することを目的としています。
変更の背景
Go言語には、公式のコンパイラであるgc
(Go Compiler)と、GCCをバックエンドとするgccgo
という2つの主要なコンパイラがあります。これらのコンパイラは、Go言語の仕様に準拠していますが、内部的な実装や最適化戦略において異なる挙動を示すことがあります。
このコミットの背景には、特に大きなデータ型やスタックフレームの扱いにおいて、gc
とgccgo
の間で挙動の差異があったことが挙げられます。Goのランタイムは、大きなローカル変数をスタックではなくヒープに割り当てることで、スタックオーバーフローを防ぐメカニズムを持っています。しかし、非常に大きな型や深い再帰によってスタックフレームが肥大化するようなケースでは、コンパイラがエラーを報告することが期待されます。
bug385_32.go
とbug385_64.go
のテストは、それぞれ32ビットおよび64ビット環境で、非常に大きな配列をローカル変数として宣言した場合に、コンパイラが「型が大きすぎる」または「スタックフレームが大きすぎる」というエラーを報告することを検証するものです。しかし、gccgo
はこれらの特定のケースでgc
と同じエラーを報告しない、あるいは異なる挙動を示す可能性がありました。
テストスイートの目的は、Go言語の正しい挙動を検証することであり、特定のコンパイラの内部的な挙動の違いによってテストが失敗することは望ましくありません。そのため、gccgo
がこれらのテストでエラーを報告しない場合でも、テストがパスするように、エラー期待のマーカーをGC_ERROR
に変更することで、gc
コンパイラのみがこのエラーを報告することを期待するように調整されました。これにより、gccgo
のテスト実行時にはこれらのエラーが無視され、テストスイート全体の安定性が向上します。
前提知識の解説
- Goコンパイラ (
gc
): Go言語の公式かつ主要なコンパイラです。Go言語のソースコードを機械語に変換します。ランタイムと密接に連携し、ガベージコレクションやスケジューリングなどの機能を提供します。 gccgo
: GCC (GNU Compiler Collection) をバックエンドとして使用するGo言語のコンパイラです。gc
とは異なるコード生成パスを持ち、GCCの最適化機能を利用できます。一部のプラットフォームや特定のユースケースで利用されますが、一般的にはgc
が主流です。- スタックフレーム (Stack Frame): 関数が呼び出されるたびに、その関数のローカル変数、引数、戻りアドレスなどを格納するためにスタック上に確保されるメモリ領域です。関数が終了すると、このスタックフレームは解放されます。
- ヒープ (Heap): プログラムが実行時に動的にメモリを割り当てるために使用するメモリ領域です。スタックとは異なり、ヒープに割り当てられたメモリは、明示的に解放されるか、ガベージコレクタによって回収されるまで保持されます。
- 大きな型とスタックフレーム: Goでは、大きなデータ構造(例:巨大な配列や構造体)をローカル変数として宣言すると、デフォルトではスタックに割り当てられようとします。しかし、スタックはサイズに限りがあるため、非常に大きなデータがスタックに割り当てられると、スタックオーバーフローのリスクがあります。Goのコンパイラは、このようなリスクを軽減するために、一定のサイズを超えるローカル変数を自動的にヒープに「エスケープ」させる(割り当てる場所をスタックからヒープに変更する)最適化を行います。
// ERROR "..."
と// GC_ERROR "..."
: Goのテストスイートでは、特定の行でコンパイラエラーが発生することを期待する場合、その行のコメントに// ERROR "期待するエラーメッセージの正規表現"
という形式で記述します。これにより、テスト実行時にそのエラーが検出されればテストは成功し、検出されなければ失敗します。// ERROR
: どのGoコンパイラでもこのエラーが発生することを期待します。// GC_ERROR
:gc
コンパイラでのみこのエラーが発生することを期待します。gccgo
などの他のコンパイラでは、このエラーが発生しなくてもテストはパスします。これは、コンパイラ間の挙動の差異を許容しつつ、gc
の特定の挙動を検証するために使用されます。
技術的詳細
このコミットは、Go言語のテストフレームワークにおける特定のマーカーのセマンティクスを利用して、コンパイラ間の挙動の差異を吸収しています。
Goのテストスイートでは、コンパイラが特定のコードに対してエラーを報告することを期待するシナリオをテストするために、特別なコメント構文を使用します。元のテストファイルbug385_32.go
とbug385_64.go
では、それぞれ以下のような行がありました。
var arr [1000200030]int // ERROR "type .* too large"
func main() { // ERROR "stack frame too large"
これらの行は、[1000200030]int
のような非常に大きな配列型を宣言したり、[10<<20]byte
のような大きなローカル変数を多数宣言することで、コンパイラが「型が大きすぎる」または「スタックフレームが大きすぎる」というエラーを報告することを期待していました。
しかし、gccgo
コンパイラは、これらの特定のケースにおいて、gc
コンパイラとは異なる方法でメモリ割り当てを処理したり、エラーを報告しない可能性がありました。例えば、gccgo
はGCCのバックエンドを利用するため、GCCの最適化パスやメモリ管理戦略がGoのランタイムとは異なる挙動を引き起こすことがあります。ウェブ検索の結果からも、gccgo
がスタックメモリの扱いやガベージコレクションにおいてgc
とは異なる特性を持つことが示唆されています。特に、大きなスタックフレームがプログラムのハングを引き起こす可能性が指摘されており、これはgccgo
が大きな型をヒープにエスケープさせる際のガベージコレクションのオーバーヘッドに関連している可能性があります。
このため、gccgo
でこれらのテストを実行すると、gccgo
が期待されるエラーを報告しないためにテストが失敗する、という問題が発生していました。これを解決するために、エラー期待のマーカーをERROR
からGC_ERROR
に変更しました。
// GC_ERROR "type .* too large"
// GC_ERROR "stack frame too large"
GC_ERROR
マーカーは、そのエラーがgc
コンパイラによってのみ報告されることを期待するという意味を持ちます。これにより、テストハーネスはgccgo
でこれらのテストを実行する際に、これらの特定のGC_ERROR
マーカーを無視するようになります。結果として、gc
コンパイラでは引き続き期待されるエラーが検証され、gccgo
ではそのエラーの有無に関わらずテストがパスするようになり、テストスイート全体の互換性と安定性が保たれます。
この変更は、gccgo
がGo言語の仕様に準拠している限り、特定の内部実装の違いによってテストが不必要に失敗するのを防ぐための実用的なアプローチです。
コアとなるコードの変更箇所
diff --git a/test/fixedbugs/bug385_32.go b/test/fixedbugs/bug385_32.go
index 724ed93262..4c3cad7798 100644
--- a/test/fixedbugs/bug385_32.go
+++ b/test/fixedbugs/bug385_32.go
@@ -9,7 +9,7 @@
package main
func main() {
- var arr [1000200030]int // ERROR "type .* too large"
+ var arr [1000200030]int // GC_ERROR "type .* too large"
arr_bkup := arr
_ = arr_bkup
}
diff --git a/test/fixedbugs/bug385_64.go b/test/fixedbugs/bug385_64.go
index aef03c389d..6789c0abf0 100644
--- a/test/fixedbugs/bug385_64.go
+++ b/test/fixedbugs/bug385_64.go
@@ -12,7 +12,7 @@ package main
var z [10<<20]byte
-func main() { // ERROR "stack frame too large"
+func main() { // GC_ERROR "stack frame too large"
// seq 1 206 | sed 's/.*/\tvar x& [10<<20]byte; z = x&/'
var x1 [10<<20]byte; z = x1
var x2 [10<<20]byte; z = x2
コアとなるコードの解説
変更は非常にシンプルで、test/fixedbugs/bug385_32.go
とtest/fixedbugs/bug385_64.go
の2つのファイルにおいて、エラーを期待するコメントのキーワードがERROR
からGC_ERROR
に変更されています。
-
test/fixedbugs/bug385_32.go
:var arr [1000200030]int // ERROR "type .* too large"
- が
var arr [1000200030]int // GC_ERROR "type .* too large"
- に変更されました。これは、32ビット環境で非常に大きな配列型を宣言した場合に、「型が大きすぎる」というエラーが
gc
コンパイラによって報告されることを期待するテストであることを示します。
-
test/fixedbugs/bug385_64.go
:func main() { // ERROR "stack frame too large"
- が
func main() { // GC_ERROR "stack frame too large"
- に変更されました。これは、64ビット環境で非常に大きなスタックフレームが生成される場合に、「スタックフレームが大きすぎる」というエラーが
gc
コンパイラによって報告されることを期待するテストであることを示します。
この変更の核心は、GoのテストハーネスがGC_ERROR
というキーワードをどのように解釈するかという点にあります。GC_ERROR
は、そのエラーがGoの標準コンパイラであるgc
によってのみ発生することを期待し、gccgo
のような他のコンパイラではこのエラーが報告されなくてもテストをパスさせるためのディレクティブです。これにより、gccgo
のビルドやテスト実行時に、これらの特定のテストが不必要に失敗するのを防ぎ、テストスイート全体の柔軟性と互換性を高めています。
関連リンク
- https://github.com/golang/go/commit/3ddd2eaebc6bfb3ef05612a354cbd4273378d18b
- https://golang.org/cl/40370052
参考にした情報源リンク
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHOMWNVF8h6U3p6BWx1HpMvswE2YQt7i2_szI-wv1Ac4SrQbuQJPaXwy-zy0iiaiHgwQHo3XEEpB6dhrFrln9zjG3BVgRoXEws2BDWyfaBIo7guUPPAp_pCikeWcTfHkzEl1u4=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGJoyQaJ79wdwpyril9XflYUI8nyKVB5dGC5XTHRrQlM0XroWVaLY0N1ww7eFBjXxHTr8bC5GStsyDKUnzU0Y39GoLzZmnqcfDGAmbPOnrp_fRGmUbHl6ZmpFdBGQVpUiylVykY5Q==
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEja72r3E0yehdF1K4Xn2SAEc_J7op77IUys8G1CXLcz_potFW0pHDVElqGeo8Z7Xful3drTEfg8IuOJZZZeWJLmfJuuabxNt6jXDyTWjwF4ZPRbCpLshLHCr4HxRjeRyusTEU=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFSX-1w96P9S2Rt5XOhv4YmDjZSj-22y3VwJ2x-wUrJ7UjtjqqeqWxtFCZ-d422UE_AwC7e0GN1IFyYS4qaWB9UUK8UCB_w9J0f8dtTCfEbgWoalKTv3UYaa0ZihztkdapdEu4=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFiZQHxGs-q3mr7mebF3SoVqgu9rCDqqmm8DRtd9tR7he0igaUCr-FDMzs_-mJeIq1asixO64lE-4XQfmKbDJnZuUSlNVB29Rcw8F4IcorP3jnQ6OXURPmcecaNJPkwrLTX2e41CldtHCtAEQ39hCRRsx_bQxL-YO0lHtbIQQmHXvzh8GVkUmJ-hiTaG7cwV6hFLPBRCrJrfDx28RwS9xpGdkV2xQ==