4172f4175403ae5ffa6117d4ff5a40a0b85eedc0
[c11tester.git] / funcnode.cc
1 #include "action.h"
2 #include "history.h"
3 #include "funcnode.h"
4 #include "funcinst.h"
5 #include "predicate.h"
6 #include "concretepredicate.h"
7
8 #include "model.h"
9 #include <cmath>
10
11 FuncNode::FuncNode(ModelHistory * history) :
12         history(history),
13         exit_count(0),
14         marker(1),
15         func_inst_map(),
16         inst_list(),
17         entry_insts(),
18         inst_pred_map(128),
19         inst_id_map(128),
20         loc_act_map(128),
21         predicate_tree_position(),
22         predicate_leaves(),
23         leaves_tmp_storage(),
24         weight_debug_vec(),
25         failed_predicates(),
26         edge_table(32),
27         out_edges()
28 {
29         predicate_tree_entry = new Predicate(NULL, true);
30         predicate_tree_entry->add_predicate_expr(NOPREDICATE, NULL, true);
31
32         predicate_tree_exit = new Predicate(NULL, false, true);
33         predicate_tree_exit->set_depth(MAX_DEPTH);
34
35         /* Snapshot data structures below */
36         action_list_buffer = new SnapList<action_list_t *>();
37         read_locations = new loc_set_t();
38         write_locations = new loc_set_t();
39         val_loc_map = new HashTable<uint64_t, loc_set_t *, uint64_t, 0, snapshot_malloc, snapshot_calloc, snapshot_free, int64_hash>();
40         loc_may_equal_map = new HashTable<void *, loc_set_t *, uintptr_t, 0>();
41
42         //values_may_read_from = new value_set_t();
43 }
44
45 /* Reallocate snapshotted memories when new executions start */
46 void FuncNode::set_new_exec_flag()
47 {
48         action_list_buffer = new SnapList<action_list_t *>();
49         read_locations = new loc_set_t();
50         write_locations = new loc_set_t();
51         val_loc_map = new HashTable<uint64_t, loc_set_t *, uint64_t, 0, snapshot_malloc, snapshot_calloc, snapshot_free, int64_hash>();
52         loc_may_equal_map = new HashTable<void *, loc_set_t *, uintptr_t, 0>();
53
54         //values_may_read_from = new value_set_t();
55 }
56
57 /* Check whether FuncInst with the same type, position, and location
58  * as act has been added to func_inst_map or not. If not, add it.
59  */
60 void FuncNode::add_inst(ModelAction *act)
61 {
62         ASSERT(act);
63         const char * position = act->get_position();
64
65         /* THREAD* actions, ATOMIC_LOCK, ATOMIC_TRYLOCK, and ATOMIC_UNLOCK
66          * actions are not tagged with their source line numbers
67          */
68         if (position == NULL)
69                 return;
70
71         FuncInst * func_inst = func_inst_map.get(position);
72
73         /* This position has not been inserted into hashtable before */
74         if (func_inst == NULL) {
75                 func_inst = create_new_inst(act);
76                 func_inst_map.put(position, func_inst);
77                 return;
78         }
79
80         /* Volatile variables that use ++ or -- syntax may result in read and write actions with the same position */
81         if (func_inst->get_type() != act->get_type()) {
82                 FuncInst * collision_inst = func_inst->search_in_collision(act);
83
84                 if (collision_inst == NULL) {
85                         collision_inst = create_new_inst(act);
86                         func_inst->add_to_collision(collision_inst);
87                         return;
88                 } else {
89                         func_inst = collision_inst;
90                 }
91         }
92
93         ASSERT(func_inst->get_type() == act->get_type());
94         int curr_execution_number = model->get_execution_number();
95
96         /* Reset locations when new executions start */
97         if (func_inst->get_execution_number() != curr_execution_number) {
98                 func_inst->set_location(act->get_location());
99                 func_inst->set_execution_number(curr_execution_number);
100         }
101
102         /* Mark the memory location of such inst as not unique */
103         if (func_inst->get_location() != act->get_location())
104                 func_inst->not_single_location();
105 }
106
107 FuncInst * FuncNode::create_new_inst(ModelAction * act)
108 {
109         FuncInst * func_inst = new FuncInst(act, this);
110         int exec_num = model->get_execution_number();
111         func_inst->set_execution_number(exec_num);
112
113         inst_list.push_back(func_inst);
114
115         return func_inst;
116 }
117
118
119 /* Get the FuncInst with the same type, position, and location
120  * as act
121  *
122  * @return FuncInst with the same type, position, and location as act */
123 FuncInst * FuncNode::get_inst(ModelAction *act)
124 {
125         ASSERT(act);
126         const char * position = act->get_position();
127
128         /* THREAD* actions, ATOMIC_LOCK, ATOMIC_TRYLOCK, and ATOMIC_UNLOCK
129          * actions are not tagged with their source line numbers
130          */
131         if (position == NULL)
132                 return NULL;
133
134         FuncInst * inst = func_inst_map.get(position);
135         if (inst == NULL)
136                 return NULL;
137
138         action_type inst_type = inst->get_type();
139         action_type act_type = act->get_type();
140
141         if (inst_type == act_type) {
142                 return inst;
143         }
144         /* RMWRCAS actions are converted to RMW or READ actions */
145         else if (inst_type == ATOMIC_RMWRCAS &&
146                                          (act_type == ATOMIC_RMW || act_type == ATOMIC_READ)) {
147                 return inst;
148         }
149         /* Return the FuncInst in the collision list */
150         else {
151                 return inst->search_in_collision(act);
152         }
153 }
154
155
156 void FuncNode::add_entry_inst(FuncInst * inst)
157 {
158         if (inst == NULL)
159                 return;
160
161         mllnode<FuncInst *> * it;
162         for (it = entry_insts.begin();it != NULL;it = it->getNext()) {
163                 if (inst == it->getVal())
164                         return;
165         }
166
167         entry_insts.push_back(inst);
168 }
169
170 /**
171  * @brief Convert ModelAdtion list to FuncInst list
172  * @param act_list A list of ModelActions
173  */
174 void FuncNode::update_tree(action_list_t * act_list)
175 {
176         if (act_list == NULL || act_list->size() == 0)
177                 return;
178
179         HashTable<void *, value_set_t *, uintptr_t, 0> * write_history = history->getWriteHistory();
180
181         /* build inst_list from act_list for later processing */
182         func_inst_list_t inst_list;
183         action_list_t rw_act_list;
184
185         for (sllnode<ModelAction *> * it = act_list->begin();it != NULL;it = it->getNext()) {
186                 ModelAction * act = it->getVal();
187
188                 if (act->get_original_type() != ATOMIC_NOP && act->get_swap_flag() == false)
189                         act->use_original_type();
190
191                 // Remove func_act_ref so that actions can be deleted by Execution::collectActions
192                 if (act->is_read()) {
193                         // For every read or rmw actions in this list, the reads_from was marked, and not deleted.
194                         // So it is safe to call get_reads_from
195                         ModelAction * rf = act->get_reads_from();
196                         if (rf->get_original_type() != ATOMIC_NOP && rf->get_swap_flag() == false)
197                                 rf->use_original_type();
198
199                         rf->setFuncActRef(NULL);
200                 }
201                 act->setFuncActRef(NULL);
202
203                 FuncInst * func_inst = get_inst(act);
204                 void * loc = act->get_location();
205
206                 if (func_inst == NULL)
207                         continue;
208
209                 inst_list.push_back(func_inst);
210                 bool act_added = false;
211
212                 if (act->is_write()) {
213                         rw_act_list.push_back(act);
214                         act_added = true;
215                         if (!write_locations->contains(loc)) {
216                                 write_locations->add(loc);
217                                 history->update_loc_wr_func_nodes_map(loc, this);
218                         }
219                 }
220
221                 if (act->is_read()) {
222                         if (!act_added)
223                                 rw_act_list.push_back(act);
224
225                         /* If func_inst may only read_from a single location, then:
226                          *
227                          * The first time an action reads from some location,
228                          * import all the values that have been written to this
229                          * location from ModelHistory and notify ModelHistory
230                          * that this FuncNode may read from this location.
231                          */
232                         if (!read_locations->contains(loc) && func_inst->is_single_location()) {
233                                 read_locations->add(loc);
234                                 value_set_t * write_values = write_history->get(loc);
235                                 add_to_val_loc_map(write_values, loc);
236                                 history->update_loc_rd_func_nodes_map(loc, this);
237                         }
238                 }
239         }
240
241         update_inst_tree(&inst_list);
242         update_predicate_tree(&rw_act_list);
243
244         // Revert back action types and free
245         for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL;) {
246                 ModelAction * act = it->getVal();
247                 // Do iteration early in case we delete act
248                 it = it->getNext();
249
250                 // Revert back action types for actions whose types have been changed. 
251                 if (act->is_read()) {
252                         ModelAction * rf = act->get_reads_from();
253                         if (rf->get_swap_flag() == true)
254                                 rf->use_original_type();
255                 }
256
257                 if (act->get_swap_flag() == true)
258                         act->use_original_type();
259
260                 if (act->is_free()) {
261                         // TODO
262                 } else if (act->is_read()) {
263                         if (act->is_rmw()) {
264                                 // reads_from can not be READY_FREE
265                         } else {
266                                 ModelAction *rf = act->get_reads_from();
267                                 if (rf->is_free()) {
268                                         model_print("delete read %d; %p\n", act->get_seq_number(), act);
269                                         delete act;
270                                 }
271                         }
272                 }
273         }
274
275 //      print_predicate_tree();
276 }
277
278 /**
279  * @brief Link FuncInsts in inst_list  - add one FuncInst to another's predecessors and successors
280  * @param inst_list A list of FuncInsts
281  */
282 void FuncNode::update_inst_tree(func_inst_list_t * inst_list)
283 {
284         if (inst_list == NULL)
285                 return;
286         else if (inst_list->size() == 0)
287                 return;
288
289         /* start linking */
290         sllnode<FuncInst *>* it = inst_list->begin();
291         sllnode<FuncInst *>* prev;
292
293         /* add the first instruction to the list of entry insts */
294         FuncInst * entry_inst = it->getVal();
295         add_entry_inst(entry_inst);
296
297         it = it->getNext();
298         while (it != NULL) {
299                 prev = it->getPrev();
300
301                 FuncInst * prev_inst = prev->getVal();
302                 FuncInst * curr_inst = it->getVal();
303
304                 prev_inst->add_succ(curr_inst);
305                 curr_inst->add_pred(prev_inst);
306
307                 it = it->getNext();
308         }
309 }
310
311 void FuncNode::update_predicate_tree(action_list_t * act_list)
312 {
313         if (act_list == NULL || act_list->size() == 0)
314                 return;
315
316         incr_marker();
317         uint32_t inst_counter = 0;
318
319         // Clear hashtables
320         loc_act_map.reset();
321         inst_pred_map.reset();
322         inst_id_map.reset();
323
324         // Clear the set of leaves encountered in this path
325         leaves_tmp_storage.clear();
326
327         sllnode<ModelAction *> *it = act_list->begin();
328         Predicate * curr_pred = predicate_tree_entry;
329         while (it != NULL) {
330                 ModelAction * next_act = it->getVal();
331                 FuncInst * next_inst = get_inst(next_act);
332                 next_inst->set_associated_act(next_act, marker);
333
334                 Predicate * unset_predicate = NULL;
335                 bool branch_found = follow_branch(&curr_pred, next_inst, next_act, &unset_predicate);
336
337                 // A branch with unset predicate expression is detected
338                 if (!branch_found && unset_predicate != NULL) {
339                         bool amended = amend_predicate_expr(curr_pred, next_inst, next_act);
340                         if (amended)
341                                 continue;
342                         else {
343                                 curr_pred = unset_predicate;
344                                 branch_found = true;
345                         }
346                 }
347
348                 // Detect loops
349                 if (!branch_found && inst_id_map.contains(next_inst)) {
350                         FuncInst * curr_inst = curr_pred->get_func_inst();
351                         uint32_t curr_id = inst_id_map.get(curr_inst);
352                         uint32_t next_id = inst_id_map.get(next_inst);
353
354                         if (curr_id >= next_id) {
355                                 Predicate * old_pred = inst_pred_map.get(next_inst);
356                                 Predicate * back_pred = old_pred->get_parent();
357
358                                 // For updating weights
359                                 leaves_tmp_storage.push_back(curr_pred);
360
361                                 // Add to the set of backedges
362                                 curr_pred->add_backedge(back_pred);
363                                 curr_pred = back_pred;
364                                 continue;
365                         }
366                 }
367
368                 // Generate new branches
369                 if (!branch_found) {
370                         SnapVector<struct half_pred_expr *> half_pred_expressions;
371                         infer_predicates(next_inst, next_act, &half_pred_expressions);
372                         generate_predicates(curr_pred, next_inst, &half_pred_expressions);
373                         continue;
374                 }
375
376                 if (next_act->is_write())
377                         curr_pred->set_write(true);
378
379                 if (next_act->is_read()) {
380                         /* Only need to store the locations of read actions */
381                         loc_act_map.put(next_act->get_location(), next_act);
382                 }
383
384                 inst_pred_map.put(next_inst, curr_pred);
385                 if (!inst_id_map.contains(next_inst))
386                         inst_id_map.put(next_inst, inst_counter++);
387
388                 it = it->getNext();
389                 curr_pred->incr_expl_count();
390         }
391
392         if (curr_pred->get_exit() == NULL) {
393                 // Exit predicate is unset yet
394                 curr_pred->set_exit(predicate_tree_exit);
395         }
396
397         leaves_tmp_storage.push_back(curr_pred);
398         update_predicate_tree_weight();
399 }
400
401 /* Given curr_pred and next_inst, find the branch following curr_pred that
402  * contains next_inst and the correct predicate.
403  * @return true if branch found, false otherwise.
404  */
405 bool FuncNode::follow_branch(Predicate ** curr_pred, FuncInst * next_inst,
406                                                                                                                  ModelAction * next_act, Predicate ** unset_predicate)
407 {
408         /* Check if a branch with func_inst and corresponding predicate exists */
409         bool branch_found = false;
410         ModelVector<Predicate *> * branches = (*curr_pred)->get_children();
411         for (uint i = 0;i < branches->size();i++) {
412                 Predicate * branch = (*branches)[i];
413                 if (branch->get_func_inst() != next_inst)
414                         continue;
415
416                 /* Check against predicate expressions */
417                 bool predicate_correct = true;
418                 PredExprSet * pred_expressions = branch->get_pred_expressions();
419
420                 /* Only read and rmw actions my have unset predicate expressions */
421                 if (pred_expressions->getSize() == 0) {
422                         predicate_correct = false;
423                         if (*unset_predicate == NULL)
424                                 *unset_predicate = branch;
425                         else
426                                 ASSERT(false);
427
428                         continue;
429                 }
430
431                 PredExprSetIter * pred_expr_it = pred_expressions->iterator();
432                 while (pred_expr_it->hasNext()) {
433                         pred_expr * pred_expression = pred_expr_it->next();
434                         uint64_t last_read, next_read;
435                         bool equality;
436
437                         switch(pred_expression->token) {
438                         case NOPREDICATE:
439                                 predicate_correct = true;
440                                 break;
441                         case EQUALITY:
442                                 FuncInst * to_be_compared;
443                                 ModelAction * last_act;
444
445                                 to_be_compared = pred_expression->func_inst;
446                                 last_act = to_be_compared->get_associated_act(marker);
447
448                                 last_read = last_act->get_reads_from_value();
449                                 next_read = next_act->get_reads_from_value();
450                                 equality = (last_read == next_read);
451                                 if (equality != pred_expression->value)
452                                         predicate_correct = false;
453
454                                 break;
455                         case NULLITY:
456                                 next_read = next_act->get_reads_from_value();
457                                 // TODO: implement likely to be null
458                                 equality = ( (void*) (next_read & 0xffffffff) == NULL);
459                                 if (equality != pred_expression->value)
460                                         predicate_correct = false;
461                                 break;
462                         default:
463                                 predicate_correct = false;
464                                 model_print("unkown predicate token\n");
465                                 break;
466                         }
467                 }
468
469                 delete pred_expr_it;
470
471                 if (predicate_correct) {
472                         *curr_pred = branch;
473                         branch_found = true;
474                         break;
475                 }
476         }
477
478         return branch_found;
479 }
480
481 /* Infer predicate expressions, which are generated in FuncNode::generate_predicates */
482 void FuncNode::infer_predicates(FuncInst * next_inst, ModelAction * next_act,
483                                                                                                                                 SnapVector<struct half_pred_expr *> * half_pred_expressions)
484 {
485         void * loc = next_act->get_location();
486
487         if (next_inst->is_read()) {
488                 /* read + rmw */
489                 if ( loc_act_map.contains(loc) ) {
490                         ModelAction * last_act = loc_act_map.get(loc);
491                         FuncInst * last_inst = get_inst(last_act);
492                         struct half_pred_expr * expression = new half_pred_expr(EQUALITY, last_inst);
493                         half_pred_expressions->push_back(expression);
494                 } else if ( next_inst->is_single_location() ) {
495                         loc_set_t * loc_may_equal = loc_may_equal_map->get(loc);
496
497                         if (loc_may_equal != NULL) {
498                                 loc_set_iter * loc_it = loc_may_equal->iterator();
499                                 while (loc_it->hasNext()) {
500                                         void * neighbor = loc_it->next();
501                                         if (loc_act_map.contains(neighbor)) {
502                                                 ModelAction * last_act = loc_act_map.get(neighbor);
503                                                 FuncInst * last_inst = get_inst(last_act);
504
505                                                 struct half_pred_expr * expression = new half_pred_expr(EQUALITY, last_inst);
506                                                 half_pred_expressions->push_back(expression);
507                                         }
508                                 }
509
510                                 delete loc_it;
511                         }
512                 } else {
513                         // next_inst is not single location
514                         uint64_t read_val = next_act->get_reads_from_value();
515
516                         // only infer NULLITY predicate when it is actually NULL.
517                         if ( (void*)read_val == NULL) {
518                                 struct half_pred_expr * expression = new half_pred_expr(NULLITY, NULL);
519                                 half_pred_expressions->push_back(expression);
520                         }
521                 }
522         } else {
523                 /* Pure writes */
524                 // TODO: do anything here?
525         }
526 }
527
528 /* Able to generate complex predicates when there are multiple predciate expressions */
529 void FuncNode::generate_predicates(Predicate * curr_pred, FuncInst * next_inst,
530                                                                                                                                          SnapVector<struct half_pred_expr *> * half_pred_expressions)
531 {
532         if (half_pred_expressions->size() == 0) {
533                 Predicate * new_pred = new Predicate(next_inst);
534                 curr_pred->add_child(new_pred);
535                 new_pred->set_parent(curr_pred);
536
537                 /* Maintain predicate leaves */
538                 predicate_leaves.add(new_pred);
539                 predicate_leaves.remove(curr_pred);
540
541                 /* entry predicates and predicates containing pure write actions
542                  * have no predicate expressions */
543                 if ( curr_pred->is_entry_predicate() )
544                         new_pred->add_predicate_expr(NOPREDICATE, NULL, true);
545                 else if (next_inst->is_write()) {
546                         /* next_inst->is_write() <==> pure writes */
547                         new_pred->add_predicate_expr(NOPREDICATE, NULL, true);
548                 }
549
550                 return;
551         }
552
553         SnapVector<Predicate *> predicates;
554
555         struct half_pred_expr * half_expr = (*half_pred_expressions)[0];
556         predicates.push_back(new Predicate(next_inst));
557         predicates.push_back(new Predicate(next_inst));
558
559         predicates[0]->add_predicate_expr(half_expr->token, half_expr->func_inst, true);
560         predicates[1]->add_predicate_expr(half_expr->token, half_expr->func_inst, false);
561
562         for (uint i = 1;i < half_pred_expressions->size();i++) {
563                 half_expr = (*half_pred_expressions)[i];
564
565                 uint old_size = predicates.size();
566                 for (uint j = 0;j < old_size;j++) {
567                         Predicate * pred = predicates[j];
568                         Predicate * new_pred = new Predicate(next_inst);
569                         new_pred->copy_predicate_expr(pred);
570
571                         pred->add_predicate_expr(half_expr->token, half_expr->func_inst, true);
572                         new_pred->add_predicate_expr(half_expr->token, half_expr->func_inst, false);
573
574                         predicates.push_back(new_pred);
575                 }
576         }
577
578         for (uint i = 0;i < predicates.size();i++) {
579                 Predicate * pred= predicates[i];
580                 curr_pred->add_child(pred);
581                 pred->set_parent(curr_pred);
582
583                 /* Add new predicate leaves */
584                 predicate_leaves.add(pred);
585         }
586
587         /* Remove predicate node that has children */
588         predicate_leaves.remove(curr_pred);
589
590         /* Free memories allocated by infer_predicate */
591         for (uint i = 0;i < half_pred_expressions->size();i++) {
592                 struct half_pred_expr * tmp = (*half_pred_expressions)[i];
593                 snapshot_free(tmp);
594         }
595 }
596
597 /* Amend predicates that contain no predicate expressions. Currenlty only amend with NULLITY predicates */
598 bool FuncNode::amend_predicate_expr(Predicate * curr_pred, FuncInst * next_inst, ModelAction * next_act)
599 {
600         ModelVector<Predicate *> * children = curr_pred->get_children();
601
602         Predicate * unset_pred = NULL;
603         for (uint i = 0;i < children->size();i++) {
604                 Predicate * child = (*children)[i];
605                 if (child->get_func_inst() == next_inst) {
606                         unset_pred = child;
607                         break;
608                 }
609         }
610
611         uint64_t read_val = next_act->get_reads_from_value();
612
613         // only generate NULLITY predicate when it is actually NULL.
614         if ( !next_inst->is_single_location() && (void*)read_val == NULL ) {
615                 Predicate * new_pred = new Predicate(next_inst);
616
617                 curr_pred->add_child(new_pred);
618                 new_pred->set_parent(curr_pred);
619
620                 unset_pred->add_predicate_expr(NULLITY, NULL, false);
621                 new_pred->add_predicate_expr(NULLITY, NULL, true);
622
623                 return true;
624         }
625
626         return false;
627 }
628
629 void FuncNode::add_to_val_loc_map(uint64_t val, void * loc)
630 {
631         loc_set_t * locations = val_loc_map->get(val);
632
633         if (locations == NULL) {
634                 locations = new loc_set_t();
635                 val_loc_map->put(val, locations);
636         }
637
638         update_loc_may_equal_map(loc, locations);
639         locations->add(loc);
640         // values_may_read_from->add(val);
641 }
642
643 void FuncNode::add_to_val_loc_map(value_set_t * values, void * loc)
644 {
645         if (values == NULL)
646                 return;
647
648         value_set_iter * it = values->iterator();
649         while (it->hasNext()) {
650                 uint64_t val = it->next();
651                 add_to_val_loc_map(val, loc);
652         }
653
654         delete it;
655 }
656
657 void FuncNode::update_loc_may_equal_map(void * new_loc, loc_set_t * old_locations)
658 {
659         if ( old_locations->contains(new_loc) )
660                 return;
661
662         loc_set_t * neighbors = loc_may_equal_map->get(new_loc);
663
664         if (neighbors == NULL) {
665                 neighbors = new loc_set_t();
666                 loc_may_equal_map->put(new_loc, neighbors);
667         }
668
669         loc_set_iter * loc_it = old_locations->iterator();
670         while (loc_it->hasNext()) {
671                 // new_loc: { old_locations, ... }
672                 void * member = loc_it->next();
673                 neighbors->add(member);
674
675                 // for each i in old_locations, i : { new_loc, ... }
676                 loc_set_t * _neighbors = loc_may_equal_map->get(member);
677                 if (_neighbors == NULL) {
678                         _neighbors = new loc_set_t();
679                         loc_may_equal_map->put(member, _neighbors);
680                 }
681                 _neighbors->add(new_loc);
682         }
683
684         delete loc_it;
685 }
686
687 /* Every time a thread enters a function, set its position to the predicate tree entry */
688 void FuncNode::init_predicate_tree_position(thread_id_t tid)
689 {
690         int thread_id = id_to_int(tid);
691         if (predicate_tree_position.size() <= (uint) thread_id)
692                 predicate_tree_position.resize(thread_id + 1);
693
694         predicate_tree_position[thread_id] = predicate_tree_entry;
695 }
696
697 void FuncNode::set_predicate_tree_position(thread_id_t tid, Predicate * pred)
698 {
699         int thread_id = id_to_int(tid);
700         predicate_tree_position[thread_id] = pred;
701 }
702
703 /* @return The position of a thread in a predicate tree */
704 Predicate * FuncNode::get_predicate_tree_position(thread_id_t tid)
705 {
706         int thread_id = id_to_int(tid);
707         return predicate_tree_position[thread_id];
708 }
709
710 /* Make sure elements of thrd_inst_act_map are initialized properly when threads enter functions */
711 void FuncNode::init_inst_act_map(thread_id_t tid)
712 {
713         int thread_id = id_to_int(tid);
714         SnapVector<inst_act_map_t *> * thrd_inst_act_map = history->getThrdInstActMap(func_id);
715         uint old_size = thrd_inst_act_map->size();
716
717         if (thrd_inst_act_map->size() <= (uint) thread_id) {
718                 uint new_size = thread_id + 1;
719                 thrd_inst_act_map->resize(new_size);
720
721                 for (uint i = old_size;i < new_size;i++)
722                         (*thrd_inst_act_map)[i] = new inst_act_map_t(128);
723         }
724 }
725
726 /* Reset elements of thrd_inst_act_map when threads exit functions */
727 void FuncNode::reset_inst_act_map(thread_id_t tid)
728 {
729         int thread_id = id_to_int(tid);
730         SnapVector<inst_act_map_t *> * thrd_inst_act_map = history->getThrdInstActMap(func_id);
731
732         inst_act_map_t * map = (*thrd_inst_act_map)[thread_id];
733         map->reset();
734 }
735
736 void FuncNode::update_inst_act_map(thread_id_t tid, ModelAction * read_act)
737 {
738         int thread_id = id_to_int(tid);
739         SnapVector<inst_act_map_t *> * thrd_inst_act_map = history->getThrdInstActMap(func_id);
740
741         inst_act_map_t * map = (*thrd_inst_act_map)[thread_id];
742         FuncInst * read_inst = get_inst(read_act);
743         map->put(read_inst, read_act);
744 }
745
746 inst_act_map_t * FuncNode::get_inst_act_map(thread_id_t tid)
747 {
748         int thread_id = id_to_int(tid);
749         SnapVector<inst_act_map_t *> * thrd_inst_act_map = history->getThrdInstActMap(func_id);
750
751         return (*thrd_inst_act_map)[thread_id];
752 }
753
754 /* Add FuncNodes that this node may follow */
755 void FuncNode::add_out_edge(FuncNode * other)
756 {
757         if ( !edge_table.contains(other) ) {
758                 edge_table.put(other, OUT_EDGE);
759                 out_edges.push_back(other);
760                 return;
761         }
762
763         edge_type_t edge = edge_table.get(other);
764         if (edge == IN_EDGE) {
765                 edge_table.put(other, BI_EDGE);
766                 out_edges.push_back(other);
767         }
768 }
769
770 /* Compute the distance between this FuncNode and the target node.
771  * Return -1 if the target node is unreachable or the actual distance
772  * is greater than max_step.
773  */
774 int FuncNode::compute_distance(FuncNode * target, int max_step)
775 {
776         if (target == NULL)
777                 return -1;
778         else if (target == this)
779                 return 0;
780
781         SnapList<FuncNode *> queue;
782         HashTable<FuncNode *, int, uintptr_t, 0> distances(128);
783
784         queue.push_back(this);
785         distances.put(this, 0);
786
787         while (!queue.empty()) {
788                 FuncNode * curr = queue.front();
789                 queue.pop_front();
790                 int dist = distances.get(curr);
791
792                 if (max_step <= dist)
793                         return -1;
794
795                 ModelList<FuncNode *> * outEdges = curr->get_out_edges();
796                 mllnode<FuncNode *> * it;
797                 for (it = outEdges->begin();it != NULL;it = it->getNext()) {
798                         FuncNode * out_node = it->getVal();
799
800                         /* This node has not been visited before */
801                         if ( !distances.contains(out_node) ) {
802                                 if (out_node == target)
803                                         return dist + 1;
804
805                                 queue.push_back(out_node);
806                                 distances.put(out_node, dist + 1);
807                         }
808                 }
809         }
810
811         /* Target node is unreachable */
812         return -1;
813 }
814
815 void FuncNode::add_failed_predicate(Predicate * pred)
816 {
817         failed_predicates.add(pred);
818 }
819
820 /* Implement quick sort to sort leaves before assigning base scores */
821 template<typename _Tp>
822 static int partition(ModelVector<_Tp *> * arr, int low, int high)
823 {
824         unsigned int pivot = (*arr)[high] -> get_depth();
825         int i = low - 1;
826
827         for (int j = low;j <= high - 1;j ++) {
828                 if ( (*arr)[j] -> get_depth() < pivot ) {
829                         i ++;
830                         _Tp * tmp = (*arr)[i];
831                         (*arr)[i] = (*arr)[j];
832                         (*arr)[j] = tmp;
833                 }
834         }
835
836         _Tp * tmp = (*arr)[i + 1];
837         (*arr)[i + 1] = (*arr)[high];
838         (*arr)[high] = tmp;
839
840         return i + 1;
841 }
842
843 /* Implement quick sort to sort leaves before assigning base scores */
844 template<typename _Tp>
845 static void quickSort(ModelVector<_Tp *> * arr, int low, int high)
846 {
847         if (low < high) {
848                 int pi = partition(arr, low, high);
849
850                 quickSort(arr, low, pi - 1);
851                 quickSort(arr, pi + 1, high);
852         }
853 }
854
855 void FuncNode::assign_initial_weight()
856 {
857         PredSetIter * it = predicate_leaves.iterator();
858         leaves_tmp_storage.clear();
859
860         while (it->hasNext()) {
861                 Predicate * pred = it->next();
862                 double weight = 100.0 / sqrt(pred->get_expl_count() + pred->get_fail_count() + 1);
863                 pred->set_weight(weight);
864                 leaves_tmp_storage.push_back(pred);
865         }
866         delete it;
867
868         quickSort(&leaves_tmp_storage, 0, leaves_tmp_storage.size() - 1);
869
870         // assign scores for internal nodes;
871         while ( !leaves_tmp_storage.empty() ) {
872                 Predicate * leaf = leaves_tmp_storage.back();
873                 leaves_tmp_storage.pop_back();
874
875                 Predicate * curr = leaf->get_parent();
876                 while (curr != NULL) {
877                         if (curr->get_weight() != 0) {
878                                 // Has been exlpored
879                                 break;
880                         }
881
882                         ModelVector<Predicate *> * children = curr->get_children();
883                         double weight_sum = 0;
884                         bool has_unassigned_node = false;
885
886                         for (uint i = 0;i < children->size();i++) {
887                                 Predicate * child = (*children)[i];
888
889                                 // If a child has unassigned weight
890                                 double weight = child->get_weight();
891                                 if (weight == 0) {
892                                         has_unassigned_node = true;
893                                         break;
894                                 } else
895                                         weight_sum += weight;
896                         }
897
898                         if (!has_unassigned_node) {
899                                 double average_weight = (double) weight_sum / (double) children->size();
900                                 double weight = average_weight * pow(0.9, curr->get_depth());
901                                 curr->set_weight(weight);
902                         } else
903                                 break;
904
905                         curr = curr->get_parent();
906                 }
907         }
908 }
909
910 void FuncNode::update_predicate_tree_weight()
911 {
912         if (marker == 2) {
913                 // Predicate tree is initially built
914                 assign_initial_weight();
915                 return;
916         }
917
918         weight_debug_vec.clear();
919
920         PredSetIter * it = failed_predicates.iterator();
921         while (it->hasNext()) {
922                 Predicate * pred = it->next();
923                 leaves_tmp_storage.push_back(pred);
924         }
925         delete it;
926         failed_predicates.reset();
927
928         quickSort(&leaves_tmp_storage, 0, leaves_tmp_storage.size() - 1);
929         for (uint i = 0;i < leaves_tmp_storage.size();i++) {
930                 Predicate * pred = leaves_tmp_storage[i];
931                 double weight = 100.0 / sqrt(pred->get_expl_count() + pred->get_fail_count() + 1);
932                 pred->set_weight(weight);
933         }
934
935         // Update weights in internal nodes
936         while ( !leaves_tmp_storage.empty() ) {
937                 Predicate * leaf = leaves_tmp_storage.back();
938                 leaves_tmp_storage.pop_back();
939
940                 Predicate * curr = leaf->get_parent();
941                 while (curr != NULL) {
942                         ModelVector<Predicate *> * children = curr->get_children();
943                         double weight_sum = 0;
944                         bool has_unassigned_node = false;
945
946                         for (uint i = 0;i < children->size();i++) {
947                                 Predicate * child = (*children)[i];
948
949                                 double weight = child->get_weight();
950                                 if (weight != 0)
951                                         weight_sum += weight;
952                                 else if ( predicate_leaves.contains(child) ) {
953                                         // If this child is a leaf
954                                         double weight = 100.0 / sqrt(child->get_expl_count() + 1);
955                                         child->set_weight(weight);
956                                         weight_sum += weight;
957                                 } else {
958                                         has_unassigned_node = true;
959                                         weight_debug_vec.push_back(child);      // For debugging purpose
960                                         break;
961                                 }
962                         }
963
964                         if (!has_unassigned_node) {
965                                 double average_weight = (double) weight_sum / (double) children->size();
966                                 double weight = average_weight * pow(0.9, curr->get_depth());
967                                 curr->set_weight(weight);
968                         } else
969                                 break;
970
971                         curr = curr->get_parent();
972                 }
973         }
974
975         for (uint i = 0;i < weight_debug_vec.size();i++) {
976                 Predicate * tmp = weight_debug_vec[i];
977                 ASSERT( tmp->get_weight() != 0 );
978         }
979 }
980
981 void FuncNode::print_predicate_tree()
982 {
983         model_print("digraph function_%s {\n", func_name);
984         predicate_tree_entry->print_pred_subtree();
985         predicate_tree_exit->print_predicate();
986         model_print("}\n");     // end of graph
987 }