Permalink
Browse files

update with erjang changes

  • Loading branch information...
1 parent 4c67437 commit 165981cdf9243e40f42424bbaba72833b18e954e @krestenkrab committed Dec 3, 2009
View
BIN libs/asm-all-2.2.3.jar
Binary file not shown.
View
BIN libs/asm-all-3.2-KRAB.jar
Binary file not shown.
View
20 src/kilim/Constants.java
@@ -35,18 +35,18 @@
String D_THROWABLE = "Ljava/lang/Throwable;";
String D_UNDEFINED = "UNDEFINED";
- String D_FIBER = "Lkilim/Fiber;";
- String D_STATE = "Lkilim/State;";
- String D_TASK = "Lkilim/Task;";
- String D_PAUSABLE = "Lkilim/Pausable;";
-
String THROWABLE_CLASS = "java/lang/Throwable";
- String FIBER_CLASS = "kilim/Fiber";
- String STATE_CLASS = "kilim/State";
- String TASK_CLASS = "kilim/Task";
- String PAUSABLE_CLASS = "kilim/Pausable";
- String NOT_PAUSABLE_CLASS = "kilim/NotPausable";
+ String FIBER_CLASS = Fiber.class.getName().replace('.', '/');
+ String STATE_CLASS = State.class.getName().replace('.', '/');
+ String TASK_CLASS = Task.class.getName().replace('.', '/');
+ String PAUSABLE_CLASS = Pausable.class.getName().replace('.', '/');
+ String NOT_PAUSABLE_CLASS = NotPausable.class.getName().replace('.', '/');
+ String D_FIBER = "L"+FIBER_CLASS+";";
+ String D_STATE = "L"+STATE_CLASS+";";
+ String D_TASK = "L"+TASK_CLASS+";";
+ String D_PAUSABLE = "L"+PAUSABLE_CLASS+";";
+
String WOVEN_FIELD = "$isWoven";
// Constant opcodes missing from asm's opcodes (as of asm 3.0)
View
72 src/kilim/Fiber.java
@@ -42,7 +42,9 @@
* One State object for each activation frame in the call hierarchy.
*/
private State[] stateStack = new State[10];
-
+ private Object[] selfStack = new Object[10];
+ private int[] pcStack = new int[10];
+
/*
* Index into stateStack and equal to depth of call hierarchy - 1
*/
@@ -60,7 +62,9 @@
/*
* Special marker state used by pause
*/
+ private static final int PAUSE_STATE_PC = 1;
private static final State PAUSE_STATE = new State();
+ private static final State EMPTY_STATE = new State();
/*
* Status indicators returned by down()
@@ -85,10 +89,6 @@
*/
private static final int PAUSING__HAS_STATE = 3;
- static {
- PAUSE_STATE.pc = 1;
- }
-
public Fiber(Task t) {
task = t;
}
@@ -152,15 +152,14 @@ public int up() {
return NOT_PAUSING__NO_STATE;
} else {
stack[d] = null; // clean up
- pc = cs.pc;
+ pc = pcStack[d];
// if (debug) System.out.println("\nup(not pausing)" + this);;
// if (debug) ds();
return NOT_PAUSING__HAS_STATE;
}
}
}
-
public final Fiber begin() {
return down();
}
@@ -201,7 +200,7 @@ public Fiber down() {
} else {
State s = stateStack[d];
curState = s;
- pc = (s == null) ? 0 : s.pc;
+ pc = (s == null) ? 0 : pcStack[d];
}
// if (debug) System.out.println("down:\n" + this);
// if (debug) ds();
@@ -244,16 +243,17 @@ static void ds() {
*/
public int upEx() {
// compute new iStack.
- int is = task.getStackDepth() - 2; // remove upEx and convert to 0-based index.
+ final int is = task.getStackDepth() - 2; // remove upEx and convert to 0-based index.
State cs = stateStack[is];
for (int i = iStack; i >= is; i--) {
stateStack[i] = null; // release state
+ selfStack[i] = null; // release state
}
iStack = is;
curState = cs;
- return (cs == null) ? 0 : cs.pc;
+ return (cs == null) ? 0 : pcStack[is];
}
/**
@@ -264,25 +264,60 @@ public int upEx() {
public Object getCallee() {
assert stateStack[iStack] != PAUSE_STATE : "No callee: this state is the pause state";
assert stateStack[iStack] != null : "Callee is null";
- return stateStack[iStack + 1].self;
+ return selfStack[iStack + 1];
}
- private State[] ensureSize(int newsize) {
+ private void ensureSize(int newsize) {
// System.out.println("ENSURE SIZE = " + newsize);
+ int len = stateStack.length;
+
State[] newStack = new State[newsize];
- System.arraycopy(stateStack, 0, newStack, 0, stateStack.length);
+ System.arraycopy(stateStack, 0, newStack, 0, len);
stateStack = newStack;
- return newStack;
- }
+
+ Object[] newSelfStack = new Object[newsize];
+ System.arraycopy(selfStack, 0, newSelfStack, 0, len);
+ selfStack = newSelfStack;
+
+ int[] newPCStack = new int[newsize];
+ System.arraycopy(pcStack, 0, newPCStack, 0, len);
+ pcStack = newPCStack;
+}
/**
* Called by the generated code before pausing and unwinding its stack
* frame.
*
* @param state
*/
- public void setState(State state) {
+ public void setState(State state, Object self, int pc) {
+ stateStack[iStack] = state;
+ selfStack[iStack] = self;
+ pcStack[iStack] = pc;
+ isPausing = true;
+// System.out.println("setState[" + + iStack + "] = " + this);
+ }
+
+ public void setState(State state, int pc) {
stateStack[iStack] = state;
+ selfStack[iStack] = null;
+ pcStack[iStack] = pc;
+ isPausing = true;
+// System.out.println("setState[" + + iStack + "] = " + this);
+ }
+
+ public void setState(Object self, int pc) {
+ stateStack[iStack] = EMPTY_STATE;
+ selfStack[iStack] = self;
+ pcStack[iStack] = pc;
+ isPausing = true;
+// System.out.println("setState[" + + iStack + "] = " + this);
+ }
+
+ public void setState(int pc) {
+ stateStack[iStack] = EMPTY_STATE;
+ selfStack[iStack] = null;
+ pcStack[iStack] = pc;
isPausing = true;
// System.out.println("setState[" + + iStack + "] = " + this);
}
@@ -293,9 +328,10 @@ void togglePause() {
// upto date.
if (curState == null) {
- setState(PAUSE_STATE);
+ setState(PAUSE_STATE, PAUSE_STATE_PC);
} else {
- assert curState == PAUSE_STATE : "togglePause: Expected PAUSE_STATE, instead got: iStack == " + iStack + ", state = " + curState;
+ assert curState == PAUSE_STATE :
+ "togglePause: Expected PAUSE_STATE, instead got: iStack == " + iStack + ", state = " + curState;
stateStack[iStack] = null;
isPausing = false;
}
View
79 src/kilim/Mailbox.java
@@ -95,6 +95,83 @@ public T get(EventSubscriber eo) {
return msg;
}
+
+ /**
+ * @return non-null message.
+ * @throws Pausable
+ */
+ public void untilHasMessage() throws Pausable{
+ while (hasMessage(Task.getCurrentTask()) == false) {
+ Task.pause(this);
+ }
+ }
+
+
+ /**
+ * @return non-null message.
+ * @throws Pausable
+ */
+ public boolean untilHasMessage(long timeoutMillis) throws Pausable {
+ final Task t = Task.getCurrentTask();
+ boolean has_msg = hasMessage(t);
+ long begin = System.currentTimeMillis();
+ while (has_msg == false) {
+ TimerTask tt = new TimerTask() {
+ public void run() {
+ Mailbox.this.removeMsgAvailableListener(t);
+ t.onEvent(Mailbox.this, timedOut);
+ }
+ };
+ Task.timer.schedule(tt, timeoutMillis);
+ Task.pause(this);
+ tt.cancel();
+ if (System.currentTimeMillis() - begin > timeoutMillis) {
+ break;
+ }
+ has_msg = hasMessage(t);
+ }
+ return has_msg;
+ }
+
+
+ /**
+ * Non-blocking, nonpausing "wait-until-message-available".
+ * @param eo. If non-null, registers this observer and calls it with a MessageAvailable event when
+ * a put() is done.
+ * @return true's one, or false
+ */
+ public boolean hasMessage(EventSubscriber eo) {
+ boolean has_msg;
+ synchronized(this) {
+ int n = numMsgs;
+ if (n > 0) {
+ has_msg = true;
+ } else {
+ has_msg = false;
+ addMsgAvailableListener(eo);
+ }
+ }
+ return has_msg;
+ }
+
+ /**
+ * Non-blocking, nonpausing peek.
+ * @return buffered message if there's one, or null
+ */
+ public T peek() {
+ T msg;
+ synchronized(this) {
+ int n = numMsgs;
+ if (n > 0) {
+ int ic = icons;
+ msg = msgs[ic];
+ } else {
+ msg = null;
+ }
+ }
+ return msg;
+ }
+
/**
* Non-blocking, nonpausing put.
* @param eo. If non-null, registers this observer and calls it with an SpaceAvailable event
@@ -234,7 +311,7 @@ public synchronized void removeSpaceAvailableListener(EventSubscriber spcSub) {
public synchronized void addMsgAvailableListener(EventSubscriber msgSub) {
- if (sink != null) {
+ if (sink != null && sink != msgSub) {
throw new AssertionError(
"Error: A mailbox can not be shared by two consumers. New = "
+ msgSub + ", Old = " + sink);
View
4 src/kilim/State.java
@@ -25,6 +25,6 @@
*/
public class State {
- public int pc;
- public Object self;
+ //public int pc;
+ //public Object self;
}
View
34 src/kilim/Task.java
@@ -7,9 +7,8 @@
package kilim;
import java.util.LinkedList;
-import java.util.TimerTask;
import java.util.Timer;
-import java.util.HashMap;
+import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -82,6 +81,9 @@
public Object exitResult = "OK";
+
+ private Error death_ex;
+
// TODO: move into a separate timer service or into the schduler.
public final static Timer timer = new Timer(true);
@@ -121,6 +123,24 @@ public Task start() {
return this;
}
+ /**
+ * Used to make an exception happen inside this task
+ * @param ex
+ */
+ public void kill(Error ex) {
+ System.err.println("killing "+this+" setting "+death_ex);
+
+ this.death_ex = ex;
+ resume();
+ }
+
+ private void maybeKill() {
+ if (this.death_ex != null) {
+ System.err.println("killing "+this+": throw "+death_ex);
+ throw this.death_ex;
+ }
+ }
+
/**
* The generated code calls Fiber.upEx, which in turn calls
* this to find out out where the current method is w.r.t
@@ -147,7 +167,7 @@ public void onEvent(EventPublisher ep, Event e) {
// is mailbox.put or get(), and that it'll be the pausereason as well.
if (ep == pauseReason) {
resume();
- }
+ }
}
/**
* This is typically called by a pauseReason to resume the task.
@@ -272,6 +292,7 @@ public static void pause(PauseReason pauseReason, Fiber f) {
f.task.setPauseReason(null);
}
f.togglePause();
+ f.task.maybeKill();
}
/*
@@ -303,11 +324,11 @@ public String dump() {
}
}
- public void pinToThread() {
+ void pinToThread() {
numActivePins++;
}
- public void unpinFromThread() {
+ void unpinFromThread() {
numActivePins--;
}
@@ -330,12 +351,13 @@ public synchronized boolean isDone() {
* execute processing (in addition to calling the execute(fiber) method
* of the task.
*/
- public void _runExecute(WorkerThread thread) throws NotPausable {
+ void _runExecute(WorkerThread thread) throws NotPausable {
Fiber f = fiber;
boolean isDone = false;
try {
currentThread = Thread.currentThread();
assert (preferredResumeThread == null || preferredResumeThread == thread) : "Resumed " + id + " in incorrect thread. ";
+
// start execute. fiber is wound to the beginning.
execute(f.begin());
View
1 src/kilim/WorkerThread.java
@@ -23,6 +23,7 @@
public int numResumes = 0;
WorkerThread(Scheduler ascheduler) {
+ setDaemon(true);
scheduler=ascheduler;
}
View
11 src/kilim/analysis/AsmDetector.java
@@ -16,21 +16,21 @@
public class AsmDetector {
static HashMap<String, ClassCache> classCacheMap= new HashMap<String, ClassCache>();
public static int getPausableStatus(String className, String methodName,
- String desc)
+ String desc, Detector detector)
{
try {
ClassCache classCache = classCacheMap.get(className);
if (classCache == null) {
ClassReader cr = new ClassReader(className);
ClassNode cn = new ClassNode();
- cr.accept(cn, false);
+ cr.accept(cn, 0);
classCache = cache(className, cn);
}
int status = classCache.getPausableStatus(methodName, desc);
if (status == Detector.METHOD_NOT_FOUND) {
// check super classes
for (String superName: classCache.superClasses) {
- status = Detector.getPausableStatus(superName, methodName, desc);
+ status = detector.getPausableStatus(superName, methodName, desc);
if (status != Detector.METHOD_NOT_FOUND)
break;
}
@@ -64,7 +64,7 @@ private static ClassCache cache(String className, ClassNode cn) {
return classCache;
}
public static void main(String[] args) {
- AsmDetector.getPausableStatus("com/sleepycat/je/Database", "putInternal", "Lcom/sleepycat/je/Transaction;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/dbi/PutMode;Lkilim/Fiber;)Lcom/sleepycat/je/OperationStatus;)V");
+ AsmDetector.getPausableStatus("com/sleepycat/je/Database", "putInternal", "Lcom/sleepycat/je/Transaction;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/DatabaseEntry;Lcom/sleepycat/je/dbi/PutMode;Lkilim/Fiber;)Lcom/sleepycat/je/OperationStatus;)V", Detector.DEFAULT);
}
static class ClassCache {
@@ -86,7 +86,8 @@ public int getPausableStatus(String methodName, String desc) {
return Detector.METHOD_NOT_FOUND;
}
}
- public String toString() {
+ @Override
+ public String toString() {
return className + "\nPausable Methods: " + pausableMethods + "\nOthers:" + otherMethods;
}
}
View
74 src/kilim/analysis/BasicBlock.java
@@ -41,8 +41,10 @@
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.IincInsnNode;
+import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.LookupSwitchInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
@@ -220,6 +222,10 @@ public BasicBlock(MethodFlow aflow, Label aStartLabel) {
successors = new ArrayList<BasicBlock>(2);
}
+ Detector detector() {
+ return flow.detector();
+ }
+
/**
* Absorb as many instructions until the next label or the next transfer of
* control instruction. In the first pass we may end up creating many many
@@ -232,7 +238,8 @@ public BasicBlock(MethodFlow aflow, Label aStartLabel) {
* 3. A pausable method is treated like a labeled instruction, and is
* given a label if there isn't one already. Constraint 2 applies.
*/
- int initialize(int pos) {
+ @SuppressWarnings("unchecked")
+ int initialize(int pos) {
AbstractInsnNode ain;
startPos = pos;
@@ -290,8 +297,8 @@ int initialize(int pos) {
case IF_ACMPNE:
case JSR:
case GOTO:
- Label l = ((JumpInsnNode) ain).label;
- bb = flow.getOrCreateBasicBlock(l);
+ LabelNode l = ((JumpInsnNode) ain).label;
+ bb = flow.getOrCreateBasicBlock(l.getLabel());
if (opcode == JSR) {
bb.setFlag(IS_SUBROUTINE);
hasFollower = false;
@@ -317,20 +324,20 @@ int initialize(int pos) {
case TABLESWITCH:
case LOOKUPSWITCH:
- Label defaultLabel;
- List otherLabels;
+ LabelNode defaultLabel;
+ List<LabelNode> otherLabels;
if (opcode == TABLESWITCH) {
defaultLabel = ((TableSwitchInsnNode) ain).dflt;
otherLabels = ((TableSwitchInsnNode) ain).labels;
} else {
defaultLabel = ((LookupSwitchInsnNode) ain).dflt;
otherLabels = ((LookupSwitchInsnNode) ain).labels;
}
- for (Iterator it = otherLabels.iterator(); it.hasNext();) {
- l = (Label) it.next();
- addSuccessor(flow.getOrCreateBasicBlock(l));
+ for (Iterator<LabelNode> it = otherLabels.iterator(); it.hasNext();) {
+ l = (LabelNode) it.next();
+ addSuccessor(flow.getOrCreateBasicBlock(l.getLabel()));
}
- addSuccessor(flow.getOrCreateBasicBlock(defaultLabel));
+ addSuccessor(flow.getOrCreateBasicBlock(defaultLabel.getLabel()));
endOfBB = true;
hasFollower = false;
break;
@@ -343,8 +350,8 @@ int initialize(int pos) {
if (pos == startPos) {
setFlag(PAUSABLE);
} else {
- l = flow.getOrCreateLabelAtPos(pos);
- bb = flow.getOrCreateBasicBlock(l);
+ Label ll = flow.getOrCreateLabelAtPos(pos);
+ bb = flow.getOrCreateBasicBlock(ll);
bb.setFlag(PAUSABLE);
addSuccessor(bb);
pos--; // don't consume this instruction
@@ -354,7 +361,11 @@ int initialize(int pos) {
}
break;
+
default:
+ if (opcode >= 26 && opcode <= 45)
+ throw new IllegalStateException("instruction variants not expected here");
+
break;
}
@@ -476,7 +487,8 @@ void interpret() {
frame.push(Value.make(startPos, D_RETURN_ADDRESS));
}
String componentType = null;
- boolean canThrowException = false;
+ @SuppressWarnings("unused")
+ boolean canThrowException = false;
boolean propagateFrame = true;
int i = 0;
try {
@@ -1053,6 +1065,8 @@ void interpret() {
v = Value.make(i, TypeDesc.getInterned(sb.toString()));
frame.push(v);
break;
+ case -1:
+ break;
default:
assert false : "Unexpected opcode: " + ain.getOpcode();
}
@@ -1078,16 +1092,16 @@ void interpret() {
}
}
-
+ /*
private boolean checkReceiverType(Value v, MethodInsnNode min) {
String t = v.getTypeDesc();
if (t == D_NULL) {
return true;
}
t = TypeDesc.getInternalName(t);
- return Detector.getPausableStatus(t, min.name, min.desc) != Detector.METHOD_NOT_FOUND;
+ return detector().getPausableStatus(t, min.name, min.desc) != Detector.METHOD_NOT_FOUND;
}
-
+ */
public boolean isCatchHandler() {
return caughtExceptionType != null;
}
@@ -1178,7 +1192,7 @@ public boolean flowVarUsage() {
*/
ArrayList<BasicBlock> inline() throws KilimException {
HashMap<BasicBlock, BasicBlock> bbCopyMap = null;
- HashMap<Label, Label> labelCopyMap = null;
+ HashMap<Label, LabelNode> labelCopyMap = null;
BasicBlock targetBB = successors.get(0);
Label returnToLabel = flow.getOrCreateLabelAtPos(endPos+1);
BasicBlock returnToBB = flow.getOrCreateBasicBlock(returnToLabel);
@@ -1199,7 +1213,7 @@ public boolean flowVarUsage() {
return null;
}
bbCopyMap = new HashMap<BasicBlock, BasicBlock>(10);
- labelCopyMap = new HashMap<Label, Label>(10);
+ labelCopyMap = new HashMap<Label, LabelNode>(10);
successors.clear();
// first pass
targetBB.dupBBAndLabels(isPausableSub, bbCopyMap, labelCopyMap, returnToBB);
@@ -1210,7 +1224,7 @@ public boolean flowVarUsage() {
void dupBBAndLabels(boolean deepCopy,
HashMap<BasicBlock, BasicBlock> bbCopyMap,
- HashMap<Label, Label> labelCopyMap, BasicBlock returnToBB)
+ HashMap<Label, LabelNode> labelCopyMap, BasicBlock returnToBB)
throws KilimException {
for (BasicBlock orig : getSubBlocks()) {
@@ -1222,7 +1236,7 @@ void dupBBAndLabels(boolean deepCopy,
for (int i = orig.startPos; i <= orig.endPos; i++) {
Label origLabel = flow.getLabelAt(i);
if (origLabel != null) {
- Label l = labelCopyMap.put(origLabel, new Label());
+ LabelNode l = labelCopyMap.put(origLabel, new LabelNode());
assert l == null;
}
}
@@ -1235,7 +1249,7 @@ void dupBBAndLabels(boolean deepCopy,
static ArrayList<BasicBlock> dupCopyContents(boolean deepCopy,
BasicBlock targetBB, BasicBlock returnToBB,
HashMap<BasicBlock, BasicBlock> bbCopyMap,
- HashMap<Label, Label> labelCopyMap) throws KilimException {
+ HashMap<Label, LabelNode> labelCopyMap) throws KilimException {
ArrayList<BasicBlock> newBBs = new ArrayList<BasicBlock>(targetBB.getSubBlocks().size());
for (BasicBlock orig : targetBB.getSubBlocks()) {
@@ -1267,9 +1281,9 @@ void dupBBAndLabels(boolean deepCopy,
if (deepCopy) {
MethodFlow flow = targetBB.flow;
- List instructions = flow.instructions;
+ InsnList instructions = flow.instructions;
// copy instructions
- dup.startLabel = labelCopyMap.get(orig.startLabel);
+ dup.startLabel = labelCopyMap.get(orig.startLabel).getLabel();
dup.startPos = instructions.size();
dup.endPos = dup.startPos + (orig.endPos - orig.startPos);
// Note: last instruction (@endPos) isn't copied in the loop.
@@ -1283,7 +1297,7 @@ void dupBBAndLabels(boolean deepCopy,
for (i = orig.startPos; i <= end; i++, newPos++) {
Label l = flow.getLabelAt(i);
if (l != null) {
- l = labelCopyMap.get(l);
+ l = labelCopyMap.get(l).getLabel();
assert l != null;
flow.setLabel(newPos, l);
}
@@ -1294,7 +1308,7 @@ void dupBBAndLabels(boolean deepCopy,
}
AbstractInsnNode lastInsn = (AbstractInsnNode) instructions.get(orig.endPos);
- Label dupLabel;
+ LabelNode dupLabel;
int opcode = lastInsn.getOpcode();
if (lastInsn instanceof JumpInsnNode) {
JumpInsnNode jin = (JumpInsnNode) lastInsn;
@@ -1306,7 +1320,7 @@ void dupBBAndLabels(boolean deepCopy,
} else if (opcode == TABLESWITCH) {
TableSwitchInsnNode tsin = (TableSwitchInsnNode) lastInsn;
- Label[] labels = new Label[tsin.labels.size()];
+ LabelNode[] labels = new LabelNode[tsin.labels.size()];
for (i = 0; i < labels.length; i++) {
dupLabel = labelCopyMap.get(tsin.labels.get(i));
assert dupLabel != null;
@@ -1317,7 +1331,7 @@ void dupBBAndLabels(boolean deepCopy,
lastInsn = new TableSwitchInsnNode(tsin.min, tsin.max, dupLabel, labels);
} else if (opcode == LOOKUPSWITCH) {
LookupSwitchInsnNode lsin = (LookupSwitchInsnNode) lastInsn;
- Label[] labels = new Label[lsin.labels.size()];
+ LabelNode[] labels = new LabelNode[lsin.labels.size()];
for (i = 0; i < labels.length; i++) {
dupLabel = labelCopyMap.get(lsin.labels.get(i));
assert dupLabel != null;
@@ -1402,7 +1416,8 @@ BasicBlock getFollowingBlock() {
return flow.getBasicBlock(l);
}
- public String toString() {
+ @Override
+ public String toString() {
StringBuffer sb = new StringBuffer(200);
sb.append("\n========== BB #").append(id).append("[").append(System.identityHashCode(this)).append("]\n");
sb.append("method: ").append(this.flow.name).append("\n");
@@ -1480,11 +1495,12 @@ void changeJSR_RET_toGOTOs() throws KilimException {
@SuppressWarnings("unchecked")
void setInstruction(int pos, AbstractInsnNode insn) {
- flow.instructions.set(pos, insn);
+ AbstractInsnNode location = flow.instructions.get(pos);
+ flow.instructions.set(location, insn);
}
void changeLastInsnToGOTO(Label label) {
- setInstruction(endPos, new JumpInsnNode(GOTO, label));
+ setInstruction(endPos, new JumpInsnNode(GOTO, flow.getLabelNode(label)));
}
public boolean isGetCurrentTask() {
View
82 src/kilim/analysis/CallWeaver.java
@@ -218,6 +218,9 @@ private void assignRegisters() {
// ensure we don't touch any of the locals in the range that the
// original
// code knows about.
+ if (f == null) {
+ System.err.println("we have no startFrame here!");
+ }
varUsage.set(0, f.getMaxLocals());
int i = bb.flow.isStatic() ? 0 : 1;
@@ -297,7 +300,7 @@ int getNumBottom() {
*/
void genRewind(MethodVisitor mv) {
Frame f = bb.startFrame;
- Usage u = bb.usage;
+ // Usage u = bb.usage;
// The last parameter to the method is fiber, but the original
// code doesn't know that and will use up that slot as it
@@ -513,27 +516,41 @@ private void genSave(MethodVisitor mv, Label saveLabel) {
* the method weaver's list. This allows us to do a switch in the
* method's entry.
*/
- mv.visitTypeInsn(NEW, stateClassName);
- mv.visitInsn(DUP); //
- // call constructor
- mv.visitMethodInsn(INVOKESPECIAL, stateClassName, "<init>", "()V");
+ boolean is_simple_state = stateClassName.equals(STATE_CLASS);
+
+ if (is_simple_state) {
+
+ loadVar(mv, TOBJECT, methodWeaver.getFiberVar());
+
+ if (!bb.flow.isStatic()) {
+ mv.visitInsn(ALOAD_0); // for state.self == this
+ }
+
+ int pc = methodWeaver.getPC(this);
+ if (pc < 6) {
+ mv.visitInsn(ICONST_0 + pc);
+ } else {
+ mv.visitIntInsn(BIPUSH, pc);
+ }
+
+ if (!bb.flow.isStatic()) {
+ methodWeaver.ensureMaxStack(3);
+ mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "(Ljava/lang/Object;I)V");
+ } else {
+ methodWeaver.ensureMaxStack(2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "(I)V");
+ }
+
+
+ } else {
+ mv.visitTypeInsn(NEW, stateClassName);
+ mv.visitInsn(DUP); //
+ // call constructor
+ mv.visitMethodInsn(INVOKESPECIAL, stateClassName, "<init>", "()V");
+
// save state in register
int stateVar = allocVar(1);
storeVar(mv, TOBJECT, stateVar);
- // state.self = this if the current executing method isn't static
- if (!bb.flow.isStatic()) {
- loadVar(mv, TOBJECT, stateVar);
- mv.visitInsn(ALOAD_0); // for state.self == this
- mv.visitFieldInsn(PUTFIELD, STATE_CLASS, "self", D_OBJECT);
- }
- int pc = methodWeaver.getPC(this);
- loadVar(mv, TOBJECT, stateVar); // state.pc
- if (pc < 6) {
- mv.visitInsn(ICONST_0 + pc);
- } else {
- mv.visitIntInsn(BIPUSH, pc);
- }
- mv.visitFieldInsn(PUTFIELD, STATE_CLASS, "pc", D_INT);
// First save bottom stack into state
int i = getNumBottom() - 1;
@@ -577,9 +594,32 @@ private void genSave(MethodVisitor mv, Label saveLabel) {
// Fiber.setState(state);
loadVar(mv, TOBJECT, methodWeaver.getFiberVar());
loadVar(mv, TOBJECT, stateVar);
- mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "("
- + D_STATE + ")V");
+
+ if (!bb.flow.isStatic()) {
+ mv.visitInsn(ALOAD_0); // for state.self == this
+ }
+
+ int pc = methodWeaver.getPC(this);
+ if (pc < 6) {
+ mv.visitInsn(ICONST_0 + pc);
+ } else {
+ mv.visitIntInsn(BIPUSH, pc);
+ }
+
+ if (!bb.flow.isStatic()) {
+ methodWeaver.ensureMaxStack(4);
+ mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "("
+ + D_STATE + "Ljava/lang/Object;I)V");
+ } else {
+ methodWeaver.ensureMaxStack(3);
+ mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "("
+ + D_STATE + "I)V");
+ }
+
releaseVar(stateVar, 1);
+ }
+
+
// Figure out the return type of the calling method and issue the
// appropriate xRETURN instruction
retType = TypeDesc.getReturnTypeDesc(bb.flow.desc);
View
28 src/kilim/analysis/ClassFlow.java
@@ -12,6 +12,7 @@
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
@@ -34,16 +35,25 @@
* true if the .class being read is already woven.
*/
public boolean isWoven = false;
+ private Detector detector;
- public ClassFlow(InputStream is) throws IOException {
+ public ClassFlow(InputStream is, Detector detector) throws IOException {
cr = new ClassReader(is);
+ this.detector = detector;
}
- public ClassFlow(String aClassName) throws IOException {
+ public ClassFlow(String aClassName, Detector detector) throws IOException {
cr = new ClassReader(aClassName);
+ this.detector = detector;
}
- @SuppressWarnings({"unchecked"})
+ public ClassFlow(byte[] data, Detector detector) {
+ cr = new ClassReader(data);
+ this.detector = detector;
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked"})
public MethodVisitor visitMethod(
final int access,
final String name,
@@ -52,7 +62,7 @@ public MethodVisitor visitMethod(
final String[] exceptions)
{
MethodFlow mn = new MethodFlow( this, access, name, desc, signature,
- exceptions);
+ exceptions, detector);
super.methods.add(mn);
return mn;
}
@@ -62,9 +72,9 @@ public MethodVisitor visitMethod(
return methodFlows;
}
- public ArrayList<MethodFlow> analyze(boolean forceAnalysis) throws KilimException {
+ public ArrayList<MethodFlow> analyze(boolean forceAnalysis) throws KilimException {
// cr.accept(this, ClassReader.SKIP_DEBUG);
- cr.accept(this, false);
+ cr.accept(this, 0);
for (Object o: this.fields) {
FieldNode fn = (FieldNode)o;
if (fn.name.equals(Constants.WOVEN_FIELD)) {
@@ -127,6 +137,10 @@ public boolean isPausable() {
boolean isInterface() {
- return (this.access & Constants.ACC_INTERFACE) != 0;
+ return (this.access & Opcodes.ACC_INTERFACE) != 0;
}
+
+ public Detector detector() {
+ return detector;
+ }
}
View
17 src/kilim/analysis/ClassWeaver.java
@@ -31,20 +31,25 @@
List<ClassInfo> classInfoList = new LinkedList<ClassInfo>();
static HashSet<String> stateClasses = new HashSet<String>();
- public ClassWeaver(InputStream is) throws IOException {
- classFlow = new ClassFlow(is);
+ public ClassWeaver(byte[] data, Detector detector) {
+ classFlow = new ClassFlow(data, detector);
weave();
}
- public ClassWeaver(String className) throws IOException {
- classFlow = new ClassFlow(className);
+ public ClassWeaver(InputStream is, Detector detector) throws IOException {
+ classFlow = new ClassFlow(is, detector);
+ weave();
+ }
+
+ public ClassWeaver(String className, Detector detector) throws IOException {
+ classFlow = new ClassFlow(className, detector);
weave();
}
private void weave() throws KilimException {
classFlow.analyze(false);
if (classFlow.isPausable() && needsWeaving()) {
- ClassWriter cw = new ClassWriter(false);
+ ClassWriter cw = new ClassWriter(0);
accept(cw);
addClassInfo(new ClassInfo(classFlow.getClassName(), cw.toByteArray()));
}
@@ -182,7 +187,7 @@ String createStateClass(ValInfoList valInfoList) {
return className;
}
stateClasses.add(className);
- ClassWriter cw = new ClassWriter(false);
+ ClassWriter cw = new ClassWriter(0);
cw.visit(V1_1, ACC_PUBLIC | ACC_FINAL, className, null, "kilim/State", null);
// Create default constructor
View
67 src/kilim/analysis/Detector.java
@@ -4,13 +4,13 @@
* specified in the file "License"
*/
package kilim.analysis;
-import java.lang.reflect.Method;
-
import kilim.Constants;
import kilim.NotPausable;
import kilim.Pausable;
-
-import org.objectweb.asm.Type;
+import kilim.mirrors.ClassMirror;
+import kilim.mirrors.ClassMirrorNotFoundException;
+import kilim.mirrors.MethodMirror;
+import kilim.mirrors.Mirrors;
/**
* Utility class to check if a method has been marked pausable
*
@@ -24,7 +24,22 @@
static final String[] STANDARD_DONT_CHECK_LIST = {
"java.", "javax." };
- public static boolean isPausable(String className, String methodName,
+ public static final Detector DEFAULT = new Detector(Mirrors.getRuntimeMirrors());
+
+ private final Mirrors mirrors;
+
+ public Detector(Mirrors mirrors) {
+ this.mirrors = mirrors;
+
+ NOT_PAUSABLE = mirrors.mirror(NotPausable.class);
+ PAUSABLE = mirrors.mirror(Pausable.class);
+ OBJECT = mirrors.mirror(Object.class);
+
+ }
+
+ ClassMirror NOT_PAUSABLE, PAUSABLE, OBJECT;
+
+ public boolean isPausable(String className, String methodName,
String desc) {
return getPausableStatus(className, methodName, desc) == PAUSABLE_METHOD_FOUND;
}
@@ -33,7 +48,7 @@ public static boolean isPausable(String className, String methodName,
* @return one of METHOD_NOT_FOUND, PAUSABLE_METHOD_FOUND, METHOD_NOT_PAUSABLE
*/
- public static int getPausableStatus(String className, String methodName,
+ public int getPausableStatus(String className, String methodName,
String desc)
{
int ret = METHOD_NOT_FOUND;
@@ -42,59 +57,59 @@ public static int getPausableStatus(String className, String methodName,
}
className = className.replace('/', '.');
try {
- Class cl = Class.forName(className);
- Method m = findMethod(cl, methodName, desc);
+ ClassMirror cl = mirrors.classForName(className);
+ MethodMirror m = findMethod(cl, methodName, desc);
if (m != null) {
- for (Class c: m.getExceptionTypes()) {
- if (NotPausable.class.isAssignableFrom(c)) {
+ for (ClassMirror c: m.getExceptionTypes()) {
+ if (NOT_PAUSABLE.isAssignableFrom(c)) {
return METHOD_NOT_PAUSABLE;
}
- if (Pausable.class.isAssignableFrom(c)) {
+ if (PAUSABLE.isAssignableFrom(c)) {
return PAUSABLE_METHOD_FOUND;
}
}
return METHOD_NOT_PAUSABLE;
}
- } catch (ClassNotFoundException ignore) {
+ } catch (ClassMirrorNotFoundException ignore) {
} catch (VerifyError ve) {
- return AsmDetector.getPausableStatus(className, methodName, desc);
+ return AsmDetector.getPausableStatus(className, methodName, desc, this);
}
return ret;
}
- public static Method findMethod(Class cl, String methodName, String desc) {
+ private MethodMirror findMethod(ClassMirror cl, String methodName, String desc) {
if (cl == null) return null;
- Method m = findMethodInHierarchy(cl, methodName, desc);
+ MethodMirror m = findMethodInHierarchy(cl, methodName, desc);
if (m == null) {
- cl = Object.class;
- for (Method om : cl.getDeclaredMethods()) {
- if (om.getName().equals(methodName) && Type.getMethodDescriptor(om).equals(desc)) {
+ cl = mirrors.mirror(Object.class);
+ for (MethodMirror om : cl.getDeclaredMethods()) {
+ if (om.getName().equals(methodName) && om.getMethodDescriptor().equals(desc)) {
return om;
}
}
}
return m;
}
- public static Method findMethodInHierarchy(Class cl, String methodName,
+ private MethodMirror findMethodInHierarchy(ClassMirror cl, String methodName,
String desc) {
if (cl == null) return null;
- for (Method om : cl.getDeclaredMethods()) {
- if (om.getName().equals(methodName) && Type.getMethodDescriptor(om).equals(desc)) {
+ for (MethodMirror om : cl.getDeclaredMethods()) {
+ if (om.getName().equals(methodName) && om.getMethodDescriptor().equals(desc)) {
if (om.isBridge()) continue;
return om;
}
}
- if (cl == Object.class)
+ if (OBJECT.equals(cl))
return null;
- Method m = findMethodInHierarchy(cl.getSuperclass(), methodName, desc);
+ MethodMirror m = findMethodInHierarchy(cl.getSuperclass(), methodName, desc);
if (m != null)
return m;
- for (Class ifcl : cl.getInterfaces()) {
+ for (ClassMirror ifcl : cl.getInterfaces()) {
m = findMethodInHierarchy(ifcl, methodName, desc);
if (m != null)
return m;
@@ -103,7 +118,9 @@ public static Method findMethodInHierarchy(Class cl, String methodName,
}
public static String D_FIBER_ = Constants.D_FIBER + ")";
- private static String statusToStr(int st) {
+
+ @SuppressWarnings("unused")
+ private static String statusToStr(int st) {
switch (st) {
case METHOD_NOT_FOUND : return "not found";
case PAUSABLE_METHOD_FOUND : return "pausable";
View
12 src/kilim/analysis/FileLister.java
@@ -60,14 +60,16 @@ public FileLister(String dirOrJarName) throws IOException {
final File file;
DirEntry(File f) {file = f;}
- public String getFileName() {
+ @Override
+ public String getFileName() {
try {
return file.getCanonicalPath();
} catch (IOException ignore) {}
return null;
}
- public InputStream getInputStream() throws IOException {
+ @Override
+ public InputStream getInputStream() throws IOException {
return new BufferedInputStream(new FileInputStream(file));
}
}
@@ -119,11 +121,13 @@ public void remove() {
private final JarEntry jarEntry;
JEntry(JarEntry j) {jarEntry = j;}
- public String getFileName() {
+ @Override
+ public String getFileName() {
return jarEntry.getName();
}
- public InputStream getInputStream() throws IOException {
+ @Override
+ public InputStream getInputStream() throws IOException {
return jarFile.getInputStream(jarEntry);
}
}
View
9 src/kilim/analysis/Frame.java
@@ -246,7 +246,8 @@ void clearStack() {
stacklen = 0;
}
- public boolean equals(Object other) {
+ @Override
+ public boolean equals(Object other) {
Frame that = (Frame)other;
for (int i = 0; i < locals.length; i++) {
if (!locals[i].equals(that.locals[i])) return false;
@@ -257,14 +258,16 @@ public boolean equals(Object other) {
return true;
}
- public int hashCode() {
+ @Override
+ public int hashCode() {
int hash = 0;
for (int i = 0; i < this.locals.length;i++) hash ^= this.locals[i].hashCode();
for (int i = 0; i < this.stacklen;i++) hash ^= this.locals[i].hashCode();
return hash;
}
- public String toString() {
+ @Override
+ public String toString() {
StringBuffer sb = new StringBuffer(100);
int numDefined = 0;
sb.append("): ");
View
57 src/kilim/analysis/MethodFlow.java
@@ -28,8 +28,10 @@
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodInsnNode;
@@ -42,6 +44,7 @@
*/
public class MethodFlow extends MethodNode {
+
/**
* The classFlow to which this methodFlow belongs
*/
@@ -80,16 +83,20 @@
private boolean suppressPausableCheck;
private List<MethodInsnNode> pausableMethods = new LinkedList<MethodInsnNode>();
+
+ private final Detector detector;
public MethodFlow(
ClassFlow classFlow,
final int access,
final String name,
final String desc,
final String signature,
- final String[] exceptions) {
+ final String[] exceptions,
+ final Detector detector) {
super(access, name, desc, signature, exceptions);
this.classFlow = classFlow;
+ this.detector = detector;
int numInstructions = instructions.size();
posToLabelMap = new ArrayList<Label>(numInstructions);
for (int i = numInstructions - 1 ; i >= 0; i--) {
@@ -149,7 +156,7 @@ public void verifyPausables() throws KilimException {
}
private void checkStatus(String superClassName, String methodName, String desc) throws KilimException {
- int status = Detector.getPausableStatus(superClassName, methodName, desc);
+ int status = detector.getPausableStatus(superClassName, methodName, desc);
if ((status == Detector.PAUSABLE_METHOD_FOUND && !hasPausableAnnotation)) {
throw new KilimException("Base class method is pausable, derived class is not: " +
"\nBase class = " + superClassName +
@@ -168,6 +175,15 @@ private String toString(String className, String methName, String desc) {
return className.replace('/', '.') + '.' + methName + desc;
}
+ /* (non-Javadoc)
+ * @see org.objectweb.asm.tree.MethodNode#visitLineNumber(int, org.objectweb.asm.Label)
+ */
+ @Override
+ public void visitLineNumber(int line, Label start) {
+ // TODO Auto-generated method stub
+ super.visitLineNumber(line, start);
+ }
+
@Override
public void visitLabel(Label label) {
// if (hasPausableAnnotation)
@@ -193,9 +209,9 @@ public void visitMethodInsn(int opcode, String owner, String name, String desc)
// method call sites. If the class is already woven, we don't need this
// functionality.
if (!classFlow.isWoven) {
- int methodStatus = Detector.getPausableStatus(owner, name, desc);
+ int methodStatus = detector.getPausableStatus(owner, name, desc);
if (methodStatus == Detector.METHOD_NOT_FOUND) {
- throw new KilimException("Check classpath. Method " + owner + name + desc + " could not be located");
+ throw new KilimException("Check classpath. Method " + owner + "." + name + desc + " could not be located");
} else if (methodStatus == Detector.PAUSABLE_METHOD_FOUND) {
MethodInsnNode min = (MethodInsnNode)instructions.get(instructions.size()-1);
pausableMethods.add(min);
@@ -245,7 +261,8 @@ boolean isPausableMethodInsn(MethodInsnNode min) {
return pausableMethods.contains(min);
}
- public String toString() {
+ @Override
+ public String toString() {
ArrayList<BasicBlock> ret = getBasicBlocks();
Collections.sort(ret);
return ret.toString();
@@ -255,20 +272,21 @@ public BBList getBasicBlocks() {
return basicBlocks;
}
- private void assignCatchHandlers() {
- ArrayList tcbs = (ArrayList) tryCatchBlocks;
+ @SuppressWarnings("unchecked")
+ private void assignCatchHandlers() {
+ ArrayList<TryCatchBlockNode> tcbs = (ArrayList<TryCatchBlockNode>) tryCatchBlocks;
/// aargh. I'd love to create an array of Handler objects, but generics
// doesn't care for it.
if (tcbs.size() == 0) return;
ArrayList<Handler> handlers= new ArrayList<Handler>(tcbs.size());
for (int i = 0; i < tcbs.size(); i++) {
- TryCatchBlockNode tcb = (TryCatchBlockNode)tcbs.get(i);
+ TryCatchBlockNode tcb = tcbs.get(i);
handlers.add(new Handler(
getLabelPosition(tcb.start),
getLabelPosition(tcb.end) - 1, // end is inclusive
tcb.type,
- getOrCreateBasicBlock(tcb.handler)));
+ getOrCreateBasicBlock(tcb.handler.getLabel())));
}
for (BasicBlock bb : basicBlocks) {
bb.chooseCatchHandlers(handlers);
@@ -388,6 +406,10 @@ Label getOrCreateLabelAtPos(int pos) {
return ret;
}
+ int getLabelPosition(LabelNode l) {
+ return labelToPosMap.get(l.getLabel());
+ }
+
int getLabelPosition(Label l) {
return labelToPosMap.get(l);
}
@@ -459,7 +481,7 @@ public void accept(final MethodVisitor mv) {
? 0
: visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = visibleParameterAnnotations[i];
+ List<?> l = visibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -472,7 +494,7 @@ public void accept(final MethodVisitor mv) {
? 0
: invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = invisibleParameterAnnotations[i];
+ List<?> l = invisibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -510,10 +532,12 @@ public void accept(final MethodVisitor mv) {
((LocalVariableNode) localVariables.get(i)).accept(mv);
}
// visits line numbers
+ /*
n = lineNumbers == null ? 0 : lineNumbers.size();
for (i = 0; i < n; ++i) {
((LineNumberNode) lineNumbers.get(i)).accept(mv);
}
+ */
// visits maxs
mv.visitMaxs(maxStack, maxLocals);
}
@@ -542,9 +566,9 @@ public static void acceptAnnotation(final AnnotationVisitor av, final String nam
} else if (value instanceof AnnotationNode) {
AnnotationNode an = (AnnotationNode) value;
an.accept(av.visitAnnotation(name, an.desc));
- } else if (value instanceof List) {
+ } else if (value instanceof List<?>) {
AnnotationVisitor v = av.visitArray(name);
- List array = (List) value;
+ List<?> array = (List<?>) value;
for (int j = 0; j < array.size(); ++j) {
acceptAnnotation(v, null, array.get(j));
}
@@ -555,7 +579,7 @@ public static void acceptAnnotation(final AnnotationVisitor av, final String nam
}
public boolean isAbstract() {
- return ((this.access & Constants.ACC_ABSTRACT) != 0);
+ return ((this.access & Opcodes.ACC_ABSTRACT) != 0);
}
public boolean isStatic() {
return ((this.access & ACC_STATIC) != 0);
@@ -565,6 +589,11 @@ public boolean isBridge() {
return ((this.access & ACC_VOLATILE) != 0);
}
+ public Detector detector() {
+ return this.classFlow.detector();
+ }
+
+
}
View
17 src/kilim/analysis/MethodWeaver.java
@@ -31,6 +31,7 @@
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.LocalVariableNode;
@@ -124,7 +125,7 @@ private void visitAttrs(MethodVisitor mv) {
n = mf.visibleParameterAnnotations == null ? 0
: mf.visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = mf.visibleParameterAnnotations[i];
+ List<?> l = mf.visibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -136,7 +137,7 @@ private void visitAttrs(MethodVisitor mv) {
n = mf.invisibleParameterAnnotations == null ? 0
: mf.invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
- List l = mf.invisibleParameterAnnotations[i];
+ List<?> l = mf.invisibleParameterAnnotations[i];
if (l == null) {
continue;
}
@@ -155,7 +156,7 @@ private void visitCode(MethodVisitor mv) {
mv.visitCode();
visitTryCatchBlocks(mv);
visitInstructions(mv);
- visitLineNumbers(mv);
+ //visitLineNumbers(mv);
visitLocals(mv);
mv.visitMaxs(maxStack, maxVars);
}
@@ -167,12 +168,14 @@ private void visitLocals(MethodVisitor mv) {
}
}
+ /*
private void visitLineNumbers(MethodVisitor mv) {
- for (Object l: methodFlow.lineNumbers) {
+ for (Object l: methodFlow.lineNumbers()) {
((LineNumberNode)l).accept(mv);
}
}
-
+*/
+
private void visitInstructions(MethodVisitor mv) {
//TODO gen code for pausable JSRs
genPrelude(mv);
@@ -481,7 +484,7 @@ void makeNotWovenMethod(ClassVisitor cv, MethodFlow mf) {
if (classWeaver.isInterface()) return;
// Turn of abstract modifier
int access = mf.access;
- access &= ~Constants.ACC_ABSTRACT;
+ access &= ~Opcodes.ACC_ABSTRACT;
MethodVisitor mv = cv.visitMethod(access, mf.name, mf.desc,
mf.signature, ClassWeaver.toStringArray(mf.exceptions));
mv.visitCode();
@@ -504,7 +507,7 @@ void makeNotWovenMethod(ClassVisitor cv, MethodFlow mf) {
}
int numlocals;
- if ((mf.access & Constants.ACC_ABSTRACT) != 0) {
+ if ((mf.access & Opcodes.ACC_ABSTRACT) != 0) {
// The abstract method doesn't contain the number of locals required to hold the
// args, so we need to calculate it.
numlocals = getNumWordsInSig() + 1 /* fiber */;
View
14 src/kilim/analysis/NopInsn.java
@@ -8,6 +8,8 @@
import static org.objectweb.asm.Opcodes.NOP;
+import java.util.Map;
+
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.AbstractInsnNode;
@@ -16,12 +18,22 @@ public NopInsn() {
super(NOP);
}
- public int getType() {
+ @Override
+ public int getType() {
return 0;
}
@Override
public void accept(MethodVisitor mv) {
// Do nothing
}
+
+ /* (non-Javadoc)
+ * @see org.objectweb.asm.tree.AbstractInsnNode#clone(java.util.Map)
+ */
+ @Override
+ public AbstractInsnNode clone(Map labels) {
+ // TODO Auto-generated method stub
+ return this;
+ }
}
View
8 src/kilim/analysis/TypeDesc.java
@@ -56,7 +56,7 @@ static boolean isDoubleWord(String desc) {
}
public static String getInterned(String desc) {
- String ret = (String)knownTypes.get(desc);
+ String ret = knownTypes.get(desc);
if (ret == null) {
switch (desc.charAt(0)) {
case 'L':
@@ -218,8 +218,8 @@ public static String commonSuperType(String oa, String ob) {
String a = toClassName(oa);
String b = toClassName(ob);
- Class ca = Class.forName(a);
- Class cb = Class.forName(b);
+ Class<?> ca = Class.forName(a);
+ Class<?> cb = Class.forName(b);
if (ca.isAssignableFrom(cb)) return oa;
if (cb.isAssignableFrom(ca)) return ob;
if (ca.isInterface() && cb.isInterface()) {
@@ -243,7 +243,7 @@ public static String commonSuperType(String oa, String ob) {
}
}
- private static ArrayList<String> getSuperClasses(Class c) {
+ private static ArrayList<String> getSuperClasses(Class<?> c) {
ArrayList<String> ret = new ArrayList<String>(3);
while (c != null) {
ret.add(c.getName());
View
3 src/kilim/analysis/Usage.java
@@ -111,7 +111,8 @@ void absorb(Usage succ) {
this.def.or(succ.def);
}
- public String toString() {
+ @Override
+ public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("use");
printBits(sb, use);
View
5 src/kilim/analysis/Value.java
@@ -130,8 +130,8 @@ public boolean equals(Object obj) {
if (sites[i] != other.sites[i]) {
return false;
}
- return true;
}
+ return true;
}
return false;
}
@@ -161,7 +161,8 @@ public boolean isCategory1() {
return category() == 1;
}
- public String toString() {
+ @Override
+ public String toString() {
if (numSites == 0 && typeDesc == D_UNDEFINED) return "undef";
StringBuffer sb = new StringBuffer(40);
sb.append(typeDesc).append('[');
View
2 src/kilim/tools/Asm.java
@@ -89,7 +89,7 @@ public static void main(String[] args) throws IOException {
public Asm(String afileName) throws IOException {
fileName = afileName;
reader = new LineNumberReader(new FileReader(fileName));
- cv = new ClassWriter(false);
+ cv = new ClassWriter(0);
try {
parseClass();
} catch (EOF eof) {
View
7 src/kilim/tools/DumpClass.java
@@ -17,6 +17,7 @@
import java.util.Enumeration;
import java.util.Formatter;
import java.util.HashMap;
+import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
@@ -43,11 +44,11 @@
public static void main(String[] args) throws IOException {
String name = args.length == 2 ? args[1] : args[0];
//int flags = args.length == 2 ? 0: ClassReader.SKIP_DEBUG;
- boolean flags = false; // skipdebug
+ int flags = ClassReader.SKIP_DEBUG; // skipdebug
if (name.endsWith(".jar")) {
try {
- Enumeration e = new JarFile(name).entries();
+ Enumeration<JarEntry> e = new JarFile(name).entries();
while (e.hasMoreElements()) {
ZipEntry en = (ZipEntry) e.nextElement();
String n = en.getName();
@@ -65,7 +66,7 @@ public static void main(String[] args) throws IOException {
- DumpClass(String className, boolean flags) throws IOException {
+ DumpClass(String className, int flags) throws IOException {
ClassReader cr;
if (className.endsWith(".class")) {
FileInputStream fis = new FileInputStream(className);
View
16 src/kilim/tools/FlowAnalyzer.java
@@ -17,11 +17,13 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import kilim.analysis.BasicBlock;
import kilim.analysis.ClassFlow;
+import kilim.analysis.Detector;
import kilim.analysis.Frame;
import kilim.analysis.MethodFlow;
import kilim.analysis.TypeDesc;
@@ -43,18 +45,18 @@ public static void main(String[] args) throws Exception {
}
String name = args[0];
if (name.endsWith(".jar")) {
- analyzeJar(name);
+ analyzeJar(name, Detector.DEFAULT);
} else {
- analyzeClass(name);
+ analyzeClass(name, Detector.DEFAULT);
}
}
- private static void analyzeClass(String className) {
+ private static void analyzeClass(String className, Detector detector) {
try {
pn("-------------------------------------------------");
pn("Class: " + className);
System.out.flush();
- ArrayList<MethodFlow> flows = new ClassFlow(className).analyze(true);
+ ArrayList<MethodFlow> flows = new ClassFlow(className, detector).analyze(true);
for (MethodFlow flow: flows) {
reportFlow(flow, className);
}
@@ -168,15 +170,15 @@ private static int getNumArgs(MethodInsnNode m) {
return ret;
}
- public static void analyzeJar(String jarFile) {
+ public static void analyzeJar(String jarFile, Detector detector) {
try {
- Enumeration e = new JarFile(jarFile).entries();
+ Enumeration<JarEntry> e = new JarFile(jarFile).entries();
while (e.hasMoreElements()) {
ZipEntry en = (ZipEntry) e.nextElement();
String n = en.getName();
if (!n.endsWith(".class")) continue;
n = n.substring(0, n.length() - 6).replace('/','.');
- analyzeClass(n);
+ analyzeClass(n, detector);
}
} catch (Exception e) {
e.printStackTrace();
View
42 src/kilim/tools/Weaver.java
@@ -19,6 +19,7 @@
import kilim.KilimException;
import kilim.analysis.ClassInfo;
import kilim.analysis.ClassWeaver;
+import kilim.analysis.Detector;
import kilim.analysis.FileLister;
/**
@@ -34,6 +35,9 @@
public static void main(String[] args) throws IOException {
// System.out.println(System.getProperty("java.class.path"));
+
+ Detector detector = Detector.DEFAULT;
+
String currentName = null;
for (String name : parseArgs(args)) {
try {
@@ -42,7 +46,7 @@ public static void main(String[] args) throws IOException {
continue;
currentName = name;
weaveFile(name, new BufferedInputStream(
- new FileInputStream(name)));
+ new FileInputStream(name)), detector);
} else if (name.endsWith(".jar")) {
for (FileLister.Entry fe : new FileLister(name)) {
currentName = fe.getFileName();
@@ -51,7 +55,7 @@ public static void main(String[] args) throws IOException {
'.');
if (exclude(currentName))
continue;
- weaveFile(currentName, fe.getInputStream());
+ weaveFile(currentName, fe.getInputStream(), detector);
}
}
} else if (new File(name).isDirectory()) {
@@ -60,11 +64,11 @@ public static void main(String[] args) throws IOException {
if (currentName.endsWith(".class")) {
if (exclude(currentName))
continue;
- weaveFile(currentName, fe.getInputStream());
+ weaveFile(currentName, fe.getInputStream(), detector);
}
}
} else {
- weaveClass(name);
+ weaveClass(name, detector);
}
} catch (KilimException ke) {
System.err.println("Error weaving " + currentName + ". " + ke.getMessage());
@@ -87,31 +91,53 @@ private static boolean exclude(String name) {
.find();
}
- static void weaveFile(String name, InputStream is) throws IOException {
+ static void weaveFile(String name, InputStream is, Detector detector) throws IOException {
try {
- ClassWeaver cw = new ClassWeaver(is);
+ ClassWeaver cw = new ClassWeaver(is, detector);
writeClasses(cw);
} catch (KilimException ke) {
System.err.println("***** Error weaving " + name + ". " + ke.getMessage());
// ke.printStackTrace();
err = 1;
+ } catch (RuntimeException re) {
+ System.err.println("***** Error weaving " + name + ". " + re.getMessage());
+ re.printStackTrace();
+ err = 1;
+ } catch (IOException ioe) {
+ err = 1;
+ System.err.println("***** Unable to find/process '" + name + "'\n" + ioe.getMessage());
+ }
+ }
+
+ public static void weaveClass(String name, Detector detector) {
+ try {
+ ClassWeaver cw = new ClassWeaver(name, detector);
+ writeClasses(cw);
+ } catch (KilimException ke) {
+ err = 1;
+ System.err.println("***** Error weaving " + name + ". " + ke.getMessage());
+// ke.printStackTrace();
+
} catch (IOException ioe) {
err = 1;
System.err.println("***** Unable to find/process '" + name + "'\n" + ioe.getMessage());
}
}
- public static void weaveClass(String name) throws IOException {
+ public static void weaveClass2(String name, Detector detector) throws IOException {
try {
- ClassWeaver cw = new ClassWeaver(name);
+ ClassWeaver cw = new ClassWeaver(name, detector);
writeClasses(cw);
} catch (KilimException ke) {
err = 1;
System.err.println("***** Error weaving " + name + ". " + ke.getMessage());
// ke.printStackTrace();
+ throw ke;
+
} catch (IOException ioe) {
err = 1;
System.err.println("***** Unable to find/process '" + name + "'\n" + ioe.getMessage());
+ throw ioe;
}
}
View
6 test/kilim/test/Base.java
@@ -10,10 +10,12 @@
import java.util.List;
import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import kilim.analysis.BasicBlock;
import kilim.analysis.ClassFlow;
+import kilim.analysis.Detector;
import kilim.analysis.MethodFlow;
import junit.framework.TestCase;
@@ -23,7 +25,7 @@
protected void cache(String className) throws Exception {
if (lastClassName != className) {
- ClassFlow cf = new ClassFlow(className);
+ ClassFlow cf = new ClassFlow(className, Detector.DEFAULT);
stflows = cf.analyze(/* forceAnalysis = */true);
lastClassName = className;
}
@@ -67,7 +69,7 @@ protected void checkCov(String methodName) {
ArrayList<BasicBlock> bbs = flow.getBasicBlocks();
// Verify that all instructions are covered and that the only ones that
// aren't are labelnodes. Also verify that there are no overlaps.
- List instructions = flow.instructions;
+ InsnList instructions = flow.instructions;
int size = instructions.size();
boolean coverage[] = new boolean[size];
for (int i = 0; i < size; i++) {
View
3 test/kilim/test/TestInvalidPausables.java
@@ -8,12 +8,13 @@
import junit.framework.TestCase;
import kilim.KilimException;
+import kilim.analysis.Detector;
import kilim.tools.Weaver;
public class TestInvalidPausables extends TestCase {
private void ensureException(String className) {
try {
- Weaver.weaveClass(className);
+ Weaver.weaveClass2(className, Detector.DEFAULT);
fail("Expected weave exception while processing " + className);
} catch (KilimException ke) {
} catch (Exception e) {

0 comments on commit 165981c

Please sign in to comment.