]> git.vpit.fr Git - perl/modules/Scope-Upper.git/commitdiff
Add some comments to the mysterious su_init()/su_pop()
authorVincent Pit <vince@profvince.com>
Mon, 3 Aug 2015 19:00:16 +0000 (16:00 -0300)
committerVincent Pit <vince@profvince.com>
Mon, 3 Aug 2015 21:30:21 +0000 (18:30 -0300)
Upper.xs

index afab7cc45defc9802a2e8d40532fdb67a5aa5e4a..ec3ecfef785efec4628b24c3fff9bc3356e042ec 100644 (file)
--- a/Upper.xs
+++ b/Upper.xs
@@ -1131,6 +1131,18 @@ static I32 su_init(pTHX_ void *ud, I32 cxix, I32 size) {
 
  SU_D(PerlIO_printf(Perl_debug_log, "%p: ### init for cx %d\n", ud, cxix));
 
 
  SU_D(PerlIO_printf(Perl_debug_log, "%p: ### init for cx %d\n", ud, cxix));
 
+ /* su_pop() is going to be called from leave_scope(), so before pushing the
+  * next callback, we'll want to flush the current scope stack slice first.
+  * However, if we want the next callback not to be processed immediately by
+  * the current leave_scope(), we'll need to hide it by artificially
+  * incrementing the scope stack marker before. For the intermediate bumps,
+  * we will only need a bump of SU_SAVE_DESTRUCTOR_SIZE items, but for the
+  * last one we will need a bump of size items. However, in order to preserve
+  * the natural ordering between scope stack markers, we cannot bump lower
+  * markers more than higher ones. This is why we bump the intermediate markers
+  * by the smallest multiple of SU_SAVE_PLACEHOLDER_SIZE greater or equal to
+  * max(SU_SAVE_DESTRUCTOR_SIZE, size). */
+
  if (size <= SU_SAVE_DESTRUCTOR_SIZE)
   pad = 0;
  else {
  if (size <= SU_SAVE_DESTRUCTOR_SIZE)
   pad = 0;
  else {
@@ -1147,6 +1159,15 @@ static I32 su_init(pTHX_ void *ud, I32 cxix, I32 size) {
  depth = PL_scopestack_ix - cxstack[cxix].blk_oldscopesp;
  SU_D(PerlIO_printf(Perl_debug_log, "%p: going down to depth %d\n", ud, depth));
 
  depth = PL_scopestack_ix - cxstack[cxix].blk_oldscopesp;
  SU_D(PerlIO_printf(Perl_debug_log, "%p: going down to depth %d\n", ud, depth));
 
+ /* We need to bump all the intermediary stack markers just in case an
+  * exception is thrown before the target scope is reached. Indeed, in this
+  * case there might be arbitrary many scope frames flushed at the same time,
+  * and since we cannot know in advance whether this will happen or not, we
+  * have to make sure the final frame is protected for the actual action. But
+  * of course, in order to do that, we also need to bump all the previous stack
+  * markers. If not for this, it should have been possible to just bump the two
+  * next frames in su_pop(). */
+
  Newx(origin, depth + 1, I32);
  base = PL_scopestack_ix - depth;
  origin[0] = PL_scopestack[base];
  Newx(origin, depth + 1, I32);
  base = PL_scopestack_ix - depth;
  origin[0] = PL_scopestack[base];