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

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

このコミットは、Goランタイムにおけるtraceback関数の呼び出しに関する修正です。具体的には、Plan 9およびWindows環境向けの386およびAMD64アーキテクチャにおける、runtime·traceback関数への引数渡しから不要な(void*)キャストを削除しています。これにより、コンパイル時の警告を解消し、コードの整合性を向上させています。

コミット

commit e5cbebc1ad3f1a6372bd1a0ac6032c6236f38f6b
Author: Russ Cox <rsc@golang.org>
Date:   Wed Jun 12 09:41:29 2013 -0400

    runtime: fix plan9, windows builds
    
    TBR=dvyukov
    CC=golang-dev
    https://golang.org/cl/10229043

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

https://github.com/golang/go/commit/e5cbebc1ad3f1a6372bd1a0ac6032c6236f38f6b

元コミット内容

runtime: fix plan9, windows builds

TBR=dvyukov
CC=golang-dev
https://golang.org/cl/10229043

変更の背景

このコミットの背景には、Goランタイムのクロスプラットフォーム対応と、C言語で記述された部分(特に低レベルなOSインタラクションやランタイムのコア部分)における型安全性の向上が挙げられます。

Go言語のランタイムは、パフォーマンスとOSとの密接な連携のために、一部がC言語(またはPlan 9 C)で記述されています。これらのCコードは、Goのガベージコレクタやスケジューラ、スタックトレース生成など、Goプログラムの実行を支える重要な役割を担っています。

runtime·traceback関数は、プログラムがクラッシュした際などに、現在の実行スタックを辿って呼び出し履歴(スタックトレース)を生成するために使用されます。この関数は、プログラムカウンタ(PC)やスタックポインタ(SP)といったレジスタの値を引数として受け取ります。

以前のコードでは、これらのレジスタ値をruntime·traceback関数に渡す際に、(void*)というキャストが明示的に行われていました。これは、C言語において任意のポインタ型を汎用ポインタ型であるvoid*に変換する一般的な手法です。しかし、特定のコンパイラやコンパイル設定、あるいはGoランタイムの内部的な型定義の進化により、この明示的な(void*)キャストが不要になったか、あるいは警告を発生させる原因となっていた可能性があります。

このコミットは、Plan 9およびWindows環境におけるビルドプロセスで発生していた問題を解決することを目的としています。具体的には、(void*)キャストが原因で発生していたコンパイル時の警告やエラーを解消し、これらのプラットフォームでのGoランタイムのビルドを成功させるための修正です。

前提知識の解説

Goランタイム

Goランタイムは、Goプログラムの実行を管理する低レベルなシステムです。これには、ガベージコレクタ、スケジューラ(ゴルーチンの管理)、メモリ管理、スタック管理、システムコールインターフェースなどが含まれます。Goランタイムの一部は、C言語(またはPlan 9 C)やアセンブリ言語で記述されており、OSとの直接的なインタラクションやパフォーマンスが要求される部分を担っています。

スタックトレース (Stack Trace)

スタックトレースは、プログラムの実行中にエラーや例外が発生した際に、その時点での関数呼び出しの履歴を一覧表示したものです。これにより、どの関数がどの関数を呼び出し、最終的にエラーが発生したのかを追跡することができます。デバッグにおいて非常に重要な情報となります。Go言語では、runtime.Stack()関数やパニック発生時に自動的にスタックトレースが出力されます。

プログラムカウンタ (Program Counter, PC) と スタックポインタ (Stack Pointer, SP)

  • プログラムカウンタ (PC): 現在実行中の命令のアドレスを保持するCPUレジスタです。Goランタイムの文脈では、ureg->pc (Plan 9) や r->Eip/r->Rip (Windows) がこれに相当します。
  • スタックポインタ (SP): 現在のスタックフレームの最上位(または最下位、アーキテクチャによる)のアドレスを指すCPUレジスタです。Goランタイムの文脈では、ureg->sp (Plan 9) や r->Esp/r->Rsp (Windows) がこれに相当します。

runtime·traceback関数は、これらのレジスタ値を使ってスタックを逆方向に辿り、関数呼び出しの履歴を再構築します。

(void*)キャスト

C言語において、void*は「汎用ポインタ」と呼ばれる特殊なポインタ型です。これは、任意のデータ型へのポインタを指すことができます。例えば、int*型のポインタをvoid*にキャストしたり、その逆を行ったりすることができます。

some_function((void*)some_variable);

