[jboss-svn-commits] JBL Code SVN: r26857 - in labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter: cfg and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Jun 5 12:47:09 EDT 2009
Author: adinn
Date: 2009-06-05 12:47:09 -0400 (Fri, 05 Jun 2009)
New Revision: 26857
Modified:
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/cfg/CFG.java
Log:
relocated trigger rethrow handlers directly after the end of the block containinig the monitor exit and fixed a bug in generating the final handler code where visitIntINsn was being called in stead of visitVarInsn
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java 2009-06-05 15:04:59 UTC (rev 26856)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java 2009-06-05 16:47:09 UTC (rev 26857)
@@ -206,9 +206,11 @@
// add this instruction to the current block and then start a new current block
cfg.add(opcode);
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
break;
case Opcodes.MONITORENTER:
@@ -300,9 +302,11 @@
// the second out
cfg.add(opcode);
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart, label, newStart);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
break;
case Opcodes.GOTO:
@@ -311,9 +315,11 @@
// first out of the old current block
cfg.add(opcode);
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart, label);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
break;
case Opcodes.JSR:
@@ -323,9 +329,11 @@
// JSR but we cannot represent that statically
cfg.add(opcode);
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart, label, newStart);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
break;
case Opcodes.IFNULL:
@@ -336,9 +344,11 @@
// the second out
cfg.add(opcode);
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart, label, newStart);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
break;
}
@@ -423,9 +433,11 @@
// create a new current block and then add the default lable and each of the switch labels as an
// outgoing path from the current block
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart, dflt, labels);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
@Override
@@ -436,9 +448,11 @@
// create a new current block and then add the default lable and each of the switch labels as an
// outgoing path from the current block
Label newStart = super.newLabel();
+ Iterator<CodeLocation> exits = cfg.currentExits();
// must call split before visiting the label
cfg.split(newStart, dflt, labels);
visitLabel(newStart);
+ checkMonitorExits(exits);
}
@Override
@@ -460,71 +474,79 @@
cfg.visitTryCatchBlock(start, end, handler, type);
}
- @Override
- public void visitMaxs(int maxStack, int maxLocals)
+ public void checkMonitorExits(Iterator<CodeLocation> exits)
{
- Type returnType = Type.getReturnType(descriptor);
+ while (exits.hasNext()) {
+ CodeLocation exit = exits.next();
+ if (cfg.isPrimaryExit(exit)) {
+ CodeLocation enter = cfg.pairedEnter(exit);
- // check whether there are outstanding monitor opens at the start of the trigger
- // block and, if so, insert a handler which unlocks the monitor and then rethrows
- // the exception.
+ // we just closed a monitor open so find any pending triggers in its scope
+ // and generate a handler block to rethrow its exceptions
- Iterator<TriggerDetails> iterator = cfg.triggerDetails();
- boolean noneLeft = true;
+ Iterator<TriggerDetails> iterator = cfg.triggerDetails();
+ boolean noneLeft = true;
- while (iterator.hasNext()) {
- TriggerDetails details = iterator.next();
- Label startLabel = details.getStart();
- CodeLocation startLocation = cfg.getLocation(startLabel);
- List<CodeLocation> openEnters = cfg.getOpenMonitors(startLocation);
- if (openEnters != null) {
- // add a handler here which unlocks each object and rethrows the
- // saved exception then protect it with a try catch block and update
- // the details so that it is the target of this block
+ while (iterator.hasNext()) {
+ TriggerDetails details = iterator.next();
+ Label startLabel = details.getStart();
+ CodeLocation startLocation = cfg.getLocation(startLabel);
+ // if the trigger start label is after the enter and before the exit
+ // then we need to generate a handler block for it now which exits the
+ // monitor and then rethrows the exception
+ if (enter.compareTo(startLocation) <= 0 && startLocation.compareTo(exit) <= 0) {
+ // add a handler here which unlocks each object and rethrows the
+ // saved exception then protect it with a try catch block and update
+ // the details so that it is the target of this block
- Label newStart = newLabel();
- Label newEnd = newLabel();
- Label newExecute = newLabel();
- Label newEarlyReturn = newLabel();
- Label newThrow = newLabel();
- // make the old exceptions arrive here
- visitLabel(details.getExecuteHandler());
- visitLabel(details.getEarlyReturnHandler());
- visitLabel(details.getThrowHandler());
- // now add a rethrow handler which exits the open monitors
- visitLabel(newStart);
- int listIdx = openEnters.size();
- while (listIdx-- > 0) {
- CodeLocation enterLocation = openEnters.get(listIdx);
- int varIdx = cfg.getSavedMonitorIdx(enterLocation);
- // call super method to avoid indexing these instructions
- visitIntInsn(Opcodes.ALOAD, varIdx);
- visitInsn(Opcodes.MONITOREXIT);
+ // make the old exceptions arrive here
+ visitLabel(details.getExecuteHandler());
+ visitLabel(details.getEarlyReturnHandler());
+ visitLabel(details.getThrowHandler());
+ // now add a rethrow handler which exits the open monitors
+ Label newStart = newLabel();
+ Label newEnd = newLabel();
+ visitLabel(newStart);
+ int varIdx = cfg.getSavedMonitorIdx(enter);
+ visitVarInsn(Opcodes.ALOAD, varIdx);
+ visitInsn(Opcodes.MONITOREXIT);
+ // throw must be in scope of the try catch
+ visitInsn(Opcodes.ATHROW);
+
+ // add try catch blocks for each of the exception types
+ Label newExecute = newLabel();
+ Label newEarlyReturn = newLabel();
+ Label newThrow = newLabel();
+
+ visitTryCatchBlock(newStart, newEnd, newEarlyReturn, EARLY_RETURN_EXCEPTION_TYPE_NAME);
+ visitTryCatchBlock(newStart, newEnd, newThrow, THROW_EXCEPTION_TYPE_NAME);
+ // this comes last because it is the superclass of the previous two
+ visitTryCatchBlock(newStart, newEnd, newExecute, EXECUTE_EXCEPTION_TYPE_NAME);
+ // now visit label so they get processed
+ visitLabel(newEnd);
+
+ // and update the details so it will catch these exceptions
+ details.setStart(newStart);
+ details.setEnd(newEnd);
+ details.setExecuteHandler(newExecute);
+ details.setEarlyReturnHandler(newEarlyReturn);
+ details.setThrowHandler(newThrow);
+ }
}
- // throw must be in scope of the try catch
- // call super method to avoid creating new blocks
- visitInsn(Opcodes.ATHROW);
- // add try catch blocks for each of the exception types
- visitTryCatchBlock(newStart, newEnd, newEarlyReturn, EARLY_RETURN_EXCEPTION_TYPE_NAME);
- visitTryCatchBlock(newStart, newEnd, newThrow, THROW_EXCEPTION_TYPE_NAME);
- // this comes last because it is the superclass of the previous two
- visitTryCatchBlock(newStart, newEnd, newExecute, EXECUTE_EXCEPTION_TYPE_NAME);
- // now visit label so they get processed
- visitLabel(newEnd);
- // and update the details so it will catch these exceptions
- details.setStart(newStart);
- details.setEnd(newEnd);
- details.setExecuteHandler(newExecute);
- details.setEarlyReturnHandler(newEarlyReturn);
- details.setThrowHandler(newThrow);
+
+
}
}
+ }
- // ok, so now we have to add the handler code for trigger block try catch handlers
+ @Override
+ public void visitMaxs(int maxStack, int maxLocals)
+ {
+ // ok, so now we have to add the real handler code for trigger block try catch handlers
// we only need to add the handler code once but we need to make sure it is the target of
// all the try catch blocks by visiting their handler label before we insert the code
- iterator = cfg.triggerDetails();
+ Iterator<TriggerDetails> iterator = cfg.triggerDetails();
while (iterator.hasNext()) {
TriggerDetails details = iterator.next();
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/cfg/CFG.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/cfg/CFG.java 2009-06-05 15:04:59 UTC (rev 26856)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/byteman/agent/adapter/cfg/CFG.java 2009-06-05 16:47:09 UTC (rev 26857)
@@ -742,6 +742,47 @@
}
/**
+ * return an iterator over the monitor exit locations for the current block
+ *
+ * @return
+ */
+ public Iterator<CodeLocation> currentExits() {
+ return current.getMonitorExits();
+ }
+
+ /**
+ * return true if a location is the first monitor exit associated with a corresponding monitor enter
+ * otherwise return false
+ * @param exit the code location which should identify a MONITOREXIT instruction
+ * @return
+ */
+ public boolean isPrimaryExit(CodeLocation exit)
+ {
+ CodeLocation enter = inverseMonitorPairs.get(exit);
+ if (enter == null) {
+ // hmm, this is not a monitor exit
+ System.out.println("cfg.isPrimaryExit : location is not a monitor exit " + exit);
+ return false;
+ }
+
+ List<CodeLocation> pairs = monitorPairs.get(enter);
+ if (pairs == null && pairs.size() == 0) {
+ System.out.println("cfg.isPrimaryExit : location is not a monitor enter " + enter);
+ return false;
+ }
+ return pairs.get(0) == exit;
+ }
+
+ /**
+ * return the location oif the enter instrution paired with a given exit
+ * @param exit the code location which should identify a MONITOREXIT instruction
+ * @return
+ */
+ public CodeLocation pairedEnter(CodeLocation exit)
+ {
+ return inverseMonitorPairs.get(exit);
+ }
+ /**
* split the graph at a control-flow dead-end using the label provided to identify the new current
* block. the caller is obliged to call visitLabel immediately after calling this method to ensure
* that the current block label is indexed appropriately.
More information about the jboss-svn-commits
mailing list