--- old/src/share/vm/c1/c1_CFGPrinter.cpp 2016-02-12 14:19:17.608824563 +0300 +++ new/src/share/vm/c1/c1_CFGPrinter.cpp 2016-02-12 14:19:17.536824566 +0300 @@ -63,7 +63,7 @@ void set_print_flags(bool do_print_HIR, bool do_print_LIR) { _do_print_HIR = do_print_HIR; _do_print_LIR = do_print_LIR; } void print_compilation(); - void print_intervals(IntervalList* intervals, const char* name); + void print_intervals(GrowableArray* intervals, const char* name); void print_state(BlockBegin* block); void print_operand(Value instr); @@ -99,7 +99,7 @@ } -void CFGPrinter::print_intervals(IntervalList* intervals, const char* name) { +void CFGPrinter::print_intervals(GrowableArray* intervals, const char* name) { output()->print_intervals(intervals, name); } @@ -368,7 +368,7 @@ -void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name) { +void CFGPrinterOutput::print_intervals(GrowableArray* intervals, const char* name) { print_begin("intervals"); print("name \"%s\"", name); --- old/src/share/vm/c1/c1_CFGPrinter.hpp 2016-02-12 14:19:17.868824554 +0300 +++ new/src/share/vm/c1/c1_CFGPrinter.hpp 2016-02-12 14:19:17.796824557 +0300 @@ -34,7 +34,7 @@ // compilation for later analysis. class CFGPrinterOutput; -class IntervalList; +class Interval; class CFGPrinter : public AllStatic { private: @@ -46,7 +46,7 @@ static void print_compilation(Compilation* compilation); static void print_cfg(BlockList* blocks, const char* name, bool do_print_HIR, bool do_print_LIR); static void print_cfg(IR* blocks, const char* name, bool do_print_HIR, bool do_print_LIR); - static void print_intervals(IntervalList* intervals, const char* name); + static void print_intervals(GrowableArray* intervals, const char* name); }; #endif --- old/src/share/vm/c1/c1_LinearScan.cpp 2016-02-12 14:19:18.124824545 +0300 +++ new/src/share/vm/c1/c1_LinearScan.cpp 2016-02-12 14:19:18.052824548 +0300 @@ -79,7 +79,7 @@ , _max_spills(0) , _unused_spill_slot(-1) , _intervals(0) // initialized later with correct length - , _new_intervals_from_allocation(new IntervalList()) + , _new_intervals_from_allocation(new GrowableArray()) , _sorted_intervals(NULL) , _needs_full_resort(false) , _lir_ops(0) // initialized later with correct length @@ -1257,7 +1257,7 @@ // initialize interval list with expected number of intervals // (32 is added to have some space for split children without having to resize the list) - _intervals = IntervalList(num_virtual_regs() + 32); + _intervals = GrowableArray(num_virtual_regs() + 32); // initialize all slots that are used by build_intervals _intervals.at_put_grow(num_virtual_regs() - 1, NULL, NULL); @@ -1434,42 +1434,74 @@ } #ifndef PRODUCT -bool LinearScan::is_sorted(IntervalArray* intervals) { +int interval_cmp(Interval* const& l, Interval* const& r) { + return l->from() - r->from(); +} + +bool find_interval(Interval* interval, GrowableArray* intervals) { + bool found; + int idx = intervals->find_sorted(interval, found); + + if (!found) { + return false; + } + + int from = interval->from(); + + // The index we've found using binary search is pointing to an interval + // that is defined in the same place as the interval we were looking for. + // So now we have to look around that index and find exact interval. + for (int i = idx; i >= 0; i--) { + if (intervals->at(i) == interval) { + return true; + } + if (intervals->at(i)->from() != from) { + break; + } + } + + for (int i = idx + 1; i < intervals->length(); i++) { + if (intervals->at(i) == interval) { + return true; + } + if (intervals->at(i)->from() != from) { + break; + } + } + + return false; +} + +bool LinearScan::is_sorted(GrowableArray* intervals) { int from = -1; - int i, j; - for (i = 0; i < intervals->length(); i ++) { + int null_count = 0; + + for (int i = 0; i < intervals->length(); i++) { Interval* it = intervals->at(i); if (it != NULL) { - if (from > it->from()) { - assert(false, ""); - return false; - } + assert(from <= it->from(), "Intervals are unordered"); from = it->from(); + } else { + null_count++; } } - // check in both directions if sorted list and unsorted list contain same intervals - for (i = 0; i < interval_count(); i++) { - if (interval_at(i) != NULL) { - int num_found = 0; - for (j = 0; j < intervals->length(); j++) { - if (interval_at(i) == intervals->at(j)) { - num_found++; - } - } - assert(num_found == 1, "lists do not contain same intervals"); - } - } - for (j = 0; j < intervals->length(); j++) { - int num_found = 0; - for (i = 0; i < interval_count(); i++) { - if (interval_at(i) == intervals->at(j)) { - num_found++; - } + assert(null_count == 0, "Sorted intervals should not contain nulls"); + + null_count = 0; + + for (int i = 0; i < interval_count(); i++) { + Interval* interval = interval_at(i); + if (interval != NULL) { + assert(find_interval(interval, intervals), "Lists do not contain same intervals"); + } else { + null_count++; } - assert(num_found == 1, "lists do not contain same intervals"); } + assert(interval_count() - null_count == intervals->length(), + "Sorted list should contain the same amount of non-NULL intervals as unsorted list"); + return true; } #endif @@ -1523,7 +1555,7 @@ _needs_full_resort = false; } - IntervalList* unsorted_list = &_intervals; + GrowableArray* unsorted_list = &_intervals; int unsorted_len = unsorted_list->length(); int sorted_len = 0; int unsorted_idx; @@ -1536,7 +1568,7 @@ sorted_len++; } } - IntervalArray* sorted_list = new IntervalArray(sorted_len); + GrowableArray* sorted_list = new GrowableArray(sorted_len, sorted_len, NULL); // special sorting algorithm: the original interval-list is almost sorted, // only some intervals are swapped. So this is much faster than a complete QuickSort @@ -1574,8 +1606,8 @@ _needs_full_resort = false; } - IntervalArray* old_list = _sorted_intervals; - IntervalList* new_list = _new_intervals_from_allocation; + GrowableArray* old_list = _sorted_intervals; + GrowableArray* new_list = _new_intervals_from_allocation; int old_len = old_list->length(); int new_len = new_list->length(); @@ -1589,7 +1621,8 @@ new_list->sort(interval_cmp); // merge old and new list (both already sorted) into one combined list - IntervalArray* combined_list = new IntervalArray(old_len + new_len); + int combined_list_len = old_len + new_len; + GrowableArray* combined_list = new GrowableArray(combined_list_len, combined_list_len, NULL); int old_idx = 0; int new_idx = 0; @@ -3395,19 +3428,19 @@ int state_size() { return LinearScan::nof_regs; } // accessors - IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); } - void set_state_for_block(BlockBegin* block, IntervalList* saved_state) { _saved_states.at_put(block->block_id(), saved_state); } + GrowableArray* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); } + void set_state_for_block(BlockBegin* block, GrowableArray* saved_state) { _saved_states.at_put(block->block_id(), saved_state); } void add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); } // helper functions - IntervalList* copy(IntervalList* input_state); - void state_put(IntervalList* input_state, int reg, Interval* interval); - bool check_state(IntervalList* input_state, int reg, Interval* interval); + GrowableArray* copy(GrowableArray* input_state); + void state_put(GrowableArray* input_state, int reg, Interval* interval); + bool check_state(GrowableArray* input_state, int reg, Interval* interval); void process_block(BlockBegin* block); - void process_xhandler(XHandler* xhandler, IntervalList* input_state); - void process_successor(BlockBegin* block, IntervalList* input_state); - void process_operations(LIR_List* ops, IntervalList* input_state); + void process_xhandler(XHandler* xhandler, GrowableArray* input_state); + void process_successor(BlockBegin* block, GrowableArray* input_state); + void process_operations(LIR_List* ops, GrowableArray* input_state); public: RegisterVerifier(LinearScan* allocator) @@ -3429,7 +3462,8 @@ void RegisterVerifier::verify(BlockBegin* start) { // setup input registers (method arguments) for first block - IntervalList* input_state = new IntervalList(state_size(), NULL); + int input_state_len = state_size(); + GrowableArray* input_state = new GrowableArray(input_state_len, input_state_len, NULL); CallingConvention* args = compilation()->frame_map()->incoming_arguments(); for (int n = 0; n < args->length(); n++) { LIR_Opr opr = args->at(n); @@ -3461,7 +3495,7 @@ TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id())); // must copy state because it is modified - IntervalList* input_state = copy(state_for_block(block)); + GrowableArray* input_state = copy(state_for_block(block)); if (TraceLinearScanLevel >= 4) { tty->print_cr("Input-State of intervals:"); @@ -3486,7 +3520,7 @@ } } -void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) { +void RegisterVerifier::process_xhandler(XHandler* xhandler, GrowableArray* input_state) { TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id())); // must copy state because it is modified @@ -3498,8 +3532,8 @@ process_successor(xhandler->entry_block(), input_state); } -void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) { - IntervalList* saved_state = state_for_block(block); +void RegisterVerifier::process_successor(BlockBegin* block, GrowableArray* input_state) { + GrowableArray* saved_state = state_for_block(block); if (saved_state != NULL) { // this block was already processed before. @@ -3541,13 +3575,13 @@ } -IntervalList* RegisterVerifier::copy(IntervalList* input_state) { - IntervalList* copy_state = new IntervalList(input_state->length()); - copy_state->push_all(input_state); +GrowableArray* RegisterVerifier::copy(GrowableArray* input_state) { + GrowableArray* copy_state = new GrowableArray(input_state->length()); + copy_state->appendAll(input_state); return copy_state; } -void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) { +void RegisterVerifier::state_put(GrowableArray* input_state, int reg, Interval* interval) { if (reg != LinearScan::any_reg && reg < state_size()) { if (interval != NULL) { TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = %d", reg, interval->reg_num())); @@ -3559,7 +3593,7 @@ } } -bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) { +bool RegisterVerifier::check_state(GrowableArray* input_state, int reg, Interval* interval) { if (reg != LinearScan::any_reg && reg < state_size()) { if (input_state->at(reg) != interval) { tty->print_cr("!! Error in register allocation: register %d does not contain interval %d", reg, interval->reg_num()); @@ -3569,7 +3603,7 @@ return false; } -void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) { +void RegisterVerifier::process_operations(LIR_List* ops, GrowableArray* input_state) { // visit all instructions of the block LIR_OpVisitState visitor; bool has_error = false; @@ -4359,7 +4393,7 @@ if (parent->_split_children.length() == 0) { assert(is_split_parent(), "list must be initialized at first split"); - parent->_split_children = IntervalList(4); + parent->_split_children = GrowableArray(4); parent->_split_children.append(this); } parent->_split_children.append(result); @@ -4810,7 +4844,7 @@ , _move_resolver(allocator) { for (int i = 0; i < LinearScan::nof_regs; i++) { - _spill_intervals[i] = new IntervalList(2); + _spill_intervals[i] = new GrowableArray(2); } } @@ -5503,10 +5537,10 @@ } if (regHi != any_reg) { - IntervalList* processed = _spill_intervals[reg]; + GrowableArray* processed = _spill_intervals[reg]; for (int i = 0; i < _spill_intervals[regHi]->length(); i++) { Interval* it = _spill_intervals[regHi]->at(i); - if (processed->index_of(it) == -1) { + if (processed->find_from_end(it) == -1) { remove_from_list(it); split_and_spill_interval(it); } --- old/src/share/vm/c1/c1_LinearScan.hpp 2016-02-12 14:19:18.500824532 +0300 +++ new/src/share/vm/c1/c1_LinearScan.hpp 2016-02-12 14:19:18.420824534 +0300 @@ -42,10 +42,7 @@ class MoveResolver; class Range; -define_array(IntervalArray, Interval*) -define_stack(IntervalList, IntervalArray) - -define_array(IntervalsArray, IntervalList*) +define_array(IntervalsArray, GrowableArray*) define_stack(IntervalsList, IntervalsArray) define_array(OopMapArray, OopMap*) @@ -145,9 +142,9 @@ int _max_spills; // number of stack slots used for intervals allocated to memory int _unused_spill_slot; // unused spill slot for a single-word value because of alignment of a double-word value - IntervalList _intervals; // mapping from register number to interval - IntervalList* _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split - IntervalArray* _sorted_intervals; // intervals sorted by Interval::from() + GrowableArray _intervals; // mapping from register number to interval + GrowableArray* _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split + GrowableArray* _sorted_intervals; // intervals sorted by Interval::from() bool _needs_full_resort; // set to true if an Interval::from() is changed and _sorted_intervals must be resorted LIR_OpArray _lir_ops; // mapping from LIR_Op id to LIR_Op node @@ -200,7 +197,7 @@ int interval_count() const { return _intervals.length(); } Interval* interval_at(int reg_num) const { return _intervals.at(reg_num); } - IntervalList* new_intervals_from_allocation() const { return _new_intervals_from_allocation; } + GrowableArray* new_intervals_from_allocation() const { return _new_intervals_from_allocation; } // access to LIR_Ops and Blocks indexed by op_id int max_lir_op_id() const { assert(_lir_ops.length() > 0, "no operations"); return (_lir_ops.length() - 1) << 1; } @@ -301,7 +298,7 @@ // (Uses LinearScanWalker) // // helper functions for building a sorted list of intervals - NOT_PRODUCT(bool is_sorted(IntervalArray* intervals);) + NOT_PRODUCT(bool is_sorted(GrowableArray* intervals);) static int interval_cmp(Interval** a, Interval** b); void add_to_list(Interval** first, Interval** prev, Interval* interval); void create_unhandled_lists(Interval** list1, Interval** list2, bool (is_list1)(const Interval* i), bool (is_list2)(const Interval* i)); @@ -427,9 +424,9 @@ int _insert_idx; LIR_InsertionBuffer _insertion_buffer; // buffer where moves are inserted - IntervalList _mapping_from; + GrowableArray _mapping_from; LIR_OprList _mapping_from_opr; - IntervalList _mapping_to; + GrowableArray _mapping_to; bool _multiple_reads_allowed; int _register_blocked[LinearScan::nof_regs]; @@ -533,7 +530,7 @@ VMReg _cached_vm_reg; Interval* _split_parent; // the original interval where this interval is derived from - IntervalList _split_children; // list of all intervals that are split off from this interval (only available for split parents) + GrowableArray _split_children; // list of all intervals that are split off from this interval (only available for split parents) Interval* _current_split_child; // the current split child that has been active or inactive last (always stored in split parents) int _canonical_spill_slot; // the stack slot where all split parts of this interval are spilled to (always stored in split parents) @@ -722,7 +719,7 @@ int _use_pos[LinearScan::nof_regs]; int _block_pos[LinearScan::nof_regs]; - IntervalList* _spill_intervals[LinearScan::nof_regs]; + GrowableArray* _spill_intervals[LinearScan::nof_regs]; MoveResolver _move_resolver; // for ordering spill moves