/** merge multiple call chains from different contexts * */ public void merge(SourceCallChainInfo other) { if (method != other.method) throw new RuntimeException( "methods don't match: " + method + ", " + other.method + " " + method.equals(other.method) + " " + method.hashCode() + " " + other.method.hashCode()); if (contents.length == 0) { contents = other.contents; return; } else if (other.contents.length == 0) { return; } List<SourceCallChainInfo> ccis = new ArrayList<SourceCallChainInfo>(Arrays.asList(contents)); Map<SootMethod, SourceCallChainInfo> minfo = new HashMap<SootMethod, SourceCallChainInfo>(); for (SourceCallChainInfo cci : contents) minfo.put(cci.method, cci); for (SourceCallChainInfo other_cci : other.contents) { SourceCallChainInfo cci = minfo.get(other_cci.method); if (cci == null) ccis.add(other_cci); else cci.merge(other_cci); } if (contents.length == ccis.size()) logger.info("merge: {} old/new size = {}", method, ccis.size()); else logger.info("merge: {} orig {} elems, new {} elems", method, contents.length, ccis.size()); contents = ccis.toArray(new SourceCallChainInfo[0]); }
/** merge any duplicate method calls * */ public void merge_contents() { if (contents.length == 0) return; Arrays.sort(contents); List<SourceCallChainInfo> unique_calls = new ArrayList<SourceCallChainInfo>(); unique_calls.add(contents[0]); for (int ii = 1; ii < contents.length; ii++) { SourceCallChainInfo top = unique_calls.get(unique_calls.size() - 1); if (contents[ii].method == top.method) top.merge(contents[ii]); else unique_calls.add(contents[ii]); } logger.info( "merge_contents {}: old {} elems, new {} elems", method, contents.length, unique_calls.size()); contents = unique_calls.toArray(new SourceCallChainInfo[0]); }