8233708: VectorSet cleanup
Reviewed-by: neliasso, shade, thartmann
This commit is contained in:
parent
f07d377d6f
commit
12adeca887
@ -151,7 +151,7 @@ bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) {
|
|||||||
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
|
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
|
||||||
for (int i = 0; i < _arg_size; i++) {
|
for (int i = 0; i < _arg_size; i++) {
|
||||||
if (vars.contains(i)) {
|
if (vars.contains(i)) {
|
||||||
bm >>= i;
|
bm.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1280,9 +1280,9 @@ void BCEscapeAnalyzer::clear_escape_info() {
|
|||||||
set_modified(var, OFFSET_ANY, 4);
|
set_modified(var, OFFSET_ANY, 4);
|
||||||
set_global_escape(var);
|
set_global_escape(var);
|
||||||
}
|
}
|
||||||
_arg_local.Clear();
|
_arg_local.clear();
|
||||||
_arg_stack.Clear();
|
_arg_stack.clear();
|
||||||
_arg_returned.Clear();
|
_arg_returned.clear();
|
||||||
_return_local = false;
|
_return_local = false;
|
||||||
_return_allocated = false;
|
_return_allocated = false;
|
||||||
_allocated_escapes = true;
|
_allocated_escapes = true;
|
||||||
@ -1334,7 +1334,7 @@ void BCEscapeAnalyzer::compute_escape_info() {
|
|||||||
|
|
||||||
// Do not scan method if it has no object parameters and
|
// Do not scan method if it has no object parameters and
|
||||||
// does not returns an object (_return_allocated is set in initialize()).
|
// does not returns an object (_return_allocated is set in initialize()).
|
||||||
if (_arg_local.Size() == 0 && !_return_allocated) {
|
if (_arg_local.is_empty() && !_return_allocated) {
|
||||||
// Clear all info since method's bytecode was not analysed and
|
// Clear all info since method's bytecode was not analysed and
|
||||||
// set pessimistic escape information.
|
// set pessimistic escape information.
|
||||||
clear_escape_info();
|
clear_escape_info();
|
||||||
@ -1457,10 +1457,10 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
|
|||||||
, _parent(parent)
|
, _parent(parent)
|
||||||
, _level(parent == NULL ? 0 : parent->level() + 1) {
|
, _level(parent == NULL ? 0 : parent->level() + 1) {
|
||||||
if (!_conservative) {
|
if (!_conservative) {
|
||||||
_arg_local.Clear();
|
_arg_local.clear();
|
||||||
_arg_stack.Clear();
|
_arg_stack.clear();
|
||||||
_arg_returned.Clear();
|
_arg_returned.clear();
|
||||||
_dirty.Clear();
|
_dirty.clear();
|
||||||
Arena* arena = CURRENT_ENV->arena();
|
Arena* arena = CURRENT_ENV->arena();
|
||||||
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
|
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
|
||||||
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
|
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
|
||||||
|
@ -758,7 +758,7 @@ bool ShenandoahBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode
|
|||||||
return true;
|
return true;
|
||||||
} else if (mode == LoopOptsShenandoahPostExpand) {
|
} else if (mode == LoopOptsShenandoahPostExpand) {
|
||||||
assert(UseShenandoahGC, "only for shenandoah");
|
assert(UseShenandoahGC, "only for shenandoah");
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
ShenandoahBarrierC2Support::optimize_after_expansion(visited, nstack, worklist, phase);
|
ShenandoahBarrierC2Support::optimize_after_expansion(visited, nstack, worklist, phase);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2368,7 +2368,7 @@ void MemoryGraphFixer::collect_memory_nodes() {
|
|||||||
// Iterate over CFG nodes in rpo and propagate memory state to
|
// Iterate over CFG nodes in rpo and propagate memory state to
|
||||||
// compute memory state at regions, creating new phis if needed.
|
// compute memory state at regions, creating new phis if needed.
|
||||||
Node_List rpo_list;
|
Node_List rpo_list;
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
_phase->rpo(_phase->C->root(), stack, visited, rpo_list);
|
_phase->rpo(_phase->C->root(), stack, visited, rpo_list);
|
||||||
Node* root = rpo_list.pop();
|
Node* root = rpo_list.pop();
|
||||||
assert(root == _phase->C->root(), "");
|
assert(root == _phase->C->root(), "");
|
||||||
|
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 1997, 2019, 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
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
|
||||||
#include "libadt/set.hpp"
|
|
||||||
#include "memory/allocation.inline.hpp"
|
|
||||||
|
|
||||||
// Sets - An Abstract Data Type
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
//-------------------------Virtual Functions-----------------------------------
|
|
||||||
// These functions MUST be implemented by the inheriting class.
|
|
||||||
class VectorSet;
|
|
||||||
const VectorSet *Set::asVectorSet() const { assert(0); return NULL; }
|
|
||||||
|
|
||||||
//------------------------------setstr-----------------------------------------
|
|
||||||
// Create a string with a printable representation of a set.
|
|
||||||
// The caller must deallocate the string.
|
|
||||||
char *Set::setstr() const
|
|
||||||
{
|
|
||||||
Set &set = clone(); // Virtually copy the basic set.
|
|
||||||
set.Sort(); // Sort elements for in-order retrieval
|
|
||||||
|
|
||||||
uint len = 128; // Total string space
|
|
||||||
char *buf = NEW_C_HEAP_ARRAY(char,len, mtCompiler);// Some initial string space
|
|
||||||
|
|
||||||
char *s = buf; // Current working string pointer
|
|
||||||
*s++ = '{';
|
|
||||||
*s = '\0';
|
|
||||||
|
|
||||||
// For all elements of the Set
|
|
||||||
uint hi = (uint)-2, lo = (uint)-2;
|
|
||||||
for( SetI i(&set); i.test(); ++i ) {
|
|
||||||
if( hi+1 == i.elem ) { // Moving sequentially thru range?
|
|
||||||
hi = i.elem; // Yes, just update hi end of range
|
|
||||||
} else { // Else range ended
|
|
||||||
if( buf+len-s < 25 ) { // Generous trailing space for upcoming numbers
|
|
||||||
int offset = (int)(s-buf);// Not enuf space; compute offset into buffer
|
|
||||||
len <<= 1; // Double string size
|
|
||||||
buf = REALLOC_C_HEAP_ARRAY(char,buf,len, mtCompiler); // Reallocate doubled size
|
|
||||||
s = buf+offset; // Get working pointer into new bigger buffer
|
|
||||||
}
|
|
||||||
if( lo != (uint)-2 ) { // Startup? No! Then print previous range.
|
|
||||||
if( lo != hi ) sprintf(s,"%d-%d,",lo,hi);
|
|
||||||
else sprintf(s,"%d,",lo);
|
|
||||||
s += strlen(s); // Advance working string
|
|
||||||
}
|
|
||||||
hi = lo = i.elem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( lo != (uint)-2 ) {
|
|
||||||
if( buf+len-s < 25 ) { // Generous trailing space for upcoming numbers
|
|
||||||
int offset = (int)(s-buf);// Not enuf space; compute offset into buffer
|
|
||||||
len <<= 1; // Double string size
|
|
||||||
buf = (char*)ReallocateHeap(buf,len, mtCompiler); // Reallocate doubled size
|
|
||||||
s = buf+offset; // Get working pointer into new bigger buffer
|
|
||||||
}
|
|
||||||
if( lo != hi ) sprintf(s,"%d-%d}",lo,hi);
|
|
||||||
else sprintf(s,"%d}",lo);
|
|
||||||
} else strcat(s,"}");
|
|
||||||
// Don't delete the clone 'set' since it is allocated on Arena.
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------print------------------------------------------
|
|
||||||
// Handier print routine
|
|
||||||
void Set::print() const
|
|
||||||
{
|
|
||||||
char *printable_set = setstr();
|
|
||||||
tty->print_cr("%s", printable_set);
|
|
||||||
FreeHeap(printable_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------parse------------------------------------------
|
|
||||||
// Convert a textual representation of a Set, to a Set and union into "this"
|
|
||||||
// Set. Return the amount of text parsed in "len", or zero in "len".
|
|
||||||
int Set::parse(const char *s)
|
|
||||||
{
|
|
||||||
char c; // Parse character
|
|
||||||
const char *t = s; // Save the starting position of s.
|
|
||||||
do c = *s++; // Skip characters
|
|
||||||
while( c && (c <= ' ') ); // Till no more whitespace or EOS
|
|
||||||
if( c != '{' ) return 0; // Oops, not a Set openner
|
|
||||||
if( *s == '}' ) return 2; // The empty Set
|
|
||||||
|
|
||||||
// Sets are filled with values of the form "xx," or "xx-yy," with the comma
|
|
||||||
// a "}" at the very end.
|
|
||||||
while( 1 ) { // While have elements in the Set
|
|
||||||
char *u; // Pointer to character ending parse
|
|
||||||
uint hi, i; // Needed for range handling below
|
|
||||||
uint elem = (uint)strtoul(s,&u,10);// Get element
|
|
||||||
if( u == s ) return 0; // Bogus crude
|
|
||||||
s = u; // Skip over the number
|
|
||||||
c = *s++; // Get the number seperator
|
|
||||||
switch ( c ) { // Different seperators
|
|
||||||
case '}': // Last simple element
|
|
||||||
case ',': // Simple element
|
|
||||||
(*this) <<= elem; // Insert the simple element into the Set
|
|
||||||
break; // Go get next element
|
|
||||||
case '-': // Range
|
|
||||||
hi = (uint)strtoul(s,&u,10); // Get element
|
|
||||||
if( u == s ) return 0; // Bogus crude
|
|
||||||
for( i=elem; i<=hi; i++ )
|
|
||||||
(*this) <<= i; // Insert the entire range into the Set
|
|
||||||
s = u; // Skip over the number
|
|
||||||
c = *s++; // Get the number seperator
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if( c == '}' ) break; // End of the Set
|
|
||||||
if( c != ',' ) return 0; // Bogus garbage
|
|
||||||
}
|
|
||||||
return (int)(s-t); // Return length parsed
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------Iterator---------------------------------------
|
|
||||||
SetI_::~SetI_()
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,231 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 1997, 2019, 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
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SHARE_LIBADT_SET_HPP
|
|
||||||
#define SHARE_LIBADT_SET_HPP
|
|
||||||
|
|
||||||
#include "memory/allocation.hpp"
|
|
||||||
|
|
||||||
// Sets - An Abstract Data Type
|
|
||||||
|
|
||||||
class SparseSet;
|
|
||||||
class VectorSet;
|
|
||||||
class ListSet;
|
|
||||||
class CoSet;
|
|
||||||
|
|
||||||
class ostream;
|
|
||||||
class SetI_;
|
|
||||||
|
|
||||||
// These sets can grow or shrink, based on the initial size and the largest
|
|
||||||
// element currently in them. Basically, they allow a bunch of bits to be
|
|
||||||
// grouped together, tested, set & cleared, intersected, etc. The basic
|
|
||||||
// Set class is an abstract class, and cannot be constructed. Instead,
|
|
||||||
// one of VectorSet, SparseSet, or ListSet is created. Each variation has
|
|
||||||
// different asymptotic running times for different operations, and different
|
|
||||||
// constants of proportionality as well.
|
|
||||||
// {n = number of elements, N = largest element}
|
|
||||||
|
|
||||||
// VectorSet SparseSet ListSet
|
|
||||||
// Create O(N) O(1) O(1)
|
|
||||||
// Clear O(N) O(1) O(1)
|
|
||||||
// Insert O(1) O(1) O(log n)
|
|
||||||
// Delete O(1) O(1) O(log n)
|
|
||||||
// Member O(1) O(1) O(log n)
|
|
||||||
// Size O(N) O(1) O(1)
|
|
||||||
// Copy O(N) O(n) O(n)
|
|
||||||
// Union O(N) O(n) O(n log n)
|
|
||||||
// Intersect O(N) O(n) O(n log n)
|
|
||||||
// Difference O(N) O(n) O(n log n)
|
|
||||||
// Equal O(N) O(n) O(n log n)
|
|
||||||
// ChooseMember O(N) O(1) O(1)
|
|
||||||
// Sort O(1) O(n log n) O(1)
|
|
||||||
// Forall O(N) O(n) O(n)
|
|
||||||
// Complement O(1) O(1) O(1)
|
|
||||||
|
|
||||||
// TIME: N/32 n 8*n Accesses
|
|
||||||
// SPACE: N/8 4*N+4*n 8*n Bytes
|
|
||||||
|
|
||||||
// Create: Make an empty set
|
|
||||||
// Clear: Remove all the elements of a Set
|
|
||||||
// Insert: Insert an element into a Set; duplicates are ignored
|
|
||||||
// Delete: Removes an element from a Set
|
|
||||||
// Member: Tests for membership in a Set
|
|
||||||
// Size: Returns the number of members of a Set
|
|
||||||
// Copy: Copy or assign one Set to another
|
|
||||||
// Union: Union 2 sets together
|
|
||||||
// Intersect: Intersect 2 sets together
|
|
||||||
// Difference: Compute A & !B; remove from set A those elements in set B
|
|
||||||
// Equal: Test for equality between 2 sets
|
|
||||||
// ChooseMember Pick a random member
|
|
||||||
// Sort: If no other operation changes the set membership, a following
|
|
||||||
// Forall will iterate the members in ascending order.
|
|
||||||
// Forall: Iterate over the elements of a Set. Operations that modify
|
|
||||||
// the set membership during iteration work, but the iterator may
|
|
||||||
// skip any member or duplicate any member.
|
|
||||||
// Complement: Only supported in the Co-Set variations. It adds a small
|
|
||||||
// constant-time test to every Set operation.
|
|
||||||
//
|
|
||||||
// PERFORMANCE ISSUES:
|
|
||||||
// If you "cast away" the specific set variation you are using, and then do
|
|
||||||
// operations on the basic "Set" object you will pay a virtual function call
|
|
||||||
// to get back the specific set variation. On the other hand, using the
|
|
||||||
// generic Set means you can change underlying implementations by just
|
|
||||||
// changing the initial declaration. Examples:
|
|
||||||
// void foo(VectorSet vs1, VectorSet vs2) { vs1 |= vs2; }
|
|
||||||
// "foo" must be called with a VectorSet. The vector set union operation
|
|
||||||
// is called directly.
|
|
||||||
// void foo(Set vs1, Set vs2) { vs1 |= vs2; }
|
|
||||||
// "foo" may be called with *any* kind of sets; suppose it is called with
|
|
||||||
// VectorSets. Two virtual function calls are used to figure out the that vs1
|
|
||||||
// and vs2 are VectorSets. In addition, if vs2 is not a VectorSet then a
|
|
||||||
// temporary VectorSet copy of vs2 will be made before the union proceeds.
|
|
||||||
//
|
|
||||||
// VectorSets have a small constant. Time and space are proportional to the
|
|
||||||
// largest element. Fine for dense sets and largest element < 10,000.
|
|
||||||
// SparseSets have a medium constant. Time is proportional to the number of
|
|
||||||
// elements, space is proportional to the largest element.
|
|
||||||
// Fine (but big) with the largest element < 100,000.
|
|
||||||
// ListSets have a big constant. Time *and space* are proportional to the
|
|
||||||
// number of elements. They work well for a few elements of *any* size
|
|
||||||
// (i.e. sets of pointers)!
|
|
||||||
|
|
||||||
//------------------------------Set--------------------------------------------
|
|
||||||
class Set : public ResourceObj {
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Creates a new, empty set.
|
|
||||||
Set(Arena *arena) : _set_arena(arena) {};
|
|
||||||
|
|
||||||
// Creates a new set from an existing set
|
|
||||||
Set(const Set & s) : ResourceObj(s) {};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Set assignment; deep-copy guts
|
|
||||||
virtual Set &operator =(const Set &s)=0;
|
|
||||||
virtual Set &clone(void) const=0;
|
|
||||||
|
|
||||||
// Virtual destructor
|
|
||||||
virtual ~Set() {};
|
|
||||||
|
|
||||||
// Add member to set
|
|
||||||
virtual Set &operator <<=(uint elem)=0;
|
|
||||||
// virtual Set operator << (uint elem);
|
|
||||||
|
|
||||||
// Delete member from set
|
|
||||||
virtual Set &operator >>=(uint elem)=0;
|
|
||||||
// virtual Set operator >> (uint elem);
|
|
||||||
|
|
||||||
// Membership test. Result is Zero (absent)/ Non-Zero (present)
|
|
||||||
virtual int operator [](uint elem) const=0;
|
|
||||||
|
|
||||||
// Intersect sets
|
|
||||||
virtual Set &operator &=(const Set &s)=0;
|
|
||||||
// virtual Set operator & (const Set &s) const;
|
|
||||||
|
|
||||||
// Union sets
|
|
||||||
virtual Set &operator |=(const Set &s)=0;
|
|
||||||
// virtual Set operator | (const Set &s) const;
|
|
||||||
|
|
||||||
// Difference sets
|
|
||||||
virtual Set &operator -=(const Set &s)=0;
|
|
||||||
// virtual Set operator - (const Set &s) const;
|
|
||||||
|
|
||||||
// Tests for equality. Result is Zero (false)/ Non-Zero (true)
|
|
||||||
virtual int operator ==(const Set &s) const=0;
|
|
||||||
int operator !=(const Set &s) const { return !(*this == s); }
|
|
||||||
virtual int disjoint(const Set &s) const=0;
|
|
||||||
|
|
||||||
// Tests for strict subset. Result is Zero (false)/ Non-Zero (true)
|
|
||||||
virtual int operator < (const Set &s) const=0;
|
|
||||||
int operator > (const Set &s) const { return s < *this; }
|
|
||||||
|
|
||||||
// Tests for subset. Result is Zero (false)/ Non-Zero (true)
|
|
||||||
virtual int operator <=(const Set &s) const=0;
|
|
||||||
int operator >=(const Set &s) const { return s <= *this; }
|
|
||||||
|
|
||||||
// Clear all the elements in the Set
|
|
||||||
virtual void Clear(void)=0;
|
|
||||||
|
|
||||||
// Return the number of members in the Set
|
|
||||||
virtual uint Size(void) const=0;
|
|
||||||
|
|
||||||
// If an iterator follows a "Sort()" without any Set-modifying operations
|
|
||||||
// inbetween then the iterator will visit the elements in ascending order.
|
|
||||||
virtual void Sort(void)=0;
|
|
||||||
|
|
||||||
// Convert a set to printable string in an allocated buffer.
|
|
||||||
// The caller must deallocate the string.
|
|
||||||
virtual char *setstr(void) const;
|
|
||||||
|
|
||||||
// Print the Set on "stdout". Can be conveniently called in the debugger
|
|
||||||
void print() const;
|
|
||||||
|
|
||||||
// Parse text from the string into the Set. Return length parsed.
|
|
||||||
virtual int parse(const char *s);
|
|
||||||
|
|
||||||
// Convert a generic Set to a specific Set
|
|
||||||
virtual const VectorSet *asVectorSet(void) const;
|
|
||||||
|
|
||||||
// Hash the set. Sets of different types but identical elements will NOT
|
|
||||||
// hash the same. Same set type, same elements WILL hash the same.
|
|
||||||
virtual int hash() const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class SetI;
|
|
||||||
virtual class SetI_ *iterate(uint&) const=0;
|
|
||||||
|
|
||||||
// Need storeage for the set
|
|
||||||
Arena *_set_arena;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------Iteration--------------------------------------
|
|
||||||
// Loop thru all elements of the set, setting "elem" to the element numbers
|
|
||||||
// in random order. Inserted or deleted elements during this operation may
|
|
||||||
// or may not be iterated over; untouched elements will be affected once.
|
|
||||||
|
|
||||||
// Usage: for( SetI i(s); i.test(); i++ ) { body = i.elem; } ...OR...
|
|
||||||
// for( i.reset(s); i.test(); i++ ) { body = i.elem; }
|
|
||||||
|
|
||||||
class SetI_ : public ResourceObj {
|
|
||||||
protected:
|
|
||||||
friend class SetI;
|
|
||||||
virtual ~SetI_();
|
|
||||||
virtual uint next(void)=0;
|
|
||||||
virtual int test(void)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SetI {
|
|
||||||
protected:
|
|
||||||
SetI_ *impl;
|
|
||||||
public:
|
|
||||||
uint elem; // The publically accessible element
|
|
||||||
|
|
||||||
SetI( const Set *s ) { impl = s->iterate(elem); }
|
|
||||||
~SetI() { delete impl; }
|
|
||||||
void reset( const Set *s ) { delete impl; impl = s->iterate(elem); }
|
|
||||||
void operator ++(void) { elem = impl->next(); }
|
|
||||||
int test(void) { return impl->test(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SHARE_LIBADT_SET_HPP
|
|
@ -27,339 +27,61 @@
|
|||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "memory/arena.hpp"
|
#include "memory/arena.hpp"
|
||||||
|
|
||||||
// Vector Sets - An Abstract Data Type
|
VectorSet::VectorSet(Arena *arena) {
|
||||||
|
_set_arena = arena;
|
||||||
// BitsInByte is a lookup table which tells the number of bits that
|
|
||||||
// are in the looked-up number. It is very useful in VectorSet_Size.
|
|
||||||
|
|
||||||
uint8_t bitsInByte[BITS_IN_BYTE_ARRAY_SIZE] = {
|
|
||||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
||||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
||||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
||||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
||||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
||||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
||||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
||||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
||||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
||||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
||||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
||||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------VectorSet--------------------------------------
|
|
||||||
// Create a new, empty Set.
|
|
||||||
VectorSet::VectorSet(Arena *arena) : Set(arena) {
|
|
||||||
size = 2; // Small initial size
|
size = 2; // Small initial size
|
||||||
data = (uint32_t *)_set_arena->Amalloc(size*sizeof(uint32_t));
|
data = (uint32_t *)_set_arena->Amalloc(size*sizeof(uint32_t));
|
||||||
data[0] = 0; // No elements
|
data[0] = 0; // No elements
|
||||||
data[1] = 0;
|
data[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------operator=--------------------------------------
|
|
||||||
Set &VectorSet::operator = (const Set &set)
|
|
||||||
{
|
|
||||||
if( &set == this ) return *this;
|
|
||||||
FREE_FAST(data);
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
slamin(*(set.asVectorSet()));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------slamin-----------------------------------------
|
|
||||||
// Initialize one set with another. No regard is made to the existing Set.
|
|
||||||
void VectorSet::slamin(const VectorSet& s)
|
|
||||||
{
|
|
||||||
size = s.size; // Use new size
|
|
||||||
data = (uint32_t*)s._set_arena->Amalloc(size*sizeof(uint32_t)); // Make array of required size
|
|
||||||
memcpy( data, s.data, size*sizeof(uint32_t) ); // Fill the array
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------grow-------------------------------------------
|
|
||||||
// Expand the existing set to a bigger size
|
// Expand the existing set to a bigger size
|
||||||
void VectorSet::grow( uint newsize )
|
void VectorSet::grow(uint newsize) {
|
||||||
{
|
newsize = (newsize+31) >> 5;
|
||||||
newsize = (newsize+31) >> 5; // Convert to longwords
|
|
||||||
uint x = size;
|
uint x = size;
|
||||||
while( x < newsize ) x <<= 1;
|
while (x < newsize) {
|
||||||
|
x <<= 1;
|
||||||
|
}
|
||||||
data = (uint32_t *)_set_arena->Arealloc(data, size*sizeof(uint32_t), x*sizeof(uint32_t));
|
data = (uint32_t *)_set_arena->Arealloc(data, size*sizeof(uint32_t), x*sizeof(uint32_t));
|
||||||
memset((char *)(data + size), 0, (x - size)*sizeof(uint32_t));
|
memset((char*)(data + size), 0, (x - size) * sizeof(uint32_t));
|
||||||
size = x;
|
size = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------operator<<=------------------------------------
|
|
||||||
// Insert a member into an existing Set.
|
// Insert a member into an existing Set.
|
||||||
Set &VectorSet::operator <<= (uint elem)
|
void VectorSet::insert(uint elem) {
|
||||||
{
|
uint word = elem >> 5;
|
||||||
uint word = elem >> 5; // Get the longword offset
|
uint32_t mask = 1L << (elem & 31);
|
||||||
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
if (word >= size) {
|
||||||
|
grow(elem + 1);
|
||||||
if( word >= size ) // Need to grow set?
|
|
||||||
grow(elem+1); // Then grow it
|
|
||||||
data[word] |= mask; // Set new bit
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator>>=------------------------------------
|
|
||||||
// Delete a member from an existing Set.
|
|
||||||
Set &VectorSet::operator >>= (uint elem)
|
|
||||||
{
|
|
||||||
uint word = elem >> 5; // Get the longword offset
|
|
||||||
if( word >= size ) // Beyond the last?
|
|
||||||
return *this; // Then it's clear & return clear
|
|
||||||
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
|
||||||
data[word] &= ~mask; // Clear bit
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator&=-------------------------------------
|
|
||||||
// Intersect one set into another.
|
|
||||||
VectorSet &VectorSet::operator &= (const VectorSet &s)
|
|
||||||
{
|
|
||||||
// NOTE: The intersection is never any larger than the smallest set.
|
|
||||||
if( s.size < size ) size = s.size; // Get smaller size
|
|
||||||
uint32_t *u1 = data; // Pointer to the destination data
|
|
||||||
uint32_t *u2 = s.data; // Pointer to the source data
|
|
||||||
for( uint i=0; i<size; i++) // For data in set
|
|
||||||
*u1++ &= *u2++; // Copy and AND longwords
|
|
||||||
return *this; // Return set
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator&=-------------------------------------
|
|
||||||
Set &VectorSet::operator &= (const Set &set)
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
return (*this) &= *(set.asVectorSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator|=-------------------------------------
|
|
||||||
// Union one set into another.
|
|
||||||
VectorSet &VectorSet::operator |= (const VectorSet &s)
|
|
||||||
{
|
|
||||||
// This many words must be unioned
|
|
||||||
uint cnt = ((size<s.size)?size:s.size);
|
|
||||||
uint32_t *u1 = data; // Pointer to the destination data
|
|
||||||
uint32_t *u2 = s.data; // Pointer to the source data
|
|
||||||
for( uint i=0; i<cnt; i++) // Copy and OR the two sets
|
|
||||||
*u1++ |= *u2++;
|
|
||||||
if( size < s.size ) { // Is set 2 larger than set 1?
|
|
||||||
// Extend result by larger set
|
|
||||||
grow(s.size*sizeof(uint32_t)*8);
|
|
||||||
memcpy(&data[cnt], u2, (s.size - cnt)*sizeof(uint32_t));
|
|
||||||
}
|
}
|
||||||
return *this; // Return result set
|
data[word] |= mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------operator|=-------------------------------------
|
|
||||||
Set &VectorSet::operator |= (const Set &set)
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
return (*this) |= *(set.asVectorSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator-=-------------------------------------
|
|
||||||
// Difference one set from another.
|
|
||||||
VectorSet &VectorSet::operator -= (const VectorSet &s)
|
|
||||||
{
|
|
||||||
// This many words must be unioned
|
|
||||||
uint cnt = ((size<s.size)?size:s.size);
|
|
||||||
uint32_t *u1 = data; // Pointer to the destination data
|
|
||||||
uint32_t *u2 = s.data; // Pointer to the source data
|
|
||||||
for( uint i=0; i<cnt; i++ ) // For data in set
|
|
||||||
*u1++ &= ~(*u2++); // A <-- A & ~B with longwords
|
|
||||||
return *this; // Return new set
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator-=-------------------------------------
|
|
||||||
Set &VectorSet::operator -= (const Set &set)
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
return (*this) -= *(set.asVectorSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------compare----------------------------------------
|
|
||||||
// Compute 2 booleans: bits in A not B, bits in B not A.
|
|
||||||
// Return X0 -- A is not a subset of B
|
|
||||||
// X1 -- A is a subset of B
|
|
||||||
// 0X -- B is not a subset of A
|
|
||||||
// 1X -- B is a subset of A
|
|
||||||
int VectorSet::compare (const VectorSet &s) const
|
|
||||||
{
|
|
||||||
uint32_t *u1 = data; // Pointer to the destination data
|
|
||||||
uint32_t *u2 = s.data; // Pointer to the source data
|
|
||||||
uint32_t AnotB = 0, BnotA = 0;
|
|
||||||
// This many words must be unioned
|
|
||||||
uint cnt = ((size<s.size)?size:s.size);
|
|
||||||
|
|
||||||
// Get bits for both sets
|
|
||||||
uint i; // Exit value of loop
|
|
||||||
for( i=0; i<cnt; i++ ) { // For data in BOTH sets
|
|
||||||
uint32_t A = *u1++; // Data from one guy
|
|
||||||
uint32_t B = *u2++; // Data from other guy
|
|
||||||
AnotB |= (A & ~B); // Compute bits in A not B
|
|
||||||
BnotA |= (B & ~A); // Compute bits in B not A
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get bits from bigger set
|
|
||||||
if( size < s.size ) {
|
|
||||||
for( ; i<s.size; i++ ) // For data in larger set
|
|
||||||
BnotA |= *u2++; // These bits are in B not A
|
|
||||||
} else {
|
|
||||||
for( ; i<size; i++ ) // For data in larger set
|
|
||||||
AnotB |= *u1++; // These bits are in A not B
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set & return boolean flags
|
|
||||||
return ((!BnotA)<<1) + (!AnotB);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator==-------------------------------------
|
|
||||||
// Test for set equality
|
|
||||||
int VectorSet::operator == (const VectorSet &s) const
|
|
||||||
{
|
|
||||||
return compare(s) == 3; // TRUE if A and B are mutual subsets
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator==-------------------------------------
|
|
||||||
int VectorSet::operator == (const Set &set) const
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
return (*this) == *(set.asVectorSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------disjoint---------------------------------------
|
|
||||||
// Check for sets being disjoint.
|
|
||||||
int VectorSet::disjoint(const Set &set) const
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
const VectorSet &s = *(set.asVectorSet());
|
|
||||||
|
|
||||||
// NOTE: The intersection is never any larger than the smallest set.
|
|
||||||
uint small_size = ((size<s.size)?size:s.size);
|
|
||||||
uint32_t *u1 = data; // Pointer to the destination data
|
|
||||||
uint32_t *u2 = s.data; // Pointer to the source data
|
|
||||||
for( uint i=0; i<small_size; i++) // For data in set
|
|
||||||
if( *u1++ & *u2++ ) // If any elements in common
|
|
||||||
return 0; // Then not disjoint
|
|
||||||
return 1; // Else disjoint
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator<--------------------------------------
|
|
||||||
// Test for strict subset
|
|
||||||
int VectorSet::operator < (const VectorSet &s) const
|
|
||||||
{
|
|
||||||
return compare(s) == 1; // A subset B, B not subset A
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator<--------------------------------------
|
|
||||||
int VectorSet::operator < (const Set &set) const
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
return (*this) < *(set.asVectorSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator<=-------------------------------------
|
|
||||||
// Test for subset
|
|
||||||
int VectorSet::operator <= (const VectorSet &s) const
|
|
||||||
{
|
|
||||||
return compare(s) & 1; // A subset B
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator<=-------------------------------------
|
|
||||||
int VectorSet::operator <= (const Set &set) const
|
|
||||||
{
|
|
||||||
// The cast is a virtual function that checks that "set" is a VectorSet.
|
|
||||||
return (*this) <= *(set.asVectorSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------operator[]-------------------------------------
|
|
||||||
// Test for membership. A Zero/Non-Zero value is returned!
|
|
||||||
int VectorSet::operator[](uint elem) const
|
|
||||||
{
|
|
||||||
uint word = elem >> 5; // Get the longword offset
|
|
||||||
if( word >= size ) // Beyond the last?
|
|
||||||
return 0; // Then it's clear
|
|
||||||
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
|
||||||
return ((data[word] & mask))!=0; // Return the sense of the bit
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------Clear------------------------------------------
|
|
||||||
// Clear a set
|
// Clear a set
|
||||||
void VectorSet::Clear(void)
|
void VectorSet::clear() {
|
||||||
{
|
|
||||||
if( size > 100 ) { // Reclaim storage only if huge
|
if( size > 100 ) { // Reclaim storage only if huge
|
||||||
FREE_RESOURCE_ARRAY(uint32_t,data,size);
|
FREE_RESOURCE_ARRAY(uint32_t,data,size);
|
||||||
size = 2; // Small initial size
|
size = 2; // Small initial size
|
||||||
data = NEW_RESOURCE_ARRAY(uint32_t,size);
|
data = NEW_RESOURCE_ARRAY(uint32_t,size);
|
||||||
}
|
}
|
||||||
memset( data, 0, size*sizeof(uint32_t) );
|
memset(data, 0, size*sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------Size-------------------------------------------
|
// Return true if the set is empty
|
||||||
// Return number of elements in a Set
|
bool VectorSet::is_empty() const {
|
||||||
uint VectorSet::Size(void) const
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
{
|
if (data[i] != 0) {
|
||||||
uint sum = 0; // Cumulative size so far.
|
return false;
|
||||||
uint8_t* currByte = (uint8_t*) data;
|
}
|
||||||
for( uint32_t i = 0; i < (size<<2); i++) // While have bytes to process
|
}
|
||||||
sum += bitsInByte[*currByte++]; // Add bits in current byte to size.
|
return true;
|
||||||
return sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------Sort-------------------------------------------
|
int VectorSet::hash() const {
|
||||||
// Sort the elements for the next forall statement
|
|
||||||
void VectorSet::Sort(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------hash-------------------------------------------
|
|
||||||
int VectorSet::hash() const
|
|
||||||
{
|
|
||||||
uint32_t _xor = 0;
|
uint32_t _xor = 0;
|
||||||
uint lim = ((size<4)?size:4);
|
uint lim = ((size < 4) ? size : 4);
|
||||||
for( uint i = 0; i < lim; i++ )
|
for (uint i = 0; i < lim; i++) {
|
||||||
_xor ^= data[i];
|
_xor ^= data[i];
|
||||||
|
}
|
||||||
return (int)_xor;
|
return (int)_xor;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------iterate----------------------------------------
|
|
||||||
// Used by Set::print().
|
|
||||||
class VSetI_ : public SetI_ {
|
|
||||||
VectorSetI vsi;
|
|
||||||
public:
|
|
||||||
VSetI_( const VectorSet *vset, uint &elem ) : vsi(vset) { elem = vsi.elem; }
|
|
||||||
|
|
||||||
uint next(void) { ++vsi; return vsi.elem; }
|
|
||||||
int test(void) { return vsi.test(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
SetI_ *VectorSet::iterate(uint &elem) const {
|
|
||||||
return new(ResourceObj::C_HEAP, mtInternal) VSetI_(this, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//------------------------------next-------------------------------------------
|
|
||||||
// Find and return the next element of a vector set, or return garbage and
|
|
||||||
// make "VectorSetI::test()" fail.
|
|
||||||
uint VectorSetI::next(void)
|
|
||||||
{
|
|
||||||
j++; // Next element in word
|
|
||||||
mask = (mask & max_jint) << 1;// Next bit in word
|
|
||||||
do { // Do While still have words
|
|
||||||
while( mask ) { // While have bits in word
|
|
||||||
if( s->data[i] & mask ) { // If found a bit
|
|
||||||
return (i<<5)+j; // Return the bit address
|
|
||||||
}
|
|
||||||
j++; // Skip to next bit
|
|
||||||
mask = (mask & max_jint) << 1;
|
|
||||||
}
|
|
||||||
j = 0; // No more bits in word; setup for next word
|
|
||||||
mask = 1;
|
|
||||||
for( i++; (i<s->size) && (!s->data[i]); i++ ); // Skip to non-zero word
|
|
||||||
} while( i<s->size );
|
|
||||||
return max_juint; // No element, iterated them all
|
|
||||||
}
|
|
||||||
|
@ -25,161 +25,85 @@
|
|||||||
#ifndef SHARE_LIBADT_VECTSET_HPP
|
#ifndef SHARE_LIBADT_VECTSET_HPP
|
||||||
#define SHARE_LIBADT_VECTSET_HPP
|
#define SHARE_LIBADT_VECTSET_HPP
|
||||||
|
|
||||||
#include "libadt/set.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
#define BITS_IN_BYTE_ARRAY_SIZE 256
|
// Vector Sets
|
||||||
|
|
||||||
// Vector Sets - An Abstract Data Type
|
|
||||||
//INTERFACE
|
|
||||||
|
|
||||||
// These sets can grow or shrink, based on the initial size and the largest
|
// These sets can grow or shrink, based on the initial size and the largest
|
||||||
// element currently in them. Slow and bulky for sparse sets, these sets
|
// element currently in them.
|
||||||
// are super for dense sets. They are fast and compact when dense.
|
|
||||||
|
|
||||||
// TIME:
|
|
||||||
// O(1) - Insert, Delete, Member, Sort
|
|
||||||
// O(max_element) - Create, Clear, Size, Copy, Union, Intersect, Difference,
|
|
||||||
// Equal, ChooseMember, Forall
|
|
||||||
|
|
||||||
// SPACE: (max_element)/(8*sizeof(int))
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------VectorSet--------------------------------------
|
//------------------------------VectorSet--------------------------------------
|
||||||
class VectorSet : public Set {
|
class VectorSet : public ResourceObj {
|
||||||
friend class VectorSetI; // Friendly iterator class
|
private:
|
||||||
protected:
|
|
||||||
uint size; // Size of data IN LONGWORDS (32bits)
|
uint size; // Size of data IN LONGWORDS (32bits)
|
||||||
uint32_t* data; // The data, bit packed
|
uint32_t* data; // The data, bit packed
|
||||||
|
Arena *_set_arena;
|
||||||
|
|
||||||
void slamin( const VectorSet& s ); // Initialize one set with another
|
void grow(uint newsize); // Grow vector to required bitsize
|
||||||
int compare(const VectorSet &s) const; // Compare set contents
|
|
||||||
void grow(uint newsize); // Grow vector to required bitsize
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VectorSet(Arena *arena); // Creates a new, empty set.
|
VectorSet(Arena *arena);
|
||||||
VectorSet(const VectorSet &s) : Set(s._set_arena) {slamin(s);} // Set clone; deep-copy guts
|
|
||||||
Set &operator =(const Set &s); // Set clone; deep-copy guts
|
|
||||||
VectorSet &operator =(const VectorSet &s) // Set clone; deep-copy guts
|
|
||||||
{ if( &s != this ) { slamin(s); } return *this; }
|
|
||||||
~VectorSet() {}
|
~VectorSet() {}
|
||||||
Set &clone(void) const { return *(new VectorSet(*this)); }
|
void insert(uint elem);
|
||||||
|
|
||||||
Set &operator <<=(uint elem); // Add member to set
|
void clear();
|
||||||
VectorSet operator << (uint elem) // Add member to new set
|
bool is_empty() const;
|
||||||
{ VectorSet foo(*this); foo <<= elem; return foo; }
|
int hash() const;
|
||||||
Set &operator >>=(uint elem); // Delete member from set
|
void reset() {
|
||||||
VectorSet operator >> (uint elem) // Delete member from new set
|
memset(data, 0, size*sizeof(uint32_t));
|
||||||
{ VectorSet foo(*this); foo >>= elem; return foo; }
|
|
||||||
|
|
||||||
VectorSet &operator &=(const VectorSet &s); // Intersect sets into first set
|
|
||||||
Set &operator &=(const Set &s); // Intersect sets into first set
|
|
||||||
VectorSet operator & (const VectorSet &s) const
|
|
||||||
{ VectorSet foo(*this); foo &= s; return foo; }
|
|
||||||
|
|
||||||
VectorSet &operator |=(const VectorSet &s); // Intersect sets into first set
|
|
||||||
Set &operator |=(const Set &s); // Intersect sets into first set
|
|
||||||
VectorSet operator | (const VectorSet &s) const
|
|
||||||
{ VectorSet foo(*this); foo |= s; return foo; }
|
|
||||||
|
|
||||||
VectorSet &operator -=(const VectorSet &s); // Intersect sets into first set
|
|
||||||
Set &operator -=(const Set &s); // Intersect sets into first set
|
|
||||||
VectorSet operator - (const VectorSet &s) const
|
|
||||||
{ VectorSet foo(*this); foo -= s; return foo; }
|
|
||||||
|
|
||||||
int operator ==(const VectorSet &s) const; // True if sets are equal
|
|
||||||
int operator ==(const Set &s) const; // True if sets are equal
|
|
||||||
int operator < (const VectorSet &s) const; // True if strict subset
|
|
||||||
int operator < (const Set &s) const; // True if strict subset
|
|
||||||
int operator <=(const VectorSet &s) const; // True if subset relation holds.
|
|
||||||
int operator <=(const Set &s) const; // True if subset relation holds.
|
|
||||||
int disjoint (const Set &s) const; // True if sets are disjoint
|
|
||||||
|
|
||||||
int operator [](uint elem) const; // Test for membership
|
|
||||||
void Clear(void); // Clear a set
|
|
||||||
uint Size(void) const; // Number of elements in the Set.
|
|
||||||
void Sort(void); // Sort before iterating
|
|
||||||
int hash() const; // Hash function
|
|
||||||
void Reset(void) { // Reset a set
|
|
||||||
memset( data, 0, size*sizeof(uint32_t) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Removed for MCC BUG
|
|
||||||
operator const VectorSet* (void) const { return this; } */
|
|
||||||
const VectorSet *asVectorSet() const { return this; }
|
|
||||||
|
|
||||||
// Expose internals for speed-critical fast iterators
|
// Expose internals for speed-critical fast iterators
|
||||||
uint word_size() const { return size; }
|
uint word_size() const { return size; }
|
||||||
|
|
||||||
// Fast inlined "test and set". Replaces the idiom:
|
// Fast inlined "test and set". Replaces the idiom:
|
||||||
// if( visited[idx] ) return;
|
// if (visited.test(idx)) return;
|
||||||
// visited <<= idx;
|
// visited.set(idx);
|
||||||
// With:
|
// With:
|
||||||
// if( visited.test_set(idx) ) return;
|
// if (visited.test_set(idx)) return;
|
||||||
//
|
//
|
||||||
int test_set( uint elem ) {
|
int test_set(uint elem) {
|
||||||
uint word = elem >> 5; // Get the longword offset
|
uint word = elem >> 5; // Get the longword offset
|
||||||
if( word >= size ) // Beyond the last?
|
if (word >= size) {
|
||||||
return test_set_grow(elem); // Then grow; set; return 0;
|
// Then grow; set; return 0;
|
||||||
|
this->insert(elem);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
uint32_t datum = data[word] & mask;// Get bit
|
uint32_t datum = data[word] & mask;// Get bit
|
||||||
data[word] |= mask; // Set bit
|
data[word] |= mask; // Set bit
|
||||||
return datum; // Return bit
|
return datum; // Return bit
|
||||||
}
|
}
|
||||||
int test_set_grow( uint elem ) { // Insert & return 0;
|
|
||||||
(*this) <<= elem; // Insert into set
|
|
||||||
return 0; // Return 0!
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fast inlined test
|
// Fast inlined test
|
||||||
int test( uint elem ) const {
|
int test(uint elem) const {
|
||||||
uint word = elem >> 5; // Get the longword offset
|
uint word = elem >> 5;
|
||||||
if( word >= size ) return 0; // Beyond the last?
|
if (word >= size) {
|
||||||
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
return 0;
|
||||||
return data[word] & mask; // Get bit
|
}
|
||||||
|
uint32_t mask = 1L << (elem & 31);
|
||||||
|
return data[word] & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(uint elem) {
|
||||||
|
uint word = elem >> 5;
|
||||||
|
if (word >= size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t mask = 1L << (elem & 31);
|
||||||
|
data[word] &= ~mask; // Clear bit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast inlined set
|
// Fast inlined set
|
||||||
void set( uint elem ) {
|
void set(uint elem) {
|
||||||
uint word = elem >> 5; // Get the longword offset
|
uint word = elem >> 5;
|
||||||
if( word >= size ) { // Beyond the last?
|
if (word >= size) {
|
||||||
test_set_grow(elem); // Then grow and set
|
this->insert(elem);
|
||||||
} else {
|
} else {
|
||||||
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
uint32_t mask = 1L << (elem & 31);
|
||||||
data[word] |= mask; // Set bit
|
data[word] |= mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
SetI_ *iterate(uint&) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------Iteration--------------------------------------
|
|
||||||
// Loop thru all elements of the set, setting "elem" to the element numbers
|
|
||||||
// in random order. Inserted or deleted elements during this operation may
|
|
||||||
// or may not be iterated over; untouched elements will be affected once.
|
|
||||||
// Usage: for( VectorSetI i(s); i.test(); i++ ) { body = i.elem; }
|
|
||||||
|
|
||||||
class VectorSetI : public StackObj {
|
|
||||||
friend class VectorSet;
|
|
||||||
const VectorSet *s;
|
|
||||||
uint i, j;
|
|
||||||
uint32_t mask;
|
|
||||||
uint next(void);
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint elem; // The publically accessible element
|
|
||||||
|
|
||||||
VectorSetI( const VectorSet *vset ) :
|
|
||||||
s(vset),
|
|
||||||
i((uint)-1L),
|
|
||||||
j((uint)-1L),
|
|
||||||
mask((unsigned)(1L<<31)) {
|
|
||||||
elem = next();
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator ++(void) { elem = next(); }
|
|
||||||
int test(void) { return i < s->size; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_LIBADT_VECTSET_HPP
|
#endif // SHARE_LIBADT_VECTSET_HPP
|
||||||
|
@ -1197,12 +1197,12 @@ void PhaseChaitin::Simplify( ) {
|
|||||||
|
|
||||||
// Check for just becoming of-low-degree just counting registers.
|
// Check for just becoming of-low-degree just counting registers.
|
||||||
// _must_spill live ranges are already on the low degree list.
|
// _must_spill live ranges are already on the low degree list.
|
||||||
if( n->just_lo_degree() && !n->_must_spill ) {
|
if (n->just_lo_degree() && !n->_must_spill) {
|
||||||
assert(!(*_ifg->_yanked)[neighbor],"Cannot move to lo degree twice");
|
assert(!_ifg->_yanked->test(neighbor), "Cannot move to lo degree twice");
|
||||||
// Pull from hi-degree list
|
// Pull from hi-degree list
|
||||||
uint prev = n->_prev;
|
uint prev = n->_prev;
|
||||||
uint next = n->_next;
|
uint next = n->_next;
|
||||||
if( prev ) lrgs(prev)._next = next;
|
if (prev) lrgs(prev)._next = next;
|
||||||
else _hi_degree = next;
|
else _hi_degree = next;
|
||||||
lrgs(next)._prev = prev;
|
lrgs(next)._prev = prev;
|
||||||
n->_next = _lo_degree;
|
n->_next = _lo_degree;
|
||||||
@ -1212,7 +1212,7 @@ void PhaseChaitin::Simplify( ) {
|
|||||||
} // End of while lo-degree/lo_stk_degree worklist not empty
|
} // End of while lo-degree/lo_stk_degree worklist not empty
|
||||||
|
|
||||||
// Check for got everything: is hi-degree list empty?
|
// Check for got everything: is hi-degree list empty?
|
||||||
if( !_hi_degree ) break;
|
if (!_hi_degree) break;
|
||||||
|
|
||||||
// Time to pick a potential spill guy
|
// Time to pick a potential spill guy
|
||||||
uint lo_score = _hi_degree;
|
uint lo_score = _hi_degree;
|
||||||
@ -1223,8 +1223,8 @@ void PhaseChaitin::Simplify( ) {
|
|||||||
|
|
||||||
// Find cheapest guy
|
// Find cheapest guy
|
||||||
debug_only( int lo_no_simplify=0; );
|
debug_only( int lo_no_simplify=0; );
|
||||||
for( uint i = _hi_degree; i; i = lrgs(i)._next ) {
|
for (uint i = _hi_degree; i; i = lrgs(i)._next) {
|
||||||
assert( !(*_ifg->_yanked)[i], "" );
|
assert(!_ifg->_yanked->test(i), "");
|
||||||
// It's just vaguely possible to move hi-degree to lo-degree without
|
// It's just vaguely possible to move hi-degree to lo-degree without
|
||||||
// going through a just-lo-degree stage: If you remove a double from
|
// going through a just-lo-degree stage: If you remove a double from
|
||||||
// a float live range it's degree will drop by 2 and you can skip the
|
// a float live range it's degree will drop by 2 and you can skip the
|
||||||
@ -1249,7 +1249,7 @@ void PhaseChaitin::Simplify( ) {
|
|||||||
// one block. In which case their area is 0 and score set to max.
|
// one block. In which case their area is 0 and score set to max.
|
||||||
// In such case choose bound live range over unbound to free registers
|
// In such case choose bound live range over unbound to free registers
|
||||||
// or with smaller cost to spill.
|
// or with smaller cost to spill.
|
||||||
if( iscore < score ||
|
if ( iscore < score ||
|
||||||
(iscore == score && iarea > area && lrgs(lo_score)._was_spilled2) ||
|
(iscore == score && iarea > area && lrgs(lo_score)._was_spilled2) ||
|
||||||
(iscore == score && iarea == area &&
|
(iscore == score && iarea == area &&
|
||||||
( (ibound && !bound) || (ibound == bound && (icost < cost)) )) ) {
|
( (ibound && !bound) || (ibound == bound && (icost < cost)) )) ) {
|
||||||
@ -1332,7 +1332,7 @@ OptoReg::Name PhaseChaitin::bias_color( LRG &lrg, int chunk ) {
|
|||||||
uint copy_lrg = _lrg_map.find(lrg._copy_bias);
|
uint copy_lrg = _lrg_map.find(lrg._copy_bias);
|
||||||
if( copy_lrg != 0 ) {
|
if( copy_lrg != 0 ) {
|
||||||
// If he has a color,
|
// If he has a color,
|
||||||
if( !(*(_ifg->_yanked))[copy_lrg] ) {
|
if(!_ifg->_yanked->test(copy_lrg)) {
|
||||||
OptoReg::Name reg = lrgs(copy_lrg).reg();
|
OptoReg::Name reg = lrgs(copy_lrg).reg();
|
||||||
// And it is legal for you,
|
// And it is legal for you,
|
||||||
if (is_legal_reg(lrg, reg, chunk))
|
if (is_legal_reg(lrg, reg, chunk))
|
||||||
|
@ -338,7 +338,7 @@ void Compile::update_dead_node_list(Unique_Node_List &useful) {
|
|||||||
for (uint node_idx = 0; node_idx < max_idx; node_idx++) {
|
for (uint node_idx = 0; node_idx < max_idx; node_idx++) {
|
||||||
// If node with index node_idx is not in useful set,
|
// If node with index node_idx is not in useful set,
|
||||||
// mark it as dead in dead node list.
|
// mark it as dead in dead node list.
|
||||||
if (! useful_node_set.test(node_idx) ) {
|
if (!useful_node_set.test(node_idx)) {
|
||||||
record_dead_node(node_idx);
|
record_dead_node(node_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -915,9 +915,7 @@ class Compile : public Phase {
|
|||||||
void record_dead_node(uint idx) { if (_dead_node_list.test_set(idx)) return;
|
void record_dead_node(uint idx) { if (_dead_node_list.test_set(idx)) return;
|
||||||
_dead_node_count++;
|
_dead_node_count++;
|
||||||
}
|
}
|
||||||
bool is_dead_node(uint idx) { return _dead_node_list.test(idx) != 0; }
|
void reset_dead_node_list() { _dead_node_list.reset();
|
||||||
uint dead_node_count() { return _dead_node_count; }
|
|
||||||
void reset_dead_node_list() { _dead_node_list.Reset();
|
|
||||||
_dead_node_count = 0;
|
_dead_node_count = 0;
|
||||||
}
|
}
|
||||||
uint live_nodes() const {
|
uint live_nodes() const {
|
||||||
|
@ -1414,7 +1414,7 @@ int ConnectionGraph::add_java_object_edges(JavaObjectNode* jobj, bool populate_w
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_worklist.clear();
|
_worklist.clear();
|
||||||
_in_worklist.Reset();
|
_in_worklist.reset();
|
||||||
return new_edges;
|
return new_edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,7 +850,7 @@ Node_Backward_Iterator::Node_Backward_Iterator( Node *root, VectorSet &visited,
|
|||||||
stack.push(root, root->outcnt());
|
stack.push(root, root->outcnt());
|
||||||
|
|
||||||
// Clear the visited bits
|
// Clear the visited bits
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterator for the Node_Backward_Iterator
|
// Iterator for the Node_Backward_Iterator
|
||||||
@ -1372,7 +1372,7 @@ void PhaseCFG::global_code_motion() {
|
|||||||
// Find the earliest Block any instruction can be placed in. Some
|
// Find the earliest Block any instruction can be placed in. Some
|
||||||
// instructions are pinned into Blocks. Unpinned instructions can
|
// instructions are pinned into Blocks. Unpinned instructions can
|
||||||
// appear in last block in which all their inputs occur.
|
// appear in last block in which all their inputs occur.
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
Node_Stack stack(arena, (C->live_nodes() >> 2) + 16); // pre-grow
|
Node_Stack stack(arena, (C->live_nodes() >> 2) + 16); // pre-grow
|
||||||
if (!schedule_early(visited, stack)) {
|
if (!schedule_early(visited, stack)) {
|
||||||
// Bailout without retry
|
// Bailout without retry
|
||||||
@ -1392,7 +1392,7 @@ void PhaseCFG::global_code_motion() {
|
|||||||
// Now schedule all codes as LATE as possible. This is the LCA in the
|
// Now schedule all codes as LATE as possible. This is the LCA in the
|
||||||
// dominator tree of all USES of a value. Pick the block with the least
|
// dominator tree of all USES of a value. Pick the block with the least
|
||||||
// loop nesting depth that is lowest in the dominator tree.
|
// loop nesting depth that is lowest in the dominator tree.
|
||||||
// ( visited.Clear() called in schedule_late()->Node_Backward_Iterator() )
|
// ( visited.clear() called in schedule_late()->Node_Backward_Iterator() )
|
||||||
schedule_late(visited, stack);
|
schedule_late(visited, stack);
|
||||||
if (C->failing()) {
|
if (C->failing()) {
|
||||||
// schedule_late fails only when graph is incorrect.
|
// schedule_late fails only when graph is incorrect.
|
||||||
@ -1473,7 +1473,7 @@ void PhaseCFG::global_code_motion() {
|
|||||||
// Schedule locally. Right now a simple topological sort.
|
// Schedule locally. Right now a simple topological sort.
|
||||||
// Later, do a real latency aware scheduler.
|
// Later, do a real latency aware scheduler.
|
||||||
GrowableArray<int> ready_cnt(C->unique(), C->unique(), -1);
|
GrowableArray<int> ready_cnt(C->unique(), C->unique(), -1);
|
||||||
visited.Clear();
|
visited.reset();
|
||||||
for (uint i = 0; i < number_of_blocks(); i++) {
|
for (uint i = 0; i < number_of_blocks(); i++) {
|
||||||
Block* block = get_block(i);
|
Block* block = get_block(i);
|
||||||
if (!schedule_local(block, ready_cnt, visited, recalc_pressure_nodes)) {
|
if (!schedule_local(block, ready_cnt, visited, recalc_pressure_nodes)) {
|
||||||
|
@ -584,7 +584,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
|
|||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (node->debug_orig() != NULL) {
|
if (node->debug_orig() != NULL) {
|
||||||
temp_set->Clear();
|
temp_set->clear();
|
||||||
stringStream dorigStream;
|
stringStream dorigStream;
|
||||||
Node* dorig = node->debug_orig();
|
Node* dorig = node->debug_orig();
|
||||||
while (dorig && temp_set->test_set(dorig->_idx)) {
|
while (dorig && temp_set->test_set(dorig->_idx)) {
|
||||||
|
@ -141,10 +141,10 @@ IndexSet *PhaseIFG::remove_node( uint a ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Re-insert a yanked Node.
|
// Re-insert a yanked Node.
|
||||||
void PhaseIFG::re_insert( uint a ) {
|
void PhaseIFG::re_insert(uint a) {
|
||||||
assert( _is_square, "only on square" );
|
assert( _is_square, "only on square" );
|
||||||
assert( _yanked->test(a), "" );
|
assert( _yanked->test(a), "" );
|
||||||
(*_yanked) >>= a;
|
_yanked->remove(a);
|
||||||
|
|
||||||
IndexSetIterator elements(&_adjs[a]);
|
IndexSetIterator elements(&_adjs[a]);
|
||||||
uint datum;
|
uint datum;
|
||||||
@ -198,7 +198,7 @@ void PhaseIFG::dump() const {
|
|||||||
_is_square ? "square" : "triangular" );
|
_is_square ? "square" : "triangular" );
|
||||||
if( _is_square ) {
|
if( _is_square ) {
|
||||||
for( uint i = 0; i < _maxlrg; i++ ) {
|
for( uint i = 0; i < _maxlrg; i++ ) {
|
||||||
tty->print( (*_yanked)[i] ? "XX " : " ");
|
tty->print(_yanked->test(i) ? "XX " : " ");
|
||||||
tty->print("L%d: { ",i);
|
tty->print("L%d: { ",i);
|
||||||
IndexSetIterator elements(&_adjs[i]);
|
IndexSetIterator elements(&_adjs[i]);
|
||||||
uint datum;
|
uint datum;
|
||||||
@ -214,7 +214,7 @@ void PhaseIFG::dump() const {
|
|||||||
// Triangular
|
// Triangular
|
||||||
for( uint i = 0; i < _maxlrg; i++ ) {
|
for( uint i = 0; i < _maxlrg; i++ ) {
|
||||||
uint j;
|
uint j;
|
||||||
tty->print( (*_yanked)[i] ? "XX " : " ");
|
tty->print(_yanked->test(i) ? "XX " : " ");
|
||||||
tty->print("L%d: { ",i);
|
tty->print("L%d: { ",i);
|
||||||
for( j = _maxlrg; j > i; j-- )
|
for( j = _maxlrg; j > i; j-- )
|
||||||
if( test_edge(j - 1,i) ) {
|
if( test_edge(j - 1,i) ) {
|
||||||
@ -249,7 +249,7 @@ void PhaseIFG::stats() const {
|
|||||||
void PhaseIFG::verify( const PhaseChaitin *pc ) const {
|
void PhaseIFG::verify( const PhaseChaitin *pc ) const {
|
||||||
// IFG is square, sorted and no need for Find
|
// IFG is square, sorted and no need for Find
|
||||||
for( uint i = 0; i < _maxlrg; i++ ) {
|
for( uint i = 0; i < _maxlrg; i++ ) {
|
||||||
assert(!((*_yanked)[i]) || !neighbor_cnt(i), "Is removed completely" );
|
assert(!_yanked->test(i) || !neighbor_cnt(i), "Is removed completely" );
|
||||||
IndexSet *set = &_adjs[i];
|
IndexSet *set = &_adjs[i];
|
||||||
IndexSetIterator elements(set);
|
IndexSetIterator elements(set);
|
||||||
uint idx;
|
uint idx;
|
||||||
@ -258,7 +258,7 @@ void PhaseIFG::verify( const PhaseChaitin *pc ) const {
|
|||||||
assert(idx != i, "Must have empty diagonal");
|
assert(idx != i, "Must have empty diagonal");
|
||||||
assert(pc->_lrg_map.find_const(idx) == idx, "Must not need Find");
|
assert(pc->_lrg_map.find_const(idx) == idx, "Must not need Find");
|
||||||
assert(_adjs[idx].member(i), "IFG not square");
|
assert(_adjs[idx].member(i), "IFG not square");
|
||||||
assert(!(*_yanked)[idx], "No yanked neighbors");
|
assert(!_yanked->test(idx), "No yanked neighbors");
|
||||||
assert(last < idx, "not sorted increasing");
|
assert(last < idx, "not sorted increasing");
|
||||||
last = idx;
|
last = idx;
|
||||||
}
|
}
|
||||||
|
@ -2121,7 +2121,7 @@ bool IdealLoopTree::beautify_loops( PhaseIdealLoop *phase ) {
|
|||||||
void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack) {
|
void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack) {
|
||||||
assert(stack.size() == 0, "empty stack");
|
assert(stack.size() == 0, "empty stack");
|
||||||
stack.push(_tail);
|
stack.push(_tail);
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
visited.set(_tail->_idx);
|
visited.set(_tail->_idx);
|
||||||
while (stack.size() > 0) {
|
while (stack.size() > 0) {
|
||||||
Node* n = stack.pop();
|
Node* n = stack.pop();
|
||||||
@ -2930,12 +2930,12 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
|
|||||||
int stack_size = (C->live_nodes() >> 1) + 16; // (live_nodes>>1)+16 from Java2D stats
|
int stack_size = (C->live_nodes() >> 1) + 16; // (live_nodes>>1)+16 from Java2D stats
|
||||||
Node_Stack nstack( a, stack_size );
|
Node_Stack nstack( a, stack_size );
|
||||||
|
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
Node_List worklist(a);
|
Node_List worklist(a);
|
||||||
// Don't need C->root() on worklist since
|
// Don't need C->root() on worklist since
|
||||||
// it will be processed among C->top() inputs
|
// it will be processed among C->top() inputs
|
||||||
worklist.push( C->top() );
|
worklist.push(C->top());
|
||||||
visited.set( C->top()->_idx ); // Set C->top() as visited now
|
visited.set(C->top()->_idx); // Set C->top() as visited now
|
||||||
build_loop_early( visited, worklist, nstack );
|
build_loop_early( visited, worklist, nstack );
|
||||||
|
|
||||||
// Given early legal placement, try finding counted loops. This placement
|
// Given early legal placement, try finding counted loops. This placement
|
||||||
@ -2945,12 +2945,12 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find latest loop placement. Find ideal loop placement.
|
// Find latest loop placement. Find ideal loop placement.
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
init_dom_lca_tags();
|
init_dom_lca_tags();
|
||||||
// Need C->root() on worklist when processing outs
|
// Need C->root() on worklist when processing outs
|
||||||
worklist.push( C->root() );
|
worklist.push(C->root());
|
||||||
NOT_PRODUCT( C->verify_graph_edges(); )
|
NOT_PRODUCT( C->verify_graph_edges(); )
|
||||||
worklist.push( C->top() );
|
worklist.push(C->top());
|
||||||
build_loop_late( visited, worklist, nstack );
|
build_loop_late( visited, worklist, nstack );
|
||||||
|
|
||||||
if (_verify_only) {
|
if (_verify_only) {
|
||||||
@ -3046,7 +3046,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
|
|||||||
// Check for aggressive application of split-if and other transforms
|
// Check for aggressive application of split-if and other transforms
|
||||||
// that require basic-block info (like cloning through Phi's)
|
// that require basic-block info (like cloning through Phi's)
|
||||||
if( SplitIfBlocks && do_split_ifs ) {
|
if( SplitIfBlocks && do_split_ifs ) {
|
||||||
visited.Clear();
|
visited.clear();
|
||||||
split_if_with_blocks( visited, nstack);
|
split_if_with_blocks( visited, nstack);
|
||||||
NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); );
|
NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); );
|
||||||
}
|
}
|
||||||
|
@ -2726,7 +2726,7 @@ void PhaseIdealLoop::clone_for_special_use_inside_loop( IdealLoopTree *loop, Nod
|
|||||||
_igvn.register_new_node_with_optimizer(n_clone);
|
_igvn.register_new_node_with_optimizer(n_clone);
|
||||||
set_ctrl(n_clone, get_ctrl(n));
|
set_ctrl(n_clone, get_ctrl(n));
|
||||||
sink_list.push(n_clone);
|
sink_list.push(n_clone);
|
||||||
not_peel <<= n_clone->_idx; // add n_clone to not_peel set.
|
not_peel.set(n_clone->_idx);
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (TracePartialPeeling) {
|
if (TracePartialPeeling) {
|
||||||
tty->print_cr("special not_peeled cloning old: %d new: %d", n->_idx, n_clone->_idx);
|
tty->print_cr("special not_peeled cloning old: %d new: %d", n->_idx, n_clone->_idx);
|
||||||
@ -3236,8 +3236,8 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
|
|||||||
if (n->in(0) == NULL && !n->is_Load() && !n->is_CMove()) {
|
if (n->in(0) == NULL && !n->is_Load() && !n->is_CMove()) {
|
||||||
cloned_for_outside_use += clone_for_use_outside_loop(loop, n, worklist);
|
cloned_for_outside_use += clone_for_use_outside_loop(loop, n, worklist);
|
||||||
sink_list.push(n);
|
sink_list.push(n);
|
||||||
peel >>= n->_idx; // delete n from peel set.
|
peel.remove(n->_idx);
|
||||||
not_peel <<= n->_idx; // add n to not_peel set.
|
not_peel.set(n->_idx);
|
||||||
peel_list.remove(i);
|
peel_list.remove(i);
|
||||||
incr = false;
|
incr = false;
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -157,7 +157,7 @@ void Matcher::verify_new_nodes_only(Node* xroot) {
|
|||||||
worklist.push(xroot);
|
worklist.push(xroot);
|
||||||
while (worklist.size() > 0) {
|
while (worklist.size() > 0) {
|
||||||
Node* n = worklist.pop();
|
Node* n = worklist.pop();
|
||||||
visited <<= n->_idx;
|
visited.set(n->_idx);
|
||||||
assert(C->node_arena()->contains(n), "dead node");
|
assert(C->node_arena()->contains(n), "dead node");
|
||||||
for (uint j = 0; j < n->req(); j++) {
|
for (uint j = 0; j < n->req(); j++) {
|
||||||
Node* in = n->in(j);
|
Node* in = n->in(j);
|
||||||
@ -340,7 +340,7 @@ void Matcher::match( ) {
|
|||||||
|
|
||||||
// Recursively match trees from old space into new space.
|
// Recursively match trees from old space into new space.
|
||||||
// Correct leaves of new-space Nodes; they point to old-space.
|
// Correct leaves of new-space Nodes; they point to old-space.
|
||||||
_visited.Clear(); // Clear visit bits for xform call
|
_visited.clear();
|
||||||
C->set_cached_top_node(xform( C->top(), live_nodes ));
|
C->set_cached_top_node(xform( C->top(), live_nodes ));
|
||||||
if (!C->failing()) {
|
if (!C->failing()) {
|
||||||
Node* xroot = xform( C->root(), 1 );
|
Node* xroot = xform( C->root(), 1 );
|
||||||
|
@ -2399,14 +2399,15 @@ void Node_List::dump_simple() const {
|
|||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//------------------------------remove-----------------------------------------
|
//------------------------------remove-----------------------------------------
|
||||||
void Unique_Node_List::remove( Node *n ) {
|
void Unique_Node_List::remove(Node* n) {
|
||||||
if( _in_worklist[n->_idx] ) {
|
if (_in_worklist.test(n->_idx)) {
|
||||||
for( uint i = 0; i < size(); i++ )
|
for (uint i = 0; i < size(); i++) {
|
||||||
if( _nodes[i] == n ) {
|
if (_nodes[i] == n) {
|
||||||
map(i,Node_List::pop());
|
map(i, Node_List::pop());
|
||||||
_in_worklist >>= n->_idx;
|
_in_worklist.remove(n->_idx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2415,11 +2416,11 @@ void Unique_Node_List::remove( Node *n ) {
|
|||||||
// Remove useless nodes from worklist
|
// Remove useless nodes from worklist
|
||||||
void Unique_Node_List::remove_useless_nodes(VectorSet &useful) {
|
void Unique_Node_List::remove_useless_nodes(VectorSet &useful) {
|
||||||
|
|
||||||
for( uint i = 0; i < size(); ++i ) {
|
for (uint i = 0; i < size(); ++i) {
|
||||||
Node *n = at(i);
|
Node *n = at(i);
|
||||||
assert( n != NULL, "Did not expect null entries in worklist");
|
assert( n != NULL, "Did not expect null entries in worklist");
|
||||||
if( ! useful.test(n->_idx) ) {
|
if (!useful.test(n->_idx)) {
|
||||||
_in_worklist >>= n->_idx;
|
_in_worklist.remove(n->_idx);
|
||||||
map(i,Node_List::pop());
|
map(i,Node_List::pop());
|
||||||
// Node *replacement = Node_List::pop();
|
// Node *replacement = Node_List::pop();
|
||||||
// if( i != size() ) { // Check if removing last entry
|
// if( i != size() ) { // Check if removing last entry
|
||||||
|
@ -1521,9 +1521,9 @@ public:
|
|||||||
|
|
||||||
void remove( Node *n );
|
void remove( Node *n );
|
||||||
bool member( Node *n ) { return _in_worklist.test(n->_idx) != 0; }
|
bool member( Node *n ) { return _in_worklist.test(n->_idx) != 0; }
|
||||||
VectorSet &member_set(){ return _in_worklist; }
|
VectorSet& member_set(){ return _in_worklist; }
|
||||||
|
|
||||||
void push( Node *b ) {
|
void push(Node* b) {
|
||||||
if( !_in_worklist.test_set(b->_idx) )
|
if( !_in_worklist.test_set(b->_idx) )
|
||||||
Node_List::push(b);
|
Node_List::push(b);
|
||||||
}
|
}
|
||||||
@ -1532,24 +1532,27 @@ public:
|
|||||||
Node *b = at(_clock_index);
|
Node *b = at(_clock_index);
|
||||||
map( _clock_index, Node_List::pop());
|
map( _clock_index, Node_List::pop());
|
||||||
if (size() != 0) _clock_index++; // Always start from 0
|
if (size() != 0) _clock_index++; // Always start from 0
|
||||||
_in_worklist >>= b->_idx;
|
_in_worklist.remove(b->_idx);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
Node *remove( uint i ) {
|
Node *remove(uint i) {
|
||||||
Node *b = Node_List::at(i);
|
Node *b = Node_List::at(i);
|
||||||
_in_worklist >>= b->_idx;
|
_in_worklist.remove(b->_idx);
|
||||||
map(i,Node_List::pop());
|
map(i,Node_List::pop());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
void yank( Node *n ) { _in_worklist >>= n->_idx; Node_List::yank(n); }
|
void yank(Node *n) {
|
||||||
|
_in_worklist.remove(n->_idx);
|
||||||
|
Node_List::yank(n);
|
||||||
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
_in_worklist.Clear(); // Discards storage but grows automatically
|
_in_worklist.clear(); // Discards storage but grows automatically
|
||||||
Node_List::clear();
|
Node_List::clear();
|
||||||
_clock_index = 0;
|
_clock_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used after parsing to remove useless nodes before Iterative GVN
|
// Used after parsing to remove useless nodes before Iterative GVN
|
||||||
void remove_useless_nodes(VectorSet &useful);
|
void remove_useless_nodes(VectorSet& useful);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void print_set() const { _in_worklist.print(); }
|
void print_set() const { _in_worklist.print(); }
|
||||||
|
@ -91,7 +91,7 @@ public:
|
|||||||
return _table[table_index];
|
return _table[table_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_useless_nodes(VectorSet &useful); // replace with sentinel
|
void remove_useless_nodes(VectorSet& useful); // replace with sentinel
|
||||||
void replace_with(NodeHash* nh);
|
void replace_with(NodeHash* nh);
|
||||||
void check_no_speculative_types(); // Check no speculative part for type nodes in table
|
void check_no_speculative_types(); // Check no speculative part for type nodes in table
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ Node_List PhaseStringOpts::collect_toString_calls() {
|
|||||||
Node_List string_calls;
|
Node_List string_calls;
|
||||||
Node_List worklist;
|
Node_List worklist;
|
||||||
|
|
||||||
_visited.Clear();
|
_visited.clear();
|
||||||
|
|
||||||
// Prime the worklist
|
// Prime the worklist
|
||||||
for (uint i = 1; i < C->root()->len(); i++) {
|
for (uint i = 1; i < C->root()->len(); i++) {
|
||||||
@ -1033,7 +1033,7 @@ bool StringConcat::validate_control_flow() {
|
|||||||
// Validate that all these results produced are contained within
|
// Validate that all these results produced are contained within
|
||||||
// this cluster of objects. First collect all the results produced
|
// this cluster of objects. First collect all the results produced
|
||||||
// by calls in the region.
|
// by calls in the region.
|
||||||
_stringopts->_visited.Clear();
|
_stringopts->_visited.clear();
|
||||||
Node_List worklist;
|
Node_List worklist;
|
||||||
Node* final_result = _end->proj_out_or_null(TypeFunc::Parms);
|
Node* final_result = _end->proj_out_or_null(TypeFunc::Parms);
|
||||||
for (uint i = 0; i < _control.size(); i++) {
|
for (uint i = 0; i < _control.size(); i++) {
|
||||||
|
@ -359,11 +359,11 @@ class SuperWord : public ResourceObj {
|
|||||||
void set_bb_idx(Node* n, int i) { _bb_idx.at_put_grow(n->_idx, i); }
|
void set_bb_idx(Node* n, int i) { _bb_idx.at_put_grow(n->_idx, i); }
|
||||||
|
|
||||||
// visited set accessors
|
// visited set accessors
|
||||||
void visited_clear() { _visited.Clear(); }
|
void visited_clear() { _visited.clear(); }
|
||||||
void visited_set(Node* n) { return _visited.set(bb_idx(n)); }
|
void visited_set(Node* n) { return _visited.set(bb_idx(n)); }
|
||||||
int visited_test(Node* n) { return _visited.test(bb_idx(n)); }
|
int visited_test(Node* n) { return _visited.test(bb_idx(n)); }
|
||||||
int visited_test_set(Node* n) { return _visited.test_set(bb_idx(n)); }
|
int visited_test_set(Node* n) { return _visited.test_set(bb_idx(n)); }
|
||||||
void post_visited_clear() { _post_visited.Clear(); }
|
void post_visited_clear() { _post_visited.clear(); }
|
||||||
void post_visited_set(Node* n) { return _post_visited.set(bb_idx(n)); }
|
void post_visited_set(Node* n) { return _post_visited.set(bb_idx(n)); }
|
||||||
int post_visited_test(Node* n) { return _post_visited.test(bb_idx(n)); }
|
int post_visited_test(Node* n) { return _post_visited.test(bb_idx(n)); }
|
||||||
|
|
||||||
|
@ -23,12 +23,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "libadt/vectset.hpp"
|
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#include "utilities/population_count.hpp"
|
#include "utilities/population_count.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
#include "unittest.hpp"
|
#include "unittest.hpp"
|
||||||
|
|
||||||
|
#define BITS_IN_BYTE_ARRAY_SIZE 256
|
||||||
|
|
||||||
uint8_t test_popcnt_bitsInByte[BITS_IN_BYTE_ARRAY_SIZE] = {
|
uint8_t test_popcnt_bitsInByte[BITS_IN_BYTE_ARRAY_SIZE] = {
|
||||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user