From ac4db735b6f4d5b7d17f0b8d093b63b910c704bd Mon Sep 17 00:00:00 2001 From: aclement Date: Thu, 11 May 2006 07:29:59 +0000 Subject: [PATCH] 134471 - incremental structure model repair code overhaul - different strategy for tidying up relationships. --- asm/src/org/aspectj/asm/AsmManager.java | 483 ++++++++++++++++++------ 1 file changed, 370 insertions(+), 113 deletions(-) diff --git a/asm/src/org/aspectj/asm/AsmManager.java b/asm/src/org/aspectj/asm/AsmManager.java index bc63e881b..cd4051915 100644 --- a/asm/src/org/aspectj/asm/AsmManager.java +++ b/asm/src/org/aspectj/asm/AsmManager.java @@ -466,6 +466,28 @@ public class AsmManager { } } + private void dumprelsStderr(String key) { + System.err.println("Relationships dump follows: "+key); + IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap(); + int ctr = 1; + Set entries = irm.getEntries(); + for (Iterator iter = entries.iterator(); iter.hasNext();) { + String hid = (String) iter.next(); + List rels = irm.get(hid); + for (Iterator iterator = rels.iterator(); iterator.hasNext();) { + IRelationship ir = (IRelationship) iterator.next(); + List targets = ir.getTargets(); + for (Iterator iterator2 = targets.iterator(); + iterator2.hasNext(); + ) { + String thid = (String) iterator2.next(); + System.err.println("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid); + } + } + } + System.err.println("End of relationships dump for: "+key); + } + //===================== DELTA PROCESSING CODE ============== start ==========// // XXX shouldn't be aware of the delimiter @@ -473,6 +495,42 @@ public class AsmManager { return hid.substring(0,hid.indexOf("|")); } + /** + * Removes the hierarchy structure for the specified files from the structure model. + * Returns true if it deleted anything + */ + public boolean removeStructureModelForFiles(Writer fw,Collection files) throws IOException { + + IHierarchy model = AsmManager.getDefault().getHierarchy(); + + boolean modelModified = false; + + Set deletedNodes = new HashSet(); + for (Iterator iter = files.iterator(); iter.hasNext();) { + File fileForCompilation = (File) iter.next(); + String correctedPath = AsmManager.getDefault().getCanonicalFilePath(fileForCompilation); + IProgramElement progElem = (IProgramElement)model.findInFileMap(correctedPath); + if (progElem!=null) { + // Found it, let's remove it + if (dumpDeltaProcessing) { + fw.write("Deleting "+progElem+" node for file "+fileForCompilation+"\n"); + } + removeNode(progElem); + deletedNodes.add(getFilename(progElem.getHandleIdentifier())); + if (!model.removeFromFileMap(correctedPath.toString())) + throw new RuntimeException("Whilst repairing model, couldn't remove entry for file: "+correctedPath.toString()+" from the filemap"); + modelModified = true; + } + } + if (modelModified) model.updateHandleMap(deletedNodes); + return modelModified; + } + + private void flushModelCache() { + IHierarchy model = AsmManager.getDefault().getHierarchy(); + model.flushTypeMap(); + } + // This code is *SLOW* but it isnt worth fixing until we address the // bugs in binary weaving. public void fixupStructureModel(Writer fw,List filesToBeCompiled,Set files_added,Set files_deleted) throws IOException { @@ -512,7 +570,8 @@ public class AsmManager { } } - public void processDelta(List filesToBeCompiled,Set files_added,Set files_deleted) { + + public void processDelta(List files_tobecompiled,Set files_added,Set files_deleted) { try { Writer fw = null; @@ -522,148 +581,346 @@ public class AsmManager { FileWriter filew = new FileWriter(dumpFilename,true); fw = new BufferedWriter(filew); fw.write("=== Processing delta changes for the model ===\n"); - fw.write("Files for compilation:#"+filesToBeCompiled.size()+":"+filesToBeCompiled+"\n"); + fw.write("Files for compilation:#"+files_tobecompiled.size()+":"+files_tobecompiled+"\n"); fw.write("Files added :#"+files_added.size()+":"+files_added+"\n"); fw.write("Files deleted :#"+files_deleted.size()+":"+files_deleted+"\n"); } long stime = System.currentTimeMillis(); - fixupStructureModel(fw,filesToBeCompiled,files_added,files_deleted); + boolean modificationOccurred = false; + //fixupStructureModel(fw,filesToBeCompiled,files_added,files_deleted); + // Let's remove all the files that are deleted on this compile + modificationOccurred = + removeStructureModelForFiles(fw,files_deleted) | + modificationOccurred; long etime1 = System.currentTimeMillis(); // etime1-stime = time to fix up the model - IHierarchy model = AsmManager.getDefault().getHierarchy(); + repairRelationships(fw); + long etime2 = System.currentTimeMillis(); // etime2-stime = time to repair the relationship map + + modificationOccurred = + removeStructureModelForFiles(fw,files_tobecompiled) | + modificationOccurred; + + if (dumpDeltaProcessing) { + fw.write("===== Delta Processing timing ==========\n"); + fw.write("Hierarchy="+(etime1-stime)+"ms Relationshipmap="+(etime2-etime1)+"ms\n"); + fw.write("===== Traversal ========================\n"); +// fw.write("Source handles processed="+srchandlecounter+"\n"); +// fw.write("Target handles processed="+tgthandlecounter+"\n"); + fw.write("========================================\n"); + fw.flush();fw.close(); - // Some of this code relies on the fact that relationships are always in pairs, so you know - // if you are the target of a relationship because you are also the source of a relationship - // This seems a valid assumption for now... + } + reportModelInfo("After delta processing"); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + * two kinds of relationships + * + * A affects B + * B affectedBy A + * + * Both of these relationships are added when 'B' is modified. Concrete examples are + * 'advises/advisedby' or 'annotates/annotatedby'. + * + * What we need to do is when 'B' is going to be woven, remove all relationships that may + * reoccur when it is woven. + * So - remove 'affects' relationships where the target is 'B', remove all 'affectedBy' + * relationships where the source is 'B'. + * + */ + public void removeRelationshipsTargettingThisType(String typename) { + boolean debug=false; + if (debug) System.err.println(">>removeRelationshipsTargettingThisType "+typename); + String pkg = null; + String type= typename; + int lastSep = typename.lastIndexOf('.'); + if (lastSep != -1) { + pkg = typename.substring(0,lastSep); + type= typename.substring(lastSep+1); + } + boolean didsomething=false; + IProgramElement typeNode = hierarchy.findElementForType(pkg,type); - //TODO Speed this code up by making this assumption: - // the only piece of the handle that is interesting is the file name. We are working at file granularity, if the - // file does not exist (i.e. its not in the filemap) then any handle inside that file cannot exist. - if (dumpDeltaProcessing) fw.write("Repairing relationships map:\n"); + // Reasons for that being null: + // 1. the file has fundamental errors and so doesn't exist in the model (-proceedOnError probably forced us to weave) + if (typeNode == null) return; + + Set sourcesToRemove = new HashSet(); + + // Iterate over the source handles in the relationships map, the aim here is to remove any 'affected by' + // relationships where the source of the relationship is the specified type (since it will be readded + // when the type is woven) + Set sourcehandlesSet = mapper.getEntries(); + List relationshipsToRemove = new ArrayList(); + for (Iterator keyiter = sourcehandlesSet.iterator(); keyiter.hasNext();) { + String hid = (String) keyiter.next(); + IProgramElement sourceElement = hierarchy.getElement(hid); + if (sourceElement == null || sameType(hid,sourceElement,typeNode)) { + // worth continuing as there may be a relationship to remove + relationshipsToRemove.clear(); + List relationships = mapper.get(hid); + for (Iterator reliter = relationships.iterator();reliter.hasNext();) { + IRelationship rel = (IRelationship) reliter.next(); + if (rel.getKind()==IRelationship.Kind.USES_POINTCUT) continue; // these relationships are added at compile time, argh + if (rel.isAffects()) continue; // we want 'affected by' relationships - (e.g. advised by) + relationshipsToRemove.add(rel); // all the relationships can be removed, regardless of the target(s) + } + // Now, were any relationships emptied during that processing and so need removing for this source handle + if (relationshipsToRemove.size()>0) { + didsomething=true; + if (relationshipsToRemove.size() == relationships.size()) sourcesToRemove.add(hid); + else { + for (int i = 0 ;i0) { - // Are we removing *all* of the relationships for this source handle? - if (relationshipsToRemove.size() == relationships.size()) { - // We know they are all going to go, so just delete the source handle. - sourcesToRemove.add(hid); - } else { - for (int i = 0 ;i0) { + // Are we removing *all* of the relationships for this source handle? + if (relationshipsToRemove.size() == relationships.size()) sourcesToRemove.add(hid); + else { + for (int i = 0 ;i0) { + // Are we removing *all* of the relationships for this source handle? + if (relationshipsToRemove.size() == relationships.size()) { + // We know they are all going to go, so just delete the source handle. + sourcesToRemove.add(hid); + } else { + // MEMORY LEAK - we don't remove the relationships !! + for (int i = 0 ;i