[jboss-svn-commits] JBL Code SVN: r25763 - in labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule: binding and 4 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Mar 20 06:16:54 EDT 2009
Author: adinn
Date: 2009-03-20 06:16:54 -0400 (Fri, 20 Mar 2009)
New Revision: 25763
Modified:
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/StackHeights.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArithmeticExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BitExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BooleanLiteral.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ComparisonExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ConditionalEvalExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Expression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/LogicalExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MinusExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NotExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NumericLiteral.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/PlusExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ReturnExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StaticExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringLiteral.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringPlusExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/TwiddleExpression.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Variable.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java
labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java
Log:
included first cut of rule compilation -- enabled by setting property org.jboss.jbossts.orchestration.compileToBytecode
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Action.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -33,8 +33,12 @@
import org.jboss.jbossts.orchestration.rule.exception.ParseException;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.helper.InterpretedHelper;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.ArrayList;
@@ -100,7 +104,36 @@
return Type.VOID;
}
- public void interpret(HelperAdapter helper)
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException {
+ int currentStack = currentStackHeights.stackCount;
+ boolean hasActions = false;
+
+ for (Expression expr : action) {
+ hasActions = true;
+ expr.compile(mv, currentStackHeights, maxStackHeights);
+ Type resultType = expr.getType();
+ if (resultType != Type.VOID) {
+ int expected = (resultType.getNBytes() > 4 ? 2 : 1);
+ for (int i = 0; i < expected; i++) {
+ mv.visitInsn(Opcodes.POP);
+ currentStackHeights.addStackCount(-1);
+ }
+ }
+ }
+ if (!hasActions) {
+ // don't check or adjust stack heights as we did nothing
+ return;
+ }
+
+ // check original stack height has been restored
+ if (currentStackHeights.stackCount != currentStack) {
+ throw new CompileException("Action.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack);
+ }
+
+ // each action will have checked whether it needed to increase the maximum stack count so just return
+ }
+
+ public Object interpret(HelperAdapter helper)
throws ExecuteException
{
if (action != null) {
@@ -108,6 +141,8 @@
expr.interpret(helper);
}
}
+
+ return null;
}
public void writeTo(StringWriter stringWriter)
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Condition.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -32,8 +32,11 @@
import org.jboss.jbossts.orchestration.rule.exception.ParseException;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.helper.InterpretedHelper;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
+import org.objectweb.asm.MethodVisitor;
import java.io.StringWriter;
import java.io.StringReader;
@@ -91,7 +94,30 @@
return Type.Z;
}
- public boolean interpret(HelperAdapter helper)
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException {
+ int currentStack = currentStackHeights.stackCount;
+ // get the condition to compile itself -- it adds 1 to stack height
+ condition.compile(mv, currentStackHeights, maxStackHeights);
+ // unbox if necessary
+ if (condition.getType() == Type.BOOLEAN) {
+ compileUnbox(Type.BOOLEAN, Type.Z, mv, currentStackHeights, maxStackHeights);
+ }
+
+ // check stack heights
+ if (currentStackHeights.stackCount != currentStack + 1) {
+ throw new CompileException("Condition.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack);
+ }
+
+ // we needed room for 1 more values on the stack -- make sure we got it
+ int maxStack = maxStackHeights.stackCount;
+ int overflow = (currentStack + 1) - maxStack;
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+
+ public Object interpret(HelperAdapter helper)
throws ExecuteException
{
Boolean result = (Boolean)condition.interpret(helper);
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Event.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -35,8 +35,13 @@
import org.jboss.jbossts.orchestration.rule.exception.ParseException;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.helper.InterpretedHelper;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
+import org.jboss.jbossts.orchestration.agent.adapter.RuleAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.ArrayList;
@@ -90,11 +95,6 @@
super(rule);
}
- public boolean compile()
- {
- return true;
- }
-
public Bindings getBindings()
{
return rule.getBindings();
@@ -249,7 +249,7 @@
}
}
- public void interpret(HelperAdapter helper)
+ public Object interpret(HelperAdapter helper)
throws ExecuteException
{
Iterator<Binding> iterator = getBindings().iterator();
@@ -257,12 +257,27 @@
while (iterator.hasNext()) {
Binding binding = iterator.next();
- if (binding.isVar()) {
- Object value = binding.getValue().interpret(helper);
- helper.bindVariable(binding.getName(), value);
- }
+ binding.interpret(helper);
}
+
+ return null;
+ }
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+
+ Iterator<Binding> iterator = getBindings().iterator();
+ while (iterator.hasNext()) {
+ Binding binding = iterator.next();
+
+ binding.compile(mv, currentStackHeights, maxStackHeights);
+ }
+
+ // check stack heights
+ if (currentStackHeights.stackCount != currentStack) {
+ throw new CompileException("Event.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack);
+ }
}
public void writeTo(StringWriter stringWriter)
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/Rule.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -216,6 +216,10 @@
return action;
}
+ public String getTriggerClass() {
+ return triggerClass;
+ }
+
public static Rule create(String name, String targetClass, String targetMethod, Class<?> helperClass, Location targetLocation, String ruleSpec, ClassLoader loader)
throws ParseException, TypeException, CompileException
{
@@ -312,7 +316,7 @@
} else {
// we need to generate a helper adapter class which either interprets or compiles
- helperImplementationClass = Compiler.getHelperAdapter(helperClass, compileToBytecode);
+ helperImplementationClass = Compiler.getHelperAdapter(this, helperClass, compileToBytecode);
}
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/RuleElement.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -27,6 +27,12 @@
import org.jboss.jbossts.orchestration.rule.type.TypeGroup;
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
+import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
+import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -54,6 +60,399 @@
public abstract Type typeCheck(Type expected) throws TypeException;
+ public abstract Object interpret(HelperAdapter helper) throws ExecuteException;
+
+ public abstract void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException;
+
+ protected void compileTypeConversion(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ // make sure we have some real work to do
+
+ if (fromType.equals(toType)) {
+ return;
+ }
+
+ if (toType.isNumeric()) {
+ // do number conversion
+ compileNumericConversion(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ } else if (toType.isString()) {
+ // do toString conversion
+ compileStringConversion(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ } else if (toType.isBoolean()) {
+ // do toString conversion
+ compileBooleanConversion(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ } else {
+ compileObjectConversion(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ }
+ }
+
+ protected void compileNumericConversion(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ // fromType != toType
+ boolean unbox = fromType.isObject();
+ boolean box = toType.isObject();
+
+ if (unbox) {
+ if (box) {
+ Type midType = Type.boxType(toType);
+ compileUnbox(fromType, midType, mv, currentStackHeights, maxStackHeights);
+ compileBox(midType, mv, currentStackHeights, maxStackHeights);
+ }
+ compileUnbox(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ } else if (box) {
+ Type midType = Type.boxType(toType);
+ if (fromType != midType) {
+ compilePrimitiveConversion(fromType, midType, mv, currentStackHeights, maxStackHeights);
+ }
+ compileBox(toType, mv, currentStackHeights, maxStackHeights);
+ } else {
+ compilePrimitiveConversion(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ }
+ }
+
+ /**
+ * compile code to convert a value of a boxed type to a primitive type, possibly not the immediately
+ * related primitive type
+ *
+ * @param fromType
+ * @param toType
+ * @param mv
+ * @param currentStackHeights
+ * @param maxStackHeights
+ * @throws CompileException
+ */
+ protected void compileUnbox(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ // we either have a Boolean, a Character or a Number for fromType
+ if (fromType == Type.BOOLEAN) {
+ assert toType == Type.Z;
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
+ } else if (fromType == Type.CHARACTER) {
+ // obtain the underlying char then massage it to the correct bit format
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
+ compilePrimitiveConversion(Type.C, toType, mv, currentStackHeights, maxStackHeights);
+ } else {
+ // we have a numeric type so call the relevant conversion method
+ if (toType == Type.B) {
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "byteValue", "()B");
+ } else if (toType == Type.S){
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "shortValue", "()S");
+ } else if (toType == Type.C){
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I");
+ // now convert to char, dropping any sign extension
+ mv.visitIntInsn(Opcodes.ISHL, 16);
+ mv.visitIntInsn(Opcodes.LSHR, 16);
+ } else if (toType == Type.I){
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I");
+ } else if (toType == Type.J){
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "longValue", "()L");
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ } else if (toType == Type.F){
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "floatValue", "()F");
+ } else {
+ assert toType == Type.D;
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "doubleValue", "()D");
+ }
+ }
+ }
+
+ /**
+ * box a value belonging to a primitive type
+ * @param toType
+ * @param mv
+ * @param currentStackHeights
+ * @param maxStackHeights
+ * @throws CompileException
+ */
+ protected void compileBox(Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ if (toType == Type.BOOLEAN) {
+ // this temporarily adds 2 to the stack height
+ if (currentStackHeights.stackCount + 2 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 2;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Boolean");
+ mv.visitInsn(Opcodes.DUP_X1);
+ mv.visitInsn(Opcodes.SWAP);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Boolean", "<init>", "(Z)V");
+ } else if (toType == Type.BOOLEAN) {
+ // this temporarily adds 2 to the stack height
+ if (currentStackHeights.stackCount + 2 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 2;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Byte");
+ mv.visitInsn(Opcodes.DUP_X1);
+ mv.visitInsn(Opcodes.SWAP);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Byte", "<init>", "(B)V");
+ } else if (toType == Type.SHORT){
+ // this temporarily adds 2 to the stack height
+ if (currentStackHeights.stackCount + 2 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 2;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Short");
+ mv.visitInsn(Opcodes.DUP_X1);
+ mv.visitInsn(Opcodes.SWAP);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Short", "<init>", "(S)V");
+ } else if (toType == Type.CHARACTER){
+ // this temporarily adds 2 to the stack height
+ if (currentStackHeights.stackCount + 2 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 2;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Character");
+ mv.visitInsn(Opcodes.DUP_X1);
+ mv.visitInsn(Opcodes.SWAP);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Character", "<init>", "(C)V");
+ } else if (toType == Type.INTEGER) {
+ // initial stack [i, ...]
+ // this temporarily adds 2 to the stack height
+ if (currentStackHeights.stackCount + 2 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 2;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Integer"); // => [Integer, i, ...]
+ mv.visitInsn(Opcodes.DUP_X1); // => [Integer, i, Integer, ...]
+ mv.visitInsn(Opcodes.SWAP); // => [i, Integer, Integer, ...]
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Integer", "<init>", "(I)V");
+ } else if (toType == Type.LONG) {
+ // initial stack [i, ...]
+ mv.visitInsn(Opcodes.I2L); // => [l1, l0, ...]
+ // this temporarily adds 4 to the stack height
+ if (currentStackHeights.stackCount + 4 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 4;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Long"); // => [Long, l1, l0, ...]
+ mv.visitInsn(Opcodes.DUP_X2); // => [Long, l1, l0, Long, ...]
+ mv.visitInsn(Opcodes.DUP_X2); // => [Long, l1, l0, Long Long, ...]
+ mv.visitInsn(Opcodes.POP); // => [l1, l0, Long, Long ...]
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Long", "<init>", "(J)V"); // => [ Long, ...]
+ } else if (toType == Type.FLOAT) {
+ // initial stack [i, ...]
+ mv.visitInsn(Opcodes.I2F); // => [f, ...]
+ // this temporarily adds 2 to the stack height
+ if (currentStackHeights.stackCount + 2 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 2;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Float"); // => [Float, f, ...]
+ mv.visitInsn(Opcodes.DUP_X1); // => [Float, f, Float, ...]
+ mv.visitInsn(Opcodes.SWAP); // => [f, Float, Float, ...]
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Float", "<init>", "(F)V");
+ } else if (toType == Type.DOUBLE) {
+ // initial stack [i, ...]
+ mv.visitInsn(Opcodes.I2D); // => [d1, d0, ...]
+ // this temporarily adds 4 to the stack height
+ if (currentStackHeights.stackCount + 4 > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount + 4;
+ }
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Double"); // => [Double, d1, d0, ...]
+ mv.visitInsn(Opcodes.DUP_X2); // => [Double, d1, d0, Double, ...]
+ mv.visitInsn(Opcodes.DUP_X2); // => [Double, d1, d0, Double, Double, ...]
+ mv.visitInsn(Opcodes.POP) ; // => [d1, d0, Double, Double, ...]
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Double", "<init>", "(D)V");
+ }
+ }
+
+ protected void compileStringConversion(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ assert toType == Type.STRING;
+ if (fromType.isObject()) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;");
+ } else if (fromType == Type.Z) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "toString", "(Z)Ljava/lang/String;");
+ } else if (fromType == Type.B) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "toString", "(B)Ljava/lang/String;");
+ } else if (fromType == Type.S) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "toString", "(S)Ljava/lang/String;");
+ } else if (fromType == Type.C) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "toString", "(C)Ljava/lang/String;");
+ } else if (fromType == Type.I) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;");
+ } else if (fromType == Type.J) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "toString", "(L)Ljava/lang/String;");
+ currentStackHeights.addStackCount(-1);
+ } else if (fromType == Type.F) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "toString", "(F)Ljava/lang/String;");
+ } else if (fromType == Type.D) {
+ // use the toString method
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "toString", "(D)Ljava/lang/String;");
+ currentStackHeights.addStackCount(-1);
+ }
+ }
+
+ /**
+ * compile code to convert a numeric or character primitive to a numeric or character primitive
+ * @param fromType
+ * @param toType
+ * @param mv
+ * @param currentStackHeights
+ * @param maxStackHeights
+ * @throws CompileException
+ */
+ protected void compilePrimitiveConversion(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ if (fromType == Type.B || fromType == Type.S || fromType == Type.I) {
+ if (toType == Type.B) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (toType == Type.S) {
+ mv.visitInsn(Opcodes.I2S);
+ } else if (toType == Type.C) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (toType == Type.I) {
+ // nothing to do
+ } else if (toType == Type.J) {
+ mv.visitInsn(Opcodes.I2L);
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ } else if (toType == Type.F) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (toType == Type.D) {
+ mv.visitInsn(Opcodes.I2D);
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ }
+ } else if (fromType == Type.C) {
+ // convert to the relevant numeric size
+ if (toType == Type.B) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (toType == Type.S) {
+ mv.visitInsn(Opcodes.I2S);
+ } else if (toType == Type.C) {
+ // nothing to do
+ } else if (toType == Type.I) {
+ // nothing to do
+ } else if (toType == Type.J) {
+ mv.visitInsn(Opcodes.I2L);
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ } else if (toType == Type.F) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (toType == Type.D) {
+ mv.visitInsn(Opcodes.I2D);
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ }
+ } else if (fromType == Type.J) {
+ if (toType == Type.B || toType == Type.S || toType == Type.I || toType == Type.C) {
+ mv.visitInsn(Opcodes.L2I);
+ currentStackHeights.addStackCount(-1);
+ } else if (toType == Type.J) {
+ // nothing to do
+ } else if (toType == Type.F) {
+ mv.visitInsn(Opcodes.L2F);
+ currentStackHeights.addStackCount(-1);
+ } else if (toType == Type.D) {
+ mv.visitInsn(Opcodes.L2D);
+ }
+ } else if (fromType == Type.F) {
+ if (toType == Type.B) {
+ mv.visitInsn(Opcodes.F2I);
+ mv.visitInsn(Opcodes.I2B);
+ } else if (toType == Type.S) {
+ mv.visitInsn(Opcodes.F2I);
+ mv.visitInsn(Opcodes.I2S);
+ } else if (toType == Type.C) {
+ mv.visitInsn(Opcodes.F2I);
+ mv.visitInsn(Opcodes.I2C);
+ } else if (toType == Type.I) {
+ mv.visitInsn(Opcodes.F2I);
+ } else if (toType == Type.J) {
+ mv.visitInsn(Opcodes.F2L);
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ } else if (toType == Type.F) {
+ // nothing to do
+ } else if (toType == Type.D) {
+ mv.visitInsn(Opcodes.F2D);
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ }
+ } else if (fromType == Type.D) {
+ if (toType == Type.B) {
+ mv.visitInsn(Opcodes.D2I);
+ mv.visitInsn(Opcodes.I2B);
+ } else if (toType == Type.S) {
+ mv.visitInsn(Opcodes.D2I);
+ mv.visitInsn(Opcodes.I2S);
+ } else if (toType == Type.C) {
+ mv.visitInsn(Opcodes.D2I);
+ mv.visitInsn(Opcodes.I2C);
+ } else if (toType == Type.I) {
+ mv.visitInsn(Opcodes.D2I);
+ } else if (toType == Type.J) {
+ mv.visitInsn(Opcodes.D2L);
+ } else if (toType == Type.F) {
+ mv.visitInsn(Opcodes.D2F);
+ currentStackHeights.addStackCount(-1);
+ } else if (toType == Type.D) {
+ // nothing to do
+ }
+ }
+ }
+
+ protected void compileBooleanConversion(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ if (toType == Type.Z) {
+ assert fromType == Type.BOOLEAN;
+ compileUnbox(fromType, toType, mv, currentStackHeights, maxStackHeights);
+ } else {
+ assert toType == Type.BOOLEAN;
+ assert fromType == Type.Z;
+ compileBox(toType, mv, currentStackHeights, maxStackHeights);
+ }
+ }
+
+ protected void compileObjectConversion(Type fromType, Type toType, MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights)
+ throws CompileException
+ {
+ // ensure any primitive type is boxed before we go any further
+
+ if (fromType.isPrimitive()) {
+ Type boxType = Type.boxType(fromType);
+ compileBox(boxType, mv, currentStackHeights, maxStackHeights);
+ fromType = boxType;
+ }
+
+ if (toType.isAssignableFrom(fromType)) {
+ // nothing more to do
+ } else {
+ // this happens when we downcast a bound variable from Object to the variable's type
+ assert fromType.isAssignableFrom(toType);
+ mv.visitTypeInsn(Opcodes.CHECKCAST, toType.getInternalName());
+ }
+ }
+
public String toString()
{
StringWriter stringWriter = new StringWriter();
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/binding/Binding.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,8 +26,14 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.expression.Expression;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
+import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
import org.jboss.jbossts.orchestration.rule.RuleElement;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
+import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -84,6 +90,49 @@
return type;
}
+ public Object interpret(HelperAdapter helper) throws ExecuteException
+ {
+ if (isVar()) {
+ Object result = value.interpret(helper);
+ helper.bindVariable(getName(), result);
+ return result;
+ }
+ return null;
+ }
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ if (isVar()) {
+ int currentStack = currentStackHeights.stackCount;
+
+ // push the current helper instance i.e. this -- adds 1 to stack height
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ // push the variable name -- adds 1 to stack height
+ mv.visitLdcInsn(name);
+ // increment stack count
+ currentStackHeights.addStackCount(2);
+ // compile the rhs expression for the binding -- adds 1 to stack height
+ value.compile(mv, currentStackHeights, maxStackHeights);
+ // make sure value is boxed if necessary
+ if (type.isPrimitive()) {
+ compileBox(Type.boxType(type), mv, currentStackHeights, maxStackHeights);
+ }
+ // compile a bindVariable call pops 3 from stack height
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "bindVariable", "(Ljava/lang/String;Ljava/lang/Object;)V");
+ currentStackHeights.addStackCount(-3);
+
+ // check the max height was enough for 3 extra values
+
+ // we needed room for 3 more values on the stack -- make sure we got it
+ int maxStack = maxStackHeights.stackCount;
+ int overflow = (currentStack + 3) - maxStack;
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+ }
+
public String getName()
{
return name;
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/Compiler.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -40,62 +40,61 @@
*/
public class Compiler implements Opcodes
{
- public static Class getHelperAdapter(Class helperClass, boolean compileToBytecode) throws CompileException
+ public static Class getHelperAdapter(Rule rule, Class helperClass, boolean compileToBytecode) throws CompileException
{
- // for now we cannot compile to bytecode
+ Class adapterClass;
+ // for each rule with the same helper we can use the same interpreted adapter
+ // we have to use a different compiled helper per rule since it encodes the
+ // details of the rule event, condition and action into its execute method
- compileToBytecode = false;
-
- Class adapterClass;
- if (compileToBytecode) {
- adapterClass = compiledAdapterMap.get(helperClass);
+ if (!compileToBytecode) {
+ // try to reuse any existing adaoter
+ adapterClass = interpretedAdapterMap.get(helperClass);
} else {
- adapterClass = interpretedAdapterMap.get(helperClass);
+ adapterClass = null;
}
- if (adapterClass != null) {
- return adapterClass;
- }
- // ok we have to create the adapter class
+ if (adapterClass == null) {
+ // ok we have to create the adapter class
- // n.b. we don't bother synchronizing here -- if another rule is racing to create an adapter
- // in parallel we don't really care about generating two of them -- we can use whichever
- // one gets intalled last
+ // n.b. we don't bother synchronizing here -- if another rule is racing to create an adapter
+ // in parallel we don't really care about generating two of them -- we can use whichever
+ // one gets intalled last
- try {
- String helperName = Type.getInternalName(helperClass);
- String compiledHelperName;
+ try {
+ String helperName = Type.getInternalName(helperClass);
+ String compiledHelperName;
- if (compileToBytecode) {
- compiledHelperName = helperName + "_HelperAdapter_Compiled";
- } else {
- compiledHelperName = helperName + "_HelperAdapter_Interpreted";
- }
+ // we put the helper in the
+ if (compileToBytecode) {
+ compiledHelperName = helperName + "_HelperAdapter_Compiled_" + nextId();
+ } else {
+ compiledHelperName = helperName + "_HelperAdapter_Interpreted";
+ }
- byte[] classBytes = compileBytes(helperClass, helperName, compiledHelperName, compileToBytecode);
- String externalName = compiledHelperName.replaceAll("/", ".");
- // dump the compiled class bytes if required
- Transformer.getTheTransformer().maybeDumpClass(externalName, classBytes);
- // ensure the class is loaded
- adapterClass = Transformer.getTheTransformer().loadHelperAdapter(helperClass, externalName, classBytes);
- } catch(CompileException ce) {
- throw ce;
- } catch (Throwable th) {
- if (compileToBytecode) {
- throw new CompileException("Compiler.createHelperAdapter : exception creating compiled helper adapter for " + helperClass.getName(), th);
- } else {
- throw new CompileException("Compiler.createHelperAdapter : exception creating interpreted helper adapter for " + helperClass.getName(), th);
+ byte[] classBytes = compileBytes(rule, helperClass, helperName, compiledHelperName, compileToBytecode);
+ String externalName = compiledHelperName.replaceAll("/", ".");
+ // dump the compiled class bytes if required
+ Transformer.getTheTransformer().maybeDumpClass(externalName, classBytes);
+ // ensure the class is loaded
+ adapterClass = Transformer.getTheTransformer().loadHelperAdapter(helperClass, externalName, classBytes);
+ } catch(CompileException ce) {
+ throw ce;
+ } catch (Throwable th) {
+ if (compileToBytecode) {
+ throw new CompileException("Compiler.createHelperAdapter : exception creating compiled helper adapter for " + helperClass.getName(), th);
+ } else {
+ throw new CompileException("Compiler.createHelperAdapter : exception creating interpreted helper adapter for " + helperClass.getName(), th);
+ }
}
- }
- // stash for later reuse
+ // if this is an interpreted adapter then stash it for later reuse
- if(compileToBytecode) {
- compiledAdapterMap.put(helperClass, adapterClass);
- } else {
- interpretedAdapterMap.put(helperClass, adapterClass);
+ if(!compileToBytecode) {
+ interpretedAdapterMap.put(helperClass, adapterClass);
+ }
}
-
+
return adapterClass;
}
@@ -108,16 +107,7 @@
*/
private static HashMap<Class<?>, Class<?>> interpretedAdapterMap = new HashMap<Class<?>, Class<?>>();
- /**
- * hashmap used to retrieve previously generated compiled adapters
- *
- * TODO strictly this should be a weak hash map so we don't hang on to adapters after the helper
- * has been dropped. but to make that work we probably need to worry about dropping references to
- * rules too.
- */
- private static HashMap<Class<?>, Class<?>> compiledAdapterMap = new HashMap<Class<?>, Class<?>>();
-
- private static byte[] compileBytes(Class helperClass, String helperName, String compiledHelperName, boolean compileToBytecode) throws Exception
+ private static byte[] compileBytes(Rule rule, Class helperClass, String helperName, String compiledHelperName, boolean compileToBytecode) throws Exception
{
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
@@ -401,24 +391,28 @@
if (compileToBytecode) {
// we generate a single execute0 method if we want to run compiled and get
// the event, condiiton and action to insert the relevant bytecode to implement
- // bind(), test() anf fire()
+ // bind(), test() and fire()
- /*
StackHeights maxStackHeights = new StackHeights();
+ StackHeights currentStackHeights;
{
// create the execute0() method
//
// private void execute0()
mv = cw.visitMethod(ACC_PRIVATE, "execute0", "()V", null, new String[] { "org/jboss/jbossts/orchestration/rule/exception/ExecuteException" });
mv.visitCode();
+ maxStackHeights.addLocalCount(3); // for this and 2 object args
// bind();
- rule.getEvent().createHelperAdapter(mv, compiledHelperName, helperName, maxStackHeights);
+ currentStackHeights = new StackHeights();
+ rule.getEvent().compile(mv, currentStackHeights, maxStackHeights);
// if (test())
- rule.getCondition().createHelperAdapter(mv, compiledHelperName, helperName, maxStackHeights);
+ currentStackHeights = new StackHeights();
+ rule.getCondition().compile(mv, currentStackHeights, maxStackHeights);
Label l0 = new Label();
mv.visitJumpInsn(IFEQ, l0);
// then
- rule.getAction().createHelperAdapter(mv, compiledHelperName, helperName, maxStackHeights);
+ currentStackHeights = new StackHeights();
+ rule.getAction().compile(mv, currentStackHeights, maxStackHeights);
// fire();
// end if
mv.visitLabel(l0);
@@ -428,7 +422,6 @@
mv.visitMaxs(maxStackHeights.stackCount, maxStackHeights.localCount);
mv.visitEnd();
}
- */
} else {
// we generate the following methods if we want to run interpreted
{
@@ -467,7 +460,7 @@
mv.visitFieldInsn(GETFIELD, compiledHelperName, "rule", "Lorg/jboss/jbossts/orchestration/rule/Rule;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Rule", "getEvent", "()Lorg/jboss/jbossts/orchestration/rule/Event;");
mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Event", "interpret", "(Lorg/jboss/jbossts/orchestration/rule/helper/HelperAdapter;)V");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Event", "interpret", "(Lorg/jboss/jbossts/orchestration/rule/helper/HelperAdapter;)Ljava/lang/Object;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
@@ -483,7 +476,10 @@
mv.visitFieldInsn(GETFIELD, compiledHelperName, "rule", "Lorg/jboss/jbossts/orchestration/rule/Rule;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Rule", "getCondition", "()Lorg/jboss/jbossts/orchestration/rule/Condition;");
mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Condition", "interpret", "(Lorg/jboss/jbossts/orchestration/rule/helper/HelperAdapter;)Z");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Condition", "interpret", "(Lorg/jboss/jbossts/orchestration/rule/helper/HelperAdapter;)Ljava/lang/Object;");
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
+ // unbox the returned Boolean
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
// return {TOS}
mv.visitInsn(IRETURN);
mv.visitMaxs(2, 1);
@@ -500,7 +496,7 @@
mv.visitFieldInsn(GETFIELD, compiledHelperName, "rule", "Lorg/jboss/jbossts/orchestration/rule/Rule;");
mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Rule", "getAction", "()Lorg/jboss/jbossts/orchestration/rule/Action;");
mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Action", "interpret", "(Lorg/jboss/jbossts/orchestration/rule/helper/HelperAdapter;)V");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/jbossts/orchestration/rule/Action", "interpret", "(Lorg/jboss/jbossts/orchestration/rule/helper/HelperAdapter;)Ljava/lang/Object;");
// return
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
@@ -512,4 +508,11 @@
return cw.toByteArray();
}
+
+ private static int nextId = 0;
+
+ private static synchronized int nextId()
+ {
+ return ++nextId;
+ }
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/StackHeights.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/StackHeights.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/compiler/StackHeights.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -37,7 +37,7 @@
/**
* number of local variable slots
*/
- int localCount;
+ public int localCount;
/**
* create withinitial counts 0
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArithmeticExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArithmeticExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArithmeticExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
/**
* A binary arithmetic operator expression
@@ -253,4 +257,165 @@
throw new ExecuteException("ArithmeticExpression.interpret : unexpected exception for operation " + token + getPos() + " in rule " + helper.getName(), e);
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int expectedStack = 0;
+ Expression operand0 = getOperand(0);
+ Expression operand1 = getOperand(1);
+ Type type0 = operand0.getType();
+ Type type1 = operand1.getType();
+ // compile lhs -- it adds 1 or 2 to the stack height
+ operand0.compile(mv, currentStackHeights, maxStackHeights);
+ // do any required type conversion
+ compileTypeConversion(type0, type, mv, currentStackHeights, maxStackHeights);
+ // compile lhs -- it adds 1 or 2 to the stack height
+ currentStackHeights.addStackCount((type0.getNBytes() > 4 ? 2 : 1));
+ // do any required type conversion
+ compileTypeConversion(type1, type, mv, currentStackHeights, maxStackHeights);
+
+ try {
+// n.b. be careful with characters here
+ if (type == type.B || type == type.S || type == type.C || type == type.I) {
+ // TODO we should probably only respect the byte, short and char types for + and -
+ // TODO also need to decide how to handle divide by zero
+
+ expectedStack = 1;
+
+ switch (oper)
+ {
+ case MUL:
+ mv.visitInsn(Opcodes.IMUL);
+ break;
+ case DIV:
+ mv.visitInsn(Opcodes.IDIV);
+ break;
+ case PLUS:
+ mv.visitInsn(Opcodes.IADD);
+ break;
+ case MINUS:
+ mv.visitInsn(Opcodes.ISUB);
+ break;
+ case MOD:
+ mv.visitInsn(Opcodes.IREM);
+ break;
+ default:
+ // should never happen
+ throw new CompileException("ArithmeticExpression.compile : unexpected operator " + oper);
+ }
+ // now coerce back to appropriate type
+ if (type == type.B) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (type == type.S) {
+ mv.visitInsn(Opcodes.I2S);
+ } else if (type == type.C) {
+ mv.visitInsn(Opcodes.I2C);
+ } // else if (type == type.I) { do nothing }
+ // ok, we popped two bytes but added one
+ currentStackHeights.addStackCount(-1);
+ } else if (type == type.J) {
+
+ expectedStack = 2;
+
+ switch (oper)
+ {
+ case MUL:
+ mv.visitInsn(Opcodes.LMUL);
+ break;
+ case DIV:
+ mv.visitInsn(Opcodes.LDIV);
+ break;
+ case PLUS:
+ mv.visitInsn(Opcodes.LADD);
+ break;
+ case MINUS:
+ mv.visitInsn(Opcodes.LSUB);
+ break;
+ case MOD:
+ mv.visitInsn(Opcodes.LREM);
+ break;
+ default:
+ // should never happen
+ throw new CompileException("ArithmeticExpression.compile : unexpected operator " + oper);
+ }
+ // ok, we popped four bytes but added two
+ currentStackHeights.addStackCount(-2);
+ } else if (type == type.F) {
+
+ expectedStack = 1;
+
+ switch (oper)
+ {
+ case MUL:
+ mv.visitInsn(Opcodes.FMUL);
+ break;
+ case DIV:
+ mv.visitInsn(Opcodes.FDIV);
+ break;
+ case PLUS:
+ mv.visitInsn(Opcodes.FADD);
+ break;
+ case MINUS:
+ mv.visitInsn(Opcodes.FSUB);
+ break;
+ case MOD:
+ mv.visitInsn(Opcodes.FREM);
+ break;
+ default:
+ // should never happen
+ throw new CompileException("ArithmeticExpression.compile : unexpected operator " + oper);
+ }
+ // ok, we popped two bytes but added one
+ currentStackHeights.addStackCount(-1);
+ } else if (type == type.D) {
+
+ expectedStack = 2;
+
+ switch (oper)
+ {
+ case MUL:
+ mv.visitInsn(Opcodes.DMUL);
+ break;
+ case DIV:
+ mv.visitInsn(Opcodes.DDIV);
+ break;
+ case PLUS:
+ mv.visitInsn(Opcodes.DADD);
+ break;
+ case MINUS:
+ mv.visitInsn(Opcodes.DSUB);
+ break;
+ case MOD:
+ mv.visitInsn(Opcodes.DREM);
+ break;
+ default:
+ // should never happen
+ throw new CompileException("ArithmeticExpression.compile : unexpected operator " + oper);
+ }
+ // ok, we popped four bytes but added two
+ currentStackHeights.addStackCount(-2);
+ } else {
+ throw new CompileException("ArithmeticExpression.compile : unexpected result type " + type.getName());
+ }
+ } catch (CompileException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CompileException("ArithmeticExpression.compile : unexpected exception for operation " + token + getPos() + " in rule " + rule.getName(), e);
+ }
+
+ // check stack heights
+ if (currentStackHeights.stackCount != currentStack + expectedStack) {
+ throw new CompileException("ArithmeticExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expectedStack);
+ }
+
+ // we needed room for 2 * expectedStack extra values on the stack -- make sure we got it
+ int maxStack = maxStackHeights.stackCount;
+ int overflow = (currentStack + (2 * expectedStack)) - maxStack;
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ArrayExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.Iterator;
@@ -121,6 +125,75 @@
}
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Type valueType = arrayRef.getType().getBaseType();
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 0;
+
+ // compile load of array reference -- adds 1 to stack height
+ arrayRef.compile(mv, currentStackHeights, maxStackHeights);
+ // for each index expression compile the expression and the do an array load
+ Iterator<Expression> iterator = idxList.iterator();
+
+ while (iterator.hasNext()) {
+ Expression idxExpr = iterator.next();
+ // compile expression index -- adds 1 to height
+ idxExpr.compile(mv, currentStackHeights, maxStackHeights);
+ // make sure the index is an integer
+ compileTypeConversion(idxExpr.getType(), Type.I, mv, currentStackHeights, maxStackHeights);
+
+ if (valueType.isObject()) {
+ // compile load object - pops 2 and adds 1
+ mv.visitInsn(Opcodes.AALOAD);
+ expected = 1;
+ } else if (valueType == Type.Z || valueType == Type.B) {
+ // compile load byte - pops 2 and adds 1
+ mv.visitInsn(Opcodes.BALOAD);
+ expected = 1;
+ } else if (valueType == Type.S) {
+ // compile load short - pops 2 and adds 1
+ mv.visitInsn(Opcodes.SALOAD);
+ expected = 1;
+ } else if (valueType == Type.C) {
+ // compile load char - pops 2 and adds 1
+ mv.visitInsn(Opcodes.CALOAD);
+ expected = 1;
+ } else if (valueType == Type.I) {
+ // compile load int - pops 2 and adds 1
+ mv.visitInsn(Opcodes.IALOAD);
+ expected = 1;
+ } else if (valueType == Type.J) {
+ // compile load long - pops 2 and adds 2
+ mv.visitInsn(Opcodes.LALOAD);
+ expected = 2;
+ } else if (valueType == Type.F) {
+ // compile load float - pops 2 and adds 1
+ mv.visitInsn(Opcodes.FALOAD);
+ expected = 1;
+ } else if (valueType == Type.D) {
+ // compile load double - pops 2 and adds 2
+ mv.visitInsn(Opcodes.DALOAD);
+ expected = 2;
+ }
+ if (iterator.hasNext()) {
+ assert valueType.isArray();
+ valueType =valueType.getBaseType();
+ }
+ }
+ // the last value for expected is how many bytes extra should be on the stack
+ currentStackHeights.addStackCount(expected);
+
+ // check stack height
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("ArrayExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // we needed room for an aray and an index or for a one or two word result
+ // but the recursive evaluations will have made sure the max stack is big enough
+ // so there is no need to update the maximum stack height
+ }
+
public void writeTo(StringWriter stringWriter) {
arrayRef.writeTo(stringWriter);
for (Expression expr : idxList) {
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BitExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BitExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BitExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
/**
* A binary arithmetic operator expression
@@ -176,4 +180,100 @@
throw new ExecuteException("BitExpression.interpret : unexpected exception for operation " + token + getPos() + " in rule " + helper.getName(), e);
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 0;
+ Expression oper0 = getOperand(0);
+ Expression oper1 = getOperand(1);
+ // compile the operands and make sure the result is our target type
+ oper0.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper0.getType(), type, mv, currentStackHeights, maxStackHeights);
+ oper1.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper1.getType(), type, mv, currentStackHeights, maxStackHeights);
+
+ if (type == Type.B || type == Type.S || type == Type.C || type == Type.I) {
+ switch (oper)
+ {
+ case BOR:
+ mv.visitInsn(Opcodes.IOR);
+ break;
+ case BAND:
+ mv.visitInsn(Opcodes.IAND);
+ break;
+ case BXOR:
+ mv.visitInsn(Opcodes.IXOR);
+ break;
+ }
+ if (type == Type.B) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (type == Type.S) {
+ mv.visitInsn(Opcodes.I2S);
+ } else if (type == Type.C) {
+ mv.visitInsn(Opcodes.I2C);
+ }
+ expected = 1;
+ } else if (type == Type.J) {
+ switch (oper)
+ {
+ case BOR:
+ mv.visitInsn(Opcodes.LOR);
+ break;
+ case BAND:
+ mv.visitInsn(Opcodes.LAND);
+ break;
+ case BXOR:
+ mv.visitInsn(Opcodes.LXOR);
+ break;
+ }
+ expected = 2;
+ } else if (type == Type.F) {
+ mv.visitInsn(Opcodes.F2L);
+ switch (oper)
+ {
+ case BOR:
+ mv.visitInsn(Opcodes.LOR);
+ break;
+ case BAND:
+ mv.visitInsn(Opcodes.LAND);
+ break;
+ case BXOR:
+ mv.visitInsn(Opcodes.LXOR);
+ break;
+ }
+ expected = 2;
+ } else if (type == Type.D) {
+ mv.visitInsn(Opcodes.D2L);
+ switch (oper)
+ {
+ case BOR:
+ mv.visitInsn(Opcodes.LOR);
+ break;
+ case BAND:
+ mv.visitInsn(Opcodes.LAND);
+ break;
+ case BXOR:
+ mv.visitInsn(Opcodes.LXOR);
+ break;
+ }
+ expected = 2;
+ }
+ // we have either a 1 byte or a 2 byte result
+ // check that the stack height is what we expect
+
+ currentStackHeights.addStackCount(expected);
+
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("BitExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // we needed room for 2 * expected stack values at the highest point
+ int maxStack = maxStackHeights.stackCount;
+ int overflow = (currentStack + (2 * expected)) - maxStack;
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BooleanLiteral.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BooleanLiteral.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/BooleanLiteral.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,12 +26,18 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
+import com.sun.org.apache.bcel.internal.generic.BIPUSH;
+
/**
* A binary logical operator expression
*/
@@ -70,6 +76,17 @@
return value;
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException {
+ // load a boolean constant
+ mv.visitLdcInsn(value);
+
+ // increment stack height and update maximmum if necessary
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ }
+
public void writeTo(StringWriter stringWriter) {
if (value) {
stringWriter.write("TRUE");
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ComparisonExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ComparisonExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ComparisonExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,15 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Label;
+import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
/**
* A binary comparison operator expression
@@ -273,6 +279,179 @@
throw new ExecuteException("ComparisonExpression.interpret : unexpected exception for operation " + token + getPos() + " in rule " + helper.getName(), e);
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper0 = getOperand(0);
+ Expression oper1 = getOperand(1);
+
+ int currentStack = currentStackHeights.stackCount;
+ int max = 0;
+
+ // evaluate the operands and ensure the reuslt is of the correct type for comparison adds 2
+ oper0.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper0.getType(), comparisonType, mv, currentStackHeights, maxStackHeights);
+ oper1.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper1.getType(), comparisonType, mv, currentStackHeights, maxStackHeights);
+
+ // now do the appropriate type of comparison
+ if (comparisonType.isNumeric()) {
+ if (comparisonType == type.B || comparisonType == type.S || comparisonType == type.S || comparisonType == type.I) {
+ Label elsetarget = new Label();
+ Label endtarget = new Label();
+ // we needed to stack two words for the operands
+ max = 2;
+ switch (oper)
+ {
+ case LT:
+ mv.visitJumpInsn(Opcodes.IF_ICMPGE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case LE:
+ mv.visitJumpInsn(Opcodes.IF_ICMPGT, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case GT:
+ mv.visitJumpInsn(Opcodes.IF_ICMPLE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case GE:
+ mv.visitJumpInsn(Opcodes.IF_ICMPLT, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case EQ:
+ mv.visitJumpInsn(Opcodes.IF_ICMPNE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case NE:
+ mv.visitJumpInsn(Opcodes.IF_ICMPEQ, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ }
+ } else if (comparisonType == type.J || comparisonType == type.F || comparisonType == type.D || comparable) {
+ if (comparisonType == type.J) {
+ mv.visitInsn(Opcodes.LCMP);
+ // we needed to stack four words for the operands
+ max = 4;
+ } else if (comparisonType == type.F) {
+ // we needed to stack two words for the operands
+ max = 2;
+ mv.visitInsn(Opcodes.FCMPG);
+ } else if (comparisonType == type.D) {
+ // we needed to stack four words for the operands
+ max = 4;
+ mv.visitInsn(Opcodes.DCMPG);
+ } else {
+ // we needed to stack two words for the operands
+ max = 2;
+ // comparable -- call compare to to leave an int
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
+ }
+ Label elsetarget = new Label();
+ Label endtarget = new Label();
+ switch (oper)
+ {
+ case LT:
+ mv.visitJumpInsn(Opcodes.IFGE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case LE:
+ mv.visitJumpInsn(Opcodes.IFGT, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case GT:
+ mv.visitJumpInsn(Opcodes.IFLE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case GE:
+ mv.visitJumpInsn(Opcodes.IFLT, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case EQ:
+ mv.visitJumpInsn(Opcodes.IFNE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ case NE:
+ mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ break;
+ }
+ }
+ } else {
+ // we needed to stack two words for the operands
+ max = 2;
+ Label elsetarget = new Label();
+ Label endtarget = new Label();
+ if (oper == EQ) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ } else {
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, elsetarget);
+ mv.visitLdcInsn(true); // or should we BIPUSH 1
+ mv.visitJumpInsn(Opcodes.GOTO, endtarget);
+ mv.visitLabel(elsetarget);
+ mv.visitLdcInsn(false);
+ mv.visitLabel(endtarget);
+ }
+ }
+ // we add a single boolean to the stack
+ currentStackHeights.addStackCount(1);
+ // no need to check the max heights as we stacked one or two words per operand and
+ // the compile and compileConvert calls will have already bumped the maximum stack
+ }
+
private Type comparisonType;
private boolean comparable;
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ConditionalEvalExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ConditionalEvalExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ConditionalEvalExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,14 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
/**
* expression representing a ternary conditional evaluation (cond ? if_expr : else_expr)
@@ -75,4 +80,46 @@
return getOperand(2).interpret(helper);
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper0 = getOperand(0);
+ Expression oper1 = getOperand(1);
+ Expression oper2 = getOperand(2);
+
+ int currentStack = currentStackHeights.stackCount;
+ int expected = (type.getNBytes() > 4 ? 2 : 1);
+
+ // compile the first operand to a boolean and ensure it is primitive -- adds 1 to stack
+ oper0.compile(mv, currentStackHeights, maxStackHeights);
+ if (oper0.getType() == Type.BOOLEAN) {
+ compileBooleanConversion(Type.BOOLEAN, Type.Z, mv, currentStackHeights, maxStackHeights);
+ }
+ // plant the test -- consumes 1 word
+ Label elseLabel = new Label();
+ Label endLabel = new Label();
+ mv.visitJumpInsn(Opcodes.IFEQ, elseLabel);
+ currentStackHeights.addStackCount(-1);
+ // compile the if branch
+ oper1.compile(mv, currentStackHeights, maxStackHeights);
+ // make sure we type convert to our result type so that either branch stacks the same thing
+ compileTypeConversion(oper1.getType(), type, mv, currentStackHeights, maxStackHeights);
+ // plant a goto skipping over the else expression
+ mv.visitJumpInsn(Opcodes.GOTO, endLabel);
+ // else starts here
+ mv.visitLabel(elseLabel);
+ // compile the else branch
+ oper2.compile(mv, currentStackHeights, maxStackHeights);
+ // make sure we type convert to our result type so that either branch stacks the same thing
+ compileTypeConversion(oper2.getType(), type, mv, currentStackHeights, maxStackHeights);
+ // the end is nigh
+ mv.visitLabel(endLabel);
+
+ // check the stack height is what we expect, either 1 or 2 words depending upon the result type
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("ConditionalEvalExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+ // no need to check max stack height as teh left and right expressions will have exceeded anything
+ // we stacked inside this call
+ }
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/DollarExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -27,9 +27,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -108,6 +112,45 @@
return helper.getBinding(name);
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+
+ if (index == -1) {
+ // reference to the current helper so just stack this
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ currentStackHeights.addStackCount(1);
+ // make sure we have room for this
+ int overflow = (currentStack + 1 - maxStackHeights.stackCount);
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ } else {
+ // stack the current helper
+ // stack the name for the variable
+ // call the getBinding method
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitLdcInsn(name);
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "getBinding", "(Ljava/lang/String;)Ljava/lang/Object;");
+ // ok, we added 2 to the stack and then popped them leaving 1
+ currentStackHeights.addStackCount(1);
+ // perform any necessary type conversion
+ if (type.isPrimitive()) {
+ // cast down to the boxed type then do an unbox
+ compileObjectConversion(Type.OBJECT, Type.boxType(type), mv, currentStackHeights, maxStackHeights);
+ compileUnbox(Type.OBJECT, type, mv, currentStackHeights, maxStackHeights);
+ } else {
+ // cast down to the required type
+ compileObjectConversion(Type.OBJECT, type, mv, currentStackHeights, maxStackHeights);
+ }
+ // make sure we have room for 2 working slots
+ int overflow = (currentStack + 2 - maxStackHeights.stackCount);
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+ }
+
public void writeTo(StringWriter stringWriter) {
stringWriter.write("$" + name);
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Expression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Expression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Expression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -27,9 +27,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
import org.jboss.jbossts.orchestration.rule.RuleElement;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ExpressionHelper.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -139,12 +139,12 @@
break;
case INTEGER_LITERAL:
{
- expr = new NumericLiteral(rule, Type.INTEGER, exprTree);
+ expr = new NumericLiteral(rule, Type.I, exprTree);
}
break;
case FLOAT_LITERAL:
{
- expr = new NumericLiteral(rule, Type.FLOAT, exprTree);
+ expr = new NumericLiteral(rule, Type.F, exprTree);
}
break;
case STRING_LITERAL:
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/FieldExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -28,9 +28,13 @@
import org.jboss.jbossts.orchestration.rule.type.TypeGroup;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
import java.lang.reflect.Field;
@@ -181,6 +185,29 @@
}
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int expected = (type.getNBytes() > 4 ? 2 : 1);
+
+ // compile the owner expression and then ensure it is typed correctly
+ owner.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(owner.getType(), type, mv, currentStackHeights, maxStackHeights);
+ if (!indirectStatic) {
+ // compile a field access
+ mv.visitFieldInsn(Opcodes.GETFIELD, field.getDeclaringClass().getName(), field.getName(), field.getType().getName());
+ }
+ // check the stack height is ok
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("FieldExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+ // make sure we have room for the field value if it is 2 words
+ int overflow = (currentStack + expected) - maxStackHeights.stackCount;
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+
public String getPath(int len)
{
StringBuffer buffer = new StringBuffer();
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/LogicalExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/LogicalExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/LogicalExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,14 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
/**
* A binary logical operator expression
@@ -60,4 +65,48 @@
return (value || (Boolean)getOperand(1).interpret(helper));
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper0 = getOperand(0);
+ Expression oper1 = getOperand(1);
+
+ int currentStack = currentStackHeights.stackCount;
+
+ // compile the first expression and make sure it is a boolean -- adds 1 to stack height
+ oper0.compile(mv, currentStackHeights, maxStackHeights);
+ if (oper0.getType() == Type.BOOLEAN) {
+ compileBooleanConversion(Type.BOOLEAN, type.Z, mv, currentStackHeights, maxStackHeights);
+ }
+ // plant a test and branch
+ Label nextLabel = new Label();
+ Label endLabel = new Label();
+ if (oper == AND) {
+ // only try next if we got true here
+ mv.visitJumpInsn(Opcodes.IFNE, nextLabel);
+ // ok, the first branch was false so stack a false for the result and skip to the end
+ mv.visitLdcInsn(false);
+ mv.visitJumpInsn(Opcodes.GOTO, endLabel);
+ } else {
+ // only try next if we got false here
+ mv.visitJumpInsn(Opcodes.IFEQ, nextLabel);
+ // ok, the first branch was true so stack a true for the result and skip to the end
+ mv.visitLdcInsn(true);
+ mv.visitJumpInsn(Opcodes.GOTO, endLabel);
+ }
+ // the else branch -- adds 1 to stack height
+ mv.visitLabel(nextLabel);
+ oper1.compile(mv, currentStackHeights, maxStackHeights);
+ if (oper0.getType() == Type.BOOLEAN) {
+ compileBooleanConversion(Type.BOOLEAN, type.Z, mv, currentStackHeights, maxStackHeights);
+ }
+ // the final result is the result of the second oper which is on the stack already
+ // This is the end, my beau-tiful friend
+ mv.visitLabel(endLabel);
+ // check stack height
+ if (currentStackHeights.stackCount != currentStack + 1) {
+ throw new CompileException("LogicalExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + 1);
+ }
+ // no need to check max stack height as recursive calls will have added at least 1
+ }
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MethodExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -28,9 +28,14 @@
import org.jboss.jbossts.orchestration.rule.binding.Binding;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@@ -49,6 +54,7 @@
this.recipient = recipient;
this.arguments = arguments;
this.argumentTypes = null;
+ this.paramTypes = null;
this.rootType = null;
this.pathList = pathList;
}
@@ -148,7 +154,6 @@
if (recipient == null) {
if (rootType == null) {
- //Type ruleType = typeGroup.create("org.jboss.jbossts.orchestration.rule.helper.Helper");
Type ruleType = typeGroup.create(rule.getHelperClass().getCanonicalName());
recipient = new DollarExpression(rule, ruleType, token, -1);
@@ -183,7 +188,7 @@
}
argumentTypes = new ArrayList<Type>();
-
+
// check each argument in turn -- if all candidates have the same argument type then
// use that as the type to check against
for (int i = 0; i < arguments.size() ; i++) {
@@ -221,6 +226,16 @@
method = candidates.get(0);
+ // now go back and identify the parameter types
+
+ this. paramTypes = new ArrayList<Type>();
+ Class<?>[] paramClasses = method.getParameterTypes();
+
+ for (int i = 0; i < arguments.size(); i++) {
+ Class<?> paramClass = paramClasses[i];
+ paramTypes.add(typeGroup.ensureType(paramClass));
+ }
+
type = typeGroup.ensureType(method.getReturnType());
if (Type.dereference(expected).isDefined() && !expected.isAssignableFrom(type)) {
@@ -254,6 +269,73 @@
}
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int extraParams = 0; // space used by stacked args after conversion
+ int expected = 0;
+ if (recipient != null) {
+ // compile code for recipient
+ recipient.compile(mv, currentStackHeights, maxStackHeights);
+
+ extraParams += 1;
+ }
+
+ int argCount = arguments.size();
+
+ for (int i = 0; i < argCount; i++) {
+ Expression argument = arguments.get(i);
+ Type argType = argumentTypes.get(i);
+ Type paramType = paramTypes.get(i);
+ // compile code to stack argument and type convert if necessary
+ argument.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(argType, paramType, mv, currentStackHeights, maxStackHeights);
+ // allow for stacked paramType value
+ extraParams += (paramType.getNBytes() > 4 ? 2 : 1);
+ }
+
+ String ownerName = Type.internalName(method.getDeclaringClass());
+
+ // ok, now just call the method -- removes extraParams words
+ if (recipient == null) {
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, ownerName, method.getName(), getDescriptor());
+ } else if (recipient.getClass().isInterface()) {
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, ownerName, method.getName(), getDescriptor());
+ } else {
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ownerName, method.getName(), getDescriptor());
+ }
+ // no need for type conversion as return type was derived from method
+ if (type.getNBytes() > 4) {
+ expected = 2;
+ } else {
+ expected = 1;
+ }
+
+ // decrement the stack height to account for stacked param values (removed) and return value (added)
+ currentStackHeights.addStackCount(expected - extraParams);
+
+ // ensure we have only increased the stack by the return value size
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("MethodExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + (currentStack + expected));
+ }
+
+ // no need to update max stack since compiling the recipient or arguments will
+ // have done so (and there will be no change if there was no such compile call)
+ }
+
+ private String getDescriptor()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("(");
+ int nParams = paramTypes.size();
+ for (int i = 0; i < nParams; i++) {
+ buffer.append(paramTypes.get(i).getInternalName(true));
+ }
+ buffer.append(")");
+ buffer.append(type.getInternalName(true));
+ return buffer.toString();
+ }
+
public Class getCandidateArgClass(List<Method> candidates, int argIdx)
{
Class argClazz = null;
@@ -330,6 +412,7 @@
private String name;
private List<Expression> arguments;
private List<Type> argumentTypes;
+ private List<Type> paramTypes;
private Expression recipient;
private Type rootType;
private Method method;
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MinusExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MinusExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/MinusExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
/**
*/
@@ -73,4 +77,45 @@
throw new ExecuteException("MinusExpression.typeCheck() : unexpected exception : " + token.getText() + getPos(), e);
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper = getOperand(0);
+ Type operType = oper.getType();
+
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 0;
+
+ // compile code to execute the value then negate it
+ oper.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(operType, type, mv, currentStackHeights, maxStackHeights);
+
+ // ok, now negate the value
+ if (type == Type.B || type == Type.S || type == Type.I) {
+ mv.visitInsn(Opcodes.INEG);
+ expected = 1;
+ } else if (type == Type.J) {
+ mv.visitInsn(Opcodes.LNEG);
+ expected = 2;
+ } else if (type == Type.F) {
+ mv.visitInsn(Opcodes.FNEG);
+ expected = 1;
+ } else if (type == Type.D) {
+ mv.visitInsn(Opcodes.DNEG);
+ expected = 2;
+ }
+
+ // check stack height
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("MinusExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // ensure we have room for any values we stacked
+
+ int overflow = (currentStack + expected) - maxStackHeights.stackCount;
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NotExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NotExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NotExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
/**
*/
@@ -52,4 +56,39 @@
Boolean result = (Boolean) getOperand(0).interpret(helper);
return !result;
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper = getOperand(0);
+ Type operType = oper.getType();
+
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 0;
+
+ // compile code to execute the operand -- adds 1
+ oper.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(operType, type, mv, currentStackHeights, maxStackHeights);
+
+ // the boolean expression will leave 0 or 1 on the stack so we can negate negate this to get
+ // 0 or -1 and then add 1 to get 1 or 0
+
+ mv.visitInsn(Opcodes.INEG);
+ // adds 1
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IADD);
+
+ // check stack height
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("NotExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // ensure we have room for the two values we stacked
+
+ int overflow = (currentStack + 2) - maxStackHeights.stackCount;
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+
+ }
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NumericLiteral.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NumericLiteral.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/NumericLiteral.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -40,7 +44,7 @@
public NumericLiteral(Rule rule, Type type, ParseNode token) {
super(rule, type, token);
- this.value = token.getChild(0);
+ this.value = (Number)token.getChild(0);
}
/**
@@ -67,9 +71,52 @@
return value;
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ if (type == Type.I) {
+ int val = value.intValue();
+ // compile code to stack int value
+ if (val >= -1 && val <= 5) {
+ // we can use an iconst instruction
+ mv.visitInsn(Opcodes.ICONST_0 + val);
+ } else {
+ // we have to add an integer constant to the constants pool
+ mv.visitLdcInsn(value);
+ }
+ // we have only added 1 to the stack height
+
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ } else { // type = type.F
+ float val = value.floatValue();
+ if (val == 0.0) {
+ // we can use an fconst instruction
+ mv.visitInsn(Opcodes.FCONST_0);
+ } else if (val == 1.0) {
+ // we can use an fconst instruction
+ mv.visitInsn(Opcodes.FCONST_1);
+ } else if (val == 2.0) {
+ // we can use an fconst instruction
+ mv.visitInsn(Opcodes.FCONST_2);
+ } else {
+ // we have to add a float constant to the constants pool
+ mv.visitLdcInsn(value);
+ }
+
+ // we have only added 1 to the stack height
+
+ currentStackHeights.addStackCount(1);
+ if (currentStackHeights.stackCount > maxStackHeights.stackCount) {
+ maxStackHeights.stackCount = currentStackHeights.stackCount;
+ }
+ }
+ }
+
public void writeTo(StringWriter stringWriter) {
stringWriter.write(value.toString());
}
- private Object value;
+ private Number value;
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/PlusExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/PlusExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/PlusExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
/**
* A plus operator expression which handles the case where we do not know the type of the first
@@ -105,4 +109,70 @@
}
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper0 = getOperand(0);
+ Expression oper1 = getOperand(1);
+
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 0;
+
+ // compile and type convert each operand -- adds 2 or 4 depending upon type
+ oper0.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper0.getType(), type, mv, currentStackHeights, maxStackHeights);
+ oper1.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper1.getType(), type, mv, currentStackHeights, maxStackHeights);
+
+ if (type == Type.S) {
+ // ok, we could optimize this for the case where the left or right operand is a String plus expression
+ // by employing a StringBuffer but for now we will just evaluate the left and right operand and
+ // then call concat to join them
+ // add two strings leaving one string
+ expected = 1;
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "concat", "(Ljava/lang/String;)Ljava/lang/String;");
+ } else if (type == Type.B) {
+ // add two bytes leaving one byte
+ expected = 1;
+ mv.visitInsn(Opcodes.IADD);
+ mv.visitInsn(Opcodes.I2B);
+ } else if (type == Type.S ) {
+ // add two shorts leaving one short
+ expected = 1;
+ mv.visitInsn(Opcodes.IADD);
+ mv.visitInsn(Opcodes.I2S);
+ } else if (type == Type.C) {
+ // add two chars leaving one char
+ expected = 1;
+ mv.visitInsn(Opcodes.IADD);
+ mv.visitInsn(Opcodes.I2C);
+ } else if (type == Type.I) {
+ // add two ints leaving one int
+ expected = 1;
+ mv.visitInsn(Opcodes.IADD);
+ } else if (type == Type.J) {
+ // add two longs leaving one long
+ expected = 1;
+ mv.visitInsn(Opcodes.LADD);
+ } else if (type == Type.F) {
+ // add two floats leaving one float
+ expected = 1;
+ mv.visitInsn(Opcodes.FADD);
+ } else if (type == Type.D) {
+ // add two doubles leaving one double
+ expected = 1;
+ mv.visitInsn(Opcodes.FADD);
+ }
+
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("PlusExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // we need room for 2 * expected words at our maximum
+
+ int overflow = (currentStack + 2 * expected) - maxStackHeights.stackCount;
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ReturnExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ReturnExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ReturnExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -28,9 +28,13 @@
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
import org.jboss.jbossts.orchestration.rule.exception.EarlyReturnException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -45,7 +49,7 @@
public ReturnExpression(Rule rule, ParseNode token, Expression returnValue)
{
- // the trigger method may return any old tyep but the return expression can only occur
+ // the trigger method may return any old type but the return expression can only occur
// at the top level in a rule action seuqence so it is actually a VOID expression
super(rule, Type.VOID, token);
@@ -118,6 +122,54 @@
}
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Type returnType = returnValue.getType();
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 1;
+ int extraSlots = 3;
+
+ // ok, we need to create the EarlyReturnException instance and then
+ // initialise it using the appropriate return value or null if no
+ // return value is needed. strictly we should maybe delay the
+ // new until after computing the return expression so we avoid a new
+ // if the expression throws an error. but that means we end up doing
+ // stack manipulations so lets do it the easy way.
+
+ // create am EarlyReturnException -- adds 1 to stack
+ String exceptionClassName = Type.internalName(EarlyReturnException.class);
+ mv.visitTypeInsn(Opcodes.NEW, exceptionClassName);
+ // stack a string constant to initialise the exception with -- adds 1 to stack
+ mv.visitLdcInsn("return from " + rule.getName());
+ // stack any required return value or null -- adds 1 to stack but may use 2 slots
+ if (returnValue != null) {
+ returnValue.compile(mv, currentStackHeights, maxStackHeights);
+ if (returnType.isPrimitive()) {
+ // we need an object not a primitive
+ compileBox(returnType, mv, currentStackHeights, maxStackHeights);
+ // if the intermediate value used 2 words then at the peak we needed an extra stack slot
+ if (returnType.getNBytes() > 4) {
+ extraSlots++;
+ }
+ }
+ } else {
+ // just push null
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ }
+ // construct the exception
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, exceptionClassName, "<init>", "(Ljava/lang/String;Ljava/lang/Object;)V");
+
+ // check current stack and increment max stack if necessary
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("ReturnExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ int overflow = ((currentStack + extraSlots) - maxStackHeights.stackCount);
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+
public void writeTo(StringWriter stringWriter) {
if (returnValue != null) {
stringWriter.write("RETURN ");
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StaticExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StaticExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StaticExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -27,9 +27,13 @@
import org.jboss.jbossts.orchestration.rule.type.TypeGroup;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
import java.lang.reflect.Field;
@@ -98,6 +102,25 @@
}
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int expected;
+
+ // compile a field access
+
+ mv.visitFieldInsn(Opcodes.GETSTATIC, ownerTypeName, fieldName, type.getName());
+ expected = (type.getNBytes() > 4 ? 2 : 1);
+
+ currentStackHeights.addStackCount(expected);
+
+ int overflow = ((currentStack + expected) - maxStackHeights.stackCount);
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+
public void writeTo(StringWriter stringWriter) {
stringWriter.write(ownerTypeName);
stringWriter.write(".");
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringLiteral.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringLiteral.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringLiteral.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -64,6 +68,26 @@
return text;
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 1;
+
+ // compile a field access
+
+ // compile a load constant instruction
+ mv.visitLdcInsn(text);
+
+ currentStackHeights.addStackCount(expected);
+
+ int overflow = ((currentStack + expected) - maxStackHeights.stackCount);
+
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+
+ }
+
public void writeTo(StringWriter stringWriter) {
stringWriter.write(text);
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringPlusExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringPlusExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/StringPlusExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
/**
* A binary string concatenation operator expression
@@ -59,4 +63,39 @@
String string2 = value2.toString();
return string1 + string2;
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ Expression oper0 = getOperand(0);
+ Expression oper1 = getOperand(1);
+
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 2;
+
+ // compile and type convert each operand
+ oper0.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper0.getType(), type, mv, currentStackHeights, maxStackHeights);
+ oper1.compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(oper1.getType(), type, mv, currentStackHeights, maxStackHeights);
+
+ // ok, we could optimize this for the case where the left or right operand is a String plus expression
+ // by employing a StringBuffer but for now we will just evaluate the left and right operand and
+ // then call concat to join them
+ // add two strings leaving one string
+ expected = 1;
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "concat", "(Ljava/lang/String;)Ljava/lang/String;");
+
+ currentStackHeights.addStackCount(-1);
+
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("StringPlusExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // we need room for 2 * expected words at our maximum
+
+ int overflow = (currentStack + 2 * expected) - maxStackHeights.stackCount;
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
}
\ No newline at end of file
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/ThrowExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -28,9 +28,13 @@
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
import org.jboss.jbossts.orchestration.rule.exception.ThrowException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
import java.util.List;
@@ -48,6 +52,7 @@
private String typeName;
private List<Expression> arguments;
private List<Type> argumentTypes;
+ private List<Type> paramTypes;
private Constructor constructor;
public ThrowExpression(Rule rule, ParseNode token, List<Expression> arguments) {
@@ -157,6 +162,15 @@
constructor = candidates.get(0);
+ // make sure we know the formal parameter types and have included them in the typegroup
+
+ paramTypes = new ArrayList<Type>();
+ Class<?>[] paramClasses = constructor.getParameterTypes();
+
+ for (int i = 0; i < arguments.size() ; i++) {
+ paramTypes.add(typeGroup.ensureType(paramClasses[i]));
+ }
+
// expected type should always be void since throw can only occur as a top level action
// however, we need to be sure that the trigering method throws this exception type or
// else that it is a subtype of runtime exception
@@ -239,6 +253,70 @@
}
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 1;
+ int extraParams = 0;
+
+ // ok, we need to create the thrown exception instance and then
+ // initialise it.
+
+ // create the thrown exception instance -- adds 1 to stack
+ String exceptionClassName = type.getInternalName();
+ mv.visitTypeInsn(Opcodes.NEW, exceptionClassName);
+ currentStackHeights.addStackCount(1);
+ extraParams++;
+
+ int argCount = arguments.size();
+
+ // stack each of the arguments to the constructor
+ for (int i = 0; i < argCount; i++) {
+ Type argType = argumentTypes.get(i);
+ Type paramType = paramTypes.get(i);
+
+ arguments.get(i).compile(mv, currentStackHeights, maxStackHeights);
+ compileTypeConversion(argType, paramType, mv, currentStackHeights, maxStackHeights);
+ // track extra storage used after type conversion
+ extraParams += (paramType.getNBytes() > 4 ? 2 : 1);
+ }
+
+ // construct the exception
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, exceptionClassName, "<init>", getDescriptor());
+ // now throw it
+ mv.visitInsn(Opcodes.ATHROW);
+
+ // decrement the stack height to account for stacked param values (removed) and return value (added)
+ currentStackHeights.addStackCount(expected - extraParams);
+
+ // we should only have the thrown exception on the stack
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("ThrowExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+
+ // no need to update max stack unless extraParams is zero in which case the exception
+ // instance may have thrown us over the limit
+
+ if (extraParams < 1) {
+ int overflow = ((currentStack + 1) - maxStackHeights.stackCount);
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+ }
+
+ private String getDescriptor()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("(");
+ int nParams = paramTypes.size();
+ for (int i = 0; i < nParams; i++) {
+ buffer.append(paramTypes.get(i).getInternalName(true));
+ }
+ buffer.append(")V");
+ return buffer.toString();
+ }
+
public void writeTo(StringWriter stringWriter) {
stringWriter.write("throw " + type.getName() + "(");
for (Expression argument : arguments) {
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/TwiddleExpression.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/TwiddleExpression.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/TwiddleExpression.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -26,9 +26,14 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import com.sun.org.apache.bcel.internal.generic.IXOR;
/**
*/
@@ -63,10 +68,6 @@
return ~value.intValue();
} else if (type == Type.J) {
return ~value.longValue();
- } else if (type == Type.F) {
- return ~value.longValue();
- } else if (type == Type.D) {
- return ~value.longValue();
} else { // (type == Type.C)
return ~value.intValue();
}
@@ -76,4 +77,47 @@
throw new ExecuteException("TwiddleExpression.typeCheck() : unexpected exception : " + token.getText() + getPos(), e);
}
}
+
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ // compile the operand and then bit twiddle it
+ Expression oper = getOperand(0);
+ Type operType = oper.getType();
+
+ int currentStack = currentStackHeights.stackCount;
+ int expected = 0;
+
+ oper.compile(mv, currentStackHeights, maxStackHeights);
+ currentStackHeights.addStackCount((operType.getNBytes() > 4 ? 2 : 1));
+ compileTypeConversion(operType, type, mv, currentStackHeights, maxStackHeights);
+ if (type == Type.B) {
+ expected = 1;
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ mv.visitInsn(Opcodes.I2B);
+ } else if (type == Type.S) {
+ expected = 1;
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ mv.visitInsn(Opcodes.I2S);
+ } else if (type == Type.C) {
+ expected = 1;
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ mv.visitInsn(Opcodes.I2C);
+ } else if (type == Type.I) {
+ expected = 1;
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ } else if (type == Type.J) {
+ expected = 2;
+ mv.visitInsn(Opcodes.LCONST_1);
+ mv.visitInsn(Opcodes.LXOR);
+ }
+
+ // check the stack height is what we expect
+ if (currentStackHeights.stackCount != currentStack + expected) {
+ throw new CompileException("MinusExpression.compile : invalid stack height " + currentStackHeights.stackCount + " expecting " + currentStack + expected);
+ }
+ }
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Variable.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Variable.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/expression/Variable.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -27,9 +27,13 @@
import org.jboss.jbossts.orchestration.rule.type.Type;
import org.jboss.jbossts.orchestration.rule.exception.TypeException;
import org.jboss.jbossts.orchestration.rule.exception.ExecuteException;
+import org.jboss.jbossts.orchestration.rule.exception.CompileException;
import org.jboss.jbossts.orchestration.rule.Rule;
+import org.jboss.jbossts.orchestration.rule.compiler.StackHeights;
import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import org.jboss.jbossts.orchestration.rule.grammar.ParseNode;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
import java.io.StringWriter;
@@ -94,6 +98,34 @@
return helper.getBinding(name);
}
+ public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
+ {
+ int currentStack = currentStackHeights.stackCount;
+
+ // stack the current helper
+ // stack the name for the variable
+ // call the getBinding method
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitLdcInsn(name);
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "getBinding", "(Ljava/lang/String;)Ljava/lang/Object;");
+ // ok, we added 2 to the stack and then popped them leaving 1
+ currentStackHeights.addStackCount(1);
+ // perform any necessary type conversion
+ if (type.isPrimitive()) {
+ // cast down to the boxed type then do an unbox
+ compileObjectConversion(Type.OBJECT, Type.boxType(type), mv, currentStackHeights, maxStackHeights);
+ compileUnbox(Type.OBJECT, type, mv, currentStackHeights, maxStackHeights);
+ } else {
+ // cast down to the required type
+ compileObjectConversion(Type.OBJECT, type, mv, currentStackHeights, maxStackHeights);
+ }
+ // make sure we have room for 2 working slots
+ int overflow = (currentStack + 2 - maxStackHeights.stackCount);
+ if (overflow > 0) {
+ maxStackHeights.addStackCount(overflow);
+ }
+ }
+
public void writeTo(StringWriter stringWriter) {
stringWriter.write(name);
}
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/helper/InterpretedHelper.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -136,7 +136,7 @@
throws ExecuteException
{
// System.out.println(rule.getName() + " test");
- return rule.getCondition().interpret(this);
+ return (Boolean)rule.getCondition().interpret(this);
}
private void fire()
Modified: labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java
===================================================================
--- labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java 2009-03-20 09:57:33 UTC (rev 25762)
+++ labs/jbosstm/workspace/adinn/orchestration/src/org/jboss/jbossts/orchestration/rule/type/Type.java 2009-03-20 10:16:54 UTC (rev 25763)
@@ -23,7 +23,7 @@
*/
package org.jboss.jbossts.orchestration.rule.type;
-import org.jboss.jbossts.orchestration.rule.exception.TypeException;
+import org.jboss.jbossts.orchestration.rule.helper.HelperAdapter;
import java.util.HashMap;
import java.util.List;
@@ -41,7 +41,7 @@
*/
public Type(String typeName, Class clazz)
{
- this(typeName, clazz, F_OBJECT, null);
+ this(typeName, clazz, F_OBJECT, 4, null);
}
/**
@@ -72,7 +72,7 @@
public Type arrayType(Class clazz)
{
if (this.arrayType == null) {
- arrayType = new Type(typeName + "[]", clazz, F_ARRAY, this);
+ arrayType = new Type(typeName + "[]", clazz, F_ARRAY, 1, this);
}
return arrayType;
}
@@ -106,13 +106,24 @@
*/
public String getInternalName()
{
+ return getInternalName(false);
+ }
+
+ /**
+ * get the internal name for this type used by the class loader. this is only valid for
+ * defined types, defined array types or primitive types
+ * @return the type name
+ */
+ public String getInternalName(boolean forDescriptor)
+ {
if (isArray()) {
- return "[" + baseType.getInternalName();
+ return "[" + baseType.getInternalName(forDescriptor);
} else if (isPrimitive()) {
return internalNames.get(typeName);
} else {
String name = aliasFor.getTargetClass().getCanonicalName();
- if (name.indexOf(';') == 0) {
+ name = name.replaceAll("\\.", "/");
+ if (forDescriptor) {
name = "L" + name + ";";
}
return name;
@@ -423,10 +434,19 @@
}
/**
+ * return the number of stack words occupied by instances of this type
+ * @return true if this is an array type
+ */
+ public int getNBytes()
+ {
+ return nBytes;
+ }
+
+ /**
* return the builtin type associated with a given class
* @return the corresponding builtin type
*/
- public Type builtinType(Class clazz)
+ public static Type builtinType(Class clazz)
{
return builtinTypes.get(clazz.getName());
}
@@ -435,27 +455,37 @@
* return the primitive type whose boxed equivalent is associated with a given class
* @return the corresponding primitive type
*/
- public Type primitiveType(Class clazz)
+ public static Type boxType(Class clazz)
{
Type type = builtinType(clazz);
return boxedTypes.get(type);
}
+ /**
+ * return the primitive type for a boxed type or vice versa
+ * @return the corresponding primitive type
+ */
+ public static Type boxType(Type type)
+ {
+ return boxedTypes.get(type);
+ }
+
private String typeName;
private Class clazz;
private String packageName;
private int flags;
+ private int nBytes;
private Type aliasFor;
private Type baseType;
private Type arrayType;
- protected Type(String typeName, Class clazz, int flags)
+ protected Type(String typeName, Class clazz, int flags, int nBytes)
{
- this(typeName, clazz, flags, null);
+ this(typeName, clazz, flags, nBytes, null);
}
- protected Type(String typeName, Class clazz, int flags, Type baseType)
+ protected Type(String typeName, Class clazz, int flags, int nBytes, Type baseType)
{
this.typeName = typeName;
@@ -466,6 +496,9 @@
this.clazz = clazz;
this.flags = flags;
+
+ this.nBytes = nBytes;
+
if ((flags & F_ARRAY) != 0) {
this.baseType = baseType;
baseType.arrayType = this;
@@ -514,13 +547,13 @@
} else if (type1 == INTEGER || type2 == INTEGER || type1 == I || type2 == I) {
return I;
} else if ((type1 == SHORT || type1 == S) && (type2 == SHORT || type2 == S)) {
- return SHORT;
+ return S;
} else if ((type1 == CHARACTER || type1 == C) && (type2 == CHARACTER || type2 == C)) {
return C;
} else if ((type1 == BYTE || type1 == B) && (type2 == BYTE || type2 == B)) {
return B;
} else {
- return INTEGER;
+ return I;
}
}
}
@@ -696,6 +729,11 @@
return result;
}
+ public static String internalName(Class<?> clazz)
+ {
+ return clazz.getName().replaceAll("\\.", "/");
+ }
+
// private class used to type unknown types
private static class Undefined {
}
@@ -727,30 +765,31 @@
// we need to cope with array types
- final public static Type Z = new Type("boolean", boolean.class, F_BOOLEAN|F_PRIMITIVE);
- final public static Type B = new Type("byte", byte.class, F_INTEGRAL|F_PRIMITIVE);
- final public static Type S = new Type("short", short.class, F_INTEGRAL|F_PRIMITIVE);
- final public static Type C = new Type("char", char.class, F_INTEGRAL|F_PRIMITIVE);
- final public static Type I = new Type("int", int.class, F_INTEGRAL|F_PRIMITIVE);
- final public static Type J = new Type("long", long.class, F_INTEGRAL|F_PRIMITIVE);
- final public static Type F = new Type("float", float.class, F_FLOATING|F_PRIMITIVE);
- final public static Type D = new Type("double", double.class, F_FLOATING|F_PRIMITIVE);
+ final public static Type Z = new Type("boolean", boolean.class, F_BOOLEAN|F_PRIMITIVE, 4);
+ final public static Type B = new Type("byte", byte.class, F_INTEGRAL|F_PRIMITIVE, 1);
+ final public static Type S = new Type("short", short.class, F_INTEGRAL|F_PRIMITIVE, 2);
+ final public static Type C = new Type("char", char.class, F_INTEGRAL|F_PRIMITIVE, 2);
+ final public static Type I = new Type("int", int.class, F_INTEGRAL|F_PRIMITIVE, 4);
+ final public static Type J = new Type("long", long.class, F_INTEGRAL|F_PRIMITIVE, 8);
+ final public static Type F = new Type("float", float.class, F_FLOATING|F_PRIMITIVE, 4);
+ final public static Type D = new Type("double", double.class, F_FLOATING|F_PRIMITIVE, 8);
// pseudo type representing an undefined numeric primitive type
- final public static Type N = new Type("", null, F_UNKNOWN|F_NUMERIC|F_PRIMITIVE);
+ final public static Type N = new Type("", null, F_UNKNOWN|F_NUMERIC|F_PRIMITIVE, 0);
- final public static Type BOOLEAN = new Type("java.lang.Boolean", Boolean.class, F_BOOLEAN);
- final public static Type BYTE = new Type("java.lang.Byte", Byte.class, F_INTEGRAL);
- final public static Type SHORT = new Type("java.lang.Short", Short.class, F_INTEGRAL);
- final public static Type CHARACTER = new Type("java.lang.Character", Character.class, F_INTEGRAL);
- final public static Type INTEGER = new Type("java.lang.Integer", Integer.class, F_INTEGRAL);
- final public static Type LONG = new Type("java.lang.Long", Long.class, F_INTEGRAL);
- final public static Type FLOAT = new Type("java.lang.Float", Float.class, F_FLOATING);
- final public static Type DOUBLE = new Type("java.lang.Double", Double.class, F_FLOATING);
- final public static Type STRING = new Type("java.lang.String", String.class, F_OBJECT|F_STRING);
- final public static Type VOID = new Type("void", void.class, F_VOID);
- final public static Type NUMBER = new Type("java.lang.Number", Number.class, F_NUMERIC);
+ final public static Type BOOLEAN = new Type("java.lang.Boolean", Boolean.class, F_BOOLEAN, 4);
+ final public static Type BYTE = new Type("java.lang.Byte", Byte.class, F_INTEGRAL, 4);
+ final public static Type SHORT = new Type("java.lang.Short", Short.class, F_INTEGRAL, 4);
+ final public static Type CHARACTER = new Type("java.lang.Character", Character.class, F_INTEGRAL, 4);
+ final public static Type INTEGER = new Type("java.lang.Integer", Integer.class, F_INTEGRAL, 4);
+ final public static Type LONG = new Type("java.lang.Long", Long.class, F_INTEGRAL, 4);
+ final public static Type FLOAT = new Type("java.lang.Float", Float.class, F_FLOATING, 4);
+ final public static Type DOUBLE = new Type("java.lang.Double", Double.class, F_FLOATING, 4);
+ final public static Type STRING = new Type("java.lang.String", String.class, F_OBJECT|F_STRING, 4);
+ final public static Type VOID = new Type("void", void.class, F_VOID, 0);
+ final public static Type NUMBER = new Type("java.lang.Number", Number.class, F_NUMERIC, 0);
+ final public static Type OBJECT = new Type("java.lang.Object", Object.class, F_OBJECT, 0);
// pseudo type representing an undefined primitive or object type
- final public static Type UNDEFINED = new Type("", Undefined.class, F_UNKNOWN);
+ final public static Type UNDEFINED = new Type("", Undefined.class, F_UNKNOWN, 0);
final private static HashMap<String, Type> builtinTypes;
final private static HashMap<String, Type> primitiveTypes;
@@ -781,6 +820,7 @@
builtinTypes.put(VOID.getTargetClass().getName(), VOID);
builtinTypes.put(NUMBER.getTargetClass().getName(), NUMBER);
builtinTypes.put(UNDEFINED.getTargetClass().getName(), UNDEFINED);
+ builtinTypes.put(OBJECT.getTargetClass().getName(), OBJECT);
// nicknames
builtinTypes.put("Boolean", BOOLEAN);
builtinTypes.put("Byte", BYTE);
@@ -791,6 +831,7 @@
builtinTypes.put("Float", FLOAT);
builtinTypes.put("String", STRING);
builtinTypes.put("Number", NUMBER);
+ builtinTypes.put("Object", OBJECT);
builtinTypes.put("", UNDEFINED);
// allow undefined to be spelled out
builtinTypes.put("Undefined", UNDEFINED);
More information about the jboss-svn-commits
mailing list