Skip to content

Commit

Permalink
Unbust re-use of continuations.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Jan 8, 2014
1 parent accb7ba commit 69396d3
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
4 changes: 3 additions & 1 deletion src/core/continuation.c
Expand Up @@ -37,10 +37,12 @@ void MVM_continuation_control(MVMThreadContext *tc, MVMint64 protect,
MVMRegister *res_reg) {
MVMObject *cont;

/* Hunt the tag on the stack. */
/* Hunt the tag on the stack; mark frames as being incorporated into a
* continuation as we go to avoid a second pass. */
MVMFrame *root_frame = tc->cur_frame;
MVMContinuationTag *tag_record = NULL;
while (root_frame) {
root_frame->in_continuation = 1;
tag_record = root_frame->continuation_tags;
while (tag_record) {
if (!tag || tag_record->tag == tag)
Expand Down
56 changes: 31 additions & 25 deletions src/core/frame.c
Expand Up @@ -221,6 +221,7 @@ void MVM_frame_invoke(MVMThreadContext *tc, MVMStaticFrame *static_frame,
else
frame->caller = NULL;
frame->keep_caller = 0;
frame->in_continuation = 0;

/* Initial reference count is 1 by virtue of it being the currently
* executing frame. */
Expand Down Expand Up @@ -345,36 +346,41 @@ static MVMuint64 remove_one_frame(MVMThreadContext *tc, MVMuint8 unwind) {
MVMFrame *returner = tc->cur_frame;
MVMFrame *caller = returner->caller;

/* Arguments buffer no longer in use (saves GC visiting it). */
returner->cur_args_callsite = NULL;
/* Some cleanup we only need do if we're not a frame involved in a
* continuation (otherwise we need to allow for multi-shot
* re-invocation. */
if (!returner->in_continuation) {
/* Arguments buffer no longer in use (saves GC visiting it). */
returner->cur_args_callsite = NULL;

/* Clear up argument processing leftovers, if any. */
if (returner->work) {
MVM_args_proc_cleanup_for_cache(tc, &returner->params);
}
/* Clear up argument processing leftovers, if any. */
if (returner->work) {
MVM_args_proc_cleanup_for_cache(tc, &returner->params);
}

/* Clear up any continuation tags. */
if (returner->continuation_tags) {
MVMContinuationTag *tag = returner->continuation_tags;
while (tag) {
MVMContinuationTag *next = tag->next;
free(tag);
tag = next;
/* Clear up any continuation tags. */
if (returner->continuation_tags) {
MVMContinuationTag *tag = returner->continuation_tags;
while (tag) {
MVMContinuationTag *next = tag->next;
free(tag);
tag = next;
}
returner->continuation_tags = NULL;
}
returner->continuation_tags = NULL;
}

/* Signal to the GC to ignore ->work */
returner->tc = NULL;
/* Signal to the GC to ignore ->work */
returner->tc = NULL;

/* Unless we need to keep the caller chain in place, clear it up. */
if (caller) {
if (!returner->keep_caller) {
MVM_frame_dec_ref(tc, caller);
returner->caller = NULL;
}
else if (unwind) {
caller->keep_caller = 1;
/* Unless we need to keep the caller chain in place, clear it up. */
if (caller) {
if (!returner->keep_caller) {
MVM_frame_dec_ref(tc, caller);
returner->caller = NULL;
}
else if (unwind) {
caller->keep_caller = 1;
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/frame.h
Expand Up @@ -111,6 +111,10 @@ struct MVMFrame {
* unwind; used to make sure we can get a backtrace after an exception. */
MVMuint8 keep_caller;

/* Flags that the frame has been captured in a continuation, and as
* such we should keep everything in place for multiple invocations. */
MVMuint8 in_continuation;

/* Assorted frame flags. */
MVMuint8 flags;
};
Expand Down

0 comments on commit 69396d3

Please sign in to comment.