#include "optimize.h" #include "junk.h" #include "TouchSet.h" bool debug_touch; static inline string S(const TouchSet *s) { if (s == NULL) return "NULL"; else return s->to_string(); } TouchSet *reads(const TreeNode *t, bool ignore_junk_method) { if (debug_touch) cout << "Compute reads(" << (ignore_junk_method ? "1" : "0") << "): " << pseudocode(t) << endl; if (isDummyNode(t) || t->absent() || (ignore_junk_method && is_junk_call(t))) return NULL; if (t->isExprNode()) return TouchSet_union(((ExprNode *) t)->mayRead(), ((ExprNode *) t)->mustRead()); TouchSet *s = NULL; foriter (i, t->allChildren(), TreeNode::ConstChildIter) s = TouchSet_union(s, reads(*i, ignore_junk_method)); if (debug_touch) cout << "Compute reads(" << (ignore_junk_method ? "1" : "0") << "): " << pseudocode(t) << " got " << S(s) << endl; return s; } TouchSet *writes(const TreeNode *t, bool ignore_junk_method) { if (isDummyNode(t) || t->absent() || t->isTypeNode() || (ignore_junk_method && is_junk_call(t))) return NULL; if (debug_touch) cout << "Compute writes(" << (ignore_junk_method ? "1" : "0") << "): " << pseudocode(t) << endl; if (t->isExprNode()) return TouchSet_union(((ExprNode *) t)->mayWrite(), ((ExprNode *) t)->mustWrite()); TouchSet *s = NULL; foriter (i, t->allChildren(), TreeNode::ConstChildIter) s = TouchSet_union(s, writes(*i, ignore_junk_method)); if (debug_touch) cout << "Compute writes(" << (ignore_junk_method ? "1" : "0") << "): " << pseudocode(t) << " got " << S(s) << endl; return s; } template static bool does_intersect(const set &x, const set &y) { for (TYPENAME set::const_iterator i = x.begin(); i != x.end(); i++) if (y.find(*i) != y.end()) return true; return false; } /* If check_arrays is false then ignore array/array conflicts (but always report array/unknown method conflicts). */ bool TouchSet_does_intersect(const TouchSet *x, const TouchSet *y, bool check_arrays) { #define YES do { result = true; goto done; } while (0) bool result = false; if (x != NULL && y != NULL) { if (x->unknownMethods && (y->unknownMethods || !y->field.empty() || !y->array.empty())) YES; if (y->unknownMethods && (!x->field.empty() || !x->array.empty())) YES; if (does_intersect(x->local, y->local)) YES; if (does_intersect(x->field_of_immutable_local, y->field_of_immutable_local)) YES; if (does_intersect(x->field, y->field)) YES; if (check_arrays && does_intersect(x->array, y->array)) YES; } done: if (debug_touch) cout << "does_intersect(\n" << S(x) << ",\n" << S(y) << ",\n" << (check_arrays ? '1' : '0') << "): " << (result ? '1' : '0') << '\n'; return result; #undef YES } /* Non-destructive. Never returns NULL. */ TouchSet * TouchSet_union(const TouchSet *t, const TouchSet *s) { // cout << "TouchSet_union()\n"; if (t == NULL && s == NULL) return new TouchSet(); bool free_t = false, free_s = false; if (t == NULL) { t = new TouchSet(); free_t = true; // cout << "t is NULL\n"; } if (s == NULL) { s = new TouchSet(); free_s = true; // cout << "s is NULL\n"; } TouchSet *z = new TouchSet(t->unknownMethods || s->unknownMethods); set_union(t->local.begin(), t->local.end(), s->local.begin(), s->local.end(), inserter(z->local, z->local.begin()), less()); set_union(t->field_of_immutable_local.begin(), t->field_of_immutable_local.end(), s->field_of_immutable_local.begin(), s->field_of_immutable_local.end(), inserter(z->field_of_immutable_local, z->field_of_immutable_local.begin()), less< pair >()); if (!z->unknownMethods) { set_union(t->field.begin(), t->field.end(), s->field.begin(), s->field.end(), inserter(z->field, z->field.begin()), less< pair >()); set_union(t->array.begin(), t->array.end(), s->array.begin(), s->array.end(), inserter(z->array, z->array.begin()), less()); } if (free_t) delete t; if (free_s) delete s; return z; }