Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move unwind logic out of invokeInternal.
  • Loading branch information
jnthn committed Mar 2, 2013
1 parent ccb441b commit f000cc7
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 33 deletions.
71 changes: 42 additions & 29 deletions lib/QAST/JASTCompiler.nqp
Expand Up @@ -2682,10 +2682,11 @@ class QAST::CompilerJAST {
}

# Emit arity check instruction.
$*JMETH.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$*JMETH.append(JAST::PushIndex.new( :value($pos_required) ));
$*JMETH.append(JAST::PushIndex.new( :value($pos_slurpy ?? -1 !! $pos_required + $pos_optional) ));
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
my $il := JAST::InstructionList.new();
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$il.append(JAST::PushIndex.new( :value($pos_required) ));
$il.append(JAST::PushIndex.new( :value($pos_slurpy ?? -1 !! $pos_required + $pos_optional) ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
"checkarity", 'Void', $TYPE_CF, 'Integer', 'Integer' ));

# Emit instructions to load each parameter.
Expand All @@ -2694,15 +2695,15 @@ class QAST::CompilerJAST {
my $type;
if $_.slurpy {
$type := $RT_OBJ;
$*JMETH.append(JAST::Instruction.new( :op('aload_1') ));
$*JMETH.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$il.append(JAST::Instruction.new( :op('aload_1') ));
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
if $_.named {
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
"namedslurpy", $TYPE_SMO, $TYPE_TC, $TYPE_CF ));
}
else {
$*JMETH.append(JAST::PushIndex.new( :value($pos_required + $pos_optional) ));
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
$il.append(JAST::PushIndex.new( :value($pos_required + $pos_optional) ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
"posslurpy", $TYPE_SMO, $TYPE_TC, $TYPE_CF, 'Integer' ));
}
}
Expand All @@ -2711,40 +2712,40 @@ class QAST::CompilerJAST {
my $jt := jtype($type);
my $tc := typechar($type);
my $opt := $_.default ?? "opt_" !! "";
$*JMETH.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
if $_.named {
$*JMETH.append(JAST::PushSVal.new( :value($_.named) ));
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
$il.append(JAST::PushSVal.new( :value($_.named) ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
"namedparam_$opt$tc", $jt, $TYPE_CF, $TYPE_STR ));
}
else {
$*JMETH.append(JAST::PushIndex.new( :value($param_idx) ));
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
$il.append(JAST::PushIndex.new( :value($param_idx) ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
"posparam_$opt$tc", $jt, $TYPE_CF, 'Integer' ));
}
if $opt {
my $lbl := JAST::Label.new( :name(self.unique("opt_param")) );
$*JMETH.append(JAST::Instruction.new( :op('aload_1') ));
$*JMETH.append(JAST::Instruction.new( :op('getfield'), $TYPE_TC,
$il.append(JAST::Instruction.new( :op('aload_1') ));
$il.append(JAST::Instruction.new( :op('getfield'), $TYPE_TC,
'lastParameterExisted', "Integer" ));
$*JMETH.append(JAST::Instruction.new( :op('ifne'), $lbl ));
$*JMETH.append(pop_ins($type));
$il.append(JAST::Instruction.new( :op('ifne'), $lbl ));
$il.append(pop_ins($type));
my $default := self.as_jast($_.default, :want($type));
$*JMETH.append($default.jast);
$il.append($default.jast);
$*STACK.obtain($default);
$*JMETH.append($lbl);
$il.append($lbl);
}
}
if $_.scope eq 'local' {
$*JMETH.append(JAST::Instruction.new( :op(store_ins($type)), $_.name ));
$il.append(JAST::Instruction.new( :op(store_ins($type)), $_.name ));
}
else {
my $jtype := jtype($type);
$*JMETH.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$*JMETH.append(JAST::PushIndex.new( :value($block.lexical_idx($_.name)) ));
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$il.append(JAST::PushIndex.new( :value($block.lexical_idx($_.name)) ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
'bindlex_' ~ typechar($type), $jtype, $jtype, $TYPE_CF, 'Integer' ));
$*JMETH.append(pop_ins($type));
$il.append(pop_ins($type));
}
$param_idx++;
}
Expand All @@ -2756,12 +2757,24 @@ class QAST::CompilerJAST {
$*BLOCK_TA.add_temps_to_method($*JMETH);

# Add method body JAST.
$*JMETH.append($body.jast);
$il.append($body.jast);

# Emit return instruction.
$*JMETH.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$*JMETH.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
# Store return value.
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
'return_' ~ typechar($body.type), 'Void', jtype($body.type), $TYPE_CF ));

# Keep the thread state in sync. Note, JVM doesn't do finally
# natively, so we just emit this in a catch as well as at the
# end before exit.
my $unwind := JAST::InstructionList.new();
for ($il, $unwind) {
$_.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$_.append(JAST::Instruction.new( :op('invokevirtual'),
$TYPE_CF, 'leave', 'Void' ));
}
$unwind.append(JAST::Instruction.new( :op('athrow') ));
$*JMETH.append(JAST::TryCatch.new( :try($il), :catch($unwind), :type('') ));
$*JMETH.append(JAST::Instruction.new( :op('return') ));

