Thu, 20 Nov 2008 16:56:09 -0800
6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
duke@435 | 1 | /* |
duke@435 | 2 | * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | // Inline function definitions for hashtable.hpp. |
duke@435 | 26 | |
duke@435 | 27 | |
duke@435 | 28 | // -------------------------------------------------------------------------- |
duke@435 | 29 | // Hash function |
duke@435 | 30 | |
duke@435 | 31 | // We originally used hashpjw, but hash P(31) gives just as good results |
duke@435 | 32 | // and is slighly faster. We would like a hash function that looks at every |
duke@435 | 33 | // character, since package names have large common prefixes, and also because |
duke@435 | 34 | // hash_or_fail does error checking while iterating. |
duke@435 | 35 | |
duke@435 | 36 | // hash P(31) from Kernighan & Ritchie |
duke@435 | 37 | |
duke@435 | 38 | inline unsigned int Hashtable::hash_symbol(const char* s, int len) { |
duke@435 | 39 | unsigned int h = 0; |
duke@435 | 40 | while (len-- > 0) { |
duke@435 | 41 | h = 31*h + (unsigned) *s; |
duke@435 | 42 | s++; |
duke@435 | 43 | } |
duke@435 | 44 | return h; |
duke@435 | 45 | } |
duke@435 | 46 | |
duke@435 | 47 | |
duke@435 | 48 | // -------------------------------------------------------------------------- |
duke@435 | 49 | |
duke@435 | 50 | // Initialize a table. |
duke@435 | 51 | |
duke@435 | 52 | inline BasicHashtable::BasicHashtable(int table_size, int entry_size) { |
duke@435 | 53 | // Called on startup, no locking needed |
duke@435 | 54 | initialize(table_size, entry_size, 0); |
duke@435 | 55 | _buckets = NEW_C_HEAP_ARRAY(HashtableBucket, table_size); |
duke@435 | 56 | for (int index = 0; index < _table_size; index++) { |
duke@435 | 57 | _buckets[index].clear(); |
duke@435 | 58 | } |
duke@435 | 59 | } |
duke@435 | 60 | |
duke@435 | 61 | |
duke@435 | 62 | inline BasicHashtable::BasicHashtable(int table_size, int entry_size, |
duke@435 | 63 | HashtableBucket* buckets, |
duke@435 | 64 | int number_of_entries) { |
duke@435 | 65 | // Called on startup, no locking needed |
duke@435 | 66 | initialize(table_size, entry_size, number_of_entries); |
duke@435 | 67 | _buckets = buckets; |
duke@435 | 68 | } |
duke@435 | 69 | |
duke@435 | 70 | |
duke@435 | 71 | inline void BasicHashtable::initialize(int table_size, int entry_size, |
duke@435 | 72 | int number_of_entries) { |
duke@435 | 73 | // Called on startup, no locking needed |
duke@435 | 74 | _table_size = table_size; |
duke@435 | 75 | _entry_size = entry_size; |
duke@435 | 76 | _free_list = NULL; |
duke@435 | 77 | _first_free_entry = NULL; |
duke@435 | 78 | _end_block = NULL; |
duke@435 | 79 | _number_of_entries = number_of_entries; |
duke@435 | 80 | #ifdef ASSERT |
duke@435 | 81 | _lookup_count = 0; |
duke@435 | 82 | _lookup_length = 0; |
duke@435 | 83 | #endif |
duke@435 | 84 | } |
duke@435 | 85 | |
duke@435 | 86 | |
duke@435 | 87 | // The following method is MT-safe and may be used with caution. |
duke@435 | 88 | inline BasicHashtableEntry* BasicHashtable::bucket(int i) { |
duke@435 | 89 | return _buckets[i].get_entry(); |
duke@435 | 90 | } |
duke@435 | 91 | |
duke@435 | 92 | |
duke@435 | 93 | inline void HashtableBucket::set_entry(BasicHashtableEntry* l) { |
duke@435 | 94 | // Warning: Preserve store ordering. The SystemDictionary is read |
duke@435 | 95 | // without locks. The new SystemDictionaryEntry must be |
duke@435 | 96 | // complete before other threads can be allowed to see it |
duke@435 | 97 | // via a store to _buckets[index]. |
duke@435 | 98 | OrderAccess::release_store_ptr(&_entry, l); |
duke@435 | 99 | } |
duke@435 | 100 | |
duke@435 | 101 | |
duke@435 | 102 | inline BasicHashtableEntry* HashtableBucket::get_entry() const { |
duke@435 | 103 | // Warning: Preserve load ordering. The SystemDictionary is read |
duke@435 | 104 | // without locks. The new SystemDictionaryEntry must be |
duke@435 | 105 | // complete before other threads can be allowed to see it |
duke@435 | 106 | // via a store to _buckets[index]. |
duke@435 | 107 | return (BasicHashtableEntry*) OrderAccess::load_ptr_acquire(&_entry); |
duke@435 | 108 | } |
duke@435 | 109 | |
duke@435 | 110 | |
duke@435 | 111 | inline void BasicHashtable::set_entry(int index, BasicHashtableEntry* entry) { |
duke@435 | 112 | _buckets[index].set_entry(entry); |
duke@435 | 113 | } |
duke@435 | 114 | |
duke@435 | 115 | |
duke@435 | 116 | inline void BasicHashtable::add_entry(int index, BasicHashtableEntry* entry) { |
duke@435 | 117 | entry->set_next(bucket(index)); |
duke@435 | 118 | _buckets[index].set_entry(entry); |
duke@435 | 119 | ++_number_of_entries; |
duke@435 | 120 | } |
duke@435 | 121 | |
duke@435 | 122 | inline void BasicHashtable::free_entry(BasicHashtableEntry* entry) { |
duke@435 | 123 | entry->set_next(_free_list); |
duke@435 | 124 | _free_list = entry; |
duke@435 | 125 | --_number_of_entries; |
duke@435 | 126 | } |