Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 18700] ファイルの概要

このコミットは、GoランタイムにおけるNative Client (NaCl) 関連の小さな修正を導入しています。具体的には、cgocall.chashmap.gocの2つのファイルに変更が加えられ、GOARCH_amd64p32アーキテクチャに対するコンパイル時の問題を解決し、データ型の整合性を確保しています。

コミット

commit 0c6e4b9660171034052f9f85c734ddb13023100e
Author: Dave Cheney <dave@cheney.net>
Date:   Sat Mar 1 11:13:29 2014 +1100

    runtime: small Native Client fixes
    
    cgocall.c: define the CBARGS macro for GOARCH_amd64p32. I don't think the value of this macro will ever be used under nacl/amd64p32 but it is required to compile even if cgo is not used.
    
    hashmap.goc: amd64p32 uses 32bit words.
    
    LGTM=iant
    R=rsc, iant
    CC=golang-codereviews
    https://golang.org/cl/69960044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/0c6e4b9660171034052f9f85c734ddb13023100e

元コミット内容

GoランタイムにおけるNative Client (NaCl) 関連の小さな修正。

  • cgocall.c: GOARCH_amd64p32向けにCBARGSマクロを定義。nacl/amd64p32ではこのマクロの値が実際に使用されることはないと思われるが、cgoが使用されない場合でもコンパイルに必要であるため定義する。
  • hashmap.goc: amd64p32は32ビットワードを使用するため、それに対応する修正を行う。

変更の背景

このコミットは、GoランタイムがGoogle Native Client (NaCl) 環境で正しくコンパイルおよび動作するための互換性修正です。特に、GOARCH_amd64p32という特定のアーキテクチャターゲットにおいて発生していたコンパイルエラーや、データ型の不整合を解消することが目的です。

GOARCH_amd64p32は、64ビットのAMD64アーキテクチャ上で動作するが、ポインタサイズが32ビットであるという特殊な環境(P32 ABI)を指します。これは主にGoogle Native Client (NaCl) のようなサンドボックス環境で利用されることがありました。NaClは、ウェブブラウザ内でネイティブコードを安全に実行するための技術であり、Go言語もNaClをターゲットとしてサポートしていました。

このコミット以前は、GOARCH_amd64p32環境でGoランタイムをコンパイルする際に、CBARGSマクロの未定義エラーや、ハッシュマップの実装におけるワードサイズの不一致が問題となっていたと考えられます。これらの問題は、Goランタイムのビルドシステムがすべてのサポート対象アーキテクチャに対して一貫した定義を要求する一方で、特定の特殊なアーキテクチャ(この場合はamd64p32)がその要件を満たしていなかったために発生しました。

前提知識の解説

Goランタイム (Go Runtime)

Goランタイムは、Goプログラムの実行を管理する低レベルのコンポーネントです。これには、ガベージコレクション、スケジューラ、メモリ管理、システムコールインターフェースなどが含まれます。ランタイムのコードは、Go言語自体とC言語(またはGoのサブセットであるPlan 9 C)で書かれており、各アーキテクチャやOSに特化した部分も多く存在します。

Google Native Client (NaCl)

Google Native Client (NaCl) は、ウェブブラウザ内でネイティブコード(C/C++など)を安全に実行するためのサンドボックス技術です。これにより、ウェブアプリケーションはCPUに近いパフォーマンスで動作するコードを利用できるようになります。NaClは、特定のアーキテクチャ(x86-32, x86-64, ARM)とOS(Linux, macOS, Windows, Chrome OS)の組み合わせをサポートしていました。Go言語もかつてNaClをターゲットとしてサポートしており、GoプログラムをNaClモジュールとしてコンパイルし、ウェブブラウザで実行することが可能でした。

GOARCH_amd64p32

GOARCHはGoのビルドシステムで使用される環境変数で、ターゲットとするCPUアーキテクチャを指定します。GOARCH_amd64p32は、64ビットのAMD64アーキテクチャをベースとしながらも、ポインタサイズが32ビットであるという特殊なABI (Application Binary Interface) を持つ環境を指します。これは、主にNaCl環境で利用されることが多く、メモリ効率や互換性のためにこのようなポインタサイズが採用されていました。通常のamd64アーキテクチャではポインタは64ビットです。

CGO

CGOは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。GoとCの間の関数呼び出しやデータ変換を可能にします。cgocall.cファイルは、このCGOの呼び出しメカニズムに関連するランタイムコードを含んでいます。

CBARGSマクロ

