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

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

このコミットは、Goランタイムのガベージコレクション(GC)コードから bitSpecial というビットフラグを削除するものです。これは、メモリ管理におけるオブジェクトの状態を示すビットマップの定義と、それに関連するクリア処理、デバッグ出力ロジックに影響を与えます。

コミット

commit 38f6c3f59d590052b43ed71a2350485bdc76ef3e
Author: Dmitriy Vyukov <dvyukov@google.com>
Date:   Tue Mar 11 17:33:03 2014 +0400

    runtime: wipe out bitSpecial from GC code
    
    LGTM=khr, rsc
    R=golang-codereviews, bradfitz, khr
    CC=golang-codereviews, khr, rsc
    https://golang.org/cl/72480044

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

https://github.com/golang/go/commit/38f6c3f59d590052b43ed71a2350485bdc76ef3e

元コミット内容

runtime: wipe out bitSpecial from GC code

このコミットの目的は、Goランタイムのガベージコレクションコードから bitSpecial という概念を完全に排除することです。

変更の背景

Goのガベージコレクションは、ヒープ上のオブジェクトを効率的に管理するために、各オブジェクトの状態をビットマップで表現しています。bitSpecial は、かつてファイナライザを持つオブジェクトやプロファイリング対象のオブジェクトを示すために使用されていたビットフラグでした。

このコミットが行われた2014年3月時点では、GoのGCは大きな進化の途上にありました。初期のGo GCは「マーク・アンド・スイープ」方式を採用しており、その実装は継続的に改善されていました。bitSpecial の削除は、GCの設計変更、特にファイナライザの処理方法やプロファイリングのメカニズムが進化し、この特定のビットフラグが不要になったことを示唆しています。

考えられる背景としては、以下の点が挙げられます。

  1. ファイナライザ処理の変更: ファイナライザを持つオブジェクトの管理方法が変更され、bitSpecial を使ってマークする必要がなくなった可能性があります。例えば、ファイナライザを持つオブジェクトを別のリストで管理したり、GCのマークフェーズとは異なる方法で識別するようになったなどが考えられます。
  2. プロファイリングメカニズムの変更: オブジェクトのプロファイリング方法が変更され、GCのビットマップにその情報を埋め込む必要がなくなった可能性があります。プロファイリングは通常、GCとは独立したメカニズムで行われることが多いため、GCの内部構造からプロファイリング関連のフラグを分離することは、設計のクリーンアップにつながります。
  3. GCの複雑性軽減: 不要なビットフラグを削除することで、GCコードの複雑性を軽減し、保守性を向上させる狙いがあったと考えられます。ビットマップの各ビットはGCのロジックに直接影響するため、不要なビットを削除することは、GCの効率性や正確性にも寄与します。
  4. メモリレイアウトの最適化: ビットマップの各ワードは限られたビット数しか持たないため、不要なビットを削除することで、将来的な拡張性や他の目的のためのビットスペースを確保できる可能性があります。

この変更は、GoランタイムのGCがより洗練され、特定の機能(ファイナライザやプロファイリング)の管理方法が進化していることを示す重要なステップです。

前提知識の解説

