< prev index next >

test/hotspot/gtest/classfile/test_symbolTable.cpp

Print this page
*** 25,30 ***
  #include "classfile/symbolTable.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "threadHelper.inline.hpp"
  #include "unittest.hpp"
  
  TEST_VM(SymbolTable, temp_new_symbol) {
    // Assert messages assume these symbols are unique, and the refcounts start at
    // one, but code does not rely on this.
    JavaThread* THREAD = JavaThread::current();
    // the thread should be in vm to use locks
    ThreadInVMfromNative ThreadInVMfromNative(THREAD);
  
    Symbol* abc = SymbolTable::new_symbol("abc");
    int abccount = abc->refcount();
!   TempNewSymbol ss = abc;
    ASSERT_EQ(ss->refcount(), abccount) << "only one abc";
    ASSERT_EQ(ss->refcount(), abc->refcount()) << "should match TempNewSymbol";
  
    Symbol* efg = SymbolTable::new_symbol("efg");
    Symbol* hij = SymbolTable::new_symbol("hij");
    int efgcount = efg->refcount();
    int hijcount = hij->refcount();
  
!   TempNewSymbol s1 = efg;
!   TempNewSymbol s2 = hij;
    ASSERT_EQ(s1->refcount(), efgcount) << "one efg";
    ASSERT_EQ(s2->refcount(), hijcount) << "one hij";
  
    // Assignment operator
    s1 = s2;
--- 25,38 ---
  #include "classfile/symbolTable.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "threadHelper.inline.hpp"
  #include "unittest.hpp"
  
+ // Helper to avoid interference from the cleanup delay queue by draining it
+ // immediately after creation.
+ TempNewSymbol stable_temp_symbol(Symbol* sym) {
+   TempNewSymbol t = sym;
+   TempSymbolCleanupDelayer::drain_queue();
+   return t;
+ }
+ 
  TEST_VM(SymbolTable, temp_new_symbol) {
    // Assert messages assume these symbols are unique, and the refcounts start at
    // one, but code does not rely on this.
    JavaThread* THREAD = JavaThread::current();
    // the thread should be in vm to use locks
    ThreadInVMfromNative ThreadInVMfromNative(THREAD);
  
    Symbol* abc = SymbolTable::new_symbol("abc");
    int abccount = abc->refcount();
!   TempNewSymbol ss = stable_temp_symbol(abc);
    ASSERT_EQ(ss->refcount(), abccount) << "only one abc";
    ASSERT_EQ(ss->refcount(), abc->refcount()) << "should match TempNewSymbol";
  
    Symbol* efg = SymbolTable::new_symbol("efg");
    Symbol* hij = SymbolTable::new_symbol("hij");
    int efgcount = efg->refcount();
    int hijcount = hij->refcount();
  
!   TempNewSymbol s1 = stable_temp_symbol(efg);
!   TempNewSymbol s2 = stable_temp_symbol(hij);
    ASSERT_EQ(s1->refcount(), efgcount) << "one efg";
    ASSERT_EQ(s2->refcount(), hijcount) << "one hij";
  
    // Assignment operator
    s1 = s2;

*** 63,17 ***
    ASSERT_EQ(s1->refcount(), abccount + 1) << "should still be two abc (s1 and ss)";
  
    TempNewSymbol s3;
    Symbol* klm = SymbolTable::new_symbol("klm");
    int klmcount = klm->refcount();
!   s3 = klm; // assignment
    ASSERT_EQ(s3->refcount(), klmcount) << "only one klm now";
  
    Symbol* xyz = SymbolTable::new_symbol("xyz");
    int xyzcount = xyz->refcount();
    { // inner scope
!     TempNewSymbol s_inner = xyz;
    }
    ASSERT_EQ(xyz->refcount(), xyzcount - 1)
            << "Should have been decremented by dtor in inner scope";
  
    // Test overflowing refcount making symbol permanent
--- 71,17 ---
    ASSERT_EQ(s1->refcount(), abccount + 1) << "should still be two abc (s1 and ss)";
  
    TempNewSymbol s3;
    Symbol* klm = SymbolTable::new_symbol("klm");
    int klmcount = klm->refcount();
!   s3 = stable_temp_symbol(klm); // assignment
    ASSERT_EQ(s3->refcount(), klmcount) << "only one klm now";
  
    Symbol* xyz = SymbolTable::new_symbol("xyz");
    int xyzcount = xyz->refcount();
    { // inner scope
!     TempNewSymbol s_inner = stable_temp_symbol(xyz);
    }
    ASSERT_EQ(xyz->refcount(), xyzcount - 1)
            << "Should have been decremented by dtor in inner scope";
  
    // Test overflowing refcount making symbol permanent

*** 137,5 ***
--- 145,52 ---
    // Note: relies on SymbolTable's use of String::hashCode which collides for these two values.
    Symbol* entry2 = SymbolTable::new_symbol("hash_collision_397476851");
  
    ASSERT_EQ(entry2->refcount(), 1) << "Symbol refcount just created is 1";
  }
+ 
+ TEST_VM(SymbolTable, test_cleanup_delay) {
+   // Check that new temp symbols have an extra refcount increment, which is then
+   // decremented when the queue spills over.
+ 
+   TempNewSymbol s1 = SymbolTable::new_symbol("temp-s1");
+   ASSERT_EQ(s1->refcount(), 2) << "TempNewSymbol refcount just created is 2";
+ 
+   // Fill up the queue
+   constexpr int symbol_name_length = 30;
+   char symbol_name[symbol_name_length];
+   for (uint i = 1; i < TempSymbolCleanupDelayer::QueueSize; i++) {
+     os::snprintf(symbol_name, symbol_name_length, "temp-filler-%d", i);
+     TempNewSymbol s = SymbolTable::new_symbol(symbol_name);
+     ASSERT_EQ(s->refcount(), 2) << "TempNewSymbol refcount just created is 2";
+   }
+ 
+   // Add one more
+   TempNewSymbol spillover = SymbolTable::new_symbol("temp-spillover");
+   ASSERT_EQ(spillover->refcount(), 2) << "TempNewSymbol refcount just created is 2";
+ 
+   // The first symbol should have been removed from the queue and decremented
+   ASSERT_EQ(s1->refcount(), 1) << "TempNewSymbol off queue refcount is 1";
+ }
+ 
+ TEST_VM(SymbolTable, test_cleanup_delay_drain) {
+   // Fill up the queue
+   constexpr int symbol_name_length = 30;
+   char symbol_name[symbol_name_length];
+   TempNewSymbol symbols[TempSymbolCleanupDelayer::QueueSize] = {};
+   for (uint i = 0; i < TempSymbolCleanupDelayer::QueueSize; i++) {
+     os::snprintf(symbol_name, symbol_name_length, "temp-%d", i);
+     TempNewSymbol s = SymbolTable::new_symbol(symbol_name);
+     symbols[i] = s;
+   }
+ 
+   // While in the queue refcounts are incremented
+   for (uint i = 0; i < TempSymbolCleanupDelayer::QueueSize; i++) {
+     ASSERT_EQ(symbols[i]->refcount(), 2) << "TempNewSymbol refcount in queue is 2";
+   }
+ 
+   // Draining the queue should decrement the refcounts
+   TempSymbolCleanupDelayer::drain_queue();
+   for (uint i = 0; i < TempSymbolCleanupDelayer::QueueSize; i++) {
+     ASSERT_EQ(symbols[i]->refcount(), 1) << "TempNewSymbol refcount after drain is 1";
+   }
+ }
< prev index next >