+ // verify the existence of allocation sites and their
+ // shadows from the callee in the context of this caller graph
+ Iterator<AllocationSite> asItr = ogCallee.allocationSites.iterator();
+ while( asItr.hasNext() ) {
+ AllocationSite allocSite = asItr.next();
+ HeapRegionNode hrnSummary = getSummaryNode ( allocSite );
+
+ // assert that the shadow nodes have no reference edges
+ // because they're brand new to the graph, or last time
+ // they were used they should have been cleared of edges
+ HeapRegionNode hrnShadowSummary = getShadowSummaryNode( allocSite );
+ assert hrnShadowSummary.getNumReferencers() == 0;
+ assert hrnShadowSummary.getNumReferencees() == 0;
+ for( int i = 0; i < allocSite.getAllocationDepth(); ++i ) {
+ Integer idShadowIth = -(allocSite.getIthOldest(i));
+ assert id2hrn.containsKey(idShadowIth);
+ HeapRegionNode hrnShadowIth = id2hrn.get(idShadowIth);
+ assert hrnShadowIth.getNumReferencers() == 0;
+ assert hrnShadowIth.getNumReferencees() == 0;
+ }
+ }
+
+
+ // define rewrite rules and other structures to organize
+ // data by parameter/argument index
+ Hashtable<Integer, ReachabilitySet> paramIndex2rewriteH =
+ new Hashtable<Integer, ReachabilitySet>();
+
+ Hashtable<Integer, ReachabilitySet> paramIndex2rewriteJ =
+ new Hashtable<Integer, ReachabilitySet>();
+
+ Hashtable<Integer, ReachabilitySet> paramIndex2rewriteK =
+ new Hashtable<Integer, ReachabilitySet>();
+
+ Hashtable<Integer, ReachabilitySet> paramIndex2rewriteD =
+ new Hashtable<Integer, ReachabilitySet>();
+
+
+ Hashtable<TokenTuple, Integer> paramToken2paramIndex =
+ new Hashtable<TokenTuple, Integer>();
+
+ Hashtable<Integer, TokenTuple> paramIndex2paramToken =
+ new Hashtable<Integer, TokenTuple>();
+
+ Hashtable<TokenTuple, Integer> paramTokenStar2paramIndex =
+ new Hashtable<TokenTuple, Integer>();
+
+ Hashtable<Integer, TokenTuple> paramIndex2paramTokenStar =
+ new Hashtable<Integer, TokenTuple>();
+
+
+ Hashtable<Integer, LabelNode> paramIndex2ln =
+ new Hashtable<Integer, LabelNode>();
+
+
+ for( int i = 0; i < fm.numParameters(); ++i ) {
+ Integer paramIndex = new Integer( i );
+
+ assert ogCallee.paramIndex2id.containsKey( paramIndex );
+ Integer idParam = ogCallee.paramIndex2id.get( paramIndex );
+
+ assert ogCallee.id2hrn.containsKey( idParam );
+ HeapRegionNode hrnParam = ogCallee.id2hrn.get( idParam );
+ assert hrnParam != null;
+ paramIndex2rewriteH.put( paramIndex, hrnParam.getAlpha() );
+
+ ReferenceEdge edgeReflexive_i = hrnParam.getReferenceTo( hrnParam, null );
+ assert edgeReflexive_i != null;
+ paramIndex2rewriteJ.put( paramIndex, edgeReflexive_i.getBeta() );
+
+ TempDescriptor tdParamQ = ogCallee.paramIndex2tdQ.get( paramIndex );
+ assert tdParamQ != null;
+ LabelNode lnParamQ = ogCallee.td2ln.get( tdParamQ );
+ assert lnParamQ != null;
+ ReferenceEdge edgeSpecialQ_i = lnParamQ.getReferenceTo( hrnParam, null );
+ assert edgeSpecialQ_i != null;
+ paramIndex2rewriteK.put( paramIndex, edgeSpecialQ_i.getBeta() );
+
+ TokenTuple p_i = new TokenTuple( hrnParam.getID(),
+ true,
+ TokenTuple.ARITY_ONE ).makeCanonical();
+ paramToken2paramIndex.put( p_i, paramIndex );
+ paramIndex2paramToken.put( paramIndex, p_i );
+
+ TokenTuple p_i_star = new TokenTuple( hrnParam.getID(),
+ true,
+ TokenTuple.ARITY_MANY ).makeCanonical();
+ paramTokenStar2paramIndex.put( p_i_star, paramIndex );
+ paramIndex2paramTokenStar.put( paramIndex, p_i_star );
+
+ // now depending on whether the callee is static or not
+ // we need to account for a "this" argument in order to
+ // find the matching argument in the caller context
+ TempDescriptor argTemp_i;
+ if( isStatic ) {
+ argTemp_i = fc.getArg( paramIndex );
+ } else {
+ if( paramIndex == 0 ) {
+ argTemp_i = fc.getThis();
+ } else {
+ argTemp_i = fc.getArg( paramIndex - 1 );
+ }
+ }
+
+ // in non-static methods there is a "this" pointer
+ // that should be taken into account
+ if( isStatic ) {
+ assert fc.numArgs() == fm.numParameters();
+ } else {
+ assert fc.numArgs() + 1 == fm.numParameters();
+ }
+
+ LabelNode argLabel_i = getLabelNodeFromTemp( argTemp_i );
+ paramIndex2ln.put( paramIndex, argLabel_i );
+
+ ReachabilitySet D_i = new ReachabilitySet().makeCanonical();
+ Iterator<ReferenceEdge> edgeItr = argLabel_i.iteratorToReferencees();
+ while( edgeItr.hasNext() ) {
+ ReferenceEdge edge = edgeItr.next();
+ D_i = D_i.union( edge.getBeta() );
+ }
+ paramIndex2rewriteD.put( paramIndex, D_i );
+ }
+
+
+ Iterator lnArgItr = paramIndex2ln.entrySet().iterator();
+ while( lnArgItr.hasNext() ) {
+ Map.Entry me = (Map.Entry) lnArgItr.next();
+ Integer index = (Integer) me.getKey();
+ LabelNode lnArg_i = (LabelNode) me.getValue();
+
+ // rewrite alpha for the nodes reachable from argument label i
+ HashSet<HeapRegionNode> reachableNodes = new HashSet<HeapRegionNode>();
+ HashSet<HeapRegionNode> todoNodes = new HashSet<HeapRegionNode>();
+
+ // to find all reachable nodes, start with label referencees
+ Iterator<ReferenceEdge> edgeArgItr = lnArg_i.iteratorToReferencees();
+ while( edgeArgItr.hasNext() ) {
+ ReferenceEdge edge = edgeArgItr.next();
+ todoNodes.add( edge.getDst() );
+ }
+
+ // then follow links until all reachable nodes have been found
+ while( !todoNodes.isEmpty() ) {
+ HeapRegionNode hrn = todoNodes.iterator().next();
+ todoNodes.remove( hrn );
+ reachableNodes.add( hrn );
+
+ Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencees();
+ while( edgeItr.hasNext() ) {
+ ReferenceEdge edge = edgeItr.next();
+
+ if( !reachableNodes.contains( edge.getDst() ) ) {
+ todoNodes.add( edge.getDst() );
+ }
+ }
+ }
+
+ // now iterate over reachable nodes to update their alpha, and
+ // classify edges found as "argument reachable" or "upstream"
+ Iterator<HeapRegionNode> hrnItr = reachableNodes.iterator();
+ while( hrnItr.hasNext() ) {
+ HeapRegionNode hrn = hrnItr.next();
+
+ rewriteCallerNodeAlpha( index,
+ hrn,
+ paramIndex2rewriteH,
+ paramIndex2rewriteD,
+ paramIndex2paramToken,
+ paramTokenStar2paramIndex );
+ }
+ }
+
+
+
+
+
+ /*
+ // make a change set to translate callee tokens into caller tokens
+ ChangeTupleSet C = new ChangeTupleSet().makeCanonical();
+
+ for( int i = 0; i < fm.numParameters(); ++i ) {
+
+ Integer paramIndex = new Integer( i );
+
+ System.out.println( "In method "+fm+ " on param "+paramIndex );
+
+ assert ogCallee.paramIndex2id.containsKey( paramIndex );
+ Integer idParam = ogCallee.paramIndex2id.get( paramIndex );
+
+ assert ogCallee.id2hrn.containsKey( idParam );
+ HeapRegionNode hrnParam = ogCallee.id2hrn.get( idParam );
+ assert hrnParam != null;
+
+ TokenTupleSet calleeTokenToMatch =
+ new TokenTupleSet( new TokenTuple( hrnParam ) ).makeCanonical();
+
+
+ // now depending on whether the callee is static or not
+ // we need to account for a "this" argument in order to
+ // find the matching argument in the caller context
+ TempDescriptor argTemp;
+ if( isStatic ) {
+ argTemp = fc.getArg( paramIndex );
+ } else {
+ if( paramIndex == 0 ) {
+ argTemp = fc.getThis();
+ } else {
+ argTemp = fc.getArg( paramIndex - 1 );
+ }
+ }
+
+ LabelNode argLabel = getLabelNodeFromTemp( argTemp );
+ Iterator argHeapRegionsItr = argLabel.setIteratorToReferencedRegions();
+ while( argHeapRegionsItr.hasNext() ) {
+ Map.Entry meArg = (Map.Entry) argHeapRegionsItr.next();
+ HeapRegionNode argHeapRegion = (HeapRegionNode) meArg.getKey();
+ ReferenceEdgeProperties repArg = (ReferenceEdgeProperties) meArg.getValue();
+
+ Iterator<TokenTupleSet> ttsItr = repArg.getBeta().iterator();
+ while( ttsItr.hasNext() ) {
+ TokenTupleSet callerTokensToReplace = ttsItr.next();
+
+ ChangeTuple ct = new ChangeTuple( calleeTokenToMatch,
+ callerTokensToReplace ).makeCanonical();
+
+ C = C.union( ct );
+ }
+ }
+ }
+ */
+