Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Provide a way to force exit after unwind.
This is needed to support the nqp::p6return op. On the JVM, we always
promote exception handlers into their own blocks, unlike on Parrot.
While this rarely leaks out, it did in this case; this is used to
contain the leak.
  • Loading branch information
jnthn committed Jun 23, 2013
1 parent 1792c64 commit 49eb104
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/vm/jvm/QAST/Compiler.nqp
Expand Up @@ -1635,11 +1635,22 @@ QAST::OperationsJAST.add_core_op('handle', sub ($qastcomp, $op) {
$*STACK.obtain($tryil, $prores);
$tryil.append(JAST::Instruction.new( :op('astore'), $result ));

# The catch part just handles unwind; grab the result.
# The catch part just handles unwind; grab the result. Also check "exit
# after unwind" flag, used to force this whole block to exit.
my $catchil := JAST::InstructionList.new();
my $exitlbl := JAST::Label.new( :name($qastcomp.unique('unwindexit')) );
$qastcomp.unwind_check($catchil, $handler);
$catchil.append(JAST::Instruction.new( :op('getfield'), $TYPE_EX_UNWIND, 'result', $TYPE_SMO ));
$catchil.append(JAST::Instruction.new( :op('astore'), $result ));
$catchil.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$catchil.append(JAST::Instruction.new( :op('getfield'), $TYPE_CF, 'exitAfterUnwind', "Z" ));
$catchil.append(JAST::Instruction.new( :op('ifeq'), $exitlbl ));
$catchil.append(JAST::Instruction.new( :op('aload'), $result ));
$catchil.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$catchil.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
'return_o', 'Void', $TYPE_SMO, $TYPE_CF ));
$catchil.append($RETURN);
$catchil.append($exitlbl);

# Wrap it all up in try/catch etc.
$il.append($qastcomp.delimit_handler(
Expand Down
6 changes: 6 additions & 0 deletions src/vm/jvm/runtime/org/perl6/nqp/runtime/CallFrame.java
Expand Up @@ -78,6 +78,12 @@ public class CallFrame implements Cloneable {
*/
public boolean stateInit;

/**
* Flags that this frame should leave immediately upon unwinding from the
* current exception handler.
*/
public boolean exitAfterUnwind;

// Empty constructor for things that want to fake one up.
public CallFrame()
{
Expand Down

0 comments on commit 49eb104

Please sign in to comment.