このコミットを理解するためには、Goランタイムのメモリ管理とガベージコレクションに関する以下の前提知識が必要です。

  1. Goのメモリ管理:

    • Goランタイムは独自のメモリマネージャを持ち、OSから大きなメモリブロック(アリーナ)を確保し、それを細かく分割してユーザープログラムに割り当てます。
    • ヒープは、Goプログラムが動的に確保するメモリ領域です。
    • MSpan は、Goランタイムが管理するメモリの単位で、連続したページ(通常は8KB)の集合です。MSpan は、特定のサイズのオブジェクトを格納するために使用されます。
  2. Goのガベージコレクション (GC):

    • Goは「マーク・アンド・スイープ」方式のGCを採用しています。
    • マークフェーズ: GCは、到達可能な(プログラムから参照されている)オブジェクトを特定し、マークします。
    • スイープフェーズ: マークされていない(到達不可能な)オブジェクトが占めるメモリを解放し、再利用可能にします。
    • GCビットマップ: GoのGCは、ヒープ上の各オブジェクトの状態を追跡するためにビットマップを使用します。このビットマップは、ヒープのメモリレイアウトに対応しており、各ビットがヒープ上の特定のメモリワード(またはオブジェクト)に関する情報を示します。
      • ビットマップは、ヒープ上のメモリワードごとに複数のビットを割り当て、それぞれ異なる意味を持たせます。例えば、オブジェクトの開始位置、マーク済みかどうか、スキャン済みかどうか、などがビットで表現されます。
      • このコミットのコードコメントにあるように、64ビットシステムでは16ヒープワードあたり1つのビットマップワードが割り当てられ、そのビットマップワード内に複数の種類のビットがパックされています。
  3. ビットフラグとビット演算:

    • uintptr は、ポインタを保持できる符号なし整数型です。ビットフラグの定義によく使われます。
    • << (左シフト): ビットを左にシフトします。1 << N2^N と同じです。
    • | (ビットOR): 複数のビットフラグを組み合わせるために使用します。
    • & (ビットAND): 特定のビットがセットされているかを確認するために使用します。
    • ~ (ビットNOT): ビットを反転させます。~((bitScan|bitMarked)<<shift) は、bitScanbitMarked に対応するビットをクリアするためのマスクを作成します。
  4. bitShift:

    • コード内で bitShift が定義されていますが、これはビットマップワード内で異なる種類のビット(bitAllocated, bitScan, bitMarked, bitSpecial など)がどれだけシフトして配置されているかを示す値です。例えば、bitShift*0bitShift*1bitShift*2bitShift*3 は、それぞれ異なるビット位置に対応します。これにより、1つのビットマップワード内に複数の情報を効率的に格納できます。

技術的詳細

このコミットの核心は、Goランタイムのガベージコレクション(GC)におけるメモリビットマップの定義から bitSpecial フラグを削除することです。

GoのGCは、ヒープ上の各メモリワード(またはオブジェクト)の状態をビットマップで管理します。このビットマップは、src/pkg/runtime/mgc0.c ファイル内で定義されており、各ビットが特定の意味を持ちます。

変更前は、ビットマップワードのレイアウトは以下のようになっていました(コメントより): bitSpecial (16ビット) -> bitMarked (16ビット) -> bitScan/bitBlockBoundary (16ビット) -> bitAllocated (16ビット)

bitSpecial は、ファイナライザを持つオブジェクトやプロファイリング対象のオブジェクトを示すために使用されていました。このコミットでは、この bitSpecial の概念が不要になったため、関連する定義と使用箇所が削除されます。

具体的には、以下の変更が行われています。

  1. bitSpecial マクロの削除:

    • #define bitSpecial ((uintptr)1<<(bitShift*3)) の定義が削除されます。これにより、bitSpecial という名前のビットフラグは存在しなくなります。
  2. bitMask の変更:

    • #define bitMask (bitAllocated | bitScan | bitMarked | bitSpecial) から bitSpecial が削除され、#define bitMask (bitAllocated | bitScan | bitMarked) となります。bitMask は、GCがオブジェクトの状態をクリアする際に使用するマスクの一部であり、bitSpecial が不要になったため、このマスクからも除外されます。
  3. runtime·MSpan_Sweep 関数内のクリア処理の変更:

    • runtime·MSpan_Sweep 関数は、GCのスイープフェーズでメモリをクリーンアップする役割を担っています。
    • 変更前は、*bitp &= ~((bitScan|bitMarked|bitSpecial)<<shift); という行で、bitScanbitMarkedbitSpecial の各ビットをクリアしていました。
    • 変更後は、*bitp &= ~((bitScan|bitMarked)<<shift); となり、bitSpecial のクリア処理が削除されます。これは、bitSpecial が存在しないため、クリアする必要がなくなったことを意味します。
  4. dumpspan 関数内のデバッグ出力の変更:

    • dumpspan 関数は、デバッグ目的でメモリのスパン(MSpan)の状態をダンプする関数です。
    • 変更前は、bool special; という変数が定義され、special = ((bits & bitSpecial) != 0);bitSpecial の状態を取得していました。
    • さらに、runtime·printf(special ? "@" : ""); という行で、bitSpecial がセットされている場合に @ を出力していました。
    • これらの special 変数と関連するロジックが削除されます。これは、bitSpecial が存在しないため、その状態を追跡したり出力したりする必要がなくなったためです。

