test
	| a b |
	a := 16rFFFFFFFF.
	b := 4294967295.
	^ a == b.

とかいうやつを作ってみる。
バイトコードを見てみると

9 <20> pushConstant: 4294967295
10 <68> popIntoTemp: 0
11 <20> pushConstant: 4294967295
12 <69> popIntoTemp: 1
13 <10> pushTemp: 0
14 <11> pushTemp: 1
15  send: ==
16 <7C> returnTop

となっている。
9バイト目も11バイト目も同じバイトコードなので、明らかに4294967295は同じ4294967295ということが分かる。
一応念のために調べてみると、バイトコード 16r20 は pushLiteralConstantBytecode だそうです。
これまた念のために確認しておくと、

Interpreter>>pushLiteralConstantBytecode
	self fetchNextBytecode.
	"this bytecode will be expanded so that refs to currentBytecode below will be constant"
	self pushLiteralConstant: (currentBytecode bitAnd: 16r1F).

らしいので、要するに、16r20は「リテラルフレームの0番目をスタックにプッシュせよ」ということになる。
勿論、リテラルフレームは #(4294967295)です。

というような見方も出来るようになりました、と何となく報告。


で、それはそうと、ではこのリテラルフレームがどう作られるのか?
という元々の疑問を、id:sumimさんの助言を参考にして追ってる。
リテラルトークンを実際にオブジェクトに変換すという作業はScannerのレベルでそうなっている。
で、Parserはコードをパースする過程でリテラルに出くわすたびに、それをLiteralDictionaryに詰め込んでいる。
LiteralDictionaryはDictionaryの一種なので、ここで同値なオブジェクトが同一なオブジェクトになる。
なるほど。