継続の話の続き

アホみたいにスタックを無駄遣いしないようにするには、以下のようにすればいいんじゃないか。


ヒープとスタックを一緒にするのはやめて、スタックはスタックとして使う。ヒープは別。

フレームを作るときに、1 word 分余計に確保する。
んで、こんな感じ

func:
	movl	%esp, %ebp
	subl	$12, %esp   # ここで1word余分に
	movb	$0, (%ebp)     # んで、余分に確保したぶんを0にしとく

	# ... なんか
	# どっかで継続を作ったら、余分に確保したところを0以外に
	
	decb	(%ebp)         # 継続を作ってなかったら 0 -> 0xff
	cmovo	%ebp, %esp     # なのでオーバーフローしたときだけesp戻す
	ret

にしておく。
継続作るときに、バックトレースをたどって、余計に確保したところをinc。
すれば、前回のと違って、継続を作らない限り無駄にスタック使うことはないはず。
コストは、

  • 継続を作らないときは return ごとにdec + cmov一回ずつと、フレームサイズ+4。関数呼ぶごとにmovb一回。
  • 継続を作るコストはバックトレースたどる + フレームごとにinc一回ずつ

妥当なところのような気が。