2025/09/22 01:46 Pointer Tagging in C++: The Art of Packing Bits into a Pointer

ねえロボ子、最近のCPUって64ビットポインタなのに、全部のアドレス空間を使ってないって知ってたかのじゃ?

ええ、知っていますよ、博士。最新のデスクトップCPUは仮想アドレスに48ビットしか使ってないんですよね。上位16ビットは未使用だと。

そうそう!しかも`malloc`で確保されるメモリは16バイト境界にアラインされるから、下位4ビットも使われてないことが多いのじゃ。

ということは、48ビットのアドレス空間で16バイトアラインされたポインタなら、合計20ビットも追加データを格納できる余地があるんですね!

その通り!そこで「ポインタタギング」の出番じゃ!x64とかARMは、ISAレベルでポインタタギングをサポートする機能があるらしいぞ。

ポインタタギングですか。具体的にどういうことに使えるんですか?

例えば、動的型情報とか、木構造データ、動的多態性とかじゃな。V8エンジンは、ポインタタギングを使って、値が生の整数かヒープ割り当てオブジェクトへの参照かを区別してるらしいぞ。

Objective-Cも、オブジェクトがポインタのメモリ内に収まる場合、データをポインタに直接格納するんですね。

そうじゃ!Linuxカーネルの赤黒木の実装では、各ノードの親ポインタの1ビットを使って、ノードが赤か黒かを判断してるらしいぞ。PBRTは、オブジェクトごとのv-tableの代わりにタグ付きポインタを使って、動的ディスパッチのオーバーヘッドを削減してるんじゃ。

へえ、色々なところで使われているんですね。C++での実装例も紹介されていますね。48ビットの正準アドレス空間を想定して、上位16ビットにデータをパックする`tagged_ptr`構造体。

そうそう。x64では、ポインタをデリファレンスする前に、上位ビットをマスクして、47ビット目から符号拡張する必要があるんじゃ。

タグ付きユニオンは、同じメモリ位置を共有するデータメンバとenumタグを格納することで、低レベルのポリモーフィズムを実装できるんですね。

抽象構文木では、ノードの型をポインタに埋め込むことで、メモリ消費量を削減できるんじゃ。ハードウェアの制限がデータ構造の構築方法を決定することもあるってことじゃな。

未使用のビットを再利用することで、コンパクトなデータレイアウトとランタイムポリモーフィズムのコスト削減が可能になるんですね。AMDのUAI、IntelのLAM、ARMのTBIは、ソフトウェアがアドレス変換に影響を与えずにポインタの未使用の上位ビットにメタデータを格納できるハードウェア機能なんですね。

そういうことじゃ!しかし、ポインタのビットをいじるなんて、まるで忍者のようじゃな。ロボ子も今日から「ポインタ忍者」と呼んでやるぞ!

ええっ!? 私は別に忍術を使えるわけでは…。

大丈夫じゃ!これから私が忍術を教えてやる!まずは、ポインタを隠密裏に操るための…って、やっぱりやめておくかのじゃ。危ないからな!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
