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
[int no_auto_statics]
[Scheme_Main main]
[Scheme_Env_Main main]
[int argc]
[char** argv])]{
@ -697,11 +697,11 @@ calling @cpp{scheme_basic_env}, and then calls @var{main} with the
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.)
The @cpp{Scheme_Main} type is defined as follows:
The @cpp{Scheme_Env_Main} type is defined as follows:
@verbatim[#:indent 4]{
typedef int (*Scheme_Main)(Scheme_Env *env,
int argc, char **argv);
typedef int (*Scheme_Env_Main)(Scheme_Env *env,
int argc, char **argv);
}
The result of @var{main} is the result of @cpp{scheme_main_setup}.
@ -711,6 +711,24 @@ explicitly registered with the garbage collector; see
@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
[void* stack_addr]
[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
may inline it and place variables containing collectable values deeper
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
[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
@filepath{include} directory.}
@item{Start your main program through the @cpp{scheme_main_setup}
trampoline, and put all uses of MzScheme functions inside the
function passed to @cpp{scheme_main_setup}. The @cpp{scheme_main_setup}
function registers the current C stack location with the memory
manager. It also creates the initial namespace @cpp{Scheme_Env*} by
calling @cppi{scheme_basic_env} and passing the result to the
function provided to @cpp{scheme_main_setup}.}
@item{Start your main program through the @cpp{scheme_main_setup} (or
@cpp{scheme_main_stack_setup}) trampoline, and put all uses of
MzScheme functions inside the function passed to
@cpp{scheme_main_setup}. The @cpp{scheme_main_setup} function
registers the current C stack location with the memory manager. It
also creates the initial namespace @cpp{Scheme_Env*} by calling
@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
initial namespace contains declarations only for a few primitive

View File

@ -252,7 +252,7 @@ int actual_main(int argc, char **argv)
return r;
}
static int main_after_stack(void *data, int argc, char *argv[])
static int main_after_stack(int argc, char *argv[])
{
int rval;
@ -299,9 +299,24 @@ static int main_after_stack(void *data, int argc, char *argv[])
/* Just jumps to generic main. */
#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[])
{
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
@ -517,22 +532,19 @@ typedef struct {
int wm_is_mred;
HINSTANCE hInstance;
HINSTANCE hPrevInstance;
int argc;
char **argv;
int nCmdShow;
} WinMain_Args;
static int call_main_after_stack(int argc, char *argv[])
{
return main_after_stack(NULL, argc, argv);
}
static int WinMain_after_stack(void *_wma, int argc, char **argv)
static int WinMain_after_stack(void *_wma)
{
WinMain_Args *wma = (WinMain_Args *)_wma;
return wxWinMain(wma->wm_is_mred, wma->hInstance, wma->hPrevInstance,
argc, argv,
wma->argc, wma->argv,
wma->nCmdShow,
call_main_after_stack);
main_after_stack);
}
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.hInstance = hInstance;
wma.hPrevInstance = hPrevInstance;
wma.argc = argc;
wma.argv = argv;
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

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);
/* Stack-preparation start-up: */
typedef int (*Scheme_Startup_Main)(void *data, int argc, char **argv);
MZ_EXTERN int scheme_main_stack_setup(int no_auto_statics, Scheme_Startup_Main _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_Nested_Main _main, void *data);
/* More automatic start-up: */
typedef int (*Scheme_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);
typedef int (*Scheme_Env_Main)(Scheme_Env *env, 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);

View File

@ -213,7 +213,7 @@ int actual_main(int argc, char *argv[]);
/* Prepare for delayload, then call main_after_dlls */
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
START_XFORM_SKIP;
@ -240,23 +240,34 @@ END_XFORM_SKIP;
/************************ main_after_dlls **************************/
/* 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)
{
return scheme_main_stack_setup(1,
(Scheme_Startup_Main)main_after_stack, NULL,
argc, (char **)argv);
Main_Args ma;
ma.argc = argc;
ma.argv = argv;
return scheme_main_stack_setup(1, main_after_stack, &ma);
}
/************************ main_after_stack *************************/
/* 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 argc;
MAIN_char **MAIN_argv;
#ifdef WINDOWS_UNICODE_MAIN
char **argv;
#endif
argc = ((Main_Args *)data)->argc;
MAIN_argv = ((Main_Args *)data)->argv;
#if defined(OSKIT) && !defined(OSKIT_TEST) && !KNIT
oskit_prepare(&argc, &argv);
#endif

View File

@ -89,30 +89,36 @@ void scheme_set_stack_base(void *base, int no_auto_statics)
}
typedef struct {
Scheme_Main _main;
Scheme_Env_Main _main;
int argc;
char **argv;
} 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;
return _main(scheme_basic_env(), argc, argv);
Scheme_Main_Data *ma = (Scheme_Main_Data *)data;
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;
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;
int volatile return_code;
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
/* Trick xform conversion to keep start_addr: */