これらの変更は、bitSpecial がGoランタイムのGCにおいて完全に役割を終え、その存在が不要になったことを明確に示しています。これにより、GCコードの簡素化と、メモリビットマップの効率的な利用が図られています。

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

変更は src/pkg/runtime/mgc0.c ファイルに集中しています。

--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -154,7 +154,7 @@ clearpools(void)
 // so on a 64-bit system there is one bitmap word per 16 heap words.
 // The bits in the word are packed together by type first, then by
 // heap location, so each 64-bit bitmap word consists of, from top to bottom,
-// the 16 bitSpecial bits for the corresponding heap words, then the 16 bitMarked bits,
+// the 16 bitMarked bits for the corresponding heap words,
 // then the 16 bitScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
 // This layout makes it easier to iterate over the bits of a given type.
 //
@@ -174,10 +174,9 @@ clearpools(void)
 #define bitAllocated		((uintptr)1<<(bitShift*0))	/* block start; eligible for garbage collection */
 #define bitScan			((uintptr)1<<(bitShift*1))	/* when bitAllocated is set */
 #define bitMarked		((uintptr)1<<(bitShift*2))	/* when bitAllocated is set */
-#define bitSpecial		((uintptr)1<<(bitShift*3))	/* when bitAllocated is set - has finalizer or being profiled */
+#define bitBlockBoundary	((uintptr)1<<(bitShift*1))	/* when bitAllocated is NOT set - mark for FlagNoGC objects */
 
-#define bitMask (bitAllocated | bitScan | bitMarked | bitSpecial)
+#define bitMask (bitAllocated | bitScan | bitMarked)
 
 // Holding worldsema grants an M the right to try to stop the world.
 // The procedure is:
@@ -1805,8 +1804,8 @@ runtime·MSpan_Sweep(MSpan *s)
 			continue;
 		}
 
