[インデックス 13918] ファイルの概要
このコミットは、Go言語のテストスイートにおいて、int
型が常に32ビットであるという仮定を排除し、64ビット整数環境への対応を準備するための変更を含んでいます。具体的には、境界チェックのテスト、make
組み込み関数によるスライス、マップ、チャネルの作成時のサイズ関連のバグテスト、およびスタックフレームサイズに関するテストが修正されています。
コミット
commit 0d82e698112464ea99bdd8cc2e695902b32e8e61
Author: Russ Cox <rsc@golang.org>
Date: Mon Sep 24 00:06:41 2012 -0400
test: prepare for 64-bit ints
Minor tweaks to avoid assuming that int is always 32 bits.
Update #2188.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/6553062
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0d82e698112464ea99bdd8cc2e695902b32e8e61
元コミット内容
test: prepare for 64-bit ints
Minor tweaks to avoid assuming that int is always 32 bits.
Update #2188.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/6553062
変更の背景
Go言語はクロスプラットフォーム対応を重視しており、異なるアーキテクチャ(32ビットシステムと64ビットシステム)で一貫した動作を保証する必要があります。Goのint
型は、その実行環境のネイティブな整数サイズに依存します。つまり、32ビットシステムではint
は32ビット、64ビットシステムではint
は64ビットになります。
このコミットが行われた2012年当時、Goのテストスイートの一部には、int
型が常に32ビットであるという暗黙の仮定が含まれていました。この仮定は、特にメモリ割り当て、配列のインデックス計算、チャネルのバッファサイズ計算など、サイズに敏感な操作において問題を引き起こす可能性がありました。64ビットシステムでこれらのテストを実行すると、期待されるエラーが発生しなかったり、異なる動作を示したりする可能性がありました。
この変更の主な目的は、int
型のサイズに依存しない堅牢なテストを作成し、Go言語が将来的に64ビットシステムでより適切に動作するように準備することです。コミットメッセージにある「Update #2188」は、この変更が特定の課題(Go issue 2188)に対応していることを示唆していますが、現時点でのWeb検索では、このコミットと直接関連するGoの公式なissue #2188の具体的な内容は特定できませんでした。しかし、文脈から判断すると、int
のサイズに関する問題や、それによって引き起こされるテストの不安定性に対処するためのものと考えられます。
前提知識の解説
- Go言語の
int
型: Go言語のint
型は、プラットフォームに依存する整数型です。32ビットシステムでは32ビット幅、64ビットシステムでは64ビット幅を持ちます。これは、C言語のint
型が通常、システムによってサイズが異なるのと同様です。 int64
型:int64
型は、Go言語において常に64ビット幅を持つ符号付き整数型です。プラットフォームに依存せず、常に同じサイズを保証します。- 境界チェック (Bounds Checking): Go言語は、スライスや配列へのアクセス時に、インデックスが有効な範囲内にあるかを自動的にチェックします。これにより、無効なメモリ領域へのアクセスを防ぎ、プログラムの安全性を高めます。コンパイラは、インデックスが常に有効であることが静的に判断できる場合、このチェックを最適化(elide)して実行時のオーバーヘッドを削減することがあります。
make
組み込み関数: Go言語のmake
関数は、スライス、マップ、チャネルといった組み込みの参照型を初期化するために使用されます。make([]T, len, cap)
: スライスを作成します。len
は初期の長さ、cap
は容量です。make(map[K]V, cap)
: マップを作成します。cap
は初期容量のヒントです。make(chan T, cap)
: チャネルを作成します。cap
はバッファ容量です。 これらの関数に負の値や非常に大きな値を渡すと、パニック(実行時エラー)が発生することが期待されます。
unsafe.Sizeof
:unsafe
パッケージは、Goの型システムの安全性をバイパスする低レベルな操作を提供します。unsafe.Sizeof
は、Goの値のメモリサイズをバイト単位で返します。この関数は、特定のアーキテクチャに依存するコードを書く際に使用されることがありますが、ポータビリティを損なう可能性があります。
技術的詳細
このコミットは、主にGoのテストコードに変更を加えており、int
型が32ビットであるという仮定を取り除くことで、64ビットシステムでのテストの信頼性を向上させています。
test/bounds.go
の変更
このファイルは、コンパイラが境界チェックを省略(elide)できるかどうかをテストするためのものです。
変更前は、use(a100k[ui/1e6]) // ERROR "index bounds check elided"
のように、特定のインデックスアクセスに対して「境界チェックが省略される」ことを期待するコメントが付いていました。
- 変更内容:
ERROR "index bounds check elided"
というコメントが削除されました。 - 技術的意味: これは、
int
が64ビットになる環境では、以前はコンパイラが静的に安全と判断して境界チェックを省略していたケースでも、もはや省略できない可能性があることを示唆しています。あるいは、テストの意図が「境界チェックが省略されること」ではなく、「コードが正しく動作すること」に変わったことを意味するかもしれません。int
が64ビットになると、ui/1e6
のような計算結果が32ビットの範囲を超える可能性があり、その結果、コンパイラがより保守的になり、境界チェックを省略しなくなることが考えられます。
test/fixedbugs/bug273.go
の変更
このファイルは、make
関数に無効な引数(負の値や非常に大きな値)を渡した場合に、期待通りパニックが発生するかどうかをテストするものです。
-
import "unsafe"
の削除:unsafe.Sizeof
の使用がなくなったため、関連するインポートも削除されました。 -
g1
の型変更:var g1 []int
からvar g1 []block
に変更されました。ここでtype block [1<<19]byte
は、1<<19
バイト(512KB)の固定サイズのバイト配列です。 -
g3
の型変更:var g3 map[int]int
からvar g3 map[block]block
に変更されました。 -
g4
の型変更:var g4 chan int
からvar g4 chan cblock
に変更されました。ここでtype cblock [1<<16-1]byte
は、1<<16-1
バイト(65535バイト、約64KB)の固定サイズのバイト配列です。 -
overflowchan
関数の変更:- 以前は
addrBits == 32
の条件分岐があり、32ビットシステムでのみチャネルのオーバーフローをテストしていました。これは、32ビットシステムではint
が32ビットであり、チャネルの最大値サイズが64KBであるため、make(chan [1<<15]byte, 1<<20)
のような大きなチャネルを作成しようとするとオーバーフローする可能性があったためです。 - 変更後、この条件分岐は削除され、
g4 = make(chan cblock, 1<<30)
となりました。cblock
は固定サイズ(約64KB)であり、1<<30
という非常に大きなバッファ容量を指定することで、int
のサイズに関わらず、チャネルの作成がメモリ制限や内部的な最大値を超過してパニックを引き起こすことを意図しています。
- 以前は
-
技術的意味:
- 以前のテストは、
int
が32ビットであることを前提に、make
関数に渡される引数がオーバーフローするかどうかを検証していました。しかし、int
が64ビットになると、これらの引数はオーバーフローしなくなり、テストが失敗する(パニックが発生しない)可能性がありました。 - 新しいテストでは、
int
の代わりに、block
やcblock
のような固定サイズの大きな型を使用しています。これにより、make
関数に渡される引数(スライス、マップ、チャネルの要素のサイズや容量)が、int
のサイズに依存せず、常に十分な大きさを持つようになります。これにより、32ビットシステムでも64ビットシステムでも、期待されるパニックが確実に発生するようになります。 - 特に
overflowchan
の変更は、int
のサイズに依存するunsafe.Sizeof
の使用を排除し、よりポータブルな方法でチャネルの容量オーバーフローをテストするように改善されています。
- 以前のテストは、
test/fixedbugs/bug385_64.go
の変更
このファイルは、非常に大きな配列をスタック上に割り当てようとした場合に、「スタックフレームが大きすぎる」というエラー(ERROR "stack frame too large"
)が発生するかどうかをテストするものです。
- 変更内容:
var arr [1000200030]int
からvar arr [1000200030]int32
に変更されました。 - 技術的意味:
- 以前のコードでは、配列の要素型が
int
でした。64ビットシステムではint
が64ビットになるため、1000200030 * 8
バイトという非常に大きなメモリがスタックに割り当てられようとします。これは32ビットシステムでの1000200030 * 4
バイトよりもさらに大きくなります。 int32
を明示的に使用することで、配列の各要素が常に32ビット(4バイト)であることを保証します。これにより、1000200030 * 4
バイトという、32ビットシステムでも64ビットシステムでも一貫して「スタックフレームが大きすぎる」と判断されるようなサイズを意図的に作成しています。- この変更により、テストが
int
のサイズに依存せず、異なるアーキテクチャで一貫して同じエラーを検出できるようになります。
- 以前のコードでは、配列の要素型が
コアとなるコードの変更箇所
このコミットは、Go言語のランタイムやコンパイラのコアコードではなく、主にテストコードに変更を加えています。
test/bounds.go
: 境界チェックの最適化に関するテストのコメント修正。test/fixedbugs/bug273.go
:make
関数によるスライス、マップ、チャネルの作成時のサイズ関連のバグテストの修正。int
型への依存を排除し、固定サイズの大きな型を使用するように変更。test/fixedbugs/bug385_64.go
: スタックフレームが大きすぎるエラーをテストする際の配列要素型をint
からint32
に明示的に変更。
コアとなるコードの解説
このコミットの「コア」は、Go言語のテストの堅牢性を高めるためのアプローチにあります。
int
型への依存の排除: 以前のテストは、int
型が32ビットであるという暗黙の仮定に基づいていました。これは、32ビットシステムでは問題ありませんでしたが、64ビットシステムではint
が64ビットになるため、テストの意図が損なわれたり、期待されるエラーが発生しなくなったりする可能性がありました。このコミットでは、int
の代わりにint32
を明示的に使用したり、block
やcblock
のような固定サイズの大きな型を導入したりすることで、int
のサイズに依存しないテストを実現しています。- ポータビリティの向上:
unsafe.Sizeof
の使用を避け、特定のアーキテクチャに依存する条件分岐を削除することで、テストコードのポータビリティが向上しています。これにより、Go言語がサポートするすべてのアーキテクチャで、テストが期待通りに動作することが保証されます。 - テストの正確性の維持:
make
関数に無効な引数を渡した場合のパニックテストや、スタックフレームが大きすぎる場合のテストなど、特定の実行時エラーを検出するテストにおいて、int
のサイズ変更によってテストの意図が曖昧になることを防ぎ、正確にエラーを検出できるように修正されています。
これらの変更は、Go言語が異なるアーキテクチャで一貫した動作を提供するための基盤を強化し、将来的なGo言語の進化に対応するための重要なステップと言えます。
関連リンク
- Go言語の
int
型に関する公式ドキュメント(Go言語のバージョンによって内容が異なる可能性がありますが、一般的な情報源として):https://go.dev/ref/spec#Numeric_types - Go言語の
make
組み込み関数に関する公式ドキュメント:https://go.dev/ref/spec#Making_slices_maps_and_channels - Go言語の
unsafe
パッケージに関する公式ドキュメント:https://pkg.go.dev/unsafe
(注:コミットメッセージに記載されているGo issue #2188の具体的な内容は、現時点でのWeb検索では特定できませんでした。)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Gitのコミットログと差分
- Go言語のテストコードの慣習に関する一般的な知識
- Go言語の
int
型の特性に関する一般的な知識