[インデックス 16564] ファイルの概要
このコミットは、Goランタイムのメモリ管理に関連するファイル src/pkg/runtime/malloc.goc
に変更を加えています。具体的には、メモリのアライメント(整列)処理において、冗長なビット演算による丸め処理を ROUND
マクロの使用に置き換えることで、コードの可読性と保守性を向上させています。
コミット
commit 2ffaefd1618efda434e3176f9bff658fbe70b003
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Thu Jun 13 16:02:50 2013 +0400
runtime: use ROUND macro for rounding
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/10256043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2ffaefd1618efda434e3176f9bff658fbe70b003
元コミット内容
runtime: use ROUND macro for rounding
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/10256043
変更の背景
このコミットの背景には、Goランタイムのメモリ管理コードにおける一貫性と保守性の向上が挙げられます。以前のコードでは、特定のバイト境界に値を丸める(アライメントする)ために、((value + (alignment - 1)) & ~(alignment - 1))
のようなビット演算が複数箇所で直接使用されていました。このパターンはメモリ管理において一般的ですが、コード中に散在すると冗長になり、理解しにくく、また将来的な変更やバグ修正の際にエラーを引き起こす可能性がありました。
ROUND
マクロを導入することで、この共通の丸めロジックが抽象化され、コードの重複が排除されます。これにより、malloc.goc
内のメモリ割り当てやサイズ計算のロジックがより明確になり、開発者がコードの意図を素早く把握できるようになります。また、もし丸めロジック自体に変更が必要になった場合でも、ROUND
マクロの定義を一度修正するだけで済むため、メンテナンスが容易になります。
前提知識の解説
1. Goランタイム (Go Runtime)
Goランタイムは、Goプログラムの実行を管理する低レベルのシステムです。これには、ガベージコレクション(GC)、スケジューラ(ゴルーチンの管理)、メモリ割り当て、システムコールインターフェースなどが含まれます。Goプログラムは、オペレーティングシステム上で直接実行されるのではなく、このランタイム上で動作します。src/pkg/runtime/
ディレクトリには、これらのランタイムのコアコンポーネントのソースコードが含まれています。
2. メモリのアライメント (Memory Alignment)
メモリのアライメントとは、データがメモリ上で特定のバイト境界に配置されることを保証するプロセスです。CPUは、特定のバイト境界(例: 4バイト、8バイト、16バイトなど)にアライメントされたデータにアクセスする方が、アライメントされていないデータにアクセスするよりも効率的です。アライメントされていないアクセスは、パフォーマンスの低下や、場合によってはハードウェアエラー(特に一部のアーキテクチャで)を引き起こす可能性があります。
例えば、4バイトのアライメントが必要な場合、データの開始アドレスは4の倍数でなければなりません。もしデータがアドレス 0x1001
から始まる場合、これは4の倍数ではないため、アライメントされていません。アライメントを保証するためには、アドレスを次の4の倍数(0x1004
)に「丸める」必要があります。
3. ビット演算による丸め (Bitwise Rounding)
特定のバイト境界 N
に値を X
を丸める一般的なビット演算のテクニックは以下の通りです。
Y = (X + (N - 1)) & ~(N - 1)
ここで、N
は2のべき乗である必要があります(例: 4, 8, 16, 256, PageSizeなど)。
N - 1
:N
が2のべき乗の場合、N - 1
はすべての下位ビットが1であるバイナリ表現になります(例:N=4 (0100b)
の場合、N-1=3 (0011b)
)。~(N - 1)
:N - 1
のビットを反転させると、N
の位置より下位のビットがすべて0になります(例:N=4
の場合、~(0011b) = 1100b
)。これは、N
の倍数を示すマスクとして機能します。X + (N - 1)
:X
にN - 1
を加えることで、X
がN
の倍数でない場合でも、次のN
の倍数に「到達」するように値を持ち上げます。& ~(N - 1)
: このビットAND演算により、N
の倍数でない部分(下位ビット)が切り捨てられ、結果としてN
の最も近い上位の倍数に丸められます。
例: X = 10
、N = 4
の場合
N - 1 = 3
~(N - 1) = ~3 = ...1100b
(2の補数表現では0xFFFFFFFC
など)X + (N - 1) = 10 + 3 = 13 (1101b)
(X + (N - 1)) & ~(N - 1) = 13 & (~3) = 1101b & ...1100b = 1100b = 12
結果として10が4の倍数である12に丸められます。
4. malloc.goc
malloc.goc
はGoランタイムのメモリ割り当て(malloc)システムの一部を実装しているファイルです。Goのガベージコレクタと連携して、ヒープメモリの管理、アリーナ(大きなメモリ領域)の予約、スパン(連続したメモリページ)の管理などを行います。このファイル内の処理は、Goプログラムのパフォーマンスと安定性に直接影響します。
技術的詳細
このコミットは、Goランタイムのメモリ管理コードにおける特定のパターンを抽象化し、ROUND
マクロとしてカプセル化することで、コードの品質を向上させています。
ROUND
マクロは、おそらく以下のような定義を持つと推測されます(GoのC言語風のソースコードにおける慣例から):
#define ROUND(val, align) (((val) + ((align) - 1)) & ~((align) - 1))
このマクロは、与えられた val
を align
の倍数に切り上げる処理を行います。align
は2のべき乗である必要があります。
コミットの変更点を見ると、spans_size
や needed
といったメモリ領域のサイズ計算、および want
のようなアドレス計算において、この ROUND
マクロが適用されています。これらの変数は、Goランタイムがヒープメモリを管理する上で重要な役割を果たします。
spans_size
: メモリのスパン(連続したメモリページ)を管理するためのメタデータ領域のサイズ。このサイズはPageSize
の倍数に丸められる必要があります。arena_size
: Goランタイムが使用する大きなメモリ領域(アリーナ)のサイズ。needed
: 新たに確保する必要があるアリーナの追加サイズ。これは256MB
の倍数に丸められています。want
:SysReserve
(OSからメモリを予約するシステムコール)に渡す、希望する仮想アドレス。これは1MB
の倍数に丸められています。nret
:SetFinalizer
関数内で、戻り値のサイズを計算する際に、型のアライメントに合わせて丸められています。
これらの丸め処理を ROUND
マクロに統一することで、コードの意図がより明確になり、「この値は特定のアライメントに丸められている」ということが一目でわかるようになります。これは、低レベルのシステムプログラミング、特にメモリ管理において非常に重要です。
コアとなるコードの変更箇所
変更は src/pkg/runtime/malloc.goc
ファイルに集中しています。
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -354,8 +354,7 @@ runtime·mallocinit(void)
arena_size = MaxMem;
bitmap_size = arena_size / (sizeof(void*)*8/4);
spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
- // round spans_size to pages
- spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
+ spans_size = ROUND(spans_size, PageSize);
for(i = 0; i <= 0x7f; i++) {
p = (void*)(i<<40 | 0x00c0ULL<<32);
p = runtime·SysReserve(p, bitmap_size + spans_size + arena_size);
@@ -389,8 +388,7 @@ runtime·mallocinit(void)
arena_size = bitmap_size * 8;
spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
}
- // round spans_size to pages
- spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
+ spans_size = ROUND(spans_size, PageSize);
// SysReserve treats the address we ask for, end, as a hint,
// not as an absolute requirement. If we ask for the end
@@ -401,7 +399,7 @@ runtime·mallocinit(void)
// So adjust it upward a little bit ourselves: 1/4 MB to get
// away from the running binary image and then round up
// to a MB boundary.
- want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+ want = (byte*)ROUND((uintptr)end + 1<<18, 1<<20);
p = runtime·SysReserve(want, bitmap_size + spans_size + arena_size);
if(p == nil)
runtime·throw("runtime: cannot reserve arena virtual address space");
@@ -438,8 +436,7 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
uintptr needed;
needed = (uintptr)h->arena_used + n - (uintptr)h->arena_end;
- // Round wanted arena size to a multiple of 256MB.
- needed = (needed + (256<<20) - 1) & ~((256<<20)-1);
+ needed = ROUND(needed, 256<<20);
new_end = h->arena_end + needed;
if(new_end <= h->arena_start + MaxArena32) {
p = runtime·SysReserve(h->arena_end, new_end - h->arena_end);
@@ -865,10 +862,9 @@ func SetFinalizer(obj Eface, finalizer Eface) {
// compute size needed for return parameters
for(i=0; i<ft->out.len; i++) {
t = ((Type**)ft->out.array)[i];
- nret = (nret + t->align - 1) & ~(t->align - 1);
- nret += t->size;
+ nret = ROUND(nret, t->align) + t->size;
}
- nret = (nret + sizeof(void*)-1) & ~(sizeof(void*)-1);
+ nret = ROUND(nret, sizeof(void*));
}
if(!runtime·addfinalizer(obj.data, finalizer.data, nret)) {
コアとなるコードの解説
このコミットでは、malloc.goc
内の複数の箇所で、特定のバイト境界への丸め処理が、直接的なビット演算から ROUND
マクロの呼び出しへと変更されています。
-
spans_size
の丸め:- 変更前:
spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
- 変更後:
spans_size = ROUND(spans_size, PageSize);
PageShift
はページサイズを決定するシフト量であり、1<<PageShift
はPageSize
に相当します。この変更は、spans_size
をメモリページの境界に丸める処理をROUND
マクロに置き換えています。これは、スパンのメタデータがページ境界に整列されることを保証し、メモリ管理の効率を高めます。
- 変更前:
-
want
アドレスの丸め:- 変更前:
want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
- 変更後:
want = (byte*)ROUND((uintptr)end + 1<<18, 1<<20);
1<<18
は256KB、1<<20
は1MBを表します。この行は、SysReserve
に渡す希望アドレスwant
を計算しています。元のend
アドレスから256KBオフセットし、その結果を1MBの境界に丸めています。これは、OSがメモリを割り当てる際に、既存のバイナリイメージから十分に離れたアドレスを選択し、かつ効率的な1MB境界に整列させるための処理です。
- 変更前:
-
needed
サイズの丸め:- 変更前:
needed = (needed + (256<<20) - 1) & ~((256<<20)-1);
- 変更後:
needed = ROUND(needed, 256<<20);
256<<20
は256MBを表します。この変更は、新たに必要となるアリーナのサイズneeded
を256MBの倍数に丸める処理をROUND
マクロに置き換えています。これは、大きなメモリブロックの割り当てを効率的に行うための戦略です。
- 変更前:
-
SetFinalizer
内のnret
の丸め:- 変更前:
nret = (nret + t->align - 1) & ~(t->align - 1);
- 変更後:
nret = ROUND(nret, t->align) + t->size;
SetFinalizer
関数は、オブジェクトがガベージコレクションされる前に実行されるファイナライザを設定します。この部分では、ファイナライザの戻り値のサイズnret
を計算しています。t->align
は型の推奨アライメントです。変更前は、nret
をt->align
の倍数に丸めてからt->size
を加えていましたが、変更後はROUND
マクロを使用してより簡潔に表現されています。- 変更前:
nret = (nret + sizeof(void*)-1) & ~(sizeof(void*)-1);
- 変更後:
nret = ROUND(nret, sizeof(void*));
- この行は、最終的な
nret
をポインタサイズ(sizeof(void*)
)の倍数に丸めています。これは、スタックフレームやレジスタに値を配置する際の効率と正確性を保証するためです。
- 変更前:
これらの変更はすべて、特定のバイト境界への丸め処理を ROUND
マクロに集約することで、コードの重複を排除し、可読性を高め、将来的なメンテナンスを容易にすることを目的としています。
関連リンク
- Go言語のソースコード: https://github.com/golang/go
- Goのメモリ管理に関するドキュメント(Goのバージョンによって異なる場合がありますが、一般的な概念は共通です): Goの公式ドキュメントやブログ記事を参照。
参考にした情報源リンク
- Goのソースコード(
src/pkg/runtime/malloc.goc
および関連ファイル) - 一般的なメモリ管理とアライメントに関するプログラミングの知識
- ビット演算による丸め処理の一般的なテクニック
- Goのコミット履歴とコードレビューコメント (golang.org/cl/10256043)# [インデックス 16564] ファイルの概要
このコミットは、Goランタイムのメモリ管理に関連するファイル src/pkg/runtime/malloc.goc
に変更を加えています。具体的には、メモリのアライメント(整列)処理において、冗長なビット演算による丸め処理を ROUND
マクロの使用に置き換えることで、コードの可読性と保守性を向上させています。
コミット
commit 2ffaefd1618efda434e3176f9bff658fbe70b003
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Thu Jun 13 16:02:50 2013 +0400
runtime: use ROUND macro for rounding
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/10256043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2ffaefd1618efda434e3176f9bff658fbe70b003
元コミット内容
runtime: use ROUND macro for rounding
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/10256043
変更の背景
このコミットの背景には、Goランタイムのメモリ管理コードにおける一貫性と保守性の向上が挙げられます。以前のコードでは、特定のバイト境界に値を丸める(アライメントする)ために、((value + (alignment - 1)) & ~(alignment - 1))
のようなビット演算が複数箇所で直接使用されていました。このパターンはメモリ管理において一般的ですが、コード中に散在すると冗長になり、理解しにくく、また将来的な変更やバグ修正の際にエラーを引き起こす可能性がありました。
ROUND
マクロを導入することで、この共通の丸めロジックが抽象化され、コードの重複が排除されます。これにより、malloc.goc
内のメモリ割り当てやサイズ計算のロジックがより明確になり、開発者がコードの意図を素早く把握できるようになります。また、もし丸めロジック自体に変更が必要になった場合でも、ROUND
マクロの定義を一度修正するだけで済むため、メンテナンスが容易になります。
前提知識の解説
1. Goランタイム (Go Runtime)
Goランタイムは、Goプログラムの実行を管理する低レベルのシステムです。これには、ガベージコレクション(GC)、スケジューラ(ゴルーチンの管理)、メモリ割り当て、システムコールインターフェースなどが含まれます。Goプログラムは、オペレーティングシステム上で直接実行されるのではなく、このランタイム上で動作します。src/pkg/runtime/
ディレクトリには、これらのランタイムのコアコンポーネントのソースコードが含まれています。
2. メモリのアライメント (Memory Alignment)
メモリのアライメントとは、データがメモリ上で特定のバイト境界に配置されることを保証するプロセスです。CPUは、特定のバイト境界(例: 4バイト、8バイト、16バイトなど)にアライメントされたデータにアクセスする方が、アライメントされていないデータにアクセスするよりも効率的です。アライメントされていないアクセスは、パフォーマンスの低下や、場合によってはハードウェアエラー(特に一部のアーキテクチャで)を引き起こす可能性があります。
例えば、4バイトのアライメントが必要な場合、データの開始アドレスは4の倍数でなければなりません。もしデータがアドレス 0x1001
から始まる場合、これは4の倍数ではないため、アライメントされていません。アライメントを保証するためには、アドレスを次の4の倍数(0x1004
)に「丸める」必要があります。
3. ビット演算による丸め (Bitwise Rounding)
特定のバイト境界 N
に値を X
を丸める一般的なビット演算のテクニックは以下の通りです。
Y = (X + (N - 1)) & ~(N - 1)
ここで、N
は2のべき乗である必要があります(例: 4, 8, 16, 256, PageSizeなど)。
N - 1
:N
が2のべき乗の場合、N - 1
はすべての下位ビットが1であるバイナリ表現になります(例:N=4 (0100b)
の場合、N-1=3 (0011b)
)。~(N - 1)
:N - 1
のビットを反転させると、N
の位置より下位のビットがすべて0になります(例:N=4
の場合、~(0011b) = 1100b
)。これは、N
の倍数を示すマスクとして機能します。X + (N - 1)
:X
にN - 1
を加えることで、X
がN
の倍数でない場合でも、次のN
の倍数に「到達」するように値を持ち上げます。& ~(N - 1)
: このビットAND演算により、N
の倍数でない部分(下位ビット)が切り捨てられ、結果としてN
の最も近い上位の倍数に丸められます。
例: X = 10
、N = 4
の場合
N - 1 = 3
~(N - 1) = ~3 = ...1100b
(2の補数表現では0xFFFFFFFC
など)X + (N - 1) = 10 + 3 = 13 (1101b)
(X + (N - 1)) & ~(N - 1) = 13 & (~3) = 1101b & ...1100b = 1100b = 12
結果として10が4の倍数である12に丸められます。
4. malloc.goc
malloc.goc
はGoランタイムのメモリ割り当て(malloc)システムの一部を実装しているファイルです。Goのガベージコレクタと連携して、ヒープメモリの管理、アリーナ(大きなメモリ領域)の予約、スパン(連続したメモリページ)の管理などを行います。このファイル内の処理は、Goプログラムのパフォーマンスと安定性に直接影響します。
技術的詳細
このコミットは、Goランタイムのメモリ管理コードにおける特定のパターンを抽象化し、ROUND
マクロとしてカプセル化することで、コードの品質を向上させています。
ROUND
マクロは、おそらく以下のような定義を持つと推測されます(GoのC言語風のソースコードにおける慣例から):
#define ROUND(val, align) (((val) + ((align) - 1)) & ~((align) - 1))
このマクロは、与えられた val
を align
の倍数に切り上げる処理を行います。align
は2のべき乗である必要があります。
コミットの変更点を見ると、spans_size
や needed
といったメモリ領域のサイズ計算、および want
のようなアドレス計算において、この ROUND
マクロが適用されています。これらの変数は、Goランタイムがヒープメモリを管理する上で重要な役割を果たします。
spans_size
: メモリのスパン(連続したメモリページ)を管理するためのメタデータ領域のサイズ。このサイズはPageSize
の倍数に丸められる必要があります。arena_size
: Goランタイムが使用する大きなメモリ領域(アリーナ)のサイズ。needed
: 新たに確保する必要があるアリーナの追加サイズ。これは256MB
の倍数に丸められています。want
:SysReserve
(OSからメモリを予約するシステムコール)に渡す、希望する仮想アドレス。これは1MB
の倍数に丸められています。nret
:SetFinalizer
関数内で、戻り値のサイズを計算する際に、型のアライメントに合わせて丸められています。
これらの丸め処理を ROUND
マクロに統一することで、コードの意図がより明確になり、「この値は特定のアライメントに丸められている」ということが一目でわかるようになります。これは、低レベルのシステムプログラミング、特にメモリ管理において非常に重要です。
コアとなるコードの変更箇所
変更は src/pkg/runtime/malloc.goc
ファイルに集中しています。
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -354,8 +354,7 @@ runtime·mallocinit(void)
arena_size = MaxMem;
bitmap_size = arena_size / (sizeof(void*)*8/4);
spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
- // round spans_size to pages
- spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
+ spans_size = ROUND(spans_size, PageSize);
for(i = 0; i <= 0x7f; i++) {
p = (void*)(i<<40 | 0x00c0ULL<<32);
p = runtime·SysReserve(p, bitmap_size + spans_size + arena_size);
@@ -389,8 +388,7 @@ runtime·mallocinit(void)
arena_size = bitmap_size * 8;
spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
}
- // round spans_size to pages
- spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
+ spans_size = ROUND(spans_size, PageSize);
// SysReserve treats the address we ask for, end, as a hint,
// not as an absolute requirement. If we ask for the end
@@ -401,7 +399,7 @@ runtime·mallocinit(void)
// So adjust it upward a little bit ourselves: 1/4 MB to get
// away from the running binary image and then round up
// to a MB boundary.
- want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+ want = (byte*)ROUND((uintptr)end + 1<<18, 1<<20);
p = runtime·SysReserve(want, bitmap_size + spans_size + arena_size);
if(p == nil)
runtime·throw("runtime: cannot reserve arena virtual address space");
@@ -438,8 +436,7 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
uintptr needed;
needed = (uintptr)h->arena_used + n - (uintptr)h->arena_end;
- // Round wanted arena size to a multiple of 256MB.
- needed = (needed + (256<<20) - 1) & ~((256<<20)-1);
+ needed = ROUND(needed, 256<<20);
new_end = h->arena_end + needed;
if(new_end <= h->arena_start + MaxArena32) {
p = runtime·SysReserve(h->arena_end, new_end - h->arena_end);
@@ -865,10 +862,9 @@ func SetFinalizer(obj Eface, finalizer Eface) {
// compute size needed for return parameters
for(i=0; i<ft->out.len; i++) {
t = ((Type**)ft->out.array)[i];
- nret = (nret + t->align - 1) & ~(t->align - 1);
- nret += t->size;
+ nret = ROUND(nret, t->align) + t->size;
}
- nret = (nret + sizeof(void*)-1) & ~(sizeof(void*)-1);
+ nret = ROUND(nret, sizeof(void*));
}
if(!runtime·addfinalizer(obj.data, finalizer.data, nret)) {
コアとなるコードの解説
このコミットでは、malloc.goc
内の複数の箇所で、特定のバイト境界への丸め処理が、直接的なビット演算から ROUND
マクロの呼び出しへと変更されています。
-
spans_size
の丸め:- 変更前:
spans_size = (spans_size + ((1<<PageShift) - 1)) & ~((1<<PageShift) - 1);
- 変更後:
spans_size = ROUND(spans_size, PageSize);
PageShift
はページサイズを決定するシフト量であり、1<<PageShift
はPageSize
に相当します。この変更は、spans_size
をメモリページの境界に丸める処理をROUND
マクロに置き換えています。これは、スパンのメタデータがページ境界に整列されることを保証し、メモリ管理の効率を高めます。
- 変更前:
-
want
アドレスの丸め:- 変更前:
want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
- 変更後:
want = (byte*)ROUND((uintptr)end + 1<<18, 1<<20);
1<<18
は256KB、1<<20
は1MBを表します。この行は、SysReserve
に渡す希望アドレスwant
を計算しています。元のend
アドレスから256KBオフセットし、その結果を1MBの境界に丸めています。これは、OSがメモリを割り当てる際に、既存のバイナリイメージから十分に離れたアドレスを選択し、かつ効率的な1MB境界に整列させるための処理です。
- 変更前:
-
needed
サイズの丸め:- 変更前:
needed = (needed + (256<<20) - 1) & ~((256<<20)-1);
- 変更後:
needed = ROUND(needed, 256<<20);
256<<20
は256MBを表します。この変更は、新たに必要となるアリーナのサイズneeded
を256MBの倍数に丸める処理をROUND
マクロに置き換えています。これは、大きなメモリブロックの割り当てを効率的に行うための戦略です。
- 変更前:
-
SetFinalizer
内のnret
の丸め:- 変更前:
nret = (nret + t->align - 1) & ~(t->align - 1);
- 変更後:
nret = ROUND(nret, t->align) + t->size;
SetFinalizer
関数は、オブジェクトがガベージコレクションされる前に実行されるファイナライザを設定します。この部分では、ファイナライザの戻り値のサイズnret
を計算しています。t->align
は型の推奨アライメントです。変更前は、nret
をt->align
の倍数に丸めてからt->size
を加えていましたが、変更後はROUND
マクロを使用してより簡潔に表現されています。- 変更前:
nret = (nret + sizeof(void*)-1) & ~(sizeof(void*)-1);
- 変更後:
nret = ROUND(nret, sizeof(void*));
- この行は、最終的な
nret
をポインタサイズ(sizeof(void*)
)の倍数に丸めています。これは、スタックフレームやレジスタに値を配置する際の効率と正確性を保証するためです。
- 変更前:
これらの変更はすべて、特定のバイト境界への丸め処理を ROUND
マクロに集約することで、コードの重複を排除し、可読性を高め、将来的なメンテナンスを容易にすることを目的としています。
関連リンク
- Go言語のソースコード: https://github.com/golang/go
- Goのメモリ管理に関するドキュメント(Goのバージョンによって異なる場合がありますが、一般的な概念は共通です): Goの公式ドキュメントやブログ記事を参照。
参考にした情報源リンク
- Goのソースコード(
src/pkg/runtime/malloc.goc
および関連ファイル) - 一般的なメモリ管理とアライメントに関するプログラミングの知識
- ビット演算による丸め処理の一般的なテクニック
- Goのコミット履歴とコードレビューコメント (golang.org/cl/10256043)