+ ClearingSummary boundSet = new ClearingSummary();
+
+ // create mapping from arg idx to its heap paths
+ Hashtable<Integer, NTuple<Descriptor>> mapArgIdx2CallerArgHeapPath =
+ new Hashtable<Integer, NTuple<Descriptor>>();
+
+ // arg idx is starting from 'this' arg
+ NTuple<Descriptor> thisHeapPath = mapHeapPath.get(fc.getThis());
+ if (thisHeapPath == null) {
+ // method is called without creating new flat node representing 'this'
+ thisHeapPath = new NTuple<Descriptor>();
+ thisHeapPath.add(fc.getThis());
+ }
+
+ mapArgIdx2CallerArgHeapPath.put(Integer.valueOf(0), thisHeapPath);
+
+ for (int i = 0; i < fc.numArgs(); i++) {
+ TempDescriptor arg = fc.getArg(i);
+ NTuple<Descriptor> argHeapPath = computePath(arg);
+ mapArgIdx2CallerArgHeapPath.put(Integer.valueOf(i + 1), argHeapPath);
+ }
+
+ Hashtable<Integer, TempDescriptor> mapParamIdx2ParamTempDesc =
+ new Hashtable<Integer, TempDescriptor>();
+ for (int i = 0; i < calleeFlatMethod.numParameters(); i++) {
+ TempDescriptor param = calleeFlatMethod.getParameter(i);
+ mapParamIdx2ParamTempDesc.put(Integer.valueOf(i), param);
+ }
+
+ // binding caller's writing effects to callee's params
+ for (int i = 0; i < calleeFlatMethod.numParameters(); i++) {
+ NTuple<Descriptor> argHeapPath = mapArgIdx2CallerArgHeapPath.get(Integer.valueOf(i));
+ TempDescriptor calleeParamHeapPath = mapParamIdx2ParamTempDesc.get(Integer.valueOf(i));
+
+ // iterate over caller's writing effect set
+ Set<NTuple<Descriptor>> hpKeySet = curr.keySet();
+ for (Iterator iterator = hpKeySet.iterator(); iterator.hasNext();) {
+ NTuple<Descriptor> hpKey = (NTuple<Descriptor>) iterator.next();
+ // current element is reachable caller's arg
+ // so need to bind it to the caller's side and add it to the callee's
+ // init summary
+ if (hpKey.startsWith(argHeapPath)) {
+ NTuple<Descriptor> boundHeapPath = replace(hpKey, argHeapPath, calleeParamHeapPath);
+ boundSet.put(boundHeapPath, curr.get(hpKey).clone());
+ }
+
+ }
+
+ }
+
+ // contribute callee's complete summary into the caller's current summary
+ ClearingSummary calleeCompleteSummary =
+ mapMethodDescriptorToCompleteClearingSummary.get(calleeFlatMethod.getMethod());
+
+ if (calleeCompleteSummary != null) {
+ ClearingSummary boundCalleeEfffects = new ClearingSummary();
+ for (int i = 0; i < calleeFlatMethod.numParameters(); i++) {
+ NTuple<Descriptor> argHeapPath = mapArgIdx2CallerArgHeapPath.get(Integer.valueOf(i));
+ TempDescriptor calleeParamHeapPath = mapParamIdx2ParamTempDesc.get(Integer.valueOf(i));
+
+ // iterate over callee's writing effect set
+ Set<NTuple<Descriptor>> hpKeySet = calleeCompleteSummary.keySet();
+ for (Iterator iterator = hpKeySet.iterator(); iterator.hasNext();) {
+ NTuple<Descriptor> hpKey = (NTuple<Descriptor>) iterator.next();
+ // current element is reachable caller's arg
+ // so need to bind it to the caller's side and add it to the callee's
+ // init summary
+ if (hpKey.startsWith(calleeParamHeapPath)) {
+
+ NTuple<Descriptor> boundHeapPathForCaller = replace(hpKey, argHeapPath);
+
+ boundCalleeEfffects.put(boundHeapPathForCaller, calleeCompleteSummary.get(hpKey)
+ .clone());
+
+ }
+ }
+ }
+ possibleCalleeCompleteSummarySetToCaller.add(boundCalleeEfffects);
+ }
+
+ return boundSet;
+ }
+
+ private NTuple<Descriptor> replace(NTuple<Descriptor> hpKey, NTuple<Descriptor> argHeapPath) {
+
+ // replace the head of heap path with caller's arg path
+ // for example, heap path 'param.a.b' in callee's side will be replaced with
+ // (corresponding arg heap path).a.b for caller's side
+
+ NTuple<Descriptor> bound = new NTuple<Descriptor>();
+
+ for (int i = 0; i < argHeapPath.size(); i++) {
+ bound.add(argHeapPath.get(i));
+ }
+
+ for (int i = 1; i < hpKey.size(); i++) {
+ bound.add(hpKey.get(i));
+ }
+
+ return bound;
+ }
+
+ private NTuple<Descriptor> replace(NTuple<Descriptor> effectHeapPath,
+ NTuple<Descriptor> argHeapPath, TempDescriptor calleeParamHeapPath) {
+ // replace the head of caller's heap path with callee's param heap path
+
+ NTuple<Descriptor> boundHeapPath = new NTuple<Descriptor>();
+ boundHeapPath.add(calleeParamHeapPath);
+
+ for (int i = argHeapPath.size(); i < effectHeapPath.size(); i++) {
+ boundHeapPath.add(effectHeapPath.get(i));
+ }
+
+ return boundHeapPath;
+ }
+
+ private void computeReadSharedDescriptorSet() {
+ Set<MethodDescriptor> methodDescriptorsToAnalyze = new HashSet<MethodDescriptor>();
+ methodDescriptorsToAnalyze.addAll(ssjava.getAnnotationRequireSet());
+
+ for (Iterator iterator = methodDescriptorsToAnalyze.iterator(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+ FlatMethod fm = state.getMethodFlat(md);
+ computeReadSharedDescriptorSet_analyzeMethod(fm, md.equals(methodContainingSSJavaLoop));
+ }
+
+ }
+
+ private void computeReadSharedDescriptorSet_analyzeMethod(FlatMethod fm,
+ boolean onlyVisitSSJavaLoop) {
+
+ Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+ Set<FlatNode> visited = new HashSet<FlatNode>();
+
+ if (onlyVisitSSJavaLoop) {
+ flatNodesToVisit.add(ssjavaLoopEntrance);