# Finalize method and add it to the class.
Expand Down
6 changes: 5 additions & 1 deletion src/org/perl6/nqp/jast2bc/JASTToJVMBytecode.java
Expand Up @@ -233,7 +233,11 @@ else if (curLine.equals(".try")) {
else if (curLine.startsWith(".catch ")) {
il.append(InstructionFactory.createBranchInstruction((short)Constants.GOTO, null));
tryEndStack.push(il.getEnd());
catchTypeStack.push((ObjectType)processType(curLine.substring(".catch ".length())));
String typeName = curLine.substring(".catch ".length());
if (typeName.equals(""))
catchTypeStack.push(null);
else
catchTypeStack.push((ObjectType)processType(typeName));
}
else if (curLine.equals(".endtry")) {
InstructionHandle tryStart = tryStartStack.pop().getNext();
Expand Down
3 changes: 0 additions & 3 deletions src/org/perl6/nqp/runtime/Ops.java
Expand Up @@ -1295,9 +1295,6 @@ private static void invokeInternal(ThreadContext tc, SixModelObject invokee, Cal
catch (Throwable e) {
ExceptionHandling.dieInternal(tc, e.getMessage());
}
finally {
cf.leave();
}
}
public static SixModelObject invokewithcapture(SixModelObject invokee, SixModelObject capture, ThreadContext tc) throws Exception {
if (capture instanceof CallCaptureInstance) {
Expand Down
12 changes: 12 additions & 0 deletions src/org/perl6/nqp/sixmodel/KnowHOWMethods.java
Expand Up @@ -48,6 +48,7 @@ public void new_type(ThreadContext tc) {

/* Return the type object. */
Ops.return_o(type_object, tc.curFrame);
tc.curFrame.leave();
}

public void add_method(ThreadContext tc) {
Expand All @@ -62,6 +63,7 @@ public void add_method(ThreadContext tc) {
((KnowHOWREPRInstance)self).methods.put(name, method);

Ops.return_o(method, tc.curFrame);
tc.curFrame.leave();
}

public void add_attribute(ThreadContext tc) {
Expand All @@ -77,6 +79,7 @@ public void add_attribute(ThreadContext tc) {
((KnowHOWREPRInstance)self).attributes.add(attribute);

Ops.return_o(attribute, tc.curFrame);
tc.curFrame.leave();
}

public void compose(ThreadContext tc) {
Expand Down Expand Up @@ -142,6 +145,7 @@ public void compose(ThreadContext tc) {
type_obj.st.REPR.compose(tc, type_obj.st, repr_info_hash);

Ops.return_o(type_obj, tc.curFrame);
tc.curFrame.leave();
}

public void attributes(ThreadContext tc) {
Expand All @@ -160,6 +164,7 @@ public void attributes(ThreadContext tc) {
result.push_boxed(tc, attr);

Ops.return_o(result, tc.curFrame);
tc.curFrame.leave();
}

public void methods(ThreadContext tc) {
Expand All @@ -178,6 +183,7 @@ public void methods(ThreadContext tc) {
result.bind_key_boxed(tc, name, methods.get(name));

Ops.return_o(result, tc.curFrame);
tc.curFrame.leave();
}

public void name(ThreadContext tc) {
Expand All @@ -188,6 +194,7 @@ public void name(ThreadContext tc) {
throw ExceptionHandling.dieInternal(tc, "KnowHOW methods must be called on object instance with REPR KnowHOWREPR");

Ops.return_s(((KnowHOWREPRInstance)self).name, tc.curFrame);
tc.curFrame.leave();
}

public void attr_new(ThreadContext tc) {
Expand All @@ -210,30 +217,35 @@ public void attr_new(ThreadContext tc) {

/* Return produced object. */
Ops.return_o(obj, tc.curFrame);
tc.curFrame.leave();
}

public void attr_compose(ThreadContext tc) {
Ops.checkarity(tc.curFrame, 1, 1);
SixModelObject self = Ops.posparam_o(tc.curFrame, 0);
Ops.return_o(self, tc.curFrame);
tc.curFrame.leave();
}

public void attr_name(ThreadContext tc) {
Ops.checkarity(tc.curFrame, 1, 1);
SixModelObject self = Ops.posparam_o(tc.curFrame, 0);
Ops.return_s(((KnowHOWAttributeInstance)self).name, tc.curFrame);
tc.curFrame.leave();
}

public void attr_type(ThreadContext tc) {
Ops.checkarity(tc.curFrame, 1, 1);
SixModelObject self = Ops.posparam_o(tc.curFrame, 0);
Ops.return_o(((KnowHOWAttributeInstance)self).type, tc.curFrame);
tc.curFrame.leave();
}

public void attr_box_target(ThreadContext tc) {
Ops.checkarity(tc.curFrame, 1, 1);
SixModelObject self = Ops.posparam_o(tc.curFrame, 0);
Ops.return_i(((KnowHOWAttributeInstance)self).box_target, tc.curFrame);
tc.curFrame.leave();
}

public CodeRef[] getCodeRefs() {
Expand Down

0 comments on commit f000cc7

Please sign in to comment.