このようなキャストは、関数が特定の型のポインタではなく、任意の型のポインタを受け取ることを意図している場合によく使用されます。しかし、厳密な型チェックを行うコンパイラや、関数定義がすでにvoid*以外の適切な型を期待している場合、この明示的なキャストは冗長になったり、警告の原因になったりすることがあります。

Plan 9

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Go言語の開発者の一部はPlan 9の開発にも携わっており、Go言語の設計思想やツールチェーンにはPlan 9の影響が色濃く見られます。GoランタイムがPlan 9をサポートしているのはそのためです。

技術的詳細

このコミットの技術的な詳細は、C言語の型システムとGoランタイムの内部構造に深く関連しています。

runtime·traceback関数は、スタックトレースを生成するために、プログラムカウンタとスタックポインタの値を必要とします。これらの値は、CPUのレジスタから取得され、通常はポインタ型として扱われます。

変更前のコードでは、これらのレジスタ値がureg->pcureg->spr->Eipr->Espr->Ripr->Rspといった形で取得されていました。これらの変数の型は、それぞれのOSおよびアーキテクチャのコンテキスト構造体(uregContext)内で定義されており、通常はポインタ型(例: uintptr_tvoid*に相当する型)またはポインタとして解釈可能な整数型です。

変更前のコードでは、これらの値をruntime·traceback関数に渡す際に、明示的に(void*)にキャストしていました。

例: runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);

このキャストは、runtime·traceback関数のプロトタイプが、引数としてvoid*を期待している場合に適切です。しかし、Goランタイムの進化に伴い、runtime·traceback関数のプロトタイプが変更されたか、あるいはコンパイラがよりスマートになり、ポインタ型間の暗黙的な変換を適切に処理できるようになった可能性があります。

具体的には、以下のような理由が考えられます。

  1. runtime·traceback関数のプロトタイプ変更: runtime·traceback関数が、引数としてvoid*ではなく、より具体的なポインタ型(例: uintptr_tや、特定の構造体へのポインタ)を期待するように変更された場合、(void*)キャストは不要になります。むしろ、不必要なキャストはコンパイラに警告を発生させる可能性があります。
  2. コンパイラの進化: 使用されているCコンパイラ(例えば、Goのツールチェーンに含まれるgcコンパイラや、クロスコンパイル環境のGCC/Clang)が、ポインタ型と整数型(特にアドレスを表現するのに十分な幅を持つ整数型)の間で、安全な暗黙的変換をより適切に処理できるようになった可能性があります。この場合、明示的な(void*)キャストは冗長となります。
  3. 型定義の整合性: Goランタイムの内部的な型定義が、レジスタ値を表す型とruntime·tracebackが期待する引数の型との間で、より直接的な互換性を持つようになった可能性があります。これにより、中間的な(void*)キャストが不要になったと考えられます。

このコミットは、これらの理由のいずれか、または複合的な理由により、(void*)キャストを削除することで、コンパイル時の警告を解消し、ビルドプロセスをクリーンに保つことを目的としています。これは、コードの可読性を向上させ、不必要な型変換を避けるという観点からも良いプラクティスです。

影響を受けるファイルは、Plan 9 (386, AMD64) と Windows (386, AMD64) のランタイム固有のCソースファイルです。これは、これらのOS/アーキテクチャのコンテキスト構造体やレジスタの扱いが、他のOS(例: Linux, macOS)とは異なるためです。

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

変更は、以下の4つのファイルにわたって行われています。

  1. src/pkg/runtime/os_plan9_386.c
  2. src/pkg/runtime/os_plan9_amd64.c
  3. src/pkg/runtime/os_windows_386.c
  4. src/pkg/runtime/os_windows_amd64.c

それぞれのファイルで、runtime·traceback関数の呼び出しから、第一引数と第二引数に適用されていた(void*)キャストが削除されています。

例: src/pkg/runtime/os_plan9_386.c の変更

--- a/src/pkg/runtime/os_plan9_386.c
+++ b/src/pkg/runtime/os_plan9_386.c
@@ -95,7 +95,7 @@ Throw:
  	runtime·printf("\n");
 
  	if(runtime·gotraceback(&crash)) {
- 		runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);
+ 		runtime·traceback(ureg->pc, ureg->sp, 0, gp);
  		runtime·tracebackothers(gp);
  		runtime·dumpregs(ureg);
  	}

同様の変更が、他の3つのファイルでも行われています。

  • os_plan9_amd64.c: ureg->ipureg->sp から(void*)キャストを削除。
  • os_windows_386.c: r->Eipr->Esp から(void*)キャストを削除。
  • os_windows_amd64.c: r->Ripr->Rsp から(void*)キャストを削除。

