… | |
… | |
120 | #endif |
120 | #endif |
121 | |
121 | |
122 | /* The next macros try to return the current stack pointer, in an as |
122 | /* The next macros try to return the current stack pointer, in an as |
123 | * portable way as possible. */ |
123 | * portable way as possible. */ |
124 | #if __GNUC__ >= 4 |
124 | #if __GNUC__ >= 4 |
|
|
125 | # define dSTACKLEVEL int stacklevel_dummy |
125 | # define dSTACKLEVEL void *stacklevel = __builtin_frame_address (0) |
126 | # define STACKLEVEL __builtin_frame_address (0) |
126 | #else |
127 | #else |
127 | # define dSTACKLEVEL volatile void *stacklevel = (volatile void *)&stacklevel |
128 | # define dSTACKLEVEL volatile void *stacklevel |
|
|
129 | # define STACKLEVEL ((void *)&stacklevel) |
128 | #endif |
130 | #endif |
129 | |
131 | |
130 | #define IN_DESTRUCT (PL_main_cv == Nullcv) |
132 | #define IN_DESTRUCT (PL_main_cv == Nullcv) |
131 | |
133 | |
132 | #if __GNUC__ >= 3 |
134 | #if __GNUC__ >= 3 |
… | |
… | |
857 | { |
859 | { |
858 | dSP; |
860 | dSP; |
859 | UNOP myop; |
861 | UNOP myop; |
860 | |
862 | |
861 | Zero (&myop, 1, UNOP); |
863 | Zero (&myop, 1, UNOP); |
862 | myop.op_next = Nullop; |
864 | myop.op_next = Nullop; |
863 | myop.op_flags = OPf_WANT_VOID; |
865 | myop.op_flags = OPf_WANT_VOID; |
864 | |
866 | |
865 | PUSHMARK (SP); |
867 | PUSHMARK (SP); |
866 | XPUSHs (sv_2mortal (av_shift (GvAV (PL_defgv)))); |
868 | XPUSHs (sv_2mortal (av_shift (GvAV (PL_defgv)))); |
867 | PUTBACK; |
869 | PUTBACK; |
… | |
… | |
875 | */ |
877 | */ |
876 | slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */ |
878 | slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */ |
877 | slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */ |
879 | slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */ |
878 | |
880 | |
879 | /* and we have to provide the pp_slf op in any case, so pp_slf can skip it */ |
881 | /* and we have to provide the pp_slf op in any case, so pp_slf can skip it */ |
|
|
882 | coro_setup_op.op_next = PL_op; |
880 | coro_setup_op.op_type = OP_CUSTOM; |
883 | coro_setup_op.op_type = OP_CUSTOM; |
881 | coro_setup_op.op_ppaddr = pp_slf; |
884 | coro_setup_op.op_ppaddr = pp_slf; |
882 | coro_setup_op.op_next = PL_op; |
885 | /* no flags required, as an init function won't be called */ |
883 | |
886 | |
884 | PL_op = (OP *)&coro_setup_op; |
887 | PL_op = (OP *)&coro_setup_op; |
885 | |
888 | |
886 | /* copy throw, in case it was set before coro_setup */ |
889 | /* copy throw, in case it was set before coro_setup */ |
887 | coro_throw = coro->throw; |
890 | coro_throw = coro->throw; |
… | |
… | |
1070 | static int |
1073 | static int |
1071 | slf_check_set_stacklevel (pTHX_ struct CoroSLF *frame) |
1074 | slf_check_set_stacklevel (pTHX_ struct CoroSLF *frame) |
1072 | { |
1075 | { |
1073 | *frame = cctx_ssl_frame; |
1076 | *frame = cctx_ssl_frame; |
1074 | |
1077 | |
1075 | return 1; /* execute the restored frame - there must be one */ |
1078 | return frame->check (aTHX_ frame); /* execute the restored frame - there must be one */ |
1076 | } |
1079 | } |
1077 | |
1080 | |
1078 | /* initialises PL_top_env and injects a pseudo-slf-call to sett he stacklevel */ |
1081 | /* initialises PL_top_env and injects a pseudo-slf-call to set the stacklevel */ |
1079 | static void NOINLINE |
1082 | static void NOINLINE |
1080 | cctx_prepare (pTHX_ coro_cctx *cctx) |
1083 | cctx_prepare (pTHX_ coro_cctx *cctx) |
1081 | { |
1084 | { |
1082 | PL_top_env = &PL_start_env; |
1085 | PL_top_env = &PL_start_env; |
1083 | |
1086 | |
… | |
… | |
1087 | /* we already must be executing an SLF op, there is no other valid way |
1090 | /* we already must be executing an SLF op, there is no other valid way |
1088 | * that can lead to creation of a new cctx */ |
1091 | * that can lead to creation of a new cctx */ |
1089 | assert (("FATAL: can't prepare slf-less cctx in Coro module (please report)", |
1092 | assert (("FATAL: can't prepare slf-less cctx in Coro module (please report)", |
1090 | slf_frame.prepare && PL_op->op_ppaddr == pp_slf)); |
1093 | slf_frame.prepare && PL_op->op_ppaddr == pp_slf)); |
1091 | |
1094 | |
|
|
1095 | /* we must emulate leaving pp_slf, which is done inside slf_check_set_stacklevel */ |
1092 | cctx_ssl_cctx = cctx; |
1096 | cctx_ssl_cctx = cctx; |
1093 | cctx_ssl_frame = slf_frame; |
1097 | cctx_ssl_frame = slf_frame; |
1094 | |
1098 | |
1095 | slf_frame.prepare = slf_prepare_set_stacklevel; |
1099 | slf_frame.prepare = slf_prepare_set_stacklevel; |
1096 | slf_frame.check = slf_check_set_stacklevel; |
1100 | slf_frame.check = slf_check_set_stacklevel; |
… | |
… | |
1317 | dSTACKLEVEL; |
1321 | dSTACKLEVEL; |
1318 | |
1322 | |
1319 | /* sometimes transfer is only called to set idle_sp */ |
1323 | /* sometimes transfer is only called to set idle_sp */ |
1320 | if (expect_false (!next)) |
1324 | if (expect_false (!next)) |
1321 | { |
1325 | { |
1322 | ((coro_cctx *)prev)->idle_sp = (void *)stacklevel; |
1326 | ((coro_cctx *)prev)->idle_sp = STACKLEVEL; |
1323 | assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */ |
1327 | assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */ |
1324 | } |
1328 | } |
1325 | else if (expect_true (prev != next)) |
1329 | else if (expect_true (prev != next)) |
1326 | { |
1330 | { |
1327 | coro_cctx *prev__cctx; |
1331 | coro_cctx *prev__cctx; |
… | |
… | |
1352 | |
1356 | |
1353 | prev__cctx = prev->cctx; |
1357 | prev__cctx = prev->cctx; |
1354 | |
1358 | |
1355 | /* possibly untie and reuse the cctx */ |
1359 | /* possibly untie and reuse the cctx */ |
1356 | if (expect_true ( |
1360 | if (expect_true ( |
1357 | prev__cctx->idle_sp == (void *)stacklevel |
1361 | prev__cctx->idle_sp == STACKLEVEL |
1358 | && !(prev__cctx->flags & CC_TRACE) |
1362 | && !(prev__cctx->flags & CC_TRACE) |
1359 | && !force_cctx |
1363 | && !force_cctx |
1360 | )) |
1364 | )) |
1361 | { |
1365 | { |
1362 | /* I assume that stacklevel is a stronger indicator than PL_top_env changes */ |
1366 | /* I assume that stacklevel is a stronger indicator than PL_top_env changes */ |