25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "classfile/javaClasses.hpp" |
26 #include "classfile/javaClasses.hpp" |
27 #include "classfile/symbolTable.hpp" |
27 #include "classfile/symbolTable.hpp" |
28 #include "classfile/systemDictionary.hpp" |
28 #include "classfile/systemDictionary.hpp" |
29 #include "gc_interface/collectedHeap.inline.hpp" |
29 #include "gc_interface/collectedHeap.inline.hpp" |
|
30 #include "memory/allocation.inline.hpp" |
30 #include "memory/filemap.hpp" |
31 #include "memory/filemap.hpp" |
31 #include "memory/gcLocker.inline.hpp" |
32 #include "memory/gcLocker.inline.hpp" |
32 #include "oops/oop.inline.hpp" |
33 #include "oops/oop.inline.hpp" |
33 #include "oops/oop.inline2.hpp" |
34 #include "oops/oop.inline2.hpp" |
34 #include "runtime/mutexLocker.hpp" |
35 #include "runtime/mutexLocker.hpp" |
35 #include "utilities/hashtable.inline.hpp" |
36 #include "utilities/hashtable.inline.hpp" |
36 |
37 |
37 // -------------------------------------------------------------------------- |
38 // -------------------------------------------------------------------------- |
38 |
39 |
39 SymbolTable* SymbolTable::_the_table = NULL; |
40 SymbolTable* SymbolTable::_the_table = NULL; |
40 |
41 // Static arena for symbols that are not deallocated |
41 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) { |
42 Arena* SymbolTable::_arena = NULL; |
|
43 |
|
44 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { |
42 // Don't allow symbols to be created which cannot fit in a Symbol*. |
45 // Don't allow symbols to be created which cannot fit in a Symbol*. |
43 if (len > Symbol::max_length()) { |
46 if (len > Symbol::max_length()) { |
44 THROW_MSG_0(vmSymbols::java_lang_InternalError(), |
47 THROW_MSG_0(vmSymbols::java_lang_InternalError(), |
45 "name is too long to represent"); |
48 "name is too long to represent"); |
46 } |
49 } |
47 Symbol* sym = new (len) Symbol(name, len); |
50 Symbol* sym; |
|
51 // Allocate symbols in the C heap when dumping shared spaces in case there |
|
52 // are temporary symbols we can remove. |
|
53 if (c_heap || DumpSharedSpaces) { |
|
54 // refcount starts as 1 |
|
55 sym = new (len, THREAD) Symbol(name, len, 1); |
|
56 } else { |
|
57 sym = new (len, arena(), THREAD) Symbol(name, len, -1); |
|
58 } |
48 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); |
59 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); |
49 return sym; |
60 return sym; |
50 } |
61 } |
51 |
62 |
52 bool SymbolTable::allocate_symbols(int names_count, const u1** names, |
63 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
53 int* lengths, Symbol** syms, TRAPS) { |
64 // Initialize the arena for global symbols, size passed in depends on CDS. |
54 for (int i = 0; i< names_count; i++) { |
65 if (arena_alloc_size == 0) { |
55 if (lengths[i] > Symbol::max_length()) { |
66 _arena = new Arena(); |
56 THROW_MSG_0(vmSymbols::java_lang_InternalError(), |
67 } else { |
57 "name is too long to represent"); |
68 _arena = new Arena(arena_alloc_size); |
58 } |
69 } |
59 } |
|
60 |
|
61 for (int i = 0; i< names_count; i++) { |
|
62 int len = lengths[i]; |
|
63 syms[i] = new (len) Symbol(names[i], len); |
|
64 assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if " |
|
65 "C_HEAP is exhausted"); |
|
66 } |
|
67 return true; |
|
68 } |
70 } |
69 |
71 |
70 // Call function for all symbols in the symbol table. |
72 // Call function for all symbols in the symbol table. |
71 void SymbolTable::symbols_do(SymbolClosure *cl) { |
73 void SymbolTable::symbols_do(SymbolClosure *cl) { |
72 const int n = the_table()->table_size(); |
74 const int n = the_table()->table_size(); |
254 UNICODE::convert_to_utf8(name, utf16_length, chars); |
255 UNICODE::convert_to_utf8(name, utf16_length, chars); |
255 return lookup_only(chars, utf8_length, hash); |
256 return lookup_only(chars, utf8_length, hash); |
256 } |
257 } |
257 } |
258 } |
258 |
259 |
259 void SymbolTable::add(constantPoolHandle cp, int names_count, |
260 void SymbolTable::add(Handle class_loader, constantPoolHandle cp, |
|
261 int names_count, |
260 const char** names, int* lengths, int* cp_indices, |
262 const char** names, int* lengths, int* cp_indices, |
261 unsigned int* hashValues, TRAPS) { |
263 unsigned int* hashValues, TRAPS) { |
262 SymbolTable* table = the_table(); |
264 SymbolTable* table = the_table(); |
263 bool added = table->basic_add(cp, names_count, names, lengths, |
265 bool added = table->basic_add(class_loader, cp, names_count, names, lengths, |
264 cp_indices, hashValues, CHECK); |
266 cp_indices, hashValues, CHECK); |
265 if (!added) { |
267 if (!added) { |
266 // do it the hard way |
268 // do it the hard way |
267 for (int i=0; i<names_count; i++) { |
269 for (int i=0; i<names_count; i++) { |
268 int index = table->hash_to_index(hashValues[i]); |
270 int index = table->hash_to_index(hashValues[i]); |
269 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], |
271 bool c_heap = class_loader() != NULL; |
270 hashValues[i], CHECK); |
272 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); |
271 cp->symbol_at_put(cp_indices[i], sym); |
273 cp->symbol_at_put(cp_indices[i], sym); |
272 } |
274 } |
273 } |
275 } |
274 } |
276 } |
275 |
277 |
|
278 Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { |
|
279 unsigned int hash; |
|
280 Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash); |
|
281 if (result != NULL) { |
|
282 return result; |
|
283 } |
|
284 SymbolTable* table = the_table(); |
|
285 int index = table->hash_to_index(hash); |
|
286 return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD); |
|
287 } |
|
288 |
276 Symbol* SymbolTable::basic_add(int index, u1 *name, int len, |
289 Symbol* SymbolTable::basic_add(int index, u1 *name, int len, |
277 unsigned int hashValue, TRAPS) { |
290 unsigned int hashValue, bool c_heap, TRAPS) { |
278 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), |
291 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), |
279 "proposed name of symbol must be stable"); |
292 "proposed name of symbol must be stable"); |
280 |
293 |
281 // We assume that lookup() has been called already, that it failed, |
294 // Grab SymbolTable_lock first. |
282 // and symbol was not found. We create the symbol here. |
|
283 Symbol* sym = allocate_symbol(name, len, CHECK_NULL); |
|
284 |
|
285 // Allocation must be done before grabbing the SymbolTable_lock lock |
|
286 MutexLocker ml(SymbolTable_lock, THREAD); |
295 MutexLocker ml(SymbolTable_lock, THREAD); |
287 |
|
288 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); |
|
289 |
296 |
290 // Since look-up was done lock-free, we need to check if another |
297 // Since look-up was done lock-free, we need to check if another |
291 // thread beat us in the race to insert the symbol. |
298 // thread beat us in the race to insert the symbol. |
292 |
|
293 Symbol* test = lookup(index, (char*)name, len, hashValue); |
299 Symbol* test = lookup(index, (char*)name, len, hashValue); |
294 if (test != NULL) { |
300 if (test != NULL) { |
295 // A race occurred and another thread introduced the symbol, this one |
301 // A race occurred and another thread introduced the symbol. |
296 // will be dropped and collected. |
|
297 delete sym; |
|
298 assert(test->refcount() != 0, "lookup should have incremented the count"); |
302 assert(test->refcount() != 0, "lookup should have incremented the count"); |
299 return test; |
303 return test; |
300 } |
304 } |
301 |
305 |
|
306 // Create a new symbol. |
|
307 Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL); |
|
308 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); |
|
309 |
302 HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); |
310 HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); |
303 sym->increment_refcount(); |
|
304 add_entry(index, entry); |
311 add_entry(index, entry); |
305 return sym; |
312 return sym; |
306 } |
313 } |
307 |
314 |
308 bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, |
315 // This version of basic_add adds symbols in batch from the constant pool |
|
316 // parsing. |
|
317 bool SymbolTable::basic_add(Handle class_loader, constantPoolHandle cp, |
|
318 int names_count, |
309 const char** names, int* lengths, |
319 const char** names, int* lengths, |
310 int* cp_indices, unsigned int* hashValues, |
320 int* cp_indices, unsigned int* hashValues, |
311 TRAPS) { |
321 TRAPS) { |
312 Symbol* syms[symbol_alloc_batch_size]; |
322 |
313 bool allocated = allocate_symbols(names_count, (const u1**)names, lengths, |
323 // Check symbol names are not too long. If any are too long, don't add any. |
314 syms, CHECK_false); |
324 for (int i = 0; i< names_count; i++) { |
315 if (!allocated) { |
325 if (lengths[i] > Symbol::max_length()) { |
316 return false; |
326 THROW_MSG_0(vmSymbols::java_lang_InternalError(), |
317 } |
327 "name is too long to represent"); |
318 |
328 } |
319 // Allocation must be done before grabbing the SymbolTable_lock lock |
329 } |
|
330 |
|
331 // Hold SymbolTable_lock through the symbol creation |
320 MutexLocker ml(SymbolTable_lock, THREAD); |
332 MutexLocker ml(SymbolTable_lock, THREAD); |
321 |
333 |
322 for (int i=0; i<names_count; i++) { |
334 for (int i=0; i<names_count; i++) { |
323 assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized"); |
|
324 // Since look-up was done lock-free, we need to check if another |
335 // Since look-up was done lock-free, we need to check if another |
325 // thread beat us in the race to insert the symbol. |
336 // thread beat us in the race to insert the symbol. |
326 int index = hash_to_index(hashValues[i]); |
337 int index = hash_to_index(hashValues[i]); |
327 Symbol* test = lookup(index, names[i], lengths[i], hashValues[i]); |
338 Symbol* test = lookup(index, names[i], lengths[i], hashValues[i]); |
328 if (test != NULL) { |
339 if (test != NULL) { |
329 // A race occurred and another thread introduced the symbol, this one |
340 // A race occurred and another thread introduced the symbol, this one |
330 // will be dropped and collected. Use test instead. |
341 // will be dropped and collected. Use test instead. |
331 cp->symbol_at_put(cp_indices[i], test); |
342 cp->symbol_at_put(cp_indices[i], test); |
332 assert(test->refcount() != 0, "lookup should have incremented the count"); |
343 assert(test->refcount() != 0, "lookup should have incremented the count"); |
333 delete syms[i]; |
|
334 } else { |
344 } else { |
335 Symbol* sym = syms[i]; |
345 // Create a new symbol. The null class loader is never unloaded so these |
|
346 // are allocated specially in a permanent arena. |
|
347 bool c_heap = class_loader() != NULL; |
|
348 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); |
|
349 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? |
336 HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym); |
350 HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym); |
337 sym->increment_refcount(); // increment refcount in external hashtable |
|
338 add_entry(index, entry); |
351 add_entry(index, entry); |
339 cp->symbol_at_put(cp_indices[i], sym); |
352 cp->symbol_at_put(cp_indices[i], sym); |
340 } |
353 } |
341 } |
354 } |
342 |
|
343 return true; |
355 return true; |
344 } |
356 } |
345 |
357 |
346 |
358 |
347 void SymbolTable::verify() { |
359 void SymbolTable::verify() { |