src/share/vm/classfile/symbolTable.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File

## src/share/vm/classfile/symbolTable.cpp

Print this page

    *** 95,104 ****
    --- 95,114 ----
      int SymbolTable::_symbols_removed = 0;
      int SymbolTable::_symbols_counted = 0;
      volatile int SymbolTable::_parallel_claimed_idx = 0;

      void SymbolTable::buckets_unlink(int start_idx, int end_idx, int* processed, int* removed, size_t* memory_total) {
    +   const int limit = the_table()->table_size();
    +
    +   assert(0 <= start_idx && start_idx <= limit,
    +          err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx));
    +   assert(0 <= end_idx && end_idx <= limit,
    +          err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx));
    +   assert(start_idx <= end_idx,
    +          err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
    +                  start_idx, end_idx));
    +
        for (int i = start_idx; i < end_idx; ++i) {
          HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
          HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
          while (entry != NULL) {
            // Shared entries are normally at the end of the bucket and if we run into
    *** 190,215 ****

      // Lookup a symbol in a bucket.

      Symbol* SymbolTable::lookup(int index, const char* name,
                                    int len, unsigned int hash) {
    !   int count = 0;
        for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) {
          count++;  // count all entries in this bucket, not just ones with same hash
          if (e->hash() == hash) {
            Symbol* sym = e->literal();
            if (sym->equals(name, len)) {
              // something is referencing this symbol now.
              sym->increment_refcount();
              return sym;
            }
          }
        }
        // If the bucket size is too deep check if this hash code is insufficient.
        if (count >= rehash_count && !needs_rehashing()) {
          _needs_rehashing = check_rehash_table(count);
        }
        return NULL;
      }

      // Pick hashing algorithm.
      unsigned int SymbolTable::hash_symbol(const char* s, int len) {
    --- 200,271 ----

      // Lookup a symbol in a bucket.

      Symbol* SymbolTable::lookup(int index, const char* name,
                                    int len, unsigned int hash) {
    ! #ifndef PRODUCT
    ! //#ifdef PRODUCT_TEST
    !   jlong time = os::javaTimeNanos();
    !   _debug_all_lookup_count++;
    !   _debug_lookup_count++;
    ! #endif
    !
    !   unsigned int count = 0;
        for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) {
          count++;  // count all entries in this bucket, not just ones with same hash
          if (e->hash() == hash) {
            Symbol* sym = e->literal();
            if (sym->equals(name, len)) {
              // something is referencing this symbol now.
              sym->increment_refcount();
    +
    +         e->_debug_lookups++;
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +         {
    +           unsigned int duration = os::javaTimeNanos()-time;
    +           _debug_lookup_found_count++;
    +           _debug_lookup_found_max_duration = (_debug_lookup_found_max_duration > duration) ? _debug_lookup_found_max_duration : duration;
    +           _debug_lookup_found_total_duration += duration;
    +           _debug_chain_found_maximum_length = (_debug_chain_found_maximum_length > count) ? _debug_chain_found_maximum_length : count;
    +           _debug_chain_found_total_length += count;
    +           //fprintf(stderr, "SymL %d:%d::%lu:\"%s\"\n", true, count, os::javaTimeNanos(), name);
    +
    +           long thread_id = os::current_thread_id();
    +           for (int i=0; i<1024; i++) {
    +             if (_debug_table_threads[i] == thread_id) {
    +               break;
    +             } else if (_debug_table_threads[i] == 0) {
    +               _debug_table_threads[i] = thread_id;
    +               break;
    +             }
    +           }
    +         }
    + #endif
    +
              return sym;
            }
          }
        }
        // If the bucket size is too deep check if this hash code is insufficient.
        if (count >= rehash_count && !needs_rehashing()) {
          _needs_rehashing = check_rehash_table(count);
        }
    +
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +   {
    +     unsigned int duration = os::javaTimeNanos()-time;
    +     _debug_lookup_failed_count++;
    +     _debug_lookup_failed_max_duration = (_debug_lookup_failed_max_duration > duration) ? _debug_lookup_failed_max_duration : duration;
    +     _debug_lookup_failed_total_duration += duration;
    +     _debug_chain_failed_maximum_length = (_debug_chain_failed_maximum_length > count) ? _debug_chain_failed_maximum_length : count;
    +     _debug_chain_failed_total_length += count;
    +     //fprintf(stderr, "SymL %d:%d::%lu:\"%s\"\n", false, count, os::javaTimeNanos(), name);
    +   }
    + #endif
    +
        return NULL;
      }

      // Pick hashing algorithm.
      unsigned int SymbolTable::hash_symbol(const char* s, int len) {
    *** 377,386 ****
    --- 433,443 ----
        return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD);
      }

      Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len,
                                     unsigned int hashValue_arg, bool c_heap, TRAPS) {
    +   assert(SymbolTable_lock->is_locked(), "must hold SymbolTable_lock");
        assert(!Universe::heap()->is_in_reserved(name),
               "proposed name of symbol must be stable");

        // Don't allow symbols to be created which cannot fit in a Symbol*.
        if (len > Symbol::max_length()) {
    *** 416,435 ****
    --- 473,503 ----
        Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
        assert(sym->equals((char*)name, len), "symbol must be properly initialized");

        HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
        add_entry(index, entry);
    +
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +   {
    +     _debug_all_insertion_count++;
    +     _debug_insertion_count++;
    +     //fprintf(stderr, "SymA %lu:\"%s\"\n", os::javaTimeNanos(), name);
    +   }
    + #endif
    +
        return sym;
      }

      // This version of basic_add adds symbols in batch from the constant pool
      // parsing.
      bool SymbolTable::basic_add(ClassLoaderData* loader_data, constantPoolHandle cp,
                                  int names_count,
                                  const char** names, int* lengths,
                                  int* cp_indices, unsigned int* hashValues,
                                  TRAPS) {
    +   assert(SymbolTable_lock->is_locked(), "must hold SymbolTable_lock");

        // Check symbol names are not too long.  If any are too long, don't add any.
        for (int i = 0; i< names_count; i++) {
          if (lengths[i] > Symbol::max_length()) {
            THROW_MSG_0(vmSymbols::java_lang_InternalError(),
    *** 465,504 ****
            Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
            assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized");  // why wouldn't it be???
            HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
            add_entry(index, entry);
            cp->symbol_at_put(cp_indices[i], sym);
          }
        }
        return true;
      }

    -
      void SymbolTable::verify() {
        for (int i = 0; i < the_table()->table_size(); ++i) {
          HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
          for ( ; p != NULL; p = p->next()) {
            Symbol* s = (Symbol*)(p->literal());
            guarantee(s != NULL, "symbol is NULL");
            unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
            guarantee(p->hash() == h, "broken hash in symbol table entry");
            guarantee(the_table()->hash_to_index(h) == i,
                      "wrong index in symbol table");
          }
        }
      }

    - void SymbolTable::dump(outputStream* st) {
    -   the_table()->dump_table(st, "SymbolTable");
    - }
    -
    -
      //---------------------------------------------------------------------------
      // Non-product code

      #ifndef PRODUCT
    -
      void SymbolTable::print_histogram() {
        MutexLocker ml(SymbolTable_lock);
        const int results_length = 100;
        int results[results_length];
        int i,j;
    --- 533,582 ----
            Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
            assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized");  // why wouldn't it be???
            HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
            add_entry(index, entry);
            cp->symbol_at_put(cp_indices[i], sym);
    +
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +       {
    +         _debug_all_insertion_count++;
    +         _debug_insertion_count++;
    +         //fprintf(stderr, "SymA %lu:\"%s\"\n", os::javaTimeNanos(), names[i]);
    +       }
    + #endif
    +
          }
        }
        return true;
      }

      void SymbolTable::verify() {
    +   MutexLocker mu(SymbolTable_lock);
    +   int actual_count = 0;
        for (int i = 0; i < the_table()->table_size(); ++i) {
          HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
          for ( ; p != NULL; p = p->next()) {
            Symbol* s = (Symbol*)(p->literal());
            guarantee(s != NULL, "symbol is NULL");
            unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
            guarantee(p->hash() == h, "broken hash in symbol table entry");
            guarantee(the_table()->hash_to_index(h) == i,
                      "wrong index in symbol table");
    +       actual_count++;
          }
        }
    +   if (the_table()->number_of_entries()!=actual_count) {
    +     tty->print("StringTable assert failure: number_of_entries()!=actual_count [%d!=%d]\n", the_table()->number_of_entries(), actual_count);
    +   }
    +   guarantee(the_table()->number_of_entries() == actual_count, "should be equal");
      }

      //---------------------------------------------------------------------------
      // Non-product code

      #ifndef PRODUCT
      void SymbolTable::print_histogram() {
        MutexLocker ml(SymbolTable_lock);
        const int results_length = 100;
        int results[results_length];
        int i,j;
    *** 644,673 ****
                                          java_lang_String::hash_code(s, len);
      }

      oop StringTable::lookup(int index, jchar* name,
                              int len, unsigned int hash) {
    !   int count = 0;
        for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
          count++;
          if (l->hash() == hash) {
            if (java_lang_String::equals(l->literal(), name, len)) {
              return l->literal();
            }
          }
        }
        // If the bucket size is too deep check if this hash code is insufficient.
        if (count >= rehash_count && !needs_rehashing()) {
          _needs_rehashing = check_rehash_table(count);
        }
        return NULL;
      }

      oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
                                 int len, unsigned int hashValue_arg, TRAPS) {

        assert(java_lang_String::equals(string(), name, len),
               "string must be properly initialized");
        // Cannot hit a safepoint in this function because the "this" pointer can move.
        No_Safepoint_Verifier nsv;

    --- 722,796 ----
                                          java_lang_String::hash_code(s, len);
      }

      oop StringTable::lookup(int index, jchar* name,
                              int len, unsigned int hash) {
    ! #ifndef PRODUCT
    ! //#ifdef PRODUCT_TEST
    !   jlong time = os::javaTimeNanos();
    !   _debug_all_lookup_count++;
    !   _debug_lookup_count++;
    ! #endif
    !
    !   unsigned int count = 0;
        for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
          count++;
          if (l->hash() == hash) {
            if (java_lang_String::equals(l->literal(), name, len)) {
    +
    +         l->_debug_lookups++;
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +         {
    +           unsigned int duration = os::javaTimeNanos()-time;
    +           _debug_lookup_found_count++;
    +           _debug_lookup_found_max_duration = (_debug_lookup_found_max_duration > duration) ? _debug_lookup_found_max_duration : duration;
    +           _debug_lookup_found_total_duration += duration;
    +           _debug_chain_found_maximum_length = (_debug_chain_found_maximum_length > count) ? _debug_chain_found_maximum_length : count;
    +           _debug_chain_found_total_length += count;
    +
    +           long thread_id = os::current_thread_id();
    +           for (int i=0; i<1024; i++) {
    +             if (_debug_table_threads[i] == thread_id) {
    +               break;
    +             } else if (_debug_table_threads[i] == 0) {
    +               _debug_table_threads[i] = thread_id;
    +               break;
    +             }
    +           }
    +         }
    + #endif
    +
              return l->literal();
            }
          }
        }
        // If the bucket size is too deep check if this hash code is insufficient.
        if (count >= rehash_count && !needs_rehashing()) {
          _needs_rehashing = check_rehash_table(count);
        }
    +
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +   {
    +     unsigned int duration = os::javaTimeNanos()-time;
    +     _debug_lookup_failed_count++;
    +     _debug_lookup_failed_max_duration = (_debug_lookup_failed_max_duration > duration) ? _debug_lookup_failed_max_duration : duration;
    +     _debug_lookup_failed_total_duration += duration;
    +     _debug_chain_failed_maximum_length = (_debug_chain_failed_maximum_length > count) ? _debug_chain_failed_maximum_length : count;
    +     _debug_chain_failed_total_length += count;
    +   }
    + #endif
    +
        return NULL;
      }

      oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
                                 int len, unsigned int hashValue_arg, TRAPS) {

    +   assert(StringTable_lock->is_locked(), "must hold StringTable_lock");
        assert(java_lang_String::equals(string(), name, len),
               "string must be properly initialized");
        // Cannot hit a safepoint in this function because the "this" pointer can move.
        No_Safepoint_Verifier nsv;

    *** 692,701 ****
    --- 815,833 ----
          return test;
        }

        HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
        add_entry(index, entry);
    +
    + #ifndef PRODUCT
    + //#ifdef PRODUCT_TEST
    +   {
    +     _debug_all_insertion_count++;
    +     _debug_insertion_count++;
    +   }
    + #endif
    +
        return string();
      }

      oop StringTable::lookup(Symbol* symbol) {
    *** 882,891 ****
    --- 1014,1024 ----
              *p = entry->next();
              the_table()->free_entry(entry);
              (*removed)++;
            }
            (*processed)++;
    +       entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
            entry = *p;
          }
        }
      }

    *** 910,934 ****
      }

      // This verification is part of Universe::verify() and needs to be quick.
      // See StringTable::verify_and_compare() below for exhaustive verification.
      void StringTable::verify() {
        for (int i = 0; i < the_table()->table_size(); ++i) {
          HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
          for ( ; p != NULL; p = p->next()) {
            oop s = p->literal();
            guarantee(s != NULL, "interned string is NULL");
            unsigned int h = java_lang_String::hash_string(s);
            guarantee(p->hash() == h, "broken hash in string table entry");
            guarantee(the_table()->hash_to_index(h) == i,
                      "wrong index in string table");
          }
        }
    ! }
    !
    ! void StringTable::dump(outputStream* st) {
    !   the_table()->dump_table(st, "StringTable");
      }

      StringTable::VerifyRetTypes StringTable::compare_entries(
                                            int bkt1, int e_cnt1,
                                            HashtableEntry<oop, mtSymbol>* e_ptr1,
    --- 1043,1075 ----
      }

      // This verification is part of Universe::verify() and needs to be quick.
      // See StringTable::verify_and_compare() below for exhaustive verification.
      void StringTable::verify() {
    +   MutexLocker mu(StringTable_lock);
    +   int actual_count = 0;
        for (int i = 0; i < the_table()->table_size(); ++i) {
          HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
          for ( ; p != NULL; p = p->next()) {
            oop s = p->literal();
            guarantee(s != NULL, "interned string is NULL");
            unsigned int h = java_lang_String::hash_string(s);
            guarantee(p->hash() == h, "broken hash in string table entry");
    + //      if (the_table()->hash_to_index(h) != i) {
    + //        fprintf(stderr, "h: %d\n", h);
    + //        fprintf(stderr, "the_table()->hash_to_index(h: %d\n", the_table()->hash_to_index(h));
    + //        fprintf(stderr, "i: %d\n", i);
    + //      }
            guarantee(the_table()->hash_to_index(h) == i,
                      "wrong index in string table");
    +       actual_count++;
          }
        }
    !   if (the_table()->number_of_entries()!=actual_count) {
    !     tty->print("StringTable assert failure: number_of_entries()!=actual_count [%d!=%d]\n", the_table()->number_of_entries(), actual_count);
    !   }
    !   guarantee(the_table()->number_of_entries() == actual_count, "should be equal");
      }

      StringTable::VerifyRetTypes StringTable::compare_entries(
                                            int bkt1, int e_cnt1,
                                            HashtableEntry<oop, mtSymbol>* e_ptr1,

src/share/vm/classfile/symbolTable.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File