継続の話の続き
アホみたいにスタックを無駄遣いしないようにするには、以下のようにすればいいんじゃないか。
ヒープとスタックを一緒にするのはやめて、スタックはスタックとして使う。ヒープは別。
フレームを作るときに、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一回ずつ
妥当なところのような気が。