-		// Clear mark, scan, and special bits.
-		*bitp &= ~((bitScan|bitMarked|bitSpecial)<<shift);
+		// Clear mark and scan bits.
+		*bitp &= ~((bitScan|bitMarked)<<shift);
 
 		if(cl == 0) {
 			// Free large span.
@@ -1953,7 +1952,7 @@ dumpspan(uint32 idx)
 	byte *p;
 	byte *arena_start;
 	MSpan *s;
-	bool allocated, special;
+	bool allocated;
 
 	s = runtime·mheap.allspans[idx];
 	if(s->state != MSpanInUse)
@@ -1980,7 +1979,6 @@ dumpspan(uint32 idx)
 		bits = *bitp>>shift;
 
 		allocated = ((bits & bitAllocated) != 0);
-		special = ((bits & bitSpecial) != 0);
 
 		for(i=0; i<size; i+=sizeof(void*)) {
 			if(column == 0) {
 			}
 			if(i == 0) {
 				runtime·printf(allocated ? "(" : "[");
-				runtime·printf(special ? "@" : "");
 			} else {
 				runtime·printf(" ");

コアとなるコードの解説

このコミットの主要な変更は、bitSpecial というビットフラグの定義と、それに関連するコードの削除です。

  1. bitSpecial の定義削除:

    • #define bitSpecial ((uintptr)1<<(bitShift*3)) の行が削除されました。これは、bitSpecial がもはやメモリビットマップの一部として使用されないことを意味します。
    • これに伴い、ビットマップのレイアウトに関するコメントも更新され、bitSpecial に関する記述が削除されています。
  2. bitMask の更新:

    • #define bitMask (bitAllocated | bitScan | bitMarked | bitSpecial) から bitSpecial が取り除かれ、#define bitMask (bitAllocated | bitScan | bitMarked) となりました。bitMask は、GCがオブジェクトの状態をクリアする際に使用するビットマスクであり、bitSpecial が不要になったため、このマスクからも除外されました。
  3. runtime·MSpan_Sweep 関数内のビットクリア処理:

    • runtime·MSpan_Sweep は、GCのスイープフェーズで、マークされていないオブジェクトのメモリを解放し、ビットマップをクリーンアップする重要な関数です。
    • 変更前は、*bitp &= ~((bitScan|bitMarked|bitSpecial)<<shift); という行で、bitScanbitMarked、そして bitSpecial の各ビットをクリアしていました。
    • 変更後は、*bitp &= ~((bitScan|bitMarked)<<shift); となり、bitSpecial のクリア処理が削除されました。これは、bitSpecial が存在しないため、クリアする必要がなくなったことを示しています。この変更は、GCの内部ロジックが bitSpecial に依存しなくなったことを直接的に示しています。
  4. dumpspan 関数内のデバッグ出力の変更:

    • dumpspan は、Goランタイムのデバッグツールとして使用される関数で、メモリのスパン(MSpan)の状態を詳細に表示します。
    • 変更前は、bool special; という変数を宣言し、special = ((bits & bitSpecial) != 0);bitSpecial の状態をチェックしていました。
    • さらに、runtime·printf(special ? "@" : ""); という行で、bitSpecial がセットされている場合に @ 記号を出力していました。
    • これらの special 変数と関連するロジックがすべて削除されました。これは、bitSpecial がもはや意味を持たないため、デバッグ情報としても表示する必要がなくなったことを意味します。

これらの変更は、GoランタイムのGCが bitSpecial という概念から完全に脱却し、よりシンプルで効率的なメモリ管理メカニズムへと進化していることを示しています。ファイナライザやプロファイリングの処理が、GCのビットマップとは独立した、より適切な方法で管理されるようになった結果と考えられます。

関連リンク

参考にした情報源リンク

  • Goのコミット履歴とソースコード (src/pkg/runtime/mgc0.c)
  • Goのガベージコレクションに関する一般的な知識
  • ビット演算に関する一般的な知識
  • Go's Garbage Collector: From 1.5 to 1.8 (間接的にGCの進化の方向性を理解するために参照)
  • Go Programming Language Specification (Goのメモリモデルやデータ型に関する基本的な理解のため)
  • Go runtime source code (特に mgc.gomheap.go など、GC関連のファイル)

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

このコミットは、Goランタイムのガベージコレクション(GC)コードから bitSpecial というビットフラグを削除するものです。これは、メモリ管理におけるオブジェクトの状態を示すビットマップの定義と、それに関連するクリア処理、デバッグ出力ロジックに影響を与えます。

コミット

commit 38f6c3f59d590052b43ed71a2350485bdc76ef3e
Author: Dmitriy Vyukov <dvyukov@google.com>
Date:   Tue Mar 11 17:33:03 2014 +0400

    runtime: wipe out bitSpecial from GC code
    
    LGTM=khr, rsc
    R=golang-codereviews, bradfitz, khr
    CC=golang-codereviews, khr, rsc
    https://golang.org/cl/72480044

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

https://github.com/golang/go/commit/38f6c3f59d590052b43ed71a2350485bdc76ef3e

元コミット内容

runtime: wipe out bitSpecial from GC code

このコミットの目的は、Goランタイムのガベージコレクションコードから bitSpecial という概念を完全に排除することです。

変更の背景

Goのガベージコレクションは、ヒープ上のオブジェクトを効率的に管理するために、各オブジェクトの状態をビットマップで表現しています。bitSpecial は、かつてファイナライザを持つオブジェクトやプロファイリング対象のオブジェクトを示すために使用されていたビットフラグでした。

このコミットが行われた2014年3月時点では、GoのGCは大きな進化の途上にありました。初期のGo GCは「マーク・アンド・スイープ」方式を採用しており、その実装は継続的に改善されていました。bitSpecial の削除は、GCの設計変更、特にファイナライザの処理方法やプロファイリングのメカニズムが進化し、この特定のビットフラグが不要になったことを示唆しています。

考えられる背景としては、以下の点が挙げられます。

  1. ファイナライザ処理の変更: ファイナライザを持つオブジェクトの管理方法が変更され、bitSpecial を使ってマークする必要がなくなった可能性があります。例えば、ファイナライザを持つオブジェクトを別のリストで管理したり、GCのマークフェーズとは異なる方法で識別するようになったなどが考えられます。
  2. プロファイリングメカニズムの変更: オブジェクトのプロファイリング方法が変更され、GCのビットマップにその情報を埋め込む必要がなくなった可能性があります。プロファイリングは通常、GCとは独立したメカニズムで行われることが多いため、GCの内部構造からプロファイリング関連のフラグを分離することは、設計のクリーンアップにつながります。
  3. GCの複雑性軽減: 不要なビットフラグを削除することで、GCコードの複雑性を軽減し、保守性を向上させる狙いがあったと考えられます。ビットマップの各ビットはGCのロジックに直接影響するため、不要なビットを削除することは、GCの効率性や正確性にも寄与します。
  4. メモリレイアウトの最適化: ビットマップの各ワードは限られたビット数しか持たないため、不要なビットを削除することで、将来的な拡張性や他の目的のためのビットスペースを確保できる可能性があります。

この変更は、GoランタイムのGCがより洗練され、特定の機能(ファイナライザやプロファイリング)の管理方法が進化していることを示す重要なステップです。

前提知識の解説

このコミットを理解するためには、Goランタイムのメモリ管理とガベージコレクションに関する以下の前提知識が必要です。

  1. Goのメモリ管理:

    • Goランタイムは独自のメモリマネージャを持ち、OSから大きなメモリブロック(アリーナ)を確保し、それを細かく分割してユーザープログラムに割り当てます。
    • ヒープは、Goプログラムが動的に確保するメモリ領域です。
    • MSpan は、Goランタイムが管理するメモリの単位で、連続したページ(通常は8KB)の集合です。MSpan は、特定のサイズのオブジェクトを格納するために使用されます。
  2. Goのガベージコレクション (GC):

    • Goは「マーク・アンド・スイープ」方式のGCを採用しています。
    • マークフェーズ: GCは、到達可能な(プログラムから参照されている)オブジェクトを特定し、マークします。
    • スイープフェーズ: マークされていない(到達不可能な)オブジェクトが占めるメモリを解放し、再利用可能にします。
    • GCビットマップ: GoのGCは、ヒープ上の各オブジェクトの状態を追跡するためにビットマップを使用します。このビットマップは、ヒープのメモリレイアウトに対応しており、各ビットがヒープ上の特定のメモリワード(またはオブジェクト)に関する情報を示します。
      • ビットマップは、ヒープ上のメモリワードごとに複数のビットを割り当て、それぞれ異なる意味を持たせます。例えば、オブジェクトの開始位置、マーク済みかどうか、スキャン済みかどうか、などがビットで表現されます。
      • このコミットのコードコメントにあるように、64ビットシステムでは16ヒープワードあたり1つのビットマップワードが割り当てられ、そのビットマップワード内に複数の種類のビットがパックされています。
  3. ビットフラグとビット演算:

    • uintptr は、ポインタを保持できる符号なし整数型です。ビットフラグの定義によく使われます。
    • << (左シフト): ビットを左にシフトします。1 << N2^N と同じです。
    • | (ビットOR): 複数のビットフラグを組み合わせるために使用します。
    • & (ビットAND): 特定のビットがセットされているかを確認するために使用します。
    • ~ (ビットNOT): ビットを反転させます。~((bitScan|bitMarked)<<shift) は、bitScanbitMarked に対応するビットをクリアするためのマスクを作成します。
  4. bitShift:

    • コード内で bitShift が定義されていますが、これはビットマップワード内で異なる種類のビット(bitAllocated, bitScan, bitMarked, bitSpecial など)がどれだけシフトして配置されているかを示す値です。例えば、bitShift*0bitShift*1bitShift*2bitShift*3 は、それぞれ異なるビット位置に対応します。これにより、1つのビットマップワード内に複数の情報を効率的に格納できます。

技術的詳細

このコミットの核心は、Goランタイムのガベージコレクション(GC)におけるメモリビットマップの定義から bitSpecial フラグを削除することです。

GoのGCは、ヒープ上の各メモリワード(またはオブジェクト)の状態をビットマップで管理します。このビットマップは、src/pkg/runtime/mgc0.c ファイル内で定義されており、各ビットが特定の意味を持ちます。

変更前は、ビットマップワードのレイアウトは以下のようになっていました(コメントより): bitSpecial (16ビット) -> bitMarked (16ビット) -> bitScan/bitBlockBoundary (16ビット) -> bitAllocated (16ビット)

bitSpecial は、ファイナライザを持つオブジェクトやプロファイリング対象のオブジェクトを示すために使用されていました。このコミットでは、この bitSpecial の概念が不要になったため、関連する定義と使用箇所が削除されます。

具体的には、以下の変更が行われています。

  1. bitSpecial マクロの削除:

    • #define bitSpecial ((uintptr)1<<(bitShift*3)) の定義が削除されます。これにより、bitSpecial という名前のビットフラグは存在しなくなります。
  2. bitMask の変更:

    • #define bitMask (bitAllocated | bitScan | bitMarked | bitSpecial) から bitSpecial が削除され、#define bitMask (bitAllocated | bitScan | bitMarked) となります。bitMask は、GCがオブジェクトの状態をクリアする際に使用するマスクの一部であり、bitSpecial が不要になったため、このマスクからも除外されます。
  3. runtime·MSpan_Sweep 関数内のクリア処理の変更:

    • runtime·MSpan_Sweep 関数は、GCのスイープフェーズでメモリをクリーンアップする役割を担っています。
    • 変更前は、*bitp &= ~((bitScan|bitMarked|bitSpecial)<<shift); という行で、bitScanbitMarkedbitSpecial の各ビットをクリアしていました。
    • 変更後は、*bitp &= ~((bitScan|bitMarked)<<shift); となり、bitSpecial のクリア処理が削除されます。これは、bitSpecial が存在しないため、クリアする必要がなくなったことを意味します。
  4. dumpspan 関数内のデバッグ出力の変更:

    • dumpspan 関数は、デバッグ目的でメモリのスパン(MSpan)の状態をダンプする関数です。
    • 変更前は、bool special; という変数が定義され、special = ((bits & bitSpecial) != 0);bitSpecial の状態を取得していました。
    • さらに、runtime·printf(special ? "@" : ""); という行で、bitSpecial がセットされている場合に @ を出力していました。
    • これらの special 変数と関連するロジックが削除されます。これは、bitSpecial が存在しないため、その状態を追跡したり出力したりする必要がなくなったためです。

これらの変更は、bitSpecial がGoランタイムのGCにおいて完全に役割を終え、その存在が不要になったことを明確に示しています。これにより、GCコードの簡素化と、メモリビットマップの効率的な利用が図られています。

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

変更は src/pkg/runtime/mgc0.c ファイルに集中しています。

--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -154,7 +154,7 @@ clearpools(void)
 // so on a 64-bit system there is one bitmap word per 16 heap words.
 // The bits in the word are packed together by type first, then by
 // heap location, so each 64-bit bitmap word consists of, from top to bottom,
-// the 16 bitSpecial bits for the corresponding heap words, then the 16 bitMarked bits,
+// the 16 bitMarked bits for the corresponding heap words,
 // then the 16 bitScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
 // This layout makes it easier to iterate over the bits of a given type.
 //
@@ -174,10 +174,9 @@ clearpools(void)
 #define bitAllocated		((uintptr)1<<(bitShift*0))	/* block start; eligible for garbage collection */
 #define bitScan			((uintptr)1<<(bitShift*1))	/* when bitAllocated is set */
 #define bitMarked		((uintptr)1<<(bitShift*2))	/* when bitAllocated is set */
-#define bitSpecial		((uintptr)1<<(bitShift*3))	/* when bitAllocated is set - has finalizer or being profiled */
+#define bitBlockBoundary	((uintptr)1<<(bitShift*1))	/* when bitAllocated is NOT set - mark for FlagNoGC objects */
 
-#define bitMask (bitAllocated | bitScan | bitMarked | bitSpecial)
+#define bitMask (bitAllocated | bitScan | bitMarked)
 
 // Holding worldsema grants an M the right to try to stop the world.
 // The procedure is:
@@ -1805,8 +1804,8 @@ runtime·MSpan_Sweep(MSpan *s)
 			continue;
 		}
 
-		// Clear mark, scan, and special bits.
-		*bitp &= ~((bitScan|bitMarked|bitSpecial)<<shift);
+		// Clear mark and scan bits.
+		*bitp &= ~((bitScan|bitMarked)<<shift);
 
 		if(cl == 0) {
 			// Free large span.
@@ -1953,7 +1952,7 @@ dumpspan(uint32 idx)
 	byte *p;
 	byte *arena_start;
 	MSpan *s;
-	bool allocated, special;
+	bool allocated;
 
 	s = runtime·mheap.allspans[idx];
 	if(s->state != MSpanInUse)
@@ -1980,7 +1979,6 @@ dumpspan(uint32 idx)
 		bits = *bitp>>shift;
 
 		allocated = ((bits & bitAllocated) != 0);
-		special = ((bits & bitSpecial) != 0);
 
 		for(i=0; i<size; i+=sizeof(void*)) {
 			if(column == 0) {
 			}
 			if(i == 0) {
 				runtime·printf(allocated ? "(" : "[");
-				runtime·printf(special ? "@" : "");
 			} else {
 				runtime·printf(" ");

コアとなるコードの解説

このコミットの主要な変更は、bitSpecial というビットフラグの定義と、それに関連するコードの削除です。

  1. bitSpecial の定義削除:

    • #define bitSpecial ((uintptr)1<<(bitShift*3)) の行が削除されました。これは、bitSpecial がもはやメモリビットマップの一部として使用されないことを意味します。
    • これに伴い、ビットマップのレイアウトに関するコメントも更新され、bitSpecial に関する記述が削除されています。
  2. bitMask の更新:

    • #define bitMask (bitAllocated | bitScan | bitMarked | bitSpecial) から bitSpecial が取り除かれ、#define bitMask (bitAllocated | bitScan | bitMarked) となりました。bitMask は、GCがオブジェクトの状態をクリアする際に使用するビットマスクであり、bitSpecial が不要になったため、このマスクからも除外されました。
  3. runtime·MSpan_Sweep 関数内のビットクリア処理:

    • runtime·MSpan_Sweep は、GCのスイープフェーズで、マークされていないオブジェクトのメモリを解放し、ビットマップをクリーンアップする重要な関数です。
    • 変更前は、*bitp &= ~((bitScan|bitMarked|bitSpecial)<<shift); という行で、bitScanbitMarked、そして bitSpecial の各ビットをクリアしていました。
    • 変更後は、*bitp &= ~((bitScan|bitMarked)<<shift); となり、bitSpecial のクリア処理が削除されました。これは、bitSpecial が存在しないため、クリアする必要がなくなったことを示しています。この変更は、GCの内部ロジックが bitSpecial に依存しなくなったことを直接的に示しています。
  4. dumpspan 関数内のデバッグ出力の変更:

    • dumpspan は、Goランタイムのデバッグツールとして使用される関数で、メモリのスパン(MSpan)の状態を詳細に表示します。
    • 変更前は、bool special; という変数を宣言し、special = ((bits & bitSpecial) != 0);bitSpecial の状態をチェックしていました。
    • さらに、runtime·printf(special ? "@" : ""); という行で、bitSpecial がセットされている場合に @ を出力していました。
    • これらの special 変数と関連するロジックがすべて削除されました。これは、bitSpecial がもはや意味を持たないため、デバッグ情報としても表示する必要がなくなったことを意味します。

これらの変更は、GoランタイムのGCが bitSpecial という概念から完全に脱却し、よりシンプルで効率的なメモリ管理メカニズムへと進化していることを示しています。ファイナライザやプロファイリングの処理が、GCのビットマップとは独立した、より適切な方法で管理されるようになった結果と考えられます。

関連リンク

参考にした情報源リンク

  • Goのコミット履歴とソースコード (src/pkg/runtime/mgc0.c)
  • Goのガベージコレクションに関する一般的な知識
  • ビット演算に関する一般的な知識
  • Go's Garbage Collector: From 1.5 to 1.8 (間接的にGCの進化の方向性を理解するために参照)
  • Go Programming Language Specification (Goのメモリモデルやデータ型に関する基本的な理解のため)
  • Go runtime source code (特に mgc.gomheap.go など、GC関連のファイル)