improved and documented new stack-registration trampoline

svn: r10677
This commit is contained in:
Matthew Flatt 2008-07-08 15:31:06 +00:00
parent c127e5fdb7
commit d406fb6dcf
6 changed files with 92 additions and 40 deletions

View File

@ -688,7 +688,7 @@ Registers an extension's global variable that can contain Scheme
@function[(int scheme_main_setup @function[(int scheme_main_setup
[int no_auto_statics] [int no_auto_statics]
[Scheme_Main main] [Scheme_Env_Main main]
[int argc] [int argc]
[char** argv])]{ [char** argv])]{
@ -697,10 +697,10 @@ calling @cpp{scheme_basic_env}, and then calls @var{main} with the
namespace, @var{argc}, and @var{argv}. (The @var{argc} and @var{argv} namespace, @var{argc}, and @var{argv}. (The @var{argc} and @var{argv}
are just passed on to @var{main}, and are not inspected in any way.) are just passed on to @var{main}, and are not inspected in any way.)
The @cpp{Scheme_Main} type is defined as follows: The @cpp{Scheme_Env_Main} type is defined as follows:
@verbatim[#:indent 4]{ @verbatim[#:indent 4]{
typedef int (*Scheme_Main)(Scheme_Env *env, typedef int (*Scheme_Env_Main)(Scheme_Env *env,
int argc, char **argv); int argc, char **argv);
} }
@ -711,6 +711,24 @@ explicitly registered with the garbage collector; see
@secref["im:memoryalloc"] for more information.} @secref["im:memoryalloc"] for more information.}
@function[(int scheme_main_stack_setup
[int no_auto_statics]
[Scheme_Nested_Main main]
[void* data])]{
A more primitive variant of @cpp{scheme_main_setup} that initializes
the GC stack base but does not create the initial namespace (so an
embedding application can perform other operations that involve
garbage-collected data before creating a namespace).
The @var{data} argument is passed through to @var{main}, where the
@cpp{Scheme_Nested_Main} type is defined as follows:
@verbatim[#:indent 4]{
typedef int (*Scheme_Nested_Main)(void *data);
}}
@function[(void scheme_set_stack_base @function[(void scheme_set_stack_base
[void* stack_addr] [void* stack_addr]
[int no_auto_statics])]{ [int no_auto_statics])]{
@ -739,7 +757,7 @@ must be the beginning or end of a local-frame registration. Worse, in
CGC or 3m, if @cpp{real_main} is declared @cpp{static}, the compiler CGC or 3m, if @cpp{real_main} is declared @cpp{static}, the compiler
may inline it and place variables containing collectable values deeper may inline it and place variables containing collectable values deeper
in the stack than @cpp{dummy}. To avoid these problems, use in the stack than @cpp{dummy}. To avoid these problems, use
@cpp{scheme_main_setup}, instead.} @cpp{scheme_main_setup} or @cpp{scheme_main_stack_setup}, instead.}
@function[(void scheme_set_stack_bounds @function[(void scheme_set_stack_bounds
[void* stack_addr] [void* stack_addr]

View File

@ -296,13 +296,16 @@ To embed PLT Scheme CGC in a program, follow these steps:
installing from source also places this file in the installation's installing from source also places this file in the installation's
@filepath{include} directory.} @filepath{include} directory.}
@item{Start your main program through the @cpp{scheme_main_setup} @item{Start your main program through the @cpp{scheme_main_setup} (or
trampoline, and put all uses of MzScheme functions inside the @cpp{scheme_main_stack_setup}) trampoline, and put all uses of
function passed to @cpp{scheme_main_setup}. The @cpp{scheme_main_setup} MzScheme functions inside the function passed to
function registers the current C stack location with the memory @cpp{scheme_main_setup}. The @cpp{scheme_main_setup} function
manager. It also creates the initial namespace @cpp{Scheme_Env*} by registers the current C stack location with the memory manager. It
calling @cppi{scheme_basic_env} and passing the result to the also creates the initial namespace @cpp{Scheme_Env*} by calling
function provided to @cpp{scheme_main_setup}.} @cppi{scheme_basic_env} and passing the result to the function
provided to @cpp{scheme_main_setup}. (The
@cpp{scheme_main_stack_setup} trampoline registers the C stack with
the memory manager without creating a namespace.)}
@item{Configure the namespace by adding module declarations. The @item{Configure the namespace by adding module declarations. The
initial namespace contains declarations only for a few primitive initial namespace contains declarations only for a few primitive

View File

@ -252,7 +252,7 @@ int actual_main(int argc, char **argv)
return r; return r;
} }
static int main_after_stack(void *data, int argc, char *argv[]) static int main_after_stack(int argc, char *argv[])
{ {
int rval; int rval;
@ -299,9 +299,24 @@ static int main_after_stack(void *data, int argc, char *argv[])
/* Just jumps to generic main. */ /* Just jumps to generic main. */
#ifndef wx_msw #ifndef wx_msw
typedef struct {
int argc;
char **argv;
} Main_Args;
static int call_main_after_stack(void *data)
{
Main_Args *ma = (Main_Args *)data;
return main_after_stack(ma->argc, ma->argv);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
return scheme_main_stack_setup(1, main_after_stack, NULL, argc, argv); Main_Args ma;
ma.argc = argc;
ma.argv = argv;
return scheme_main_stack_setup(1, call_main_after_stack, &ma);
} }
#endif #endif
@ -517,22 +532,19 @@ typedef struct {
int wm_is_mred; int wm_is_mred;
HINSTANCE hInstance; HINSTANCE hInstance;
HINSTANCE hPrevInstance; HINSTANCE hPrevInstance;
int argc;
char **argv;
int nCmdShow; int nCmdShow;
} WinMain_Args; } WinMain_Args;
static int call_main_after_stack(int argc, char *argv[]) static int WinMain_after_stack(void *_wma)
{
return main_after_stack(NULL, argc, argv);
}
static int WinMain_after_stack(void *_wma, int argc, char **argv)
{ {
WinMain_Args *wma = (WinMain_Args *)_wma; WinMain_Args *wma = (WinMain_Args *)_wma;
return wxWinMain(wma->wm_is_mred, wma->hInstance, wma->hPrevInstance, return wxWinMain(wma->wm_is_mred, wma->hInstance, wma->hPrevInstance,
argc, argv, wma->argc, wma->argv,
wma->nCmdShow, wma->nCmdShow,
call_main_after_stack); main_after_stack);
} }
int APIENTRY WinMain_dlls_ready(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored, int nCmdShow) int APIENTRY WinMain_dlls_ready(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored, int nCmdShow)
@ -628,9 +640,11 @@ int APIENTRY WinMain_dlls_ready(HINSTANCE hInstance, HINSTANCE hPrevInstance, LP
wma.wm_is_mred = wm_is_mred; wma.wm_is_mred = wm_is_mred;
wma.hInstance = hInstance; wma.hInstance = hInstance;
wma.hPrevInstance = hPrevInstance; wma.hPrevInstance = hPrevInstance;
wma.argc = argc;
wma.argv = argv;
wma.nCmdShow = nCmdShow; wma.nCmdShow = nCmdShow;
return scheme_main_stack_setup(1, WinMain_after_stack, &wma, argc, argv); return scheme_main_stack_setup(1, WinMain_after_stack, &wma);
} }
# ifdef MZ_PRECISE_GC # ifdef MZ_PRECISE_GC

View File

@ -1697,12 +1697,12 @@ MZ_EXTERN void scheme_set_stack_base(void *base, int no_auto_statics);
MZ_EXTERN void scheme_set_stack_bounds(void *base, void *deepest, int no_auto_statics); MZ_EXTERN void scheme_set_stack_bounds(void *base, void *deepest, int no_auto_statics);
/* Stack-preparation start-up: */ /* Stack-preparation start-up: */
typedef int (*Scheme_Startup_Main)(void *data, int argc, char **argv); typedef int (*Scheme_Nested_Main)(void *data);
MZ_EXTERN int scheme_main_stack_setup(int no_auto_statics, Scheme_Startup_Main _main, void *data, int argc, char **argv); MZ_EXTERN int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data);
/* More automatic start-up: */ /* More automatic start-up: */
typedef int (*Scheme_Main)(Scheme_Env *env, int argc, char **argv); typedef int (*Scheme_Env_Main)(Scheme_Env *env, int argc, char **argv);
MZ_EXTERN int scheme_main_setup(int no_auto_statics, Scheme_Main _main, int argc, char **argv); MZ_EXTERN int scheme_main_setup(int no_auto_statics, Scheme_Env_Main _main, int argc, char **argv);
MZ_EXTERN void scheme_register_static(void *ptr, long size); MZ_EXTERN void scheme_register_static(void *ptr, long size);