コアとなるコードの解説

変更されたコードは、Goランタイムがパニックやクラッシュなどの致命的なエラーに遭遇した際に、スタックトレースを生成する部分です。

if(runtime·gotraceback(&crash)) の条件は、スタックトレースを生成する必要があるかどうかを判断しています。crash変数は、クラッシュの種類や状態を示すフラグであると考えられます。

条件が真の場合、runtime·traceback関数が呼び出されます。

  • 変更前: runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);

    • ureg->pc (プログラムカウンタ) と ureg->sp (スタックポインタ) の値が、明示的にvoid*にキャストされてruntime·tracebackに渡されていました。
    • 0 はおそらくフレームスキップ数などの追加引数、gp は現在のゴルーチン(goroutine)のポインタです。
  • 変更後: runtime·traceback(ureg->pc, ureg->sp, 0, gp);

    • (void*)キャストが削除され、ureg->pcureg->spの値が直接runtime·tracebackに渡されるようになりました。

この変更は、runtime·traceback関数の内部的なプロトタイプが、これらの引数を直接受け入れられるようになったことを示唆しています。例えば、runtime·tracebackの定義が以下のように変更された可能性があります。

変更前(想定): void runtime·traceback(void* pc, void* sp, int skip, G* gp);

変更後(想定): void runtime·traceback(uintptr_t pc, uintptr_t sp, int skip, G* gp); または、コンパイラがポインタ型とアドレスを表す整数型との間の変換をより柔軟に扱えるようになったため、明示的なキャストが不要になった、という可能性もあります。

この修正により、Plan 9およびWindows環境でのGoランタイムのビルドが、不必要な警告なしにクリーンに完了するようになります。これは、Goのクロスプラットフォーム対応とビルドシステムの健全性を維持するために重要な変更です。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特にsrc/pkg/runtimeディレクトリ内のファイル)
  • C言語のポインタと型キャストに関する一般的な知識
  • Go言語のクロスコンパイルとビルドに関する情報
  • Plan 9オペレーティングシステムに関する一般的な情報
  • Windowsのシステムプログラミングにおけるレジスタとコンテキスト構造に関する情報# [インデックス 16554] ファイルの概要

このコミットは、Goランタイムにおけるtraceback関数の呼び出しに関する修正です。具体的には、Plan 9およびWindows環境向けの386およびAMD64アーキテクチャにおける、runtime·traceback関数への引数渡しから不要な(void*)キャストを削除しています。これにより、コンパイル時の警告を解消し、コードの整合性を向上させています。

コミット

commit e5cbebc1ad3f1a6372bd1a0ac6032c6236f38f6b
Author: Russ Cox <rsc@golang.org>
Date:   Wed Jun 12 09:41:29 2013 -0400

    runtime: fix plan9, windows builds
    
    TBR=dvyukov
    CC=golang-dev
    https://golang.org/cl/10229043

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

https://github.com/golang/go/commit/e5cbebc1ad3f1a6372bd1a0ac6032c6236f38f6b

元コミット内容

runtime: fix plan9, windows builds

TBR=dvyukov
CC=golang-dev
https://golang.org/cl/10229043

変更の背景

このコミットの背景には、Goランタイムのクロスプラットフォーム対応と、C言語で記述された部分(特に低レベルなOSインタラクションやランタイムのコア部分)における型安全性の向上が挙げられます。

Go言語のランタイムは、パフォーマンスとOSとの密接な連携のために、一部がC言語(またはPlan 9 C)で記述されています。これらのCコードは、Goのガベージコレクタやスケジューラ、スタックトレース生成など、Goプログラムの実行を支える重要な役割を担っています。

runtime·traceback関数は、プログラムがクラッシュした際などに、現在の実行スタックを辿って呼び出し履歴(スタックトレース)を生成するために使用されます。この関数は、プログラムカウンタ(PC)やスタックポインタ(SP)といったレジスタの値を引数として受け取ります。

以前のコードでは、これらのレジスタ値をruntime·traceback関数に渡す際に、(void*)というキャストが明示的に行われていました。これは、C言語において任意のポインタ型を汎用ポインタ型であるvoid*に変換する一般的な手法です。しかし、特定のコンパイラやコンパイル設定、あるいはGoランタイムの内部的な型定義の進化により、この明示的な(void*)キャストが不要になったか、あるいは警告を発生させる原因となっていた可能性があります。

このコミットは、Plan 9およびWindows環境におけるビルドプロセスで発生していた問題を解決することを目的としています。具体的には、(void*)キャストが原因で発生していたコンパイル時の警告やエラーを解消し、これらのプラットフォームでのGoランタイムのビルドを成功させるための修正です。

前提知識の解説

Goランタイム

Goランタイムは、Goプログラムの実行を管理する低レベルなシステムです。これには、ガベージコレクタ、スケジューラ(ゴルーチンの管理)、メモリ管理、スタック管理、システムコールインターフェースなどが含まれます。Goランタイムの一部は、C言語(またはPlan 9 C)やアセンブリ言語で記述されており、OSとの直接的なインタラクションやパフォーマンスが要求される部分を担っています。

スタックトレース (Stack Trace)

スタックトレースは、プログラムの実行中にエラーや例外が発生した際に、その時点での関数呼び出しの履歴を一覧表示したものです。これにより、どの関数がどの関数を呼び出し、最終的にエラーが発生したのかを追跡することができます。デバッグにおいて非常に重要な情報となります。Go言語では、runtime.Stack()関数やパニック発生時に自動的にスタックトレースが出力されます。

プログラムカウンタ (Program Counter, PC) と スタックポインタ (Stack Pointer, SP)

  • プログラムカウンタ (PC): 現在実行中の命令のアドレスを保持するCPUレジスタです。Goランタイムの文脈では、ureg->pc (Plan 9) や r->Eip/r->Rip (Windows) がこれに相当します。
  • スタックポインタ (SP): 現在のスタックフレームの最上位(または最下位、アーキテクチャによる)のアドレスを指すCPUレジスタです。Goランタイムの文脈では、ureg->sp (Plan 9) や r->Esp/r->Rsp (Windows) がこれに相当します。

runtime·traceback関数は、これらのレジスタ値を使ってスタックを逆方向に辿り、関数呼び出しの履歴を再構築します。

(void*)キャスト

C言語において、void*は「汎用ポインタ」と呼ばれる特殊なポインタ型です。これは、任意のデータ型へのポインタを指すことができます。例えば、int*型のポインタをvoid*にキャストしたり、その逆を行ったりすることができます。

some_function((void*)some_variable);

このようなキャストは、関数が特定の型のポインタではなく、任意の型のポインタを受け取ることを意図している場合によく使用されます。しかし、厳密な型チェックを行うコンパイラや、関数定義がすでにvoid*以外の適切な型を期待している場合、この明示的なキャストは冗長になったり、警告の原因になったりすることがあります。

Plan 9

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Go言語の開発者の一部はPlan 9の開発にも携わっており、Go言語の設計思想やツールチェーンにはPlan 9の影響が色濃く見られます。GoランタイムがPlan 9をサポートしているのはそのためです。

技術的詳細

このコミットの技術的な詳細は、C言語の型システムとGoランタイムの内部構造に深く関連しています。

runtime·traceback関数は、スタックトレースを生成するために、プログラムカウンタとスタックポインタの値を必要とします。これらの値は、CPUのレジスタから取得され、通常はポインタ型として扱われます。

変更前のコードでは、これらのレジスタ値がureg->pcureg->spr->Eipr->Espr->Ripr->Rspといった形で取得されていました。これらの変数の型は、それぞれのOSおよびアーキテクチャのコンテキスト構造体(uregContext)内で定義されており、通常はポインタ型(例: uintptr_tvoid*に相当する型)またはポインタとして解釈可能な整数型です。

変更前のコードでは、これらの値をruntime·traceback関数に渡す際に、明示的に(void*)にキャストしていました。

例: runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);

このキャストは、runtime·traceback関数のプロトタイプが、引数としてvoid*を期待している場合に適切です。しかし、Goランタイムの進化に伴い、runtime·traceback関数のプロトタイプが変更されたか、あるいはコンパイラがよりスマートになり、ポインタ型間の暗黙的な変換を適切に処理できるようになった可能性があります。

具体的には、以下のような理由が考えられます。

  1. runtime·traceback関数のプロトタイプ変更: runtime·traceback関数が、引数としてvoid*ではなく、より具体的なポインタ型(例: uintptr_tや、特定の構造体へのポインタ)を期待するように変更された場合、(void*)キャストは不要になります。むしろ、不必要なキャストはコンパイラに警告を発生させる可能性があります。
  2. コンパイラの進化: 使用されているCコンパイラ(例えば、Goのツールチェーンに含まれるgcコンパイラや、クロスコンパイル環境のGCC/Clang)が、ポインタ型と整数型(特にアドレスを表現するのに十分な幅を持つ整数型)の間で、安全な暗黙的変換をより適切に処理できるようになった可能性があります。この場合、明示的な(void*)キャストは冗長となります。
  3. 型定義の整合性: Goランタイムの内部的な型定義が、レジスタ値を表す型とruntime·tracebackが期待する引数の型との間で、より直接的な互換性を持つようになった可能性があります。これにより、中間的な(void*)キャストが不要になったと考えられます。

