+ 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);
+ }