View File

@ -213,7 +213,7 @@ int actual_main(int argc, char *argv[]);
/* Prepare for delayload, then call main_after_dlls */ /* Prepare for delayload, then call main_after_dlls */
static int main_after_dlls(int argc, MAIN_char **MAIN_argv); static int main_after_dlls(int argc, MAIN_char **MAIN_argv);
static int main_after_stack(void *data, int argc, MAIN_char **MAIN_argv); static int main_after_stack(void *data);
# ifdef MZ_PRECISE_GC # ifdef MZ_PRECISE_GC
START_XFORM_SKIP; START_XFORM_SKIP;
@ -240,23 +240,34 @@ END_XFORM_SKIP;
/************************ main_after_dlls **************************/ /************************ main_after_dlls **************************/
/* Prep stack for GC, then call main_after_stack (indirectly) */ /* Prep stack for GC, then call main_after_stack (indirectly) */
typedef struct {
int argc;
MAIN_char **argv;
} Main_Args;
static int main_after_dlls(int argc, MAIN_char **argv) static int main_after_dlls(int argc, MAIN_char **argv)
{ {
return scheme_main_stack_setup(1, Main_Args ma;
(Scheme_Startup_Main)main_after_stack, NULL, ma.argc = argc;
argc, (char **)argv); ma.argv = argv;
return scheme_main_stack_setup(1, main_after_stack, &ma);
} }
/************************ main_after_stack *************************/ /************************ main_after_stack *************************/
/* Phase 1 setup, then call actual_main (indirectly) */ /* Phase 1 setup, then call actual_main (indirectly) */
static int main_after_stack(void *data, int argc, MAIN_char **MAIN_argv) static int main_after_stack(void *data)
{ {
int rval; int rval;
int argc;
MAIN_char **MAIN_argv;
#ifdef WINDOWS_UNICODE_MAIN #ifdef WINDOWS_UNICODE_MAIN
char **argv; char **argv;
#endif #endif
argc = ((Main_Args *)data)->argc;
MAIN_argv = ((Main_Args *)data)->argv;
#if defined(OSKIT) && !defined(OSKIT_TEST) && !KNIT #if defined(OSKIT) && !defined(OSKIT_TEST) && !KNIT
oskit_prepare(&argc, &argv); oskit_prepare(&argc, &argv);
#endif #endif

View File

@ -89,30 +89,36 @@ void scheme_set_stack_base(void *base, int no_auto_statics)
} }
typedef struct { typedef struct {
Scheme_Main _main; Scheme_Env_Main _main;
int argc;
char **argv;
} Scheme_Main_Data; } Scheme_Main_Data;
static int call_with_basic(void *data, int argc, char **argv) static int call_with_basic(void *data)
{ {
Scheme_Main _main = ((Scheme_Main_Data *)data)->_main; Scheme_Main_Data *ma = (Scheme_Main_Data *)data;
return _main(scheme_basic_env(), argc, argv); Scheme_Env_Main _main = ma->_main;
return _main(scheme_basic_env(), ma->argc, ma->argv);
} }
int scheme_main_setup(int no_auto_statics, Scheme_Main _main, int argc, char **argv) int scheme_main_setup(int no_auto_statics, Scheme_Env_Main _main, int argc, char **argv)
{ {
Scheme_Main_Data d; Scheme_Main_Data d;
d._main = _main; d._main = _main;
return scheme_main_stack_setup(no_auto_statics, call_with_basic, &d, argc, argv); d.argc = argc;
d.argv = argv;
return scheme_main_stack_setup(no_auto_statics, call_with_basic, &d);
} }
int scheme_main_stack_setup(int no_auto_statics, Scheme_Startup_Main _main, void *data, int argc, char **argv) int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data)
{ {
void *stack_start; void *stack_start;
int volatile return_code; int volatile return_code;
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics); scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);
return_code = _main(data, argc, argv); return_code = _main(data);
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
/* Trick xform conversion to keep start_addr: */ /* Trick xform conversion to keep start_addr: */