このコミットは、これらの理由のいずれか、または複合的な理由により、(void*)キャストを削除することで、コンパイル時の警告を解消し、ビルドプロセスをクリーンに保つことを目的としています。これは、コードの可読性を向上させ、不必要な型変換を避けるという観点からも良いプラクティスです。

影響を受けるファイルは、Plan 9 (386, AMD64) と Windows (386, AMD64) のランタイム固有のCソースファイルです。これは、これらのOS/アーキテクチャのコンテキスト構造体やレジスタの扱いが、他のOS(例: Linux, macOS)とは異なるためです。

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

変更は、以下の4つのファイルにわたって行われています。

  1. src/pkg/runtime/os_plan9_386.c
  2. src/pkg/runtime/os_plan9_amd64.c
  3. src/pkg/runtime/os_windows_386.c
  4. src/pkg/runtime/os_windows_amd64.c

それぞれのファイルで、runtime·traceback関数の呼び出しから、第一引数と第二引数に適用されていた(void*)キャストが削除されています。

例: src/pkg/runtime/os_plan9_386.c の変更

--- a/src/pkg/runtime/os_plan9_386.c
+++ b/src/pkg/runtime/os_plan9_386.c
@@ -95,7 +95,7 @@ Throw:
  	runtime·printf("\n");
 
  	if(runtime·gotraceback(&crash)) {
- 		runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);
+ 		runtime·traceback(ureg->pc, ureg->sp, 0, gp);
  		runtime·tracebackothers(gp);
  		runtime·dumpregs(ureg);
  	}

同様の変更が、他の3つのファイルでも行われています。

  • os_plan9_amd64.c: ureg->ipureg->sp から(void*)キャストを削除。
  • os_windows_386.c: r->Eipr->Esp から(void*)キャストを削除。
  • os_windows_amd64.c: r->Ripr->Rsp から(void*)キャストを削除。

コアとなるコードの解説

変更されたコードは、Goランタイムがパニックやクラッシュなどの致命的なエラーに遭遇した際に、スタックトレースを生成する部分です。

if(runtime·gotraceback(&crash)) の条件は、スタックトレースを生成する必要があるかどうかを判断しています。crash変数は、クラッシュの種類や状態を示すフラグであると考えられます。

条件が真の場合、runtime·traceback関数が呼び出されます。

  • 変更前: runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);

    • ureg->pc (プログラムカウンタ) と ureg->sp (スタックポインタ) の値が、明示的にvoid*にキャストされてruntime·tracebackに渡されていました。
    • 0 はおそらくフレームスキップ数などの追加引数、gp は現在のゴルーチン(goroutine)のポインタです。
  • 変更後: runtime·traceback(ureg->pc, ureg->sp, 0, gp);

    • (void*)キャストが削除され、ureg->pcureg->spの値が直接runtime·tracebackに渡されるようになりました。

この変更は、runtime·traceback関数の内部的なプロトタイプが、これらの引数を直接受け入れられるようになったことを示唆しています。例えば、runtime·tracebackの定義が以下のように変更された可能性があります。

変更前(想定): void runtime·traceback(void* pc, void* sp, int skip, G* gp);

変更後(想定): void runtime·traceback(uintptr_t pc, uintptr_t sp, int skip, G* gp); または、コンパイラがポインタ型とアドレスを表す整数型との間の変換をより柔軟に扱えるようになったため、明示的なキャストが不要になった、という可能性もあります。

この修正により、Plan 9およびWindows環境でのGoランタイムのビルドが、不必要な警告なしにクリーンに完了するようになります。これは、Goのクロスプラットフォーム対応とビルドシステムの健全性を維持するために重要な変更です。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特にsrc/pkg/runtimeディレクトリ内のファイル)
  • C言語のポインタと型キャストに関する一般的な知識
  • Go言語のクロスコンパイルとビルドに関する情報
  • Plan 9オペレーティングシステムに関する一般的な情報
  • Windowsのシステムプログラミングにおけるレジスタとコンテキスト構造に関する情報