return returnType;
}
- String toString(StringMaker sm) {
+ protected String createToString(StringMaker sm) {
//XXX this signature needs a lot of work
StringBuffer buf = new StringBuffer("ADVICE: ");
buf.append(sm.makeModifiersString(getModifiers()));
return parameterName;
}
- String toString(StringMaker sm) {
+ protected String createToString(StringMaker sm) {
return "catch(" + sm.makeTypeName(getParameterType()) + ")";
}
}
public String getName() { return "<init>"; }
- String toString(StringMaker sm) {
+ protected String createToString(StringMaker sm) {
StringBuffer buf = new StringBuffer();
buf.append(sm.makeModifiersString(getModifiers()));
buf.append(sm.makePrimaryTypeName(getDeclaringType(),getDeclaringTypeName()));
public SourceLocation makeSourceLoc(int line, int col)
{
- return new SourceLocationImpl(lexicalClass, this.filename, line, col);
+ return new SourceLocationImpl(lexicalClass, this.filename, line);
}
}
return fieldType;
}
- String toString(StringMaker sm) {
+ protected String createToString(StringMaker sm) {
StringBuffer buf = new StringBuffer();
buf.append(sm.makeModifiersString(getModifiers()));
if (sm.includeArgs) buf.append(sm.makeTypeName(getFieldType()));
return Modifier.isStatic(getModifiers()) ? "<clinit>": "<init>";
}
- String toString(StringMaker sm) {
+ protected String createToString(StringMaker sm) {
StringBuffer buf = new StringBuffer();
buf.append(sm.makeModifiersString(getModifiers()));
buf.append(sm.makePrimaryTypeName(getDeclaringType(),getDeclaringTypeName()));
return returnType;
}
- String toString(StringMaker sm) {
+ protected String createToString(StringMaker sm) {
StringBuffer buf = new StringBuffer();
buf.append(sm.makeModifiersString(getModifiers()));
if (sm.includeArgs) buf.append(sm.makeTypeName(getReturnType()));
import org.aspectj.lang.Signature;
+import java.lang.ref.SoftReference;
import java.util.Hashtable;
import java.util.StringTokenizer;
abstract class SignatureImpl implements Signature {
+
+ private static boolean useCache = true;
+
int modifiers = -1;
String name;
String declaringTypeName;
Class declaringType;
+ SoftReference toStringCacheRef;
SignatureImpl(int modifiers, String name, Class declaringType) {
this.modifiers = modifiers;
this.declaringType = declaringType;
}
- abstract String toString(StringMaker sm);
+ protected abstract String createToString (StringMaker sm);
+
+ /* Use a soft cache for the short, middle and long String representations */
+ String toString (StringMaker sm) {
+ String[] toStringCache = null;
+ if (toStringCacheRef == null || toStringCacheRef.get() == null) {
+ toStringCache = new String[3];
+ if (useCache) toStringCacheRef = new SoftReference(toStringCache);
+ }
+ else {
+ toStringCache = (String[])toStringCacheRef.get();
+ }
+
+ if (toStringCache[sm.cacheOffset] == null) {
+ toStringCache[sm.cacheOffset] = createToString(sm);
+ }
+ return toStringCache[sm.cacheOffset];
+ }
public final String toString() { return toString(StringMaker.middleStringMaker); }
public final String toShortString() { return toString(StringMaker.shortStringMaker); }
}
// lazy version
- String stringRep;
+ private String stringRep;
ClassLoader lookupClassLoader = null;
public void setLookupClassLoader(ClassLoader loader) {
for (int i = 0; i < N; i++) ret[i]= makeClass(st.nextToken());
return ret;
}
+
+ /*
+ * Used for testing
+ */
+ static void setUseCache (boolean b) {
+ useCache = b;
+ }
+
+ static boolean getUseCache () {
+ return useCache;
+ }
+
}
Class withinType;
String fileName;
int line;
- int column;
- SourceLocationImpl(Class withinType, String fileName, int line, int column) {
+ SourceLocationImpl(Class withinType, String fileName, int line) {
this.withinType = withinType;
this.fileName = fileName;
this.line = line;
- this.column = column;
}
public Class getWithinType() { return withinType; }
public String getFileName() { return fileName; }
public int getLine() { return line; }
- public int getColumn() { return column; }
+ public int getColumn() { return -1; }
public String toString() {
- return getFileName() + ":" + getLine() +
- ((getColumn() == -1) ? "" : ":" + getColumn());
+ return getFileName() + ":" + getLine();
}
}
boolean includeJoinPointTypeName = true;
boolean includeEnclosingPoint = true;
boolean shortKindName = true;
+ int cacheOffset;
static StringMaker shortStringMaker;
static {
shortStringMaker.includeJoinPointTypeName = false;
shortStringMaker.includeEnclosingPoint = false;
+ shortStringMaker.cacheOffset = 0;
}
static StringMaker middleStringMaker;
middleStringMaker.includeThrows = false;
middleStringMaker.includeModifiers = false;
middleStringMaker.shortPrimaryTypeNames = false;
+
+ shortStringMaker.cacheOffset = 1;
}
static StringMaker longStringMaker;
longStringMaker.includeModifiers = true;
longStringMaker.shortPrimaryTypeNames = false;
longStringMaker.shortKindName = false;
+
+ longStringMaker.cacheOffset = 2;
}
String makeKindName(String name) {
import org.aspectj.lang.*;
import org.aspectj.runtime.reflect.JoinPointImplTest;
+import org.aspectj.runtime.reflect.RuntimePerformanceTest;
import org.aspectj.runtime.reflect.SignatureTest;
import junit.framework.*;
TestSuite suite = new TestSuite(RuntimeModuleTests.class.getName());
suite.addTestSuite(RuntimeModuleTests.class); // minimum 1 test (testNothing)
suite.addTestSuite(SignatureTest.class);
- suite.addTestSuite(JoinPointImplTest.class);
+ suite.addTestSuite(JoinPointImplTest.class);
+ suite.addTestSuite(RuntimePerformanceTest.class);
return suite;
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Matthew Webster - initial implementation
+ *******************************************************************************/
+package org.aspectj.runtime.reflect;
+
+import java.lang.reflect.Method;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.aspectj.lang.Signature;
+
+import junit.framework.TestCase;
+
+public class RuntimePerformanceTest extends TestCase {
+
+ private static final Timer timer = new Timer(true);
+ private static final long TIMEOUT = 10000;
+ private static final long ITERATIONS = 1000000;
+ private static final long WARMUP_ITERATIONS = 10000;
+ private static final long EXPECTED_RATIO = 10;
+ private static final Factory factory = new Factory("RutimePerformanceTest.java",RuntimePerformanceTest.class);
+
+ private boolean savedUseCaches;
+ private Method method;
+ private Signature signature;
+
+ private TimerTask task;
+ private boolean abort;
+
+ public RuntimePerformanceTest(String name) {
+ super(name);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ /* Save default state */
+ savedUseCaches = SignatureImpl.getUseCache();
+
+ /* If a test takes too long we can kill it and fail */
+ abort = false;
+ task = new TimerTask() {
+ public void run () {
+ abort = true;
+ }
+ };
+ timer.schedule(task,TIMEOUT);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ /* Restore default state */
+ SignatureImpl.setUseCache(savedUseCaches);
+
+ task.cancel();
+ }
+
+ public void testToString () {
+ Signature signature = makeMethodSig("test");
+
+ SignatureImpl.setUseCache(false);
+ warmUp(signature);
+ long noCache = invokeSignatureToString(signature,ITERATIONS/EXPECTED_RATIO);
+ System.out.println("noCache=" + noCache);
+
+ SignatureImpl.setUseCache(true);
+ warmUp(signature);
+ long cache = invokeSignatureToString(signature,ITERATIONS);
+ System.out.println("cache=" + cache);
+
+ long ratio = (EXPECTED_RATIO*noCache/cache);
+ System.out.println("ratio=" + ratio);
+ assertTrue("Using cache should be " + EXPECTED_RATIO + " times faster: " + ratio,(ratio > EXPECTED_RATIO));
+ }
+
+ private long invokeSignatureToString (Signature sig, long iterations) {
+ long start = System.currentTimeMillis();
+ String s;
+
+ for (long l = 0; !abort && (l < iterations); l++) {
+ s = sig.toShortString();
+ s = sig.toString();
+ s = sig.toLongString();
+ }
+ if (abort) throw new RuntimeException("invokeSignatureToString aborted after " + (TIMEOUT/1000) + " seconds");
+
+ long finish = System.currentTimeMillis();
+ return (finish-start);
+ }
+
+ private void warmUp (Signature sig) {
+ invokeSignatureToString(sig,WARMUP_ITERATIONS);
+ }
+
+ private Signature makeMethodSig (String methodName) {
+ Class clazz = getClass();
+ Class[] parameterTypes = new Class[] { String.class };
+ String[] parameterNames = new String[] { "s" };
+ Class[] exceptionTypes = new Class[] {};
+ Class returnType = Void.TYPE;
+ return factory.makeMethodSig(1,methodName,clazz,parameterTypes,parameterNames,exceptionTypes,returnType);
+ }
+}
\ No newline at end of file
assertEquals(SignatureTest.class.getName(),fsi.getDeclaringTypeName());
assertSame(fsi.getDeclaringTypeName(),fsi.getDeclaringTypeName()); // should be cached.
}
+
+ public void testToShortMiddleLongString () {
+ MethodSignatureImpl msi = new MethodSignatureImpl(0,"test",SignatureTest.class,new Class[] { String.class, Integer.TYPE }, new String[] { "s", "i" }, new Class[] {}, Runnable.class);
+ String shortString = msi.toShortString();
+ assertSame(shortString,msi.toShortString()); // should be cached.
+ String middleString = msi.toString();
+ assertSame(middleString,msi.toString()); // should be cached.
+ String longString = msi.toLongString();
+ assertSame(longString,msi.toLongString()); // should be cached.
+ assertTrue("String representations should be different",!(shortString.equals(middleString) || middleString.equals(longString) || longString.equals(shortString)));
+ }
}