Mercurial > hg > graal-compiler
comparison src/share/vm/ci/ciTypeFlow.hpp @ 367:194b8e3a2fc4
6384206: Phis which are later unneeded are impairing our ability to inline based on static types
Reviewed-by: rasbold, jrose
author | never |
---|---|
date | Wed, 17 Sep 2008 12:59:52 -0700 |
parents | fa4d1d240383 |
children | eb28cf662f56 |
comparison
equal
deleted
inserted
replaced
366:8261ee795323 | 367:194b8e3a2fc4 |
---|---|
32 | 32 |
33 // information cached from the method: | 33 // information cached from the method: |
34 int _max_locals; | 34 int _max_locals; |
35 int _max_stack; | 35 int _max_stack; |
36 int _code_size; | 36 int _code_size; |
37 bool _has_irreducible_entry; | |
37 | 38 |
38 const char* _failure_reason; | 39 const char* _failure_reason; |
39 | 40 |
40 public: | 41 public: |
41 class StateVector; | 42 class StateVector; |
43 class Loop; | |
42 class Block; | 44 class Block; |
43 | 45 |
44 // Build a type flow analyzer | 46 // Build a type flow analyzer |
45 // Do an OSR analysis if osr_bci >= 0. | 47 // Do an OSR analysis if osr_bci >= 0. |
46 ciTypeFlow(ciEnv* env, ciMethod* method, int osr_bci = InvocationEntryBci); | 48 ciTypeFlow(ciEnv* env, ciMethod* method, int osr_bci = InvocationEntryBci); |
53 int start_bci() const { return is_osr_flow()? _osr_bci: 0; } | 55 int start_bci() const { return is_osr_flow()? _osr_bci: 0; } |
54 int max_locals() const { return _max_locals; } | 56 int max_locals() const { return _max_locals; } |
55 int max_stack() const { return _max_stack; } | 57 int max_stack() const { return _max_stack; } |
56 int max_cells() const { return _max_locals + _max_stack; } | 58 int max_cells() const { return _max_locals + _max_stack; } |
57 int code_size() const { return _code_size; } | 59 int code_size() const { return _code_size; } |
60 bool has_irreducible_entry() const { return _has_irreducible_entry; } | |
58 | 61 |
59 // Represents information about an "active" jsr call. This | 62 // Represents information about an "active" jsr call. This |
60 // class represents a call to the routine at some entry address | 63 // class represents a call to the routine at some entry address |
61 // with some distinct return address. | 64 // with some distinct return address. |
62 class JsrRecord : public ResourceObj { | 65 class JsrRecord : public ResourceObj { |
123 int size() const { return _set->length(); } | 126 int size() const { return _set->length(); } |
124 | 127 |
125 void print_on(outputStream* st) const PRODUCT_RETURN; | 128 void print_on(outputStream* st) const PRODUCT_RETURN; |
126 }; | 129 }; |
127 | 130 |
131 class LocalSet VALUE_OBJ_CLASS_SPEC { | |
132 private: | |
133 enum Constants { max = 63 }; | |
134 uint64_t _bits; | |
135 public: | |
136 LocalSet() : _bits(0) {} | |
137 void add(uint32_t i) { if (i < (uint32_t)max) _bits |= (1LL << i); } | |
138 void add(LocalSet* ls) { _bits |= ls->_bits; } | |
139 bool test(uint32_t i) const { return i < (uint32_t)max ? (_bits>>i)&1U : true; } | |
140 void clear() { _bits = 0; } | |
141 void print_on(outputStream* st, int limit) const PRODUCT_RETURN; | |
142 }; | |
143 | |
128 // Used as a combined index for locals and temps | 144 // Used as a combined index for locals and temps |
129 enum Cell { | 145 enum Cell { |
130 Cell_0, Cell_max = INT_MAX | 146 Cell_0, Cell_max = INT_MAX |
131 }; | 147 }; |
132 | 148 |
139 int _monitor_count; | 155 int _monitor_count; |
140 ciTypeFlow* _outer; | 156 ciTypeFlow* _outer; |
141 | 157 |
142 int _trap_bci; | 158 int _trap_bci; |
143 int _trap_index; | 159 int _trap_index; |
160 | |
161 LocalSet _def_locals; // For entire block | |
144 | 162 |
145 static ciType* type_meet_internal(ciType* t1, ciType* t2, ciTypeFlow* analyzer); | 163 static ciType* type_meet_internal(ciType* t1, ciType* t2, ciTypeFlow* analyzer); |
146 | 164 |
147 public: | 165 public: |
148 // Special elements in our type lattice. | 166 // Special elements in our type lattice. |
179 void set_stack_size(int ss) { _stack_size = ss; } | 197 void set_stack_size(int ss) { _stack_size = ss; } |
180 | 198 |
181 int monitor_count() const { return _monitor_count; } | 199 int monitor_count() const { return _monitor_count; } |
182 void set_monitor_count(int mc) { _monitor_count = mc; } | 200 void set_monitor_count(int mc) { _monitor_count = mc; } |
183 | 201 |
202 LocalSet* def_locals() { return &_def_locals; } | |
203 const LocalSet* def_locals() const { return &_def_locals; } | |
204 | |
184 static Cell start_cell() { return (Cell)0; } | 205 static Cell start_cell() { return (Cell)0; } |
185 static Cell next_cell(Cell c) { return (Cell)(((int)c) + 1); } | 206 static Cell next_cell(Cell c) { return (Cell)(((int)c) + 1); } |
186 Cell limit_cell() const { | 207 Cell limit_cell() const { |
187 return (Cell)(outer()->max_locals() + stack_size()); | 208 return (Cell)(outer()->max_locals() + stack_size()); |
188 } | 209 } |
246 bool is_float(ciType* type) const { | 267 bool is_float(ciType* type) const { |
247 return type->basic_type() == T_FLOAT; | 268 return type->basic_type() == T_FLOAT; |
248 } | 269 } |
249 bool is_double(ciType* type) const { | 270 bool is_double(ciType* type) const { |
250 return type->basic_type() == T_DOUBLE; | 271 return type->basic_type() == T_DOUBLE; |
272 } | |
273 | |
274 void store_to_local(int lnum) { | |
275 _def_locals.add((uint) lnum); | |
251 } | 276 } |
252 | 277 |
253 void push_translate(ciType* type); | 278 void push_translate(ciType* type); |
254 | 279 |
255 void push_int() { | 280 void push_int() { |
356 ciType* type = pop_value(); | 381 ciType* type = pop_value(); |
357 assert(is_reference(type) || type->is_return_address(), | 382 assert(is_reference(type) || type->is_return_address(), |
358 "must be reference type or return address"); | 383 "must be reference type or return address"); |
359 overwrite_local_double_long(index); | 384 overwrite_local_double_long(index); |
360 set_type_at(local(index), type); | 385 set_type_at(local(index), type); |
386 store_to_local(index); | |
361 } | 387 } |
362 | 388 |
363 void load_local_double(int index) { | 389 void load_local_double(int index) { |
364 ciType* type = type_at(local(index)); | 390 ciType* type = type_at(local(index)); |
365 ciType* type2 = type_at(local(index+1)); | 391 ciType* type2 = type_at(local(index+1)); |
374 assert(is_double(type), "must be double"); | 400 assert(is_double(type), "must be double"); |
375 assert(type2 == double2_type(), "must be 2nd half"); | 401 assert(type2 == double2_type(), "must be 2nd half"); |
376 overwrite_local_double_long(index); | 402 overwrite_local_double_long(index); |
377 set_type_at(local(index), type); | 403 set_type_at(local(index), type); |
378 set_type_at(local(index+1), type2); | 404 set_type_at(local(index+1), type2); |
405 store_to_local(index); | |
406 store_to_local(index+1); | |
379 } | 407 } |
380 | 408 |
381 void load_local_float(int index) { | 409 void load_local_float(int index) { |
382 ciType* type = type_at(local(index)); | 410 ciType* type = type_at(local(index)); |
383 assert(is_float(type), "must be float type"); | 411 assert(is_float(type), "must be float type"); |
386 void store_local_float(int index) { | 414 void store_local_float(int index) { |
387 ciType* type = pop_value(); | 415 ciType* type = pop_value(); |
388 assert(is_float(type), "must be float type"); | 416 assert(is_float(type), "must be float type"); |
389 overwrite_local_double_long(index); | 417 overwrite_local_double_long(index); |
390 set_type_at(local(index), type); | 418 set_type_at(local(index), type); |
419 store_to_local(index); | |
391 } | 420 } |
392 | 421 |
393 void load_local_int(int index) { | 422 void load_local_int(int index) { |
394 ciType* type = type_at(local(index)); | 423 ciType* type = type_at(local(index)); |
395 assert(is_int(type), "must be int type"); | 424 assert(is_int(type), "must be int type"); |
398 void store_local_int(int index) { | 427 void store_local_int(int index) { |
399 ciType* type = pop_value(); | 428 ciType* type = pop_value(); |
400 assert(is_int(type), "must be int type"); | 429 assert(is_int(type), "must be int type"); |
401 overwrite_local_double_long(index); | 430 overwrite_local_double_long(index); |
402 set_type_at(local(index), type); | 431 set_type_at(local(index), type); |
432 store_to_local(index); | |
403 } | 433 } |
404 | 434 |
405 void load_local_long(int index) { | 435 void load_local_long(int index) { |
406 ciType* type = type_at(local(index)); | 436 ciType* type = type_at(local(index)); |
407 ciType* type2 = type_at(local(index+1)); | 437 ciType* type2 = type_at(local(index+1)); |
416 assert(is_long(type), "must be long"); | 446 assert(is_long(type), "must be long"); |
417 assert(type2 == long2_type(), "must be 2nd half"); | 447 assert(type2 == long2_type(), "must be 2nd half"); |
418 overwrite_local_double_long(index); | 448 overwrite_local_double_long(index); |
419 set_type_at(local(index), type); | 449 set_type_at(local(index), type); |
420 set_type_at(local(index+1), type2); | 450 set_type_at(local(index+1), type2); |
451 store_to_local(index); | |
452 store_to_local(index+1); | |
421 } | 453 } |
422 | 454 |
423 // Stop interpretation of this path with a trap. | 455 // Stop interpretation of this path with a trap. |
424 void trap(ciBytecodeStream* str, ciKlass* klass, int index); | 456 void trap(ciBytecodeStream* str, ciKlass* klass, int index); |
425 | 457 |
448 void print_cell_on(outputStream* st, Cell c) const PRODUCT_RETURN; | 480 void print_cell_on(outputStream* st, Cell c) const PRODUCT_RETURN; |
449 void print_on(outputStream* st) const PRODUCT_RETURN; | 481 void print_on(outputStream* st) const PRODUCT_RETURN; |
450 }; | 482 }; |
451 | 483 |
452 // Parameter for "find_block" calls: | 484 // Parameter for "find_block" calls: |
453 // Describes the difference between a public and private copy. | 485 // Describes the difference between a public and backedge copy. |
454 enum CreateOption { | 486 enum CreateOption { |
455 create_public_copy, | 487 create_public_copy, |
456 create_private_copy, | 488 create_backedge_copy, |
457 no_create | 489 no_create |
490 }; | |
491 | |
492 // Successor iterator | |
493 class SuccIter : public StackObj { | |
494 private: | |
495 Block* _pred; | |
496 int _index; | |
497 Block* _succ; | |
498 public: | |
499 SuccIter() : _pred(NULL), _index(-1), _succ(NULL) {} | |
500 SuccIter(Block* pred) : _pred(pred), _index(-1), _succ(NULL) { next(); } | |
501 int index() { return _index; } | |
502 Block* pred() { return _pred; } // Return predecessor | |
503 bool done() { return _index < 0; } // Finished? | |
504 Block* succ() { return _succ; } // Return current successor | |
505 void next(); // Advance | |
506 void set_succ(Block* succ); // Update current successor | |
507 bool is_normal_ctrl() { return index() < _pred->successors()->length(); } | |
458 }; | 508 }; |
459 | 509 |
460 // A basic block | 510 // A basic block |
461 class Block : public ResourceObj { | 511 class Block : public ResourceObj { |
462 private: | 512 private: |
468 JsrSet* _jsrs; | 518 JsrSet* _jsrs; |
469 | 519 |
470 int _trap_bci; | 520 int _trap_bci; |
471 int _trap_index; | 521 int _trap_index; |
472 | 522 |
473 // A reasonable approximation to pre-order, provided.to the client. | 523 // pre_order, assigned at first visit. Used as block ID and "visited" tag |
474 int _pre_order; | 524 int _pre_order; |
475 | 525 |
476 // Has this block been cloned for some special purpose? | 526 // A post-order, used to compute the reverse post order (RPO) provided to the client |
477 bool _private_copy; | 527 int _post_order; // used to compute rpo |
528 | |
529 // Has this block been cloned for a loop backedge? | |
530 bool _backedge_copy; | |
478 | 531 |
479 // A pointer used for our internal work list | 532 // A pointer used for our internal work list |
480 Block* _next; | 533 Block* _next; |
481 bool _on_work_list; | 534 bool _on_work_list; // on the work list |
535 Block* _rpo_next; // Reverse post order list | |
536 | |
537 // Loop info | |
538 Loop* _loop; // nearest loop | |
539 bool _irreducible_entry; // entry to irreducible loop | |
540 bool _exception_entry; // entry to exception handler | |
482 | 541 |
483 ciBlock* ciblock() const { return _ciblock; } | 542 ciBlock* ciblock() const { return _ciblock; } |
484 StateVector* state() const { return _state; } | 543 StateVector* state() const { return _state; } |
485 | 544 |
486 // Compute the exceptional successors and types for this Block. | 545 // Compute the exceptional successors and types for this Block. |
502 // accessors | 561 // accessors |
503 ciTypeFlow* outer() const { return state()->outer(); } | 562 ciTypeFlow* outer() const { return state()->outer(); } |
504 int start() const { return _ciblock->start_bci(); } | 563 int start() const { return _ciblock->start_bci(); } |
505 int limit() const { return _ciblock->limit_bci(); } | 564 int limit() const { return _ciblock->limit_bci(); } |
506 int control() const { return _ciblock->control_bci(); } | 565 int control() const { return _ciblock->control_bci(); } |
507 | 566 JsrSet* jsrs() const { return _jsrs; } |
508 bool is_private_copy() const { return _private_copy; } | 567 |
509 void set_private_copy(bool z); | 568 bool is_backedge_copy() const { return _backedge_copy; } |
510 int private_copy_count() const { return outer()->private_copy_count(ciblock()->index(), _jsrs); } | 569 void set_backedge_copy(bool z); |
570 int backedge_copy_count() const { return outer()->backedge_copy_count(ciblock()->index(), _jsrs); } | |
511 | 571 |
512 // access to entry state | 572 // access to entry state |
513 int stack_size() const { return _state->stack_size(); } | 573 int stack_size() const { return _state->stack_size(); } |
514 int monitor_count() const { return _state->monitor_count(); } | 574 int monitor_count() const { return _state->monitor_count(); } |
515 ciType* local_type_at(int i) const { return _state->local_type_at(i); } | 575 ciType* local_type_at(int i) const { return _state->local_type_at(i); } |
516 ciType* stack_type_at(int i) const { return _state->stack_type_at(i); } | 576 ciType* stack_type_at(int i) const { return _state->stack_type_at(i); } |
577 | |
578 // Data flow on locals | |
579 bool is_invariant_local(uint v) const { | |
580 assert(is_loop_head(), "only loop heads"); | |
581 // Find outermost loop with same loop head | |
582 Loop* lp = loop(); | |
583 while (lp->parent() != NULL) { | |
584 if (lp->parent()->head() != lp->head()) break; | |
585 lp = lp->parent(); | |
586 } | |
587 return !lp->def_locals()->test(v); | |
588 } | |
589 LocalSet* def_locals() { return _state->def_locals(); } | |
590 const LocalSet* def_locals() const { return _state->def_locals(); } | |
517 | 591 |
518 // Get the successors for this Block. | 592 // Get the successors for this Block. |
519 GrowableArray<Block*>* successors(ciBytecodeStream* str, | 593 GrowableArray<Block*>* successors(ciBytecodeStream* str, |
520 StateVector* state, | 594 StateVector* state, |
521 JsrSet* jsrs); | 595 JsrSet* jsrs); |
522 GrowableArray<Block*>* successors() { | 596 GrowableArray<Block*>* successors() { |
523 assert(_successors != NULL, "must be filled in"); | 597 assert(_successors != NULL, "must be filled in"); |
524 return _successors; | 598 return _successors; |
525 } | 599 } |
526 | 600 |
527 // Helper function for "successors" when making private copies of | |
528 // loop heads for C2. | |
529 Block * clone_loop_head(ciTypeFlow* analyzer, | |
530 int branch_bci, | |
531 Block* target, | |
532 JsrSet* jsrs); | |
533 | |
534 // Get the exceptional successors for this Block. | 601 // Get the exceptional successors for this Block. |
535 GrowableArray<Block*>* exceptions() { | 602 GrowableArray<Block*>* exceptions() { |
536 if (_exceptions == NULL) { | 603 if (_exceptions == NULL) { |
537 compute_exceptions(); | 604 compute_exceptions(); |
538 } | 605 } |
582 | 649 |
583 void set_on_work_list(bool c) { _on_work_list = c; } | 650 void set_on_work_list(bool c) { _on_work_list = c; } |
584 bool is_on_work_list() const { return _on_work_list; } | 651 bool is_on_work_list() const { return _on_work_list; } |
585 | 652 |
586 bool has_pre_order() const { return _pre_order >= 0; } | 653 bool has_pre_order() const { return _pre_order >= 0; } |
587 void set_pre_order(int po) { assert(!has_pre_order() && po >= 0, ""); _pre_order = po; } | 654 void set_pre_order(int po) { assert(!has_pre_order(), ""); _pre_order = po; } |
588 int pre_order() const { assert(has_pre_order(), ""); return _pre_order; } | 655 int pre_order() const { assert(has_pre_order(), ""); return _pre_order; } |
656 void set_next_pre_order() { set_pre_order(outer()->inc_next_pre_order()); } | |
589 bool is_start() const { return _pre_order == outer()->start_block_num(); } | 657 bool is_start() const { return _pre_order == outer()->start_block_num(); } |
590 | 658 |
591 // A ranking used in determining order within the work list. | 659 // Reverse post order |
592 bool is_simpler_than(Block* other); | 660 void df_init(); |
661 bool has_post_order() const { return _post_order >= 0; } | |
662 void set_post_order(int po) { assert(!has_post_order() && po >= 0, ""); _post_order = po; } | |
663 void reset_post_order(int o){ _post_order = o; } | |
664 int post_order() const { assert(has_post_order(), ""); return _post_order; } | |
665 | |
666 bool has_rpo() const { return has_post_order() && outer()->have_block_count(); } | |
667 int rpo() const { assert(has_rpo(), ""); return outer()->block_count() - post_order() - 1; } | |
668 void set_rpo_next(Block* b) { _rpo_next = b; } | |
669 Block* rpo_next() { return _rpo_next; } | |
670 | |
671 // Loops | |
672 Loop* loop() const { return _loop; } | |
673 void set_loop(Loop* lp) { _loop = lp; } | |
674 bool is_loop_head() const { return _loop && _loop->head() == this; } | |
675 void set_irreducible_entry(bool c) { _irreducible_entry = c; } | |
676 bool is_irreducible_entry() const { return _irreducible_entry; } | |
677 bool is_visited() const { return has_pre_order(); } | |
678 bool is_post_visited() const { return has_post_order(); } | |
679 bool is_clonable_exit(Loop* lp); | |
680 Block* looping_succ(Loop* lp); // Successor inside of loop | |
681 bool is_single_entry_loop_head() const { | |
682 if (!is_loop_head()) return false; | |
683 for (Loop* lp = loop(); lp != NULL && lp->head() == this; lp = lp->parent()) | |
684 if (lp->is_irreducible()) return false; | |
685 return true; | |
686 } | |
593 | 687 |
594 void print_value_on(outputStream* st) const PRODUCT_RETURN; | 688 void print_value_on(outputStream* st) const PRODUCT_RETURN; |
595 void print_on(outputStream* st) const PRODUCT_RETURN; | 689 void print_on(outputStream* st) const PRODUCT_RETURN; |
690 }; | |
691 | |
692 // Loop | |
693 class Loop : public ResourceObj { | |
694 private: | |
695 Loop* _parent; | |
696 Loop* _sibling; // List of siblings, null terminated | |
697 Loop* _child; // Head of child list threaded thru sibling pointer | |
698 Block* _head; // Head of loop | |
699 Block* _tail; // Tail of loop | |
700 bool _irreducible; | |
701 LocalSet _def_locals; | |
702 | |
703 public: | |
704 Loop(Block* head, Block* tail) : | |
705 _head(head), _tail(tail), | |
706 _parent(NULL), _sibling(NULL), _child(NULL), | |
707 _irreducible(false), _def_locals() {} | |
708 | |
709 Loop* parent() const { return _parent; } | |
710 Loop* sibling() const { return _sibling; } | |
711 Loop* child() const { return _child; } | |
712 Block* head() const { return _head; } | |
713 Block* tail() const { return _tail; } | |
714 void set_parent(Loop* p) { _parent = p; } | |
715 void set_sibling(Loop* s) { _sibling = s; } | |
716 void set_child(Loop* c) { _child = c; } | |
717 void set_head(Block* hd) { _head = hd; } | |
718 void set_tail(Block* tl) { _tail = tl; } | |
719 | |
720 int depth() const; // nesting depth | |
721 | |
722 // Returns true if lp is a nested loop or us. | |
723 bool contains(Loop* lp) const; | |
724 bool contains(Block* blk) const { return contains(blk->loop()); } | |
725 | |
726 // Data flow on locals | |
727 LocalSet* def_locals() { return &_def_locals; } | |
728 const LocalSet* def_locals() const { return &_def_locals; } | |
729 | |
730 // Merge the branch lp into this branch, sorting on the loop head | |
731 // pre_orders. Returns the new branch. | |
732 Loop* sorted_merge(Loop* lp); | |
733 | |
734 // Mark non-single entry to loop | |
735 void set_irreducible(Block* entry) { | |
736 _irreducible = true; | |
737 entry->set_irreducible_entry(true); | |
738 } | |
739 bool is_irreducible() const { return _irreducible; } | |
740 | |
741 bool is_root() const { return _tail->pre_order() == max_jint; } | |
742 | |
743 void print(outputStream* st = tty, int indent = 0) const PRODUCT_RETURN; | |
744 }; | |
745 | |
746 // Postorder iteration over the loop tree. | |
747 class PostorderLoops : public StackObj { | |
748 private: | |
749 Loop* _root; | |
750 Loop* _current; | |
751 public: | |
752 PostorderLoops(Loop* root) : _root(root), _current(root) { | |
753 while (_current->child() != NULL) { | |
754 _current = _current->child(); | |
755 } | |
756 } | |
757 bool done() { return _current == NULL; } // Finished iterating? | |
758 void next(); // Advance to next loop | |
759 Loop* current() { return _current; } // Return current loop. | |
760 }; | |
761 | |
762 // Preorder iteration over the loop tree. | |
763 class PreorderLoops : public StackObj { | |
764 private: | |
765 Loop* _root; | |
766 Loop* _current; | |
767 public: | |
768 PreorderLoops(Loop* root) : _root(root), _current(root) {} | |
769 bool done() { return _current == NULL; } // Finished iterating? | |
770 void next(); // Advance to next loop | |
771 Loop* current() { return _current; } // Return current loop. | |
596 }; | 772 }; |
597 | 773 |
598 // Standard indexes of successors, for various bytecodes. | 774 // Standard indexes of successors, for various bytecodes. |
599 enum { | 775 enum { |
600 FALL_THROUGH = 0, // normal control | 776 FALL_THROUGH = 0, // normal control |
617 int _ciblock_count; | 793 int _ciblock_count; |
618 | 794 |
619 // Tells if a given instruction is able to generate an exception edge. | 795 // Tells if a given instruction is able to generate an exception edge. |
620 bool can_trap(ciBytecodeStream& str); | 796 bool can_trap(ciBytecodeStream& str); |
621 | 797 |
798 // Clone the loop heads. Returns true if any cloning occurred. | |
799 bool clone_loop_heads(Loop* lp, StateVector* temp_vector, JsrSet* temp_set); | |
800 | |
801 // Clone lp's head and replace tail's successors with clone. | |
802 Block* clone_loop_head(Loop* lp, StateVector* temp_vector, JsrSet* temp_set); | |
803 | |
622 public: | 804 public: |
623 // Return the block beginning at bci which has a JsrSet compatible | 805 // Return the block beginning at bci which has a JsrSet compatible |
624 // with jsrs. | 806 // with jsrs. |
625 Block* block_at(int bci, JsrSet* set, CreateOption option = create_public_copy); | 807 Block* block_at(int bci, JsrSet* set, CreateOption option = create_public_copy); |
626 | 808 |
627 // block factory | 809 // block factory |
628 Block* get_block_for(int ciBlockIndex, JsrSet* jsrs, CreateOption option = create_public_copy); | 810 Block* get_block_for(int ciBlockIndex, JsrSet* jsrs, CreateOption option = create_public_copy); |
629 | 811 |
630 // How many of the blocks have the private_copy bit set? | 812 // How many of the blocks have the backedge_copy bit set? |
631 int private_copy_count(int ciBlockIndex, JsrSet* jsrs) const; | 813 int backedge_copy_count(int ciBlockIndex, JsrSet* jsrs) const; |
632 | 814 |
633 // Return an existing block containing bci which has a JsrSet compatible | 815 // Return an existing block containing bci which has a JsrSet compatible |
634 // with jsrs, or NULL if there is none. | 816 // with jsrs, or NULL if there is none. |
635 Block* existing_block_at(int bci, JsrSet* set) { return block_at(bci, set, no_create); } | 817 Block* existing_block_at(int bci, JsrSet* set) { return block_at(bci, set, no_create); } |
636 | 818 |
649 return _next_pre_order; } | 831 return _next_pre_order; } |
650 Block* pre_order_at(int po) const { assert(0 <= po && po < block_count(), "out of bounds"); | 832 Block* pre_order_at(int po) const { assert(0 <= po && po < block_count(), "out of bounds"); |
651 return _block_map[po]; } | 833 return _block_map[po]; } |
652 Block* start_block() const { return pre_order_at(start_block_num()); } | 834 Block* start_block() const { return pre_order_at(start_block_num()); } |
653 int start_block_num() const { return 0; } | 835 int start_block_num() const { return 0; } |
836 Block* rpo_at(int rpo) const { assert(0 <= rpo && rpo < block_count(), "out of bounds"); | |
837 return _block_map[rpo]; } | |
838 int next_pre_order() { return _next_pre_order; } | |
839 int inc_next_pre_order() { return _next_pre_order++; } | |
654 | 840 |
655 private: | 841 private: |
656 // A work list used during flow analysis. | 842 // A work list used during flow analysis. |
657 Block* _work_list; | 843 Block* _work_list; |
658 | 844 |
845 // List of blocks in reverse post order | |
846 Block* _rpo_list; | |
847 | |
659 // Next Block::_pre_order. After mapping, doubles as block_count. | 848 // Next Block::_pre_order. After mapping, doubles as block_count. |
660 int _next_pre_order; | 849 int _next_pre_order; |
661 | 850 |
662 // Are there more blocks on the work list? | 851 // Are there more blocks on the work list? |
663 bool work_list_empty() { return _work_list == NULL; } | 852 bool work_list_empty() { return _work_list == NULL; } |
665 // Get the next basic block from our work list. | 854 // Get the next basic block from our work list. |
666 Block* work_list_next(); | 855 Block* work_list_next(); |
667 | 856 |
668 // Add a basic block to our work list. | 857 // Add a basic block to our work list. |
669 void add_to_work_list(Block* block); | 858 void add_to_work_list(Block* block); |
859 | |
860 // Prepend a basic block to rpo list. | |
861 void prepend_to_rpo_list(Block* blk) { | |
862 blk->set_rpo_next(_rpo_list); | |
863 _rpo_list = blk; | |
864 } | |
865 | |
866 // Root of the loop tree | |
867 Loop* _loop_tree_root; | |
670 | 868 |
671 // State used for make_jsr_record | 869 // State used for make_jsr_record |
672 int _jsr_count; | 870 int _jsr_count; |
673 GrowableArray<JsrRecord*>* _jsr_records; | 871 GrowableArray<JsrRecord*>* _jsr_records; |
674 | 872 |
675 public: | 873 public: |
676 // Make a JsrRecord for a given (entry, return) pair, if such a record | 874 // Make a JsrRecord for a given (entry, return) pair, if such a record |
677 // does not already exist. | 875 // does not already exist. |
678 JsrRecord* make_jsr_record(int entry_address, int return_address); | 876 JsrRecord* make_jsr_record(int entry_address, int return_address); |
877 | |
878 void set_loop_tree_root(Loop* ltr) { _loop_tree_root = ltr; } | |
879 Loop* loop_tree_root() { return _loop_tree_root; } | |
679 | 880 |
680 private: | 881 private: |
681 // Get the initial state for start_bci: | 882 // Get the initial state for start_bci: |
682 const StateVector* get_start_state(); | 883 const StateVector* get_start_state(); |
683 | 884 |
701 | 902 |
702 // Perform the type flow analysis, creating and cloning Blocks as | 903 // Perform the type flow analysis, creating and cloning Blocks as |
703 // necessary. | 904 // necessary. |
704 void flow_types(); | 905 void flow_types(); |
705 | 906 |
907 // Perform the depth first type flow analysis. Helper for flow_types. | |
908 void df_flow_types(Block* start, | |
909 bool do_flow, | |
910 StateVector* temp_vector, | |
911 JsrSet* temp_set); | |
912 | |
913 // Incrementally build loop tree. | |
914 void build_loop_tree(Block* blk); | |
915 | |
706 // Create the block map, which indexes blocks in pre_order. | 916 // Create the block map, which indexes blocks in pre_order. |
707 void map_blocks(); | 917 void map_blocks(); |
708 | 918 |
709 public: | 919 public: |
710 // Perform type inference flow analysis. | 920 // Perform type inference flow analysis. |
711 void do_flow(); | 921 void do_flow(); |
712 | 922 |
713 void print_on(outputStream* st) const PRODUCT_RETURN; | 923 void print_on(outputStream* st) const PRODUCT_RETURN; |
924 | |
925 void rpo_print_on(outputStream* st) const PRODUCT_RETURN; | |
714 }; | 926 }; |