Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/symbolTable.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | ace99a6ffc83 |
children | 2aa953165ade |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
46 | 46 |
47 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { | 47 Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) { |
48 assert (len <= Symbol::max_length(), "should be checked by caller"); | 48 assert (len <= Symbol::max_length(), "should be checked by caller"); |
49 | 49 |
50 Symbol* sym; | 50 Symbol* sym; |
51 // Allocate symbols in the C heap when dumping shared spaces in case there | 51 |
52 // are temporary symbols we can remove. | 52 if (c_heap) { |
53 if (c_heap || DumpSharedSpaces) { | |
54 // refcount starts as 1 | 53 // refcount starts as 1 |
54 assert(!DumpSharedSpaces, "never allocate to C heap"); | |
55 sym = new (len, THREAD) Symbol(name, len, 1); | 55 sym = new (len, THREAD) Symbol(name, len, 1); |
56 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); | |
57 } else { | |
58 if (DumpSharedSpaces) { | |
59 sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1); | |
56 } else { | 60 } else { |
57 sym = new (len, arena(), THREAD) Symbol(name, len, -1); | 61 sym = new (len, arena(), THREAD) Symbol(name, len, -1); |
58 } | 62 } |
59 assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); | 63 } |
60 return sym; | 64 return sym; |
61 } | 65 } |
62 | 66 |
63 void SymbolTable::initialize_symbols(int arena_alloc_size) { | 67 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
64 // Initialize the arena for global symbols, size passed in depends on CDS. | 68 // Initialize the arena for global symbols, size passed in depends on CDS. |
100 // end of the bucket. | 104 // end of the bucket. |
101 if (entry->is_shared() && !use_alternate_hashcode()) { | 105 if (entry->is_shared() && !use_alternate_hashcode()) { |
102 break; | 106 break; |
103 } | 107 } |
104 Symbol* s = entry->literal(); | 108 Symbol* s = entry->literal(); |
105 memory_total += s->object_size(); | 109 memory_total += s->size(); |
106 total++; | 110 total++; |
107 assert(s != NULL, "just checking"); | 111 assert(s != NULL, "just checking"); |
108 // If reference count is zero, remove. | 112 // If reference count is zero, remove. |
109 if (s->refcount() == 0) { | 113 if (s->refcount() == 0) { |
110 assert(!entry->is_shared(), "shared entries should be kept live"); | 114 assert(!entry->is_shared(), "shared entries should be kept live"); |
300 UNICODE::convert_to_utf8(name, utf16_length, chars); | 304 UNICODE::convert_to_utf8(name, utf16_length, chars); |
301 return lookup_only(chars, utf8_length, hash); | 305 return lookup_only(chars, utf8_length, hash); |
302 } | 306 } |
303 } | 307 } |
304 | 308 |
305 void SymbolTable::add(Handle class_loader, constantPoolHandle cp, | 309 void SymbolTable::add(ClassLoaderData* loader_data, constantPoolHandle cp, |
306 int names_count, | 310 int names_count, |
307 const char** names, int* lengths, int* cp_indices, | 311 const char** names, int* lengths, int* cp_indices, |
308 unsigned int* hashValues, TRAPS) { | 312 unsigned int* hashValues, TRAPS) { |
309 // Grab SymbolTable_lock first. | 313 // Grab SymbolTable_lock first. |
310 MutexLocker ml(SymbolTable_lock, THREAD); | 314 MutexLocker ml(SymbolTable_lock, THREAD); |
311 | 315 |
312 SymbolTable* table = the_table(); | 316 SymbolTable* table = the_table(); |
313 bool added = table->basic_add(class_loader, cp, names_count, names, lengths, | 317 bool added = table->basic_add(loader_data, cp, names_count, names, lengths, |
314 cp_indices, hashValues, CHECK); | 318 cp_indices, hashValues, CHECK); |
315 if (!added) { | 319 if (!added) { |
316 // do it the hard way | 320 // do it the hard way |
317 for (int i=0; i<names_count; i++) { | 321 for (int i=0; i<names_count; i++) { |
318 int index = table->hash_to_index(hashValues[i]); | 322 int index = table->hash_to_index(hashValues[i]); |
319 bool c_heap = class_loader() != NULL; | 323 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
320 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); | 324 Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); |
321 cp->symbol_at_put(cp_indices[i], sym); | 325 cp->symbol_at_put(cp_indices[i], sym); |
322 } | 326 } |
323 } | 327 } |
324 } | 328 } |
381 return sym; | 385 return sym; |
382 } | 386 } |
383 | 387 |
384 // This version of basic_add adds symbols in batch from the constant pool | 388 // This version of basic_add adds symbols in batch from the constant pool |
385 // parsing. | 389 // parsing. |
386 bool SymbolTable::basic_add(Handle class_loader, constantPoolHandle cp, | 390 bool SymbolTable::basic_add(ClassLoaderData* loader_data, constantPoolHandle cp, |
387 int names_count, | 391 int names_count, |
388 const char** names, int* lengths, | 392 const char** names, int* lengths, |
389 int* cp_indices, unsigned int* hashValues, | 393 int* cp_indices, unsigned int* hashValues, |
390 TRAPS) { | 394 TRAPS) { |
391 | 395 |
419 cp->symbol_at_put(cp_indices[i], test); | 423 cp->symbol_at_put(cp_indices[i], test); |
420 assert(test->refcount() != 0, "lookup should have incremented the count"); | 424 assert(test->refcount() != 0, "lookup should have incremented the count"); |
421 } else { | 425 } else { |
422 // Create a new symbol. The null class loader is never unloaded so these | 426 // Create a new symbol. The null class loader is never unloaded so these |
423 // are allocated specially in a permanent arena. | 427 // are allocated specially in a permanent arena. |
424 bool c_heap = class_loader() != NULL; | 428 bool c_heap = !loader_data->is_the_null_class_loader_data(); |
425 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); | 429 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); |
426 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? | 430 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? |
427 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); | 431 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
428 add_entry(index, entry); | 432 add_entry(index, entry); |
429 cp->symbol_at_put(cp_indices[i], sym); | 433 cp->symbol_at_put(cp_indices[i], sym); |
488 int memory_total = 0; | 492 int memory_total = 0; |
489 int count = 0; | 493 int count = 0; |
490 for (i = 0; i < the_table()->table_size(); i++) { | 494 for (i = 0; i < the_table()->table_size(); i++) { |
491 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); | 495 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
492 for ( ; p != NULL; p = p->next()) { | 496 for ( ; p != NULL; p = p->next()) { |
493 memory_total += p->literal()->object_size(); | 497 memory_total += p->literal()->size(); |
494 count++; | 498 count++; |
495 int counter = p->literal()->utf8_length(); | 499 int counter = p->literal()->utf8_length(); |
496 total += counter; | 500 total += counter; |
497 if (counter < results_length) { | 501 if (counter < results_length) { |
498 results[counter]++; | 502 results[counter]++; |
693 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), | 697 assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), |
694 "proposed name of symbol must be stable"); | 698 "proposed name of symbol must be stable"); |
695 | 699 |
696 Handle string; | 700 Handle string; |
697 // try to reuse the string if possible | 701 // try to reuse the string if possible |
698 if (!string_or_null.is_null() && (!JavaObjectsInPerm || string_or_null()->is_perm())) { | 702 if (!string_or_null.is_null()) { |
699 string = string_or_null; | 703 string = string_or_null; |
700 } else { | 704 } else { |
701 string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL); | 705 string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); |
702 } | 706 } |
703 | 707 |
704 // Grab the StringTable_lock before getting the_table() because it could | 708 // Grab the StringTable_lock before getting the_table() because it could |
705 // change at safepoint. | 709 // change at safepoint. |
706 MutexLocker ml(StringTable_lock, THREAD); | 710 MutexLocker ml(StringTable_lock, THREAD); |
795 for (int i = 0; i < the_table()->table_size(); ++i) { | 799 for (int i = 0; i < the_table()->table_size(); ++i) { |
796 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); | 800 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); |
797 for ( ; p != NULL; p = p->next()) { | 801 for ( ; p != NULL; p = p->next()) { |
798 oop s = p->literal(); | 802 oop s = p->literal(); |
799 guarantee(s != NULL, "interned string is NULL"); | 803 guarantee(s != NULL, "interned string is NULL"); |
800 guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace"); | |
801 unsigned int h = java_lang_String::hash_string(s); | 804 unsigned int h = java_lang_String::hash_string(s); |
802 guarantee(p->hash() == h, "broken hash in string table entry"); | 805 guarantee(p->hash() == h, "broken hash in string table entry"); |
803 guarantee(the_table()->hash_to_index(h) == i, | 806 guarantee(the_table()->hash_to_index(h) == i, |
804 "wrong index in string table"); | 807 "wrong index in string table"); |
805 } | 808 } |