#
# calloc() の落とし穴
# 2002/09/17 Naoyuki Sawa
#
# 症状	ヒープの残りがまだ充分あるのに、割当てに失敗する場合がある。
#	<例>
#	ヒープの残りが32KBの時に、1バイト単位で16K個の割当て:
#		calloc(16384, 1)
#	を行うと失敗する。16Kバイト単位で1個の割当て:
#		calloc(1, 16384)
#		malloc(16384)
#	ならば成功する。なぜか？
#
# 原因	実際に割当てるバイト数を計算するときに、
#		実際に割当てるバイト数 = 割当て数 × 割当て単位
#	を計算するが、この計算よりも*先に*割当て単位を4バイト単位に切り上げている。
#	従って、先ほどの例:
#		calloc(16384, 1)
#	による実際の割当てバイト数は、
#		16384 + (1 + 3 & ~3) = 16384 × 4 = 65536
#	となり、残りヒープ容量よりも大きくなり、割当て失敗する。
#	仮に残りヒープ容量が充分あり割当て成功したとしても、かなり無駄な割当てが発生している。
#
#	このふるまいはcalloc()の正しい仕様に合致しています。
#	ライブラリの実装には問題ありません。
#
# 対策	・calloc()で特に割当て単位を意識しない場合（単にゼロクリアを利用したい場合）は、
#		calloc(割当てバイト数, 1) /* 悪い例 */
#	　*ではなく*
#		calloc(1, 割当てバイト数) /* 良い例 */
#	　の形式で利用する。
#	・calloc()は使わない。malloc()とmemset()によるゼロフィルに分解する。
#

calloc:
0010D98C   0201	pushn %r1
0010D98E   680C	cmp %r12, 0x0		if(num == 0) then 0010D9BC
0010D990   1816	jreq 0x16
0010D992   680D	cmp %r13, 0x0		if(size == 0) then 0010D9BC
0010D994   1814	jreq 0x14
0010D996   C003	ext 0x3			%r10 = size + 3 & ~3 ←※ここに注目！num×sizeする前にsizeが4バイト単位に切り上げられる
0010D998   22DA	add %r10, %r13
0010D99A   73CA	and %r10, 0x3C
0010D99C   AAAC	mlt.w %r12, %r10	%alr = (short)num * (short)size
0010D99E   A421	ld.w %r1, %alr		%r1 = %alr
0010D9A0   2E1C	ld.w %r12, %r1		%r12 = %r1
0010D9A2   DFF8	ext 0x1FF8		たぶん %r10 = malloc(%r12)
0010D9A4   DFFE	ext 0x1FFE
0010D9A6   1C63	call 0x63
0010D9A8   2EA0	ld.w %r0, %r10		%r0 = %r10
0010D9AA   6800	cmp %r0, 0x0		if %r0 == NULL then 0010D9BC
0010D9AC   1808	jreq 0x8
0010D9AE   2E0C	ld.w %r12, %r0		%r12 = %r0 ... 確保したメモリブロックの先頭アドレス
0010D9B0   2E1D	ld.w %r13, %r1		%r13 = %r1 ... メモリブロックのサイズ
0010D9B2   DFF8	ext 0x1FF8		たぶん internal_memory_zero_fill_function(%r12, %r13)
0010D9B4   DFFF	ext 0x1FFF
0010D9B6   1C2C	call 0x2C
0010D9B8   2E0A	ld.w %r10, %r0		retval = %r10 ... 確保したメモリブロックの先頭アドレス
0010D9BA   1E02	jp 0x2			goto 0010D9BE
0010D9BC   6C0A	ld.w %r10, 0x0		retval = NULL
0010D9BE   0241	popn %r1
0010D9C0   0640	ret
