From: aclement Date: Tue, 25 Aug 2009 17:02:22 +0000 (+0000) Subject: stateless jdtlikehandleprovider so handles can optionally be cached now. Currently... X-Git-Tag: PRE_J5~9 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=64c613985aa8c128c1423af97d27d08fb6e074f7;p=aspectj.git stateless jdtlikehandleprovider so handles can optionally be cached now. Currently still cached --- diff --git a/asm/src/org/aspectj/asm/AsmManager.java b/asm/src/org/aspectj/asm/AsmManager.java index 423158951..0423fa1f7 100644 --- a/asm/src/org/aspectj/asm/AsmManager.java +++ b/asm/src/org/aspectj/asm/AsmManager.java @@ -83,9 +83,11 @@ public class AsmManager implements IStructureModel { // below to the AjState for a compilation and recover it if switching // between projects. protected IHierarchy hierarchy; - - /* Map from String > String - it maps absolute paths for - * inpath dirs/jars to workspace relative paths suitable for handle inclusion */ + + /* + * Map from String > String - it maps absolute paths for inpath dirs/jars to workspace relative paths suitable for handle + * inclusion + */ protected Map inpathMap; private IRelationshipMap mapper; private IElementHandleProvider handleProvider; @@ -654,16 +656,16 @@ public class AsmManager implements IStructureModel { } - private String getTypeNameFromHandle(String handle,Map cache) { - String typename = (String)cache.get(handle); - if (typename!=null) { + private String getTypeNameFromHandle(String handle, Map cache) { + String typename = (String) cache.get(handle); + if (typename != null) { return typename; } // inpath handle - but for which type? // let's do it the slow way, we can optimize this with a cache perhaps int hasPackage = handle.indexOf('<'); - int typeLocation = handle.indexOf('['); - if (typeLocation==-1) { + int typeLocation = handle.indexOf('['); + if (typeLocation == -1) { typeLocation = handle.indexOf('}'); } if (typeLocation == -1) { @@ -671,15 +673,16 @@ public class AsmManager implements IStructureModel { return ""; } StringBuffer qualifiedTypeNameFromHandle = new StringBuffer(); - if (hasPackage!=-1) { - qualifiedTypeNameFromHandle.append(handle.substring(hasPackage+1,handle.indexOf('(',hasPackage))); + if (hasPackage != -1) { + qualifiedTypeNameFromHandle.append(handle.substring(hasPackage + 1, handle.indexOf('(', hasPackage))); qualifiedTypeNameFromHandle.append('.'); } - qualifiedTypeNameFromHandle.append(handle.substring(typeLocation+1)); + qualifiedTypeNameFromHandle.append(handle.substring(typeLocation + 1)); typename = qualifiedTypeNameFromHandle.toString(); - cache.put(handle,typename); + cache.put(handle, typename); return typename; } + /** * two kinds of relationships * @@ -726,7 +729,7 @@ public class AsmManager implements IStructureModel { if (isPhantomHandle(hid)) { // inpath handle - but for which type? // TODO promote cache for reuse during one whole model update - if (!getTypeNameFromHandle(hid,handleToTypenameCache).equals(typename)) { + if (!getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) { continue; } } @@ -805,7 +808,7 @@ public class AsmManager implements IStructureModel { // they need removing for (Iterator targetsIter = targets.iterator(); targetsIter.hasNext();) { String targethid = (String) targetsIter.next(); - if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid,handleToTypenameCache).equals(typename)) { + if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) { continue; } // Does this point to the same type? @@ -910,13 +913,13 @@ public class AsmManager implements IStructureModel { } return (type.equals(containingType)); } - + /** * @param handle a JDT like handle, following the form described in AsmRelationshipProvider.findOrFakeUpNode * @return true if the handle contains ';' - the char indicating that it is a phantom handle */ private boolean isPhantomHandle(String handle) { - return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter())!=-1; + return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter()) != -1; } /** @@ -1307,7 +1310,208 @@ public class AsmManager implements IStructureModel { } public String getHandleElementForInpath(String binaryPath) { - return (String)inpathMap.get(new File(binaryPath)); + return (String) inpathMap.get(new File(binaryPath)); } + private List pieces = new ArrayList(); + + private Object intern(String substring) { + int lastIdx = -1; + if ((lastIdx = substring.lastIndexOf('/')) != -1) { + String pkg = substring.substring(0, lastIdx); + String type = substring.substring(lastIdx + 1); + pkg = internOneThing(pkg); + type = internOneThing(type); + return new String[] { pkg, type }; + } else { + return internOneThing(substring); + } + } + + private String internOneThing(String substring) { + // simple name + for (int p = 0, max = pieces.size(); p < max; p++) { + String s = (String) pieces.get(p); + if (s.equals(substring)) { + return s; + } + } + pieces.add(substring); + return substring; + } + + /** + * What we can rely on:
+ * - it is a method signature of the form (La/B;Lc/D;)LFoo;
+ * - there are no generics
+ * + * What we must allow for: - may use primitive refs (single chars rather than L) + */ +/* + public List compress(String s) { + int openParen = 0; + int closeParen = s.indexOf(')'); + int pos = 1; + List compressed = new ArrayList(); + // do the parens + while (pos < closeParen) { + char ch = s.charAt(pos); + if (ch == 'L') { + int idx = s.indexOf(';', pos); + compressed.add(intern(s.substring(pos + 1, idx))); + pos = idx + 1; + } else if (ch == '[') { + int x = pos; + while (s.charAt(++pos) == '[') + ; + // now pos will point at something not an array + compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[ + char ch2 = s.charAt(pos); + if (ch2 == 'L') { + int idx = s.indexOf(';', pos); + compressed.add(intern(s.substring(pos + 1, idx))); + pos = idx + 1; + } else if (ch2 == 'T') { + int idx = s.indexOf(';'); + compressed.add(intern(s.substring(pos, idx + 1))); // should be TT; + pos = idx + 1; + } else { + compressed.add(toCharacter(s.charAt(pos))); + pos++; + } + } else { + // it is a primitive ref (SVBCZJ) + compressed.add(toCharacter(ch)); + pos++; + } + } + // do the return type + pos++; + char ch = s.charAt(pos); + if (ch == 'L') { + int idx = s.indexOf(';', pos); + compressed.add(intern(s.substring(pos, idx))); + } else if (ch == '[') { + int x = pos; + while (s.charAt(++pos) == '[') + ; + // now pos will point at something not an array + compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[ + char ch2 = s.charAt(pos); + if (ch2 == 'L') { + int idx = s.indexOf(';', pos); + compressed.add(intern(s.substring(pos + 1, idx))); + pos = idx + 1; + } else if (ch2 == 'T') { + int idx = s.indexOf(';'); + compressed.add(intern(s.substring(pos, idx + 1))); // should be TT; + pos = idx + 2; + } else { + compressed.add(toCharacter(s.charAt(pos))); + pos++; + } + } else { + // it is a primitive ref (SVBCZJ) + compressed.add(new Character(ch)); + } + return compressed; + + // char delimiter = '/'; + // int pos = -1; + // List compressed = new ArrayList(); + // int start = 0; + // while ((pos = s.indexOf(delimiter, start)) != -1) { + // String part = s.substring(start, pos); + // int alreadyRecorded = pieces.indexOf(part); + // if (alreadyRecorded != -1) { + // compressed.add(new Integer(alreadyRecorded)); + // } else { + // compressed.add(new Integer(pieces.size())); + // pieces.add(part); + // } + // start = pos + 1; + // } + // // last piece + // String part = s.substring(start, s.length()); + // int alreadyRecorded = pieces.indexOf(part); + // if (alreadyRecorded != -1) { + // compressed.add(youkirtyounew Integer(alreadyRecorded)); + // } else { + // compressed.add(new Integer(pieces.size())); + // pieces.add(part); + // } + // return compressed; + } + + static final Character charB = new Character('B'); + static final Character charS = new Character('S'); + static final Character charI = new Character('I'); + static final Character charF = new Character('F'); + static final Character charD = new Character('D'); + static final Character charJ = new Character('J'); + static final Character charC = new Character('C'); + static final Character charV = new Character('V'); + static final Character charZ = new Character('Z'); + + private Character toCharacter(char ch) { + switch (ch) { + case 'B': + return charB; + case 'S': + return charS; + case 'I': + return charI; + case 'F': + return charF; + case 'D': + return charD; + case 'J': + return charJ; + case 'C': + return charC; + case 'V': + return charV; + case 'Z': + return charZ; + default: + throw new IllegalStateException(new Character(ch).toString()); + } + } + + public String decompress(List refs, char delimiter) { + StringBuilder result = new StringBuilder(); + result.append("("); + for (int i = 0, max = refs.size() - 1; i < max; i++) { + result.append(unintern(refs.get(i))); + } + result.append(")"); + result.append(unintern(refs.get(refs.size() - 1))); + return result.toString(); + } + + private String unintern(Object o) { + if (o instanceof Character) { + return ((Character) o).toString(); + } else if (o instanceof String[]) { + String[] strings = (String[]) o; + StringBuilder sb = new StringBuilder(); + sb.append('L'); + sb.append(strings[0]).append('/').append(strings[1]); + sb.append(';'); + return sb.toString(); + } else { // String + String so = (String) o; + if (so.endsWith(";")) { + // will be TT; + return so; + } else { + StringBuilder sb = new StringBuilder(); + sb.append('L'); + sb.append(so); + sb.append(';'); + return sb.toString(); + } + } + } + */ } diff --git a/asm/src/org/aspectj/asm/internal/JDTLikeHandleProvider.java b/asm/src/org/aspectj/asm/internal/JDTLikeHandleProvider.java index 2954f2780..8ab5a5af2 100644 --- a/asm/src/org/aspectj/asm/internal/JDTLikeHandleProvider.java +++ b/asm/src/org/aspectj/asm/internal/JDTLikeHandleProvider.java @@ -31,10 +31,6 @@ public class JDTLikeHandleProvider implements IElementHandleProvider { private final AsmManager asm; - // Need to keep our own count of the number of initializers - // because this information cannot be gained from the ipe. - private int initializerCounter = 0; - private static final char[] empty = new char[] {}; private static final char[] countDelim = new char[] { HandleProviderDelimiter.COUNT.getDelimiter() }; @@ -46,7 +42,6 @@ public class JDTLikeHandleProvider implements IElementHandleProvider { } public String createHandleIdentifier(IProgramElement ipe) { - // AjBuildManager.setupModel --> top of the tree is either // or the .lst file if (ipe == null || (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA) && ipe.getName().equals(""))) { @@ -284,7 +279,74 @@ public class JDTLikeHandleProvider implements IElementHandleProvider { return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray()); } } else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) { - return String.valueOf(++initializerCounter).toCharArray(); + // return String.valueOf(++initializerCounter).toCharArray(); + // Look at any peer advice + int count = 1; + List kids = ipe.getParent().getChildren(); + String ipeSig = ipe.getBytecodeSignature(); + // remove return type from the signature - it should not be included in the comparison + int idx = 0; + if (ipeSig != null && ((idx = ipeSig.indexOf(")")) != -1)) { + ipeSig = ipeSig.substring(0, idx); + } + if (ipeSig != null) { + if (ipeSig.indexOf("Lorg/aspectj/lang") != -1) { + if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) { + ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;")); + } + if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint;")) { + ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint;")); + } + if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) { + ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;")); + } + } + } + for (Iterator iterator = kids.iterator(); iterator.hasNext();) { + IProgramElement object = (IProgramElement) iterator.next(); + if (object.equals(ipe)) { + break; + } + if (object.getKind() == ipe.getKind()) { + if (object.getName().equals(ipe.getName())) { + String sig1 = object.getBytecodeSignature(); + if (sig1 != null && (idx = sig1.indexOf(")")) != -1) { + sig1 = sig1.substring(0, idx); + } + // this code needs a speed overhaul... and some proper tests + // Two static parts because one may be enclosing jpsp (269522) + if (sig1 != null) { + if (sig1.indexOf("Lorg/aspectj/lang") != -1) { + if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) { + sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;")); + } + if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint;")) { + sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint;")); + } + if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) { + sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;")); + } + } + } + + if (sig1 == null && ipeSig == null || (sig1 != null && sig1.equals(ipeSig))) { + String existingHandle = object.getHandleIdentifier(); + int suffixPosition = existingHandle.indexOf('!'); + if (suffixPosition != -1) { + count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1; + } else { + if (count == 1) { + count = 2; + } + } + } + } + } + } + // if (count > 1) { + return new Integer(count).toString().toCharArray(); + // return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray()); + // } } else if (ipe.getKind().equals(IProgramElement.Kind.CODE)) { int index = CharOperation.lastIndexOf('!', byteCodeName); if (index != -1) { @@ -419,8 +481,6 @@ public class JDTLikeHandleProvider implements IElementHandleProvider { } public void initialize() { - // reset the initializer count. This ensures we return the - // same handle as JDT for initializers. - initializerCounter = 0; + // nop } } diff --git a/asm/src/org/aspectj/asm/internal/ProgramElement.java b/asm/src/org/aspectj/asm/internal/ProgramElement.java index e9e6a9fb2..812518b09 100644 --- a/asm/src/org/aspectj/asm/internal/ProgramElement.java +++ b/asm/src/org/aspectj/asm/internal/ProgramElement.java @@ -305,12 +305,6 @@ public class ProgramElement implements IProgramElement { return s; } - public String getBytecodeSignature() { - String s = (String) kvpairs.get("bytecodeSignature"); - // if (s==null) return UNDEFINED; - return s; - } - public void setBytecodeName(String s) { if (kvpairs == Collections.EMPTY_MAP) kvpairs = new HashMap(); @@ -318,9 +312,36 @@ public class ProgramElement implements IProgramElement { } public void setBytecodeSignature(String s) { - if (kvpairs == Collections.EMPTY_MAP) - kvpairs = new HashMap(); + initMap(); + // Different kinds of format here. The one worth compressing starts with a '(': + // (La/b/c/D;Le/f/g/G;)Ljava/lang/String; + // maybe want to avoid generics initially. + // boolean worthCompressing = s.charAt(0) == '(' && s.indexOf('<') == -1 && s.indexOf('P') == -1; // starts parentheses and + // no + // // generics + // if (worthCompressing) { + // kvpairs.put("bytecodeSignatureCompressed", asm.compress(s)); + // } else { kvpairs.put("bytecodeSignature", s); + // } + } + + public String getBytecodeSignature() { + String s = (String) kvpairs.get("bytecodeSignature"); + // if (s == null) { + // List compressed = (List) kvpairs.get("bytecodeSignatureCompressed"); + // if (compressed != null) { + // return asm.decompress(compressed, '/'); + // } + // } + // if (s==null) return UNDEFINED; + return s; + } + + private void initMap() { + if (kvpairs == Collections.EMPTY_MAP) { + kvpairs = new HashMap(); + } } public String getSourceSignature() { @@ -566,18 +587,20 @@ public class ProgramElement implements IProgramElement { } public String getHandleIdentifier(boolean create) { + String h = handle; if (null == handle && create) { if (asm == null && name.equals("")) { - handle = ""; + h = ""; } else { try { - handle = asm.getHandleProvider().createHandleIdentifier(this); + h = asm.getHandleProvider().createHandleIdentifier(this); } catch (ArrayIndexOutOfBoundsException aioobe) { throw new RuntimeException("AIOOBE whilst building handle for " + this, aioobe); } } } - return handle; + setHandleIdentifier(h); + return h; } public void setHandleIdentifier(String handle) {