+
+ return false;
+}
+
+void FuncNode::add_to_val_loc_map(uint64_t val, void * loc)
+{
+ loc_set_t * locations = val_loc_map->get(val);
+
+ if (locations == NULL) {
+ locations = new loc_set_t();
+ val_loc_map->put(val, locations);
+ }
+
+ update_loc_may_equal_map(loc, locations);
+ locations->add(loc);
+ // values_may_read_from->add(val);
+}
+
+void FuncNode::add_to_val_loc_map(value_set_t * values, void * loc)
+{
+ if (values == NULL)
+ return;
+
+ value_set_iter * it = values->iterator();
+ while (it->hasNext()) {
+ uint64_t val = it->next();
+ add_to_val_loc_map(val, loc);
+ }
+
+ delete it;
+}
+
+void FuncNode::update_loc_may_equal_map(void * new_loc, loc_set_t * old_locations)
+{
+ if ( old_locations->contains(new_loc) )
+ return;
+
+ loc_set_t * neighbors = loc_may_equal_map->get(new_loc);
+
+ if (neighbors == NULL) {
+ neighbors = new loc_set_t();
+ loc_may_equal_map->put(new_loc, neighbors);
+ }
+
+ loc_set_iter * loc_it = old_locations->iterator();
+ while (loc_it->hasNext()) {
+ // new_loc: { old_locations, ... }
+ void * member = loc_it->next();
+ neighbors->add(member);
+
+ // for each i in old_locations, i : { new_loc, ... }
+ loc_set_t * _neighbors = loc_may_equal_map->get(member);
+ if (_neighbors == NULL) {
+ _neighbors = new loc_set_t();
+ loc_may_equal_map->put(member, _neighbors);
+ }
+ _neighbors->add(new_loc);
+ }
+
+ delete loc_it;
+}
+
+bool FuncNode::likely_reads_from_null(ModelAction * read)
+{
+ uint64_t read_val = read->get_reads_from_value();
+ if ( (void *)(read_val && 0xffffffff) == NULL )
+ return true;
+
+ return false;
+}
+
+void FuncNode::set_predicate_tree_position(thread_id_t tid, Predicate * pred)
+{
+ int thread_id = id_to_int(tid);
+ ModelVector<Predicate *> * stack = thrd_predicate_tree_position[thread_id];
+ (*stack)[stack->size() - 1] = pred;
+}
+
+/* @return The position of a thread in a predicate tree */
+Predicate * FuncNode::get_predicate_tree_position(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ return thrd_predicate_tree_position[thread_id]->back();
+}
+
+void FuncNode::add_predicate_to_trace(thread_id_t tid, Predicate * pred)
+{
+ int thread_id = id_to_int(tid);
+ thrd_predicate_trace[thread_id]->back()->push_back(pred);
+}
+
+void FuncNode::init_marker(thread_id_t tid)
+{
+ marker++;
+
+ int thread_id = id_to_int(tid);
+ int old_size = thrd_markers.size();
+
+ if (old_size < thread_id + 1) {
+ thrd_markers.resize(thread_id + 1);
+
+ for (int i = old_size;i < thread_id + 1;i++) {
+ thrd_markers[i] = new ModelVector<uint32_t>();
+ thrd_recursion_depth.push_back(-1);
+ }
+ }
+
+ thrd_markers[thread_id]->push_back(marker);
+ thrd_recursion_depth[thread_id]++;
+}
+
+uint64_t FuncNode::get_associated_read(thread_id_t tid, FuncInst * inst)
+{
+ int thread_id = id_to_int(tid);
+ int recursion_depth = thrd_recursion_depth[thread_id];
+ uint marker = thrd_markers[thread_id]->back();
+
+ return inst->get_associated_read(tid, recursion_depth, marker);
+}
+
+/* Make sure elements of maps are initialized properly when threads enter functions */
+void FuncNode::init_local_maps(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ int old_size = thrd_loc_inst_maps.size();
+
+ if (old_size < thread_id + 1) {
+ int new_size = thread_id + 1;
+
+ thrd_loc_inst_maps.resize(new_size);
+ thrd_inst_id_maps.resize(new_size);
+ thrd_inst_pred_maps.resize(new_size);
+
+ for (int i = old_size;i < new_size;i++) {
+ thrd_loc_inst_maps[i] = new ModelVector<loc_inst_map_t *>;
+ thrd_inst_id_maps[i] = new ModelVector<inst_id_map_t *>;
+ thrd_inst_pred_maps[i] = new ModelVector<inst_pred_map_t *>;
+ }
+ }
+
+ ModelVector<loc_inst_map_t *> * map = thrd_loc_inst_maps[thread_id];
+ int index = thrd_recursion_depth[thread_id];
+
+ // If there are recursive calls, push more hashtables into the vector.
+ if (map->size() < (uint) index + 1) {
+ thrd_loc_inst_maps[thread_id]->push_back(new loc_inst_map_t(64));
+ thrd_inst_id_maps[thread_id]->push_back(new inst_id_map_t(64));
+ thrd_inst_pred_maps[thread_id]->push_back(new inst_pred_map_t(64));
+ }
+
+ ASSERT(map->size() == (uint) index + 1);
+}
+
+/* Reset elements of maps when threads exit functions */
+void FuncNode::reset_local_maps(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ int index = thrd_recursion_depth[thread_id];
+
+ // When recursive call ends, keep only one hashtable in the vector
+ if (index > 0) {
+ delete thrd_loc_inst_maps[thread_id]->back();
+ delete thrd_inst_id_maps[thread_id]->back();
+ delete thrd_inst_pred_maps[thread_id]->back();
+
+ thrd_loc_inst_maps[thread_id]->pop_back();
+ thrd_inst_id_maps[thread_id]->pop_back();
+ thrd_inst_pred_maps[thread_id]->pop_back();
+ } else {
+ thrd_loc_inst_maps[thread_id]->back()->reset();
+ thrd_inst_id_maps[thread_id]->back()->reset();
+ thrd_inst_pred_maps[thread_id]->back()->reset();
+ }
+}
+
+void FuncNode::init_predicate_tree_data_structure(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ int old_size = thrd_predicate_tree_position.size();
+
+ if (old_size < thread_id + 1) {
+ thrd_predicate_tree_position.resize(thread_id + 1);
+ thrd_predicate_trace.resize(thread_id + 1);
+
+ for (int i = old_size;i < thread_id + 1;i++) {
+ thrd_predicate_tree_position[i] = new ModelVector<Predicate *>();
+ thrd_predicate_trace[i] = new ModelVector<predicate_trace_t *>();
+ }
+ }
+
+ thrd_predicate_tree_position[thread_id]->push_back(predicate_tree_entry);
+ thrd_predicate_trace[thread_id]->push_back(new predicate_trace_t());
+}
+
+void FuncNode::reset_predicate_tree_data_structure(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ thrd_predicate_tree_position[thread_id]->pop_back();
+
+ // Free memories allocated in init_predicate_tree_data_structure
+ delete thrd_predicate_trace[thread_id]->back();
+ thrd_predicate_trace[thread_id]->pop_back();
+}
+
+/* Add FuncNodes that this node may follow */
+void FuncNode::add_out_edge(FuncNode * other)
+{
+ if ( !edge_table.contains(other) ) {
+ edge_table.put(other, OUT_EDGE);
+ out_edges.push_back(other);
+ return;
+ }
+
+ edge_type_t edge = edge_table.get(other);
+ if (edge == IN_EDGE) {
+ edge_table.put(other, BI_EDGE);
+ out_edges.push_back(other);
+ }
+}
+
+/* Compute the distance between this FuncNode and the target node.
+ * Return -1 if the target node is unreachable or the actual distance
+ * is greater than max_step.
+ */
+int FuncNode::compute_distance(FuncNode * target, int max_step)
+{
+ if (target == NULL)
+ return -1;
+ else if (target == this)
+ return 0;
+
+ // Be careful with memory
+ SnapList<FuncNode *> queue;
+ HashTable<FuncNode *, int, uintptr_t, 0> distances(128);
+
+ queue.push_back(this);
+ distances.put(this, 0);
+
+ while (!queue.empty()) {
+ FuncNode * curr = queue.front();
+ queue.pop_front();
+ int dist = distances.get(curr);
+
+ if (max_step <= dist)
+ return -1;
+
+ ModelList<FuncNode *> * outEdges = curr->get_out_edges();
+ mllnode<FuncNode *> * it;
+ for (it = outEdges->begin();it != NULL;it = it->getNext()) {
+ FuncNode * out_node = it->getVal();
+
+ /* This node has not been visited before */
+ if ( !distances.contains(out_node) ) {
+ if (out_node == target)
+ return dist + 1;
+
+ queue.push_back(out_node);
+ distances.put(out_node, dist + 1);
+ }
+ }
+ }
+
+ /* Target node is unreachable */
+ return -1;
+}
+
+void FuncNode::update_predicate_tree_weight(thread_id_t tid)
+{
+ predicate_trace_t * trace = thrd_predicate_trace[id_to_int(tid)]->back();
+
+ // Update predicate weights based on prediate trace
+ for (int i = trace->size() - 1;i >= 0;i--) {
+ Predicate * node = (*trace)[i];
+ ModelVector<Predicate *> * children = node->get_children();
+
+ if (children->size() == 0) {
+ double weight = 100.0 / sqrt(node->get_expl_count() + node->get_fail_count() + 1);
+ node->set_weight(weight);
+ } else {
+ double weight_sum = 0.0;
+ for (uint i = 0;i < children->size();i++) {
+ Predicate * child = (*children)[i];
+ double weight = child->get_weight();
+ weight_sum += weight;
+ }
+
+ double average_weight = (double) weight_sum / (double) children->size();
+ double weight = average_weight * pow(0.9, node->get_depth());
+ node->set_weight(weight);
+ }
+ }
+}
+
+void FuncNode::print_predicate_tree()
+{
+ model_print("digraph function_%s {\n", func_name);
+ predicate_tree_entry->print_pred_subtree();
+ predicate_tree_exit->print_predicate();
+ model_print("}\n"); // end of graph