8007986: GrowableArray should implement binary search
Binary search method for GrowableArray Reviewed-by: vlivanov, jrose
This commit is contained in:
parent
0e31a18fd1
commit
449c65bf50
@ -41,58 +41,37 @@ ciConstantPoolCache::ciConstantPoolCache(Arena* arena,
|
||||
_keys = new (arena) GrowableArray<int>(arena, expected_size, 0, 0);
|
||||
}
|
||||
|
||||
int ciConstantPoolCache::key_compare(const int& key, const int& elt) {
|
||||
if (key < elt) return -1;
|
||||
else if (key > elt) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciConstantPoolCache::get
|
||||
//
|
||||
// Get the entry at some index
|
||||
void* ciConstantPoolCache::get(int index) {
|
||||
ASSERT_IN_VM;
|
||||
int pos = find(index);
|
||||
if (pos >= _keys->length() ||
|
||||
_keys->at(pos) != index) {
|
||||
bool found = false;
|
||||
int pos = _keys->find_sorted<int, ciConstantPoolCache::key_compare>(index, found);
|
||||
if (!found) {
|
||||
// This element is not present in the cache.
|
||||
return NULL;
|
||||
}
|
||||
return _elements->at(pos);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciConstantPoolCache::find
|
||||
//
|
||||
// Use binary search to find the position of this index in the cache.
|
||||
// If there is no entry in the cache corresponding to this oop, return
|
||||
// the position at which the index would be inserted.
|
||||
int ciConstantPoolCache::find(int key) {
|
||||
int min = 0;
|
||||
int max = _keys->length()-1;
|
||||
|
||||
while (max >= min) {
|
||||
int mid = (max + min) / 2;
|
||||
int value = _keys->at(mid);
|
||||
if (value < key) {
|
||||
min = mid + 1;
|
||||
} else if (value > key) {
|
||||
max = mid - 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciConstantPoolCache::insert
|
||||
//
|
||||
// Insert a ciObject into the table at some index.
|
||||
void ciConstantPoolCache::insert(int index, void* elem) {
|
||||
int i;
|
||||
int pos = find(index);
|
||||
for (i = _keys->length()-1; i >= pos; i--) {
|
||||
_keys->at_put_grow(i+1, _keys->at(i));
|
||||
_elements->at_put_grow(i+1, _elements->at(i));
|
||||
}
|
||||
_keys->at_put_grow(pos, index);
|
||||
_elements->at_put_grow(pos, elem);
|
||||
bool found = false;
|
||||
int pos = _keys->find_sorted<int, ciConstantPoolCache::key_compare>(index, found);
|
||||
assert(!found, "duplicate");
|
||||
_keys->insert_before(pos, index);
|
||||
_elements->insert_before(pos, elem);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -38,7 +38,7 @@ private:
|
||||
GrowableArray<int>* _keys;
|
||||
GrowableArray<void*>* _elements;
|
||||
|
||||
int find(int index);
|
||||
static int key_compare(const int& key, const int& elt);
|
||||
|
||||
public:
|
||||
ciConstantPoolCache(Arena* arena, int expected_size);
|
||||
|
@ -260,6 +260,13 @@ ciObject* ciObjectFactory::get(oop key) {
|
||||
return new_object;
|
||||
}
|
||||
|
||||
int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) {
|
||||
Metadata* value = elt->constant_encoding();
|
||||
if (key < value) return -1;
|
||||
else if (key > value) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciObjectFactory::get_metadata
|
||||
//
|
||||
@ -280,7 +287,8 @@ ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
|
||||
}
|
||||
#endif // ASSERT
|
||||
int len = _ci_metadata->length();
|
||||
int index = find(key, _ci_metadata);
|
||||
bool found = false;
|
||||
int index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
|
||||
#ifdef ASSERT
|
||||
if (CIObjectFactoryVerify) {
|
||||
for (int i=0; i<_ci_metadata->length(); i++) {
|
||||
@ -290,7 +298,8 @@ ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!is_found_at(index, key, _ci_metadata)) {
|
||||
|
||||
if (!found) {
|
||||
// The ciMetadata does not yet exist. Create it and insert it
|
||||
// into the cache.
|
||||
ciMetadata* new_object = create_new_metadata(key);
|
||||
@ -300,10 +309,10 @@ ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
|
||||
if (len != _ci_metadata->length()) {
|
||||
// creating the new object has recursively entered new objects
|
||||
// into the table. We need to recompute our index.
|
||||
index = find(key, _ci_metadata);
|
||||
index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
|
||||
}
|
||||
assert(!is_found_at(index, key, _ci_metadata), "no double insert");
|
||||
insert(index, new_object, _ci_metadata);
|
||||
assert(!found, "no double insert");
|
||||
_ci_metadata->insert_before(index, new_object);
|
||||
return new_object;
|
||||
}
|
||||
return _ci_metadata->at(index)->as_metadata();
|
||||
@ -655,60 +664,6 @@ void ciObjectFactory::init_ident_of(ciBaseObject* obj) {
|
||||
obj->set_ident(_next_ident++);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciObjectFactory::find
|
||||
//
|
||||
// Use binary search to find the position of this oop in the cache.
|
||||
// If there is no entry in the cache corresponding to this oop, return
|
||||
// the position at which the oop should be inserted.
|
||||
int ciObjectFactory::find(Metadata* key, GrowableArray<ciMetadata*>* objects) {
|
||||
int min = 0;
|
||||
int max = objects->length()-1;
|
||||
|
||||
// print_contents();
|
||||
|
||||
while (max >= min) {
|
||||
int mid = (max + min) / 2;
|
||||
Metadata* value = objects->at(mid)->constant_encoding();
|
||||
if (value < key) {
|
||||
min = mid + 1;
|
||||
} else if (value > key) {
|
||||
max = mid - 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciObjectFactory::is_found_at
|
||||
//
|
||||
// Verify that the binary seach found the given key.
|
||||
bool ciObjectFactory::is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects) {
|
||||
return (index < objects->length() &&
|
||||
objects->at(index)->constant_encoding() == key);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciObjectFactory::insert
|
||||
//
|
||||
// Insert a ciObject into the table at some index.
|
||||
void ciObjectFactory::insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects) {
|
||||
int len = objects->length();
|
||||
if (len == index) {
|
||||
objects->append(obj);
|
||||
} else {
|
||||
objects->append(objects->at(len-1));
|
||||
int pos;
|
||||
for (pos = len-2; pos >= index; pos--) {
|
||||
objects->at_put(pos+1,objects->at(pos));
|
||||
}
|
||||
objects->at_put(index, obj);
|
||||
}
|
||||
}
|
||||
|
||||
static ciObjectFactory::NonPermObject* emptyBucket = NULL;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -68,9 +68,7 @@ private:
|
||||
NonPermObject* _non_perm_bucket[NON_PERM_BUCKETS];
|
||||
int _non_perm_count;
|
||||
|
||||
int find(Metadata* key, GrowableArray<ciMetadata*>* objects);
|
||||
bool is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects);
|
||||
void insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects);
|
||||
static int metadata_compare(Metadata* const& key, ciMetadata* const& elt);
|
||||
|
||||
ciObject* create_new_object(oop o);
|
||||
ciMetadata* create_new_metadata(Metadata* o);
|
||||
|
@ -88,7 +88,27 @@ MachConstantBaseNode* Compile::mach_constant_base_node() {
|
||||
|
||||
// Return the index at which m must be inserted (or already exists).
|
||||
// The sort order is by the address of the ciMethod, with is_virtual as minor key.
|
||||
int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual) {
|
||||
class IntrinsicDescPair {
|
||||
private:
|
||||
ciMethod* _m;
|
||||
bool _is_virtual;
|
||||
public:
|
||||
IntrinsicDescPair(ciMethod* m, bool is_virtual) : _m(m), _is_virtual(is_virtual) {}
|
||||
static int compare(IntrinsicDescPair* const& key, CallGenerator* const& elt) {
|
||||
ciMethod* m= elt->method();
|
||||
ciMethod* key_m = key->_m;
|
||||
if (key_m < m) return -1;
|
||||
else if (key_m > m) return 1;
|
||||
else {
|
||||
bool is_virtual = elt->is_virtual();
|
||||
bool key_virtual = key->_is_virtual;
|
||||
if (key_virtual < is_virtual) return -1;
|
||||
else if (key_virtual > is_virtual) return 1;
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found) {
|
||||
#ifdef ASSERT
|
||||
for (int i = 1; i < _intrinsics->length(); i++) {
|
||||
CallGenerator* cg1 = _intrinsics->at(i-1);
|
||||
@ -99,63 +119,28 @@ int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual) {
|
||||
"compiler intrinsics list must stay sorted");
|
||||
}
|
||||
#endif
|
||||
// Binary search sorted list, in decreasing intervals [lo, hi].
|
||||
int lo = 0, hi = _intrinsics->length()-1;
|
||||
while (lo <= hi) {
|
||||
int mid = (uint)(hi + lo) / 2;
|
||||
ciMethod* mid_m = _intrinsics->at(mid)->method();
|
||||
if (m < mid_m) {
|
||||
hi = mid-1;
|
||||
} else if (m > mid_m) {
|
||||
lo = mid+1;
|
||||
} else {
|
||||
// look at minor sort key
|
||||
bool mid_virt = _intrinsics->at(mid)->is_virtual();
|
||||
if (is_virtual < mid_virt) {
|
||||
hi = mid-1;
|
||||
} else if (is_virtual > mid_virt) {
|
||||
lo = mid+1;
|
||||
} else {
|
||||
return mid; // exact match
|
||||
}
|
||||
}
|
||||
}
|
||||
return lo; // inexact match
|
||||
IntrinsicDescPair pair(m, is_virtual);
|
||||
return _intrinsics->find_sorted<IntrinsicDescPair*, IntrinsicDescPair::compare>(&pair, found);
|
||||
}
|
||||
|
||||
void Compile::register_intrinsic(CallGenerator* cg) {
|
||||
if (_intrinsics == NULL) {
|
||||
_intrinsics = new (comp_arena())GrowableArray<CallGenerator*>(comp_arena(), 60, 0, NULL);
|
||||
}
|
||||
// This code is stolen from ciObjectFactory::insert.
|
||||
// Really, GrowableArray should have methods for
|
||||
// insert_at, remove_at, and binary_search.
|
||||
int len = _intrinsics->length();
|
||||
int index = intrinsic_insertion_index(cg->method(), cg->is_virtual());
|
||||
if (index == len) {
|
||||
_intrinsics->append(cg);
|
||||
} else {
|
||||
#ifdef ASSERT
|
||||
CallGenerator* oldcg = _intrinsics->at(index);
|
||||
assert(oldcg->method() != cg->method() || oldcg->is_virtual() != cg->is_virtual(), "don't register twice");
|
||||
#endif
|
||||
_intrinsics->append(_intrinsics->at(len-1));
|
||||
int pos;
|
||||
for (pos = len-2; pos >= index; pos--) {
|
||||
_intrinsics->at_put(pos+1,_intrinsics->at(pos));
|
||||
}
|
||||
_intrinsics->at_put(index, cg);
|
||||
}
|
||||
bool found = false;
|
||||
int index = intrinsic_insertion_index(cg->method(), cg->is_virtual(), found);
|
||||
assert(!found, "registering twice");
|
||||
_intrinsics->insert_before(index, cg);
|
||||
assert(find_intrinsic(cg->method(), cg->is_virtual()) == cg, "registration worked");
|
||||
}
|
||||
|
||||
CallGenerator* Compile::find_intrinsic(ciMethod* m, bool is_virtual) {
|
||||
assert(m->is_loaded(), "don't try this on unloaded methods");
|
||||
if (_intrinsics != NULL) {
|
||||
int index = intrinsic_insertion_index(m, is_virtual);
|
||||
if (index < _intrinsics->length()
|
||||
&& _intrinsics->at(index)->method() == m
|
||||
&& _intrinsics->at(index)->is_virtual() == is_virtual) {
|
||||
bool found = false;
|
||||
int index = intrinsic_insertion_index(m, is_virtual, found);
|
||||
if (found) {
|
||||
return _intrinsics->at(index);
|
||||
}
|
||||
}
|
||||
|
@ -1250,7 +1250,7 @@ class Compile : public Phase {
|
||||
// Intrinsic setup.
|
||||
void register_library_intrinsics(); // initializer
|
||||
CallGenerator* make_vm_intrinsic(ciMethod* m, bool is_virtual); // constructor
|
||||
int intrinsic_insertion_index(ciMethod* m, bool is_virtual); // helper
|
||||
int intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found); // helper
|
||||
CallGenerator* find_intrinsic(ciMethod* m, bool is_virtual); // query fn
|
||||
void register_intrinsic(CallGenerator* cg); // update fn
|
||||
|
||||
|
@ -396,7 +396,7 @@ template<class E> class GrowableArray : public GenericGrowableArray {
|
||||
int max = length() - 1;
|
||||
|
||||
while (max >= min) {
|
||||
int mid = (max + min) / 2;
|
||||
int mid = (int)(((uint)max + min) / 2);
|
||||
E value = at(mid);
|
||||
int diff = compare(key, value);
|
||||
if (diff > 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user