CBARGS (Callback Arguments) マクロは、Goランタイム内でCGOコールバックの引数にアクセスするために使用されます。GoからC関数を呼び出す際、またはCからGo関数を呼び出す際に、スタック上に配置された引数へのポインタを計算するために利用されます。アーキテクチャによってスタックフレームのレイアウトが異なるため、このマクロの定義もアーキテクチャごとに調整される必要があります。

ハッシュマップ (Hashmap)

ハッシュマップ(Goではmap型)は、キーと値のペアを格納するためのデータ構造です。Goランタイムのhashmap.gocファイルは、このハッシュマップの内部実装に関連するコードを含んでいます。ハッシュマップの内部処理では、キーのハッシュ値を計算したり、メモリ上のデータを操作したりする際に、ワードサイズ(ポインタサイズ)に依存する処理が含まれることがあります。

CHECKTYPEマクロ

CHECKTYPEマクロは、ハッシュマップの内部実装において、特定のデータ型(通常はワードサイズに合わせた整数型)を定義するために使用されます。これにより、異なるアーキテクチャ間でハッシュマップの内部処理が正しく動作するように、適切なサイズのデータ型が選択されます。

技術的詳細

このコミットは、GOARCH_amd64p32という特殊なアーキテクチャターゲットに対するGoランタイムの互換性を向上させるものです。

cgocall.cにおけるCBARGSマクロの定義

cgocall.cはCGO呼び出しに関連するランタイムコードを含んでいます。CBARGSマクロは、CGOコールバックの引数がスタック上のどこに配置されているかを計算するために使用されます。

通常のamd64アーキテクチャでは、ポインタは64ビットですが、amd64p32ではポインタが32ビットです。しかし、スタックフレームのレイアウトや引数の渡し方は、アーキテクチャのABIに厳密に依存します。このコミットでは、GOARCH_amd64p32に対して、既存のamd64の定義と同じCBARGSマクロの定義をコピーしています。

#ifdef GOARCH_amd64p32
#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*))
#endif

コミットメッセージにあるように、「nacl/amd64p32ではこのマクロの値が実際に使用されることはないと思われるが、cgoが使用されない場合でもコンパイルに必要であるため定義する」という点が重要です。これは、Goのビルドシステムが、たとえ特定の機能(この場合はCGO)がそのアーキテクチャで完全にサポートされていなくても、関連するマクロや定義が存在することを期待しているためです。定義がないとコンパイルエラーが発生する可能性があります。この修正は、機能的な変更というよりも、ビルドの成功を保証するための「プレースホルダー」的な役割を果たしています。

hashmap.gocにおけるCHECKTYPEの定義

hashmap.gocはGoのmap型の内部実装の一部です。ハッシュマップの内部では、キーの比較やハッシュ値の操作など、ワードサイズに依存する処理が行われます。

CHECKTYPEマクロは、これらの内部処理で使用される整数型を定義します。amd64アーキテクチャでは64ビットのuint64が使用されますが、amd64p32ではポインタが32ビットであるため、内部的なワードサイズも32ビットとして扱われるべきです。

#ifdef GOARCH_amd64p32
#define CHECKTYPE uint32
#endif

この修正により、GOARCH_amd64p32環境でハッシュマップが正しく動作するように、CHECKTYPEuint32として定義されます。これにより、ハッシュマップの内部ロジックが32ビットワードの仮定に基づいて正しく動作し、データ破損や予期せぬ動作を防ぎます。これは、amd64p32が「32ビットワードを使用する」という特性に直接対応する重要な修正です。

コアとなるコードの変更箇所

src/pkg/runtime/cgocall.c

--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -223,6 +223,12 @@ struct CallbackArgs
 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*))\n #endif\n \n+// There is no cgo support for nacl/amd64p32 but we need to have something here \n+// so use the amd64 value as a placeholder.\n+#ifdef GOARCH_amd64p32\n+#define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*))\n+#endif\n+\n // On 386, stack frame is three words, plus caller PC.\n #ifdef GOARCH_386\n #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*))\n```

### `src/pkg/runtime/hashmap.goc`

```diff
--- a/src/pkg/runtime/hashmap.goc
+++ b/src/pkg/runtime/hashmap.goc
@@ -448,6 +448,9 @@ hash_lookup(MapType *t, Hmap *h, byte **keyp)\n #ifdef GOARCH_amd64\n #define CHECKTYPE uint64\n #endif\n+#ifdef GOARCH_amd64p32\n+#define CHECKTYPE uint32\n+#endif\n #ifdef GOARCH_386\n #define CHECKTYPE uint32\n #endif\n```

## コアとなるコードの解説

### `src/pkg/runtime/cgocall.c`の変更

