forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stackless issue python#97: Fix stack switching for optimized builds
This change removes the "static" declaration from the function slp_switch(). This forces the compiler to adhere to the ABI specification. On i386 and amd64 it is now save to configure stackless with --enable-stacklessfewerregisters, except if you compile for darwin. The flag disables explicit saving of %ebp/%rbp. On Unix-like systems the source file slp_transfer.c now gets compiled with the additional flag -fno-inline-functions instead of -O2. https://bitbucket.org/stackless-dev/stackless/issues/98 (grafted from 4f7698499ad53e5fad61fb415fbfe2c036672a9c)
- Loading branch information
Anselm Kruis
committed
Nov 7, 2016
1 parent
0884eb3
commit 7ae6176
Showing
11 changed files
with
616 additions
and
473 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
* this is the internal transfer function. | ||
* | ||
* HISTORY | ||
* 06-Nov-16 Anselm Kruis <[email protected]> | ||
* Reworked based on the i386 ABI spec. | ||
* 24-Nov-02 Christian Tismer <[email protected]> | ||
* needed to add another magic constant to insure | ||
* that f in slp_eval_frame(PyFrameObject *f) | ||
|
@@ -23,36 +25,84 @@ | |
|
||
#ifdef SLP_EVAL | ||
|
||
/* #define STACK_MAGIC 3 */ | ||
/* the above works fine with gcc 2.96, but 2.95.3 wants this */ | ||
#define STACK_MAGIC 0 | ||
|
||
static int | ||
/* | ||
* In order to switch the stack, we use the fact, that the compiler | ||
* already knows how to preserve registers accross function calls. | ||
* | ||
* The relevant i386 ABI specifigation pecisely defines which registers | ||
* must be preserved and which registers may be modified. | ||
* We use a gcc inline assembly feature to pretend that the inline | ||
* assembly block modifies the registers to be preserved. As a result, | ||
* the compiler emits code to preserve those registers. | ||
* | ||
* The "System V Application Binary Interface Intel386 Architecture Processor Supplment, Fourth Edition" | ||
* Section 3 chapter "Function Calling Sequence" states: | ||
* All registers on the Intel386 are global and thus visible to both a calling and a | ||
* called function. Registers %ebp, %ebx, %edi, %esi, and %esp "belong" to the cal- | ||
* ling function. In other words, a called function must preserve these registers’ | ||
* values for its caller. Remaining registers ‘‘belong’’ to the called function. | ||
* | ||
* The compiler always preserves the %esp register accros a function call. | ||
* | ||
* Depending on the usage of a frame pointer, which is optional | ||
* for the i386 ABI, the compiler already preserves the %ebp | ||
* register. Unfortunately, we must not add "ebp" to the clobber list, if | ||
* ebp is used as a frame pointer (won't compile). Therefore we save | ||
* ebp manually. | ||
* | ||
* For the other registers we tell the compiler, | ||
* that we are going to clobber the registers. The compiler will then save the registers | ||
* for us. (However the compiler gives no guarantee, when it will restore | ||
* the registers.) And the compiler only preserves those registers, that must | ||
* be preserved according to the calling convention. It does not preserve any other | ||
* register, that may be modified during a function call. Therefore specifying additional | ||
* registers has no effect at all. Take a look at the generated assembly code! | ||
*/ | ||
|
||
/* Registers marked as clobbered, minimum set according to the ABI spec. */ | ||
#define REGS_CLOBBERED "ebx", "edi", "esi" | ||
|
||
/* | ||
* You may want to make the function static enable optimizations. | ||
* However, the ABI SPEC does not apply to static functions. Therefore | ||
* I make slp_switch a regular global function. | ||
*/ | ||
#if 0 | ||
static | ||
#endif | ||
int | ||
slp_switch(void) | ||
{ | ||
register int *stackref, stsizediff; | ||
#if STACKLESS_FRHACK | ||
__asm__ volatile ("" : : : "esi", "edi"); | ||
__asm__ volatile ( | ||
"" | ||
: : : REGS_CLOBBERED ); | ||
#else | ||
__asm__ volatile ("" : : : "ebx", "esi", "edi"); | ||
void * ebp; | ||
__asm__ volatile ( | ||
"movl %%ebp, %0\n\t" | ||
: "=m" (ebp) : : REGS_CLOBBERED ); | ||
#endif | ||
__asm__ ("movl %%esp, %0" : "=g" (stackref)); | ||
{ | ||
SLP_SAVE_STATE(stackref, stsizediff); | ||
__asm__ volatile ( | ||
"addl %0, %%esp\n" | ||
"addl %0, %%ebp\n" | ||
"addl %0, %%esp\n\t" | ||
"addl %0, %%ebp\n\t" | ||
: | ||
: "r" (stsizediff) | ||
); | ||
SLP_RESTORE_STATE(); | ||
#if ! STACKLESS_FRHACK | ||
__asm__ volatile ( | ||
"movl %0, %%ebp\n\t" | ||
: : "m" (ebp) ); | ||
#endif | ||
return 0; | ||
} | ||
#if STACKLESS_FRHACK | ||
__asm__ volatile ("" : : : "esi", "edi"); | ||
#else | ||
__asm__ volatile ("" : : : "ebx", "esi", "edi"); | ||
#endif | ||
} | ||
|
||
|
||
|
Oops, something went wrong.