8067014: LinearScan::is_sorted significantly slows down fastdebug builds' performance
Reviewed-by: vlivanov, shade
--- a/hotspot/src/share/vm/c1/c1_CFGPrinter.hpp Fri Feb 19 20:41:36 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_CFGPrinter.hpp Fri Feb 19 20:45:26 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,9 @@
// compilation for later analysis.
class CFGPrinterOutput;
-class IntervalList;
+class Interval;
+
+typedef GrowableArray<Interval*> IntervalList;
class CFGPrinter : public AllStatic {
private:
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Feb 19 20:41:36 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Feb 19 20:45:26 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1434,41 +1434,73 @@
}
#ifndef PRODUCT
+int interval_cmp(Interval* const& l, Interval* const& r) {
+ return l->from() - r->from();
+}
+
+bool find_interval(Interval* interval, IntervalArray* intervals) {
+ bool found;
+ int idx = intervals->find_sorted<Interval*, interval_cmp>(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(IntervalArray* 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();
- }
- }
-
- // 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(num_found == 1, "lists do not contain same intervals");
- }
+ } else {
+ null_count++;
+ }
+ }
+
+ 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(interval_count() - null_count == intervals->length(),
+ "Sorted list should contain the same amount of non-NULL intervals as unsorted list");
return true;
}
@@ -1536,7 +1568,7 @@
sorted_len++;
}
}
- IntervalArray* sorted_list = new IntervalArray(sorted_len);
+ IntervalArray* sorted_list = new IntervalArray(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;
+ IntervalArray* old_list = _sorted_intervals;
+ IntervalList* 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;
+ IntervalArray* combined_list = new IntervalArray(combined_list_len, combined_list_len, NULL);
int old_idx = 0;
int new_idx = 0;
@@ -3211,6 +3244,10 @@
has_error = true;
}
+ // special intervals that are created in MoveResolver
+ // -> ignore them because the range information has no meaning there
+ if (i1->from() == 1 && i1->to() == 2) continue;
+
if (i1->first() == Range::end()) {
tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
has_error = true;
@@ -3225,18 +3262,13 @@
for (int j = i + 1; j < len; j++) {
Interval* i2 = interval_at(j);
- if (i2 == NULL) continue;
-
- // special intervals that are created in MoveResolver
- // -> ignore them because the range information has no meaning there
- if (i1->from() == 1 && i1->to() == 2) continue;
- if (i2->from() == 1 && i2->to() == 2) continue;
+ if (i2 == NULL || (i2->from() == 1 && i2->to() == 2)) continue;
int r1 = i1->assigned_reg();
int r1Hi = i1->assigned_regHi();
int r2 = i2->assigned_reg();
int r2Hi = i2->assigned_regHi();
- if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
+ if ((r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi))) && i1->intersects(i2)) {
tty->print_cr("Intervals %d and %d overlap and have the same register assigned", i1->reg_num(), i2->reg_num());
i1->print(); tty->cr();
i2->print(); tty->cr();
@@ -3429,7 +3461,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();
+ IntervalList* input_state = new IntervalList(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);
@@ -3543,7 +3576,7 @@
IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
IntervalList* copy_state = new IntervalList(input_state->length());
- copy_state->push_all(input_state);
+ copy_state->appendAll(input_state);
return copy_state;
}
@@ -5506,7 +5539,7 @@
IntervalList* 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);
}
--- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Fri Feb 19 20:41:36 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Fri Feb 19 20:45:26 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,8 +42,8 @@
class MoveResolver;
class Range;
-define_array(IntervalArray, Interval*)
-define_stack(IntervalList, IntervalArray)
+typedef GrowableArray<Interval*> IntervalArray;
+typedef GrowableArray<Interval*> IntervalList;
define_array(IntervalsArray, IntervalList*)
define_stack(IntervalsList, IntervalsArray)