この変更は、`GOARCH_amd64p32`というコンパイルターゲットに対して、`CBARGS`マクロを定義しています。`CBARGS`マクロは、CGOコールバックの引数がGoのランタイムスタック上のどこに位置するかを計算するために使用されます。

`#ifdef GOARCH_amd64p32`ディレクティブは、コンパイラが`GOARCH_amd64p32`というシンボルが定義されている場合にのみ、その中のコードをコンパイルするように指示します。これにより、この定義は`amd64p32`アーキテクチャに特化したものとなります。

定義されている`CBARGS`の値は、`amd64`アーキテクチャの既存の定義と同じです。コメントにあるように、`nacl/amd64p32`ではCGOが完全にサポートされていない、あるいはこのマクロが実際に使用されるシナリオがない可能性が高いですが、Goのビルドシステムがこのマクロの存在を要求するため、コンパイルエラーを避けるためにプレースホルダーとして定義されています。`m->g0->sched.sp`は現在のM (Machine) のg0 (システムゴルーチン) のスタックポインタを指し、そこからオフセットを計算して`CallbackArgs`構造体へのポインタを得ています。`2*sizeof(void*)`は、スタック上の特定のオフセットを意味し、これはABIに依存します。

### `src/pkg/runtime/hashmap.goc`の変更

この変更は、`GOARCH_amd64p32`コンパイルターゲットに対して、`CHECKTYPE`マクロを`uint32`として定義しています。

`CHECKTYPE`マクロは、ハッシュマップの内部実装、特に`hash_lookup`関数のような場所で、キーの比較やハッシュ値の操作に使用されるデータ型を決定します。`amd64`アーキテクチャでは64ビットの`uint64`が適切ですが、`amd64p32`はポインタが32ビットであるため、内部的なワードサイズも32ビットとして扱われるべきです。

`#ifdef GOARCH_amd64p32`ディレクティブにより、この定義は`amd64p32`アーキテクチャに限定されます。`CHECKTYPE`を`uint32`とすることで、ハッシュマップの内部ロジックが`amd64p32`の32ビットワードの特性と整合し、データの整合性が保たれ、ハッシュマップ操作が正しく実行されるようになります。これは、アーキテクチャ固有のデータ表現に対応するための重要な修正です。

## 関連リンク

- Go言語公式ウェブサイト: [https://golang.org/](https://golang.org/)
- Goのソースコードリポジトリ (GitHub): [https://github.com/golang/go](https://github.com/golang/go)
- Goのコードレビューシステム (Gerrit): [https://go-review.googlesource.com/](https://go-review.googlesource.com/)
- このコミットのGerritレビューページ: [https://golang.org/cl/69960044](https://golang.org/cl/69960044)

## 参考にした情報源リンク

- Google Native Client (Wikipedia): [https://en.wikipedia.org/wiki/Google_Native_Client](https://en.wikipedia.org/wiki/Google_Native_Client)
- Goのアーキテクチャ固有のビルドタグに関する議論 (例: `GOARCH`): [https://go.dev/doc/install/source#environment](https://go.dev/doc/install/source#environment) (Goの環境変数に関する公式ドキュメント)
- Goのランタイムソースコード (GitHub): [https://github.com/golang/go/tree/master/src/runtime](https://github.com/golang/go/tree/master/src/runtime)
- GoのCGOに関するドキュメント: [https://go.dev/blog/cgo](https://go.dev/blog/cgo)
- Goのマップ実装に関する情報 (例: Goのブログや設計ドキュメントなど、より詳細な技術解説): [https://go.dev/blog/maps](https://go.dev/blog/maps) (Goのマップに関するブログ記事)
- `amd64p32` ABIに関する情報 (主にNaCl関連のドキュメントやLLVM/GCCのドキュメント): [https://chromium.googlesource.com/native_client/src/native_client/+/master/docs/nacl_abi_x86_64.txt](https://chromium.googlesource.com/native_client/src/native_client/+/master/docs/nacl_abi_x86_64.txt) (NaCl x86-64 ABIに関するドキュメント)
- Dave Cheney氏のブログ (Goに関する深い洞察): [https://dave.cheney.net/](https://dave.cheney.net/) (コミット著者によるGo関連のブログ)
- Ian Lance Taylor氏のブログ (Goコンパイラとランタイムに関する深い洞察): [https://www.airs.com/blog/](https://www.airs.com/blog/) (レビュー担当者によるGo関連のブログ)
- Russ Cox氏のブログ (Goの設計と歴史に関する深い洞察): [https://research.swtch.com/](https://research.swtch.com/) (レビュー担当者によるGo関連のブログ)