plop
__code cs_a(int num) { : : goto cs_b(); } |
Cの継続 |
CbCの継続(軽量継続) |
|
|
__code print_factorial(int prod) { printf("factorial = %d\n",prod); exit(0); } __code factorial0(int prod, int x) { if ( x >= 1) { goto factorial0(prod*x, x-1); }else{ goto print_factorial(prod); } } __code factorial(int x) { goto factorial0(1, x); } int main(int argc, char **argv) { int i; i = atoi(argv[1]); goto factorial(i); } |
|
void f(int a, int b) { printf("f: a=%d b=%d\n",a,b); return ; } void g(int a, int b){ printf("g: a=%d b=%d\n",a,b); f(a,b); return; } int main() { g(3,4); return 0; } |
x86/Linux | x86/OS X (10.7) |
void func(){ A; B; } int main() { func(); func(); } |
int main() { A; B; A; B; } |
最適化なし | GCC-4.5の最適化(-O2) | GCC-4.6の最適化(-O2) |
__code func(int, func*);
__code func(int, __code (*)());
__code func(int, __code ()(int, __code()(int, __code(*)(int, ...))))
__code func(int, rectype*);
しかし状態のいくつかへは関数ポインタとして保存させておき継続を行う。
__code g(int i,stack sp) { // Caller struct f_g0_interface c = (struct f_g0_interface )(sp -= sizeof(struct f_g0_interface)); c->ret = g_h1; c->i_ = i; goto h(i+3,sp); } __code h(int i,stack sp) { struct f_g0_interface c = (struct f_g0_interface )sp; goto (c->ret)(i+4,sp); }
関数ポインタへの継続はインライン展開されない。
以下の使い方の場合、戻値 1 を返す。
code c1(code ret(int,void ),void env) { goto ret(1,env); } int main() { goto c1(return, environment); }
今回この環境付き継続をスレッドセーフの実装へと修正した。
fastcall無し |
fastcall有り |
void funcA(int a, int b) { funcB(b, a); }
x86/Linux | x86/OS X (10.7) |
CbC-GCC-4.5 | CbC-GCC-4.6 |
main: call f : jmp f_g0 : movq $f_g1, -24(%rdx) addl $10, %edi movq $g_h1, -48(%rdx) jmp g_h1 : movq 24(%rsi), %rdx movq %rax, %rsi : jmp *%rdx : movq 24(%rsi), %rdx : jmp *%rdx |
main: movq $f_g1, main_stack+2000(%rip) : call g_h1 : movq 24(%rax), %rdx : jmp *%rdx : movq 24(%rax), %rdx : jmp *%rdx |
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |