Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refactors in preparation for exceptions support.
This adds in some pieces that will be needed for exceptions in the more
general case, then switches the existing next/last/redo exceptions over
to using the new approach. (Note, they need integrating so CONTROL,
which may run on the stack top and resume, will work out.)
  • Loading branch information
jnthn committed Feb 21, 2013
1 parent 6375842 commit b25f471
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 78 deletions.
209 changes: 161 additions & 48 deletions lib/QAST/JASTCompiler.nqp

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/org/perl6/nqp/runtime/CallFrame.java
Expand Up @@ -81,6 +81,11 @@ public class CallFrame {
public static final int RET_NUM = 2;
public static final int RET_STR = 3;

/**
* The current handler we're in, in this block. 0 if none.
*/
public long curHandler = 0;

/**
* Current working copy of the named arguments data.
*/
Expand Down
5 changes: 3 additions & 2 deletions src/org/perl6/nqp/runtime/CodeRef.java
Expand Up @@ -27,10 +27,11 @@ public class CodeRef extends SixModelObject {
public CodeRef(CompilationUnit compUnit, int idx, String name, String uniqueId,
String[] oLexicalNames, String[] iLexicalNames,
String[] nLexicalNames, String[] sLexicalNames,
short oMaxArgs, short iMaxArgs, short nMaxArgs, short sMaxArgs) {
short oMaxArgs, short iMaxArgs, short nMaxArgs, short sMaxArgs,
long[][] handlers) {
staticInfo = new StaticCodeInfo(compUnit, idx, name,uniqueId,
oLexicalNames, iLexicalNames, nLexicalNames, sLexicalNames,
oMaxArgs, iMaxArgs, nMaxArgs, sMaxArgs);
oMaxArgs, iMaxArgs, nMaxArgs, sMaxArgs, handlers);
}

/**
Expand Down
57 changes: 57 additions & 0 deletions src/org/perl6/nqp/runtime/ExceptionHandling.java
@@ -0,0 +1,57 @@
package org.perl6.nqp.runtime;

import org.perl6.nqp.sixmodel.*;

public class ExceptionHandling {
/* Exception handler categories. */
public static final int EX_CAT_CATCH = 1;
public static final int EX_CAT_CONTROL = 2;
public static final int EX_CAT_NEXT = 4;
public static final int EX_CAT_REDO = 8;
public static final int EX_CAT_LAST = 16;

/* Exception handler kinds. */
public static final int EX_UNWIND_SIMPLE = 0;
public static final int EX_UNWIND_OBJECT = 1;
public static final int EX_BLOCK = 2;

/* Finds and executes a handler, using dynamic scope to find it. */
public static SixModelObject handlerDynamic(ThreadContext tc, long category) {
CallFrame f = tc.curFrame;
while (f != null) {
if (f.curHandler != 0) {
long tryHandler = f.curHandler;
long[][] handlers = f.codeRef.staticInfo.handlers;
while (tryHandler != 0) {
for (int i = 0; i < handlers.length; i++) {
if (handlers[i][0] == tryHandler) {
// Found an active one, but is it the right category?
if ((handlers[i][2] & category) != 0)
return invokeHandler(tc, handlers[i], category);

// If not, try outer one.
tryHandler = handlers[i][1];
break;
}
}
}
}
f = f.caller;
}
return panic(tc, category);
}

/* Invokes the handler. */
private static SixModelObject invokeHandler(ThreadContext tc, long[] handlerInfo, long category) {
// TODO: Should not always just blindly go unwinding, may need an
// exception object or to run it in the current dynamic context.
tc.unwinder.unwindTarget = handlerInfo[0];
tc.unwinder.category = category;
throw tc.unwinder;
}

/* Unahndled exception. */
private static SixModelObject panic(ThreadContext tc, long category) {
throw new RuntimeException("Unhandled exception; category = " + category);
}
}
5 changes: 0 additions & 5 deletions src/org/perl6/nqp/runtime/LastControlException.java

This file was deleted.

5 changes: 0 additions & 5 deletions src/org/perl6/nqp/runtime/NextControlException.java

This file was deleted.

3 changes: 3 additions & 0 deletions src/org/perl6/nqp/runtime/Ops.java
Expand Up @@ -2206,6 +2206,9 @@ public static SixModelObject die(SixModelObject msg, ThreadContext tc) {
// TODO Implement exceptions properly.
throw new RuntimeException(msg.get_str(tc));
}
public static SixModelObject throwcatdyn(long category, ThreadContext tc) {
return ExceptionHandling.handlerDynamic(tc, category);
}

/* HLL configuration and compiler related options. */
public static SixModelObject sethllconfig(String language, SixModelObject configHash, ThreadContext tc) {
Expand Down
5 changes: 0 additions & 5 deletions src/org/perl6/nqp/runtime/RedoControlException.java

This file was deleted.

9 changes: 8 additions & 1 deletion src/org/perl6/nqp/runtime/StaticCodeInfo.java
Expand Up @@ -56,6 +56,11 @@ public class StaticCodeInfo {
public String[] nLexicalNames;
public String[] sLexicalNames;

/**
* Map of handlers.
*/
public long[][] handlers;

/**
* Lexical name maps (produced lazily on first use). Note they are only
* used when we do lexical lookup by name.
Expand Down Expand Up @@ -115,7 +120,8 @@ public Integer sTryGetLexicalIdx(String name) {
public StaticCodeInfo(CompilationUnit compUnit, int idx, String name, String uniqueId,
String[] oLexicalNames, String[] iLexicalNames,
String[] nLexicalNames, String[] sLexicalNames,
short oMaxArgs, short iMaxArgs, short nMaxArgs, short sMaxArgs) {
short oMaxArgs, short iMaxArgs, short nMaxArgs, short sMaxArgs,
long[][] handlers) {
this.compUnit = compUnit;
this.idx = idx;
this.name = name;
Expand All @@ -128,6 +134,7 @@ public StaticCodeInfo(CompilationUnit compUnit, int idx, String name, String uni
this.iMaxArgs = iMaxArgs;
this.nMaxArgs = nMaxArgs;
this.sMaxArgs = sMaxArgs;
this.handlers = handlers;
if (oLexicalNames != null)
this.oLexStatic = new SixModelObject[oLexicalNames.length];
}
Expand Down
6 changes: 6 additions & 0 deletions src/org/perl6/nqp/runtime/ThreadContext.java
Expand Up @@ -42,6 +42,11 @@ public class ThreadContext {
public static final int NATIVE_STR = 3;
public static final int NATIVE_JVM_OBJ = 4;

/**
* The current unwind exception.
*/
public UnwindException unwinder;

/**
* The current lexotic we're throwing.
*/
Expand All @@ -55,6 +60,7 @@ public class ThreadContext {
public ThreadContext(GlobalContext gc) {
this.gc = gc;
this.theLexotic = new LexoticException();
this.unwinder = new UnwindException();
if (gc.CallCapture != null) {
savedCC = (CallCaptureInstance)gc.CallCapture.st.REPR.allocate(this, gc.CallCapture.st);
savedCC.initialize(this);
Expand Down
7 changes: 7 additions & 0 deletions src/org/perl6/nqp/runtime/UnwindException.java
@@ -0,0 +1,7 @@
package org.perl6.nqp.runtime;

public class UnwindException extends RuntimeException {
private static final long serialVersionUID = -2452898396745530180L;
public long unwindTarget;
public long category;
}
25 changes: 13 additions & 12 deletions src/org/perl6/nqp/sixmodel/KnowHOWMethods.java
Expand Up @@ -235,19 +235,20 @@ public void InvokeCode(ThreadContext tc, int idx) {
public CodeRef[] getCodeRefs() {
CodeRef[] refs = new CodeRef[12];
String[] snull = null;
long[][] hnull = new long[0][];
short zero = 0;
refs[0] = new CodeRef(this, 0, "new_type", "new_type", snull, snull, snull, snull, zero, zero, zero, zero);
refs[1] = new CodeRef(this, 1, "add_method", "add_method", snull, snull, snull, snull, zero, zero, zero, zero);
refs[2] = new CodeRef(this, 2, "add_attribute", "add_attribute", snull, snull, snull, snull, zero, zero, zero, zero);
refs[3] = new CodeRef(this, 3, "compose", "compose", snull, snull, snull, snull, zero, zero, zero, zero);
refs[4] = new CodeRef(this, 4, "attributes", "attributes", snull, snull, snull, snull, zero, zero, zero, zero);
refs[5] = new CodeRef(this, 5, "methods", "methods", snull, snull, snull, snull, zero, zero, zero, zero);
refs[6] = new CodeRef(this, 6, "name", "name", snull, snull, snull, snull, zero, zero, zero, zero);
refs[7] = new CodeRef(this, 7, "new", "attr_new", snull, snull, snull, snull, zero, zero, zero, zero);
refs[8] = new CodeRef(this, 8, "compose", "attr_compose", snull, snull, snull, snull, zero, zero, zero, zero);
refs[9] = new CodeRef(this, 9, "name", "attr_name", snull, snull, snull, snull, zero, zero, zero, zero);
refs[10] = new CodeRef(this, 10, "type", "attr_type", snull, snull, snull, snull, zero, zero, zero, zero);
refs[11] = new CodeRef(this, 11, "box_target", "attr_box_target", snull, snull, snull, snull, zero, zero, zero, zero);
refs[0] = new CodeRef(this, 0, "new_type", "new_type", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[1] = new CodeRef(this, 1, "add_method", "add_method", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[2] = new CodeRef(this, 2, "add_attribute", "add_attribute", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[3] = new CodeRef(this, 3, "compose", "compose", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[4] = new CodeRef(this, 4, "attributes", "attributes", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[5] = new CodeRef(this, 5, "methods", "methods", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[6] = new CodeRef(this, 6, "name", "name", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[7] = new CodeRef(this, 7, "new", "attr_new", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[8] = new CodeRef(this, 8, "compose", "attr_compose", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[9] = new CodeRef(this, 9, "name", "attr_name", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[10] = new CodeRef(this, 10, "type", "attr_type", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
refs[11] = new CodeRef(this, 11, "box_target", "attr_box_target", snull, snull, snull, snull, zero, zero, zero, zero, hnull);
return refs;
}

Expand Down

0 comments on commit b25f471

Please sign in to comment.