[jboss-svn-commits] JBL Code SVN: r28931 - in labs/jbosstm/workspace/adinn/byteman/trunk: src/org/jboss/byteman/rule/binding and 5 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Aug 14 06:17:43 EDT 2009
Author: adinn
Date: 2009-08-14 06:17:43 -0400 (Fri, 14 Aug 2009)
New Revision: 28931
Added:
labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestMethodParamName.txt
labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestMethodParamName.java
Modified:
labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java
labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/binding/Binding.java
labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/compiler/Compiler.java
labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/InterpretedHelper.java
labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml
Log:
added support for referring to method arguments using symbol names e.g. , etc - fixes BYTEMAN-23
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java 2009-08-14 07:08:11 UTC (rev 28930)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/agent/adapter/RuleTriggerMethodAdapter.java 2009-08-14 10:17:43 UTC (rev 28931)
@@ -48,9 +48,10 @@
super(mv, rule, access, name, descriptor);
this.access = access;
this.descriptor = descriptor;
- this.paramBindings = new ArrayList<Binding>();
+ this.callArrayBindings = new ArrayList<Binding>();
this.returnType = Type.getReturnType(descriptor);
this.argumentTypes = Type.getArgumentTypes(descriptor);
+ this.argLocalIndices = new int[argumentTypes.length];
this.bindingsDone = false;
this.localTypes = new ArrayList();
}
@@ -59,23 +60,63 @@
{
Bindings bindings = rule.getBindings();
Iterator<Binding> iterator = bindings.iterator();
+ List<Binding> aliasBindings = new ArrayList<Binding>();
+ int argLocalIndex = 0;
- // make sure all entries are valid
+ // if this is an instance method then the local 0 holds this and args start at local index 1
+
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ argLocalIndex += 1;
+ }
+
+ // compute the local indices of each method parameter
+
+ for (int i = 0; i < argumentTypes.length; i++) {
+ argLocalIndices[i] = argLocalIndex;
+ argLocalIndex += argumentTypes[i].getSize();
+ }
+
+ // check the local var bindings and, if any of them are actually refereces to method params
+ // alias them to the corresponding param binding
+
while (iterator.hasNext()) {
Binding binding = iterator.next();
+ if (binding.isLocalVar()){
+ int localIdx = binding.getLocalIndex();
+ if (localIdx < argLocalIndex) {
+ binding = alias(binding, bindings, localIdx);
+ if (binding != null) {
+ // the aliased param binding was not present so ensure it gets added to the
+ // binding set once we have finished iterating. there is no need to add it
+ // to the call bindings since we pass the aliased method param instead
+ aliasBindings.add(binding);
+ }
+ } else {
+ callArrayBindings.add(binding);
+ }
+ }
+ }
+
+ bindings.addBindings(aliasBindings);
+
+ // now iterate over the param vars and ensure they go into the call bindings list
+
+ iterator = bindings.iterator();
+
+ while (iterator.hasNext()) {
+ Binding binding = iterator.next();
if (binding.isParam()) {
- paramBindings.add(binding);
+ callArrayBindings.add(binding);
} else if (binding.isReturn()) {
// at some point we will allow reference to the current return value so we need
- // to be sure that the method has a non-void return type bit for now we do nothing
- } else if (binding.isLocalVar()){
- paramBindings.add(binding);
+ // to be sure that the method has a non-void return type and that the location
+ // specifier is AT RETURN but for now we do nothing
}
}
// we don't have to do this but it makes debgging easier
if (true) {
- // ok now sort the paramBindings for later use
+ // ok now sort the callArrayBindings for later use
Comparator<Binding> comparator = new Comparator<Binding>() {
public int compare(Binding b1, Binding b2)
@@ -100,16 +141,57 @@
}
};
- Collections.sort(paramBindings, comparator);
+ Collections.sort(callArrayBindings, comparator);
}
// now give each binding a unique index in the object array
- int n = paramBindings.size();
+ int n = callArrayBindings.size();
for (int i = 0; i < n; i++) {
- paramBindings.get(i).setObjectArrayIndex(i);
+ callArrayBindings.get(i).setCallArrayIndex(i);
}
}
+ private Binding alias(Binding binding, Bindings bindings, int localIdx)
+ {
+ if (((access & Opcodes.ACC_STATIC) == 0) && (localIdx == 0)) {
+ String name = "$0";
+ Binding alias = bindings.lookup(name);
+ if (alias == null) {
+ alias = new Binding(rule, name);
+ alias.setDescriptor(binding.getDescriptor());
+ alias.setLocalIndex(binding.getLocalIndex());
+ binding.aliasTo(alias);
+ // alias var was new so return it for addition to the binding set
+ return alias;
+ } else {
+ // just alias the binding
+ binding.aliasTo(alias);
+ return null;
+ }
+ }
+
+ for (int i = 0; i < argLocalIndices.length; i++) {
+ if (argLocalIndices[i] == localIdx) {
+ String name = "$" + (i + 1);
+ Binding alias = bindings.lookup(name);
+ if (alias == null) {
+ alias = new Binding(rule, name);
+ alias.setDescriptor(binding.getDescriptor());
+ alias.setLocalIndex(binding.getLocalIndex());
+ binding.aliasTo(alias);
+ // alias var was new so return it for addition to the binding set
+ return alias;
+ } else {
+ // just alias the binding
+ binding.aliasTo(alias);
+ return null;
+ }
+ }
+ }
+
+ return null;
+ }
+
public void doArgLoad()
{
if (!bindingsDone) {
@@ -117,19 +199,19 @@
bindingsDone = true;
}
- if (paramBindings.size() == 0) {
+ if (callArrayBindings.size() == 0) {
push((org.objectweb.asm.Type)null);
return;
}
- int arraySize = paramBindings.size();
+ int arraySize = callArrayBindings.size();
push(arraySize);
Type objectType = Type.getType(Object.class);
newArray(objectType);
for (int i = 0; i < arraySize; i++) {
- Binding binding = paramBindings.get(i);
+ Binding binding = callArrayBindings.get(i);
dup();
push(i);
if (binding.isParam()) {
@@ -159,7 +241,8 @@
private String descriptor;
private Type returnType;
private Type[] argumentTypes;
- private List<Binding> paramBindings;
+ private int[] argLocalIndices;
+ private List<Binding> callArrayBindings;
private boolean bindingsDone;
private final List localTypes;
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/binding/Binding.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/binding/Binding.java 2009-08-14 07:08:11 UTC (rev 28930)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/binding/Binding.java 2009-08-14 10:17:43 UTC (rev 28931)
@@ -60,6 +60,7 @@
this.name = name;
this.type = (type != null ? type : Type.UNDEFINED);
this.value = value;
+ this.alias = null;
// ok, check the name to see what type of binding we have
if (name.matches("\\$[0-9].*")) {
// $NNN references the method target or a parameter from 0 upwards
@@ -78,12 +79,16 @@
// anything else must be a variable introduced in the BINDS clause
index = BINDVAR;
}
- this.objectArrayIndex = 0;
+ this.callArrayIndex = 0;
}
public Type typeCheck(Type expected)
throws TypeException
{
+ if (alias != null) {
+ return alias.typeCheck(expected);
+ }
+
// value can be null if this is a rule method parameter
if (value != null) {
// type check the binding expression, using the bound variable's expected if it is known
@@ -112,7 +117,9 @@
public void compile(MethodVisitor mv, StackHeights currentStackHeights, StackHeights maxStackHeights) throws CompileException
{
- if (isBindVar()) {
+ if (alias != null) {
+ alias.compile(mv, currentStackHeights, maxStackHeights);
+ } else if (isBindVar()) {
int currentStack = currentStackHeights.stackCount;
// push the current helper instance i.e. this -- adds 1 to stack height
@@ -150,6 +157,9 @@
public Expression getValue()
{
+ if (alias != null) {
+ return alias.getValue();
+ }
return value;
}
@@ -163,6 +173,9 @@
public Type getType()
{
+ if (alias != null) {
+ return alias.getType();
+ }
return type;
}
@@ -171,18 +184,24 @@
this.type = type;
}
- public int getObjectArrayIndex()
+ public int getCallArrayIndex()
{
- return objectArrayIndex;
+ if (alias != null) {
+ return alias.getCallArrayIndex();
+ }
+ return callArrayIndex;
}
- public void setObjectArrayIndex(int objectArrayIndex)
+ public void setCallArrayIndex(int callArrayIndex)
{
- this.objectArrayIndex = objectArrayIndex;
+ this.callArrayIndex = callArrayIndex;
}
public int getLocalIndex()
{
+ if (alias != null) {
+ return alias.getLocalIndex();
+ }
return localIndex;
}
@@ -257,6 +276,26 @@
}
}
+
+ public void aliasTo(Binding alias)
+ {
+ if (this.isLocalVar()) {
+ this.alias = alias;
+ } else {
+ System.out.println("Binding : attempt to alias non-local var " + getName() + " to " + alias.getName());
+ }
+ }
+
+ public boolean isAlias()
+ {
+ return (alias != null);
+ }
+
+ public Binding getAlias()
+ {
+ return alias;
+ }
+
// special index values for non-positional parameters
private final static int HELPER = -1;
@@ -272,7 +311,8 @@
// values for other types of parameters.
private int index;
// the offset into the trigger method Object array of the initial value for this parameter
- private int objectArrayIndex;
+ private int callArrayIndex;
// the offset into the stack at which a local var is located
private int localIndex;
+ private Binding alias; // aliases $x to $n where x is a method parameter name and n its index in the parameter list
}
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/compiler/Compiler.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/compiler/Compiler.java 2009-08-14 07:08:11 UTC (rev 28930)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/compiler/Compiler.java 2009-08-14 10:17:43 UTC (rev 28931)
@@ -254,6 +254,18 @@
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/byteman/rule/binding/Binding", "getName", "()Ljava/lang/String;");
mv.visitVarInsn(ASTORE, 6);
+ // if (binding.isAlias())
+ mv.visitVarInsn(ALOAD, 5);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/byteman/rule/binding/Binding", "isAlias", "()Z");
+ Label l2a = new Label();
+ mv.visitJumpInsn(IFEQ, l2a);
+ // then
+ // binding = binding.getAlias();
+ mv.visitVarInsn(ALOAD, 5);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/byteman/rule/binding/Binding", "getAlias", "()Lorg/jboss/byteman/rule/binding/Binding;");
+ mv.visitVarInsn(ASTORE, 5);
+ // endif
+ mv.visitLabel(l2a);
// Type type = binding.getType();
mv.visitVarInsn(ALOAD, 5);
mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/byteman/rule/binding/Binding", "getType", "()Lorg/jboss/byteman/rule/type/Type;");
@@ -313,13 +325,13 @@
mv.visitJumpInsn(IFEQ, l4); // bypass this branch
mv.visitLabel(l6);
// then
- // bindingMap.put(name, args[binding.getObjectArrayIndex]);
+ // bindingMap.put(name, args[binding.getCallArrayIndex]);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, compiledHelperName, "bindingMap", "Ljava/util/HashMap;");
mv.visitVarInsn(ALOAD, 6);
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 5);
- mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/byteman/rule/binding/Binding", "getObjectArrayIndex", "()I");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/jboss/byteman/rule/binding/Binding", "getCallArrayIndex", "()I");
mv.visitInsn(AALOAD);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
mv.visitInsn(POP);
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/InterpretedHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/InterpretedHelper.java 2009-08-14 07:08:11 UTC (rev 28930)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/InterpretedHelper.java 2009-08-14 10:17:43 UTC (rev 28931)
@@ -81,6 +81,11 @@
while (iterator.hasNext()) {
Binding binding = iterator.next();
String name = binding.getName();
+ if (binding.isAlias()) {
+ // this is a local var used to refer to a method recipient or parameter
+ // so use the value and type associated with the alias
+ binding = binding.getAlias();
+ }
Type type = binding.getType();
if (binding.isHelper()) {
bindingMap.put(name, this);
@@ -89,7 +94,7 @@
bindingMap.put(name, recipient);
bindingTypeMap.put(name, type);
} else if (binding.isParam() || binding.isLocalVar()) {
- bindingMap.put(name, args[binding.getObjectArrayIndex()]);
+ bindingMap.put(name, args[binding.getCallArrayIndex()]);
bindingTypeMap.put(name, type);
}
}
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml 2009-08-14 07:08:11 UTC (rev 28930)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml 2009-08-14 10:17:43 UTC (rev 28931)
@@ -407,6 +407,27 @@
-->
<test name="org.jboss.byteman.tests.bugfixes.TestEnclosedSynchronizationPropagation"/>
</junit>
+ <junit fork="true" showoutput="true">
+ <classpath>
+ <pathelement location="${build.lib.dir}/byteman-tests.jar"/>
+ <pathelement location="${junit.home}/${junit.jar}"/>
+ </classpath>
+ <jvmarg value="-javaagent:${byteman.home}/${byteman.jar}=script:${scripts.dir}/bugfixes/TestMethodParamName.txt"/>
+ <!-- uncomment for verbose byteman output
+ <jvmarg value="-Dorg.jboss.byteman.verbose"/>
+ -->
+ <!-- uncomment to dump generated code
+ <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes"/>
+ <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes.directory=dump"/>
+ -->
+ <!-- uncomment to enable debug
+ <jvmarg value="-Xdebug"/>
+ <jvmarg value="-Xnoagent"/>
+ <jvmarg value="-Djava.compiler=NONE"/>
+ <jvmarg value="-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=5005"/>
+ -->
+ <test name="org.jboss.byteman.tests.bugfixes.TestMethodParamName"/>
+ </junit>
</target>
<target name="tests.bugfixes.compiled">
@@ -457,6 +478,27 @@
-->
<test name="org.jboss.byteman.tests.bugfixes.TestEnclosedSynchronizationPropagation"/>
</junit>
+ <junit fork="true" showoutput="true">
+ <classpath>
+ <pathelement location="${build.lib.dir}/byteman-tests.jar"/>
+ <pathelement location="${junit.home}/${junit.jar}"/>
+ </classpath>
+ <jvmarg value="-javaagent:${byteman.home}/${byteman.jar}=script:${scripts.dir}/bugfixes/TestMethodParamName.txt"/>
+ <jvmarg value="-Dorg.jboss.byteman.compileToBytecode"/>
+ <!-- uncomment for verbose byteman output
+ <jvmarg value="-Dorg.jboss.byteman.verbose"/>
+ -->
+ <!-- uncomment to dump generated code
+ <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes"/>
+ <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes.directory=dump"/>
+ -->
+ <!-- uncomment to enable debug
+ <jvmarg value="-Xdebug"/>
+ <jvmarg value="-Xnoagent"/>
+ <jvmarg value="-Djava.compiler=NONE"/>
+ <jvmarg value="-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=5005"/>
+ -->
+ <test name="org.jboss.byteman.tests.bugfixes.TestMethodParamName"/>
+ </junit>
</target>
-
</project>
Added: labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestMethodParamName.txt
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestMethodParamName.txt (rev 0)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestMethodParamName.txt 2009-08-14 10:17:43 UTC (rev 28931)
@@ -0,0 +1,34 @@
+##############################################################################
+# JBoss, Home of Professional Open Source
+# Copyright 2009, Red Hat Middleware LLC, and individual contributors
+# by the @authors tag. See the copyright.txt in the distribution for a
+# full listing of individual contributors.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this software; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+#
+# @authors Andrew Dinn
+#
+# Test for BYTEMAN-23 to ensure that a method parameter can be referred to
+# by its local variable name as well as using syntax $0, $1 etc
+
+RULE test use of method param names
+CLASS TestMethodParamName
+METHOD callWithNamedParams
+# HELPER org.jboss.byteman.tests.helpers.Default
+AT ENTRY
+IF TRUE
+DO test.log("injected foo() " + $this + " " + $bar + " " + $baz)
+ENDRULE
Added: labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestMethodParamName.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestMethodParamName.java (rev 0)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestMethodParamName.java 2009-08-14 10:17:43 UTC (rev 28931)
@@ -0,0 +1,62 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2009, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*
+* @authors Andrew Dinn
+*/
+package org.jboss.byteman.tests.bugfixes;
+
+import org.jboss.byteman.tests.Test;
+
+/**
+ * Test to check that a script can refer to a method parameter by its name as well as using the
+ * $N syntax.
+ */
+public class TestMethodParamName extends Test
+{
+ public TestMethodParamName()
+ {
+ super(TestMethodParamName.class.getCanonicalName());
+ }
+
+ public void test()
+ {
+ try {
+ callWithNamedParams("bar", "baz");
+ } catch (Exception e) {
+ log(e);
+ }
+
+ checkOutput();
+ }
+
+ public void callWithNamedParams(String bar, String baz)
+ {
+ log("inside foo() " + this + " " + bar + " " + baz);
+ }
+
+ @Override
+ public String getExpected() {
+ logExpected("injected foo() " + this + " bar baz");
+ logExpected("inside foo() " + this + " bar baz");
+
+ return super.getExpected();
+ }
+}
\ No newline at end of file
More information about the jboss-svn-commits
mailing list