src/share/vm/classfile/placeholders.hpp

Tue, 07 Dec 2010 03:15:45 -0800

author
sla
date
Tue, 07 Dec 2010 03:15:45 -0800
changeset 2331
017cd8bce8a8
parent 2325
c760f78e0a53
child 2497
3582bf76420e
permissions
-rw-r--r--

6539281: -Xcheck:jni should validate char* argument to ReleaseStringUTFChars
Summary: Tag allocated memory with a magic value and verify when releasing.
Reviewed-by: phh, stefank

     1 /*
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #ifndef SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
    26 #define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
    28 #include "runtime/thread.hpp"
    29 #include "utilities/hashtable.hpp"
    31 class PlaceholderEntry;
    33 // Placeholder objects. These represent classes currently
    34 // being loaded, as well as arrays of primitives.
    35 //
    37 class PlaceholderTable : public TwoOopHashtable {
    38   friend class VMStructs;
    40 public:
    41   PlaceholderTable(int table_size);
    43   PlaceholderEntry* new_entry(int hash, symbolOop name, oop loader, bool havesupername, symbolOop supername);
    45   PlaceholderEntry* bucket(int i) {
    46     return (PlaceholderEntry*)Hashtable::bucket(i);
    47   }
    49   PlaceholderEntry** bucket_addr(int i) {
    50     return (PlaceholderEntry**)Hashtable::bucket_addr(i);
    51   }
    53   void add_entry(int index, PlaceholderEntry* new_entry) {
    54     Hashtable::add_entry(index, (HashtableEntry*)new_entry);
    55   }
    57   void add_entry(int index, unsigned int hash, symbolHandle name,
    58                 Handle loader, bool havesupername, symbolHandle supername);
    60 // This returns a symbolOop to match type for SystemDictionary
    61   symbolOop find_entry(int index, unsigned int hash,
    62                        symbolHandle name, Handle loader);
    64   PlaceholderEntry* get_entry(int index, unsigned int hash,
    65                        symbolHandle name, Handle loader);
    67 // caller to create a placeholder entry must enumerate an action
    68 // caller claims ownership of that action
    69 // For parallel classloading:
    70 // multiple LOAD_INSTANCE threads can proceed in parallel
    71 // multiple LOAD_SUPER threads can proceed in parallel
    72 // LOAD_SUPER needed to check for class circularity
    73 // DEFINE_CLASS: ultimately define class must be single threaded
    74 // on a class/classloader basis
    75 // so the head of that queue owns the token
    76 // and the rest of the threads return the result the first thread gets
    77  enum classloadAction {
    78     LOAD_INSTANCE = 1,             // calling load_instance_class
    79     LOAD_SUPER = 2,                // loading superclass for this class
    80     DEFINE_CLASS = 3               // find_or_define class
    81  };
    83   // find_and_add returns probe pointer - old or new
    84   // If no entry exists, add a placeholder entry and push SeenThread
    85   // If entry exists, reuse entry and push SeenThread for classloadAction
    86   PlaceholderEntry* find_and_add(int index, unsigned int hash,
    87                                  symbolHandle name, Handle loader,
    88                                  classloadAction action, symbolHandle supername,
    89                                  Thread* thread);
    91   void remove_entry(int index, unsigned int hash,
    92                     symbolHandle name, Handle loader);
    94 // Remove placeholder information
    95   void find_and_remove(int index, unsigned int hash,
    96                        symbolHandle name, Handle loader, Thread* thread);
    98   // GC support.
    99   void oops_do(OopClosure* f);
   101   // JVMTI support
   102   void entries_do(void f(symbolOop, oop));
   104 #ifndef PRODUCT
   105   void print();
   106 #endif
   107   void verify();
   108 };
   110 // SeenThread objects represent list of threads that are
   111 // currently performing a load action on a class.
   112 // For class circularity, set before loading a superclass.
   113 // For bootclasssearchpath, set before calling load_instance_class.
   114 // Defining must be single threaded on a class/classloader basis
   115 // For DEFINE_CLASS, the head of the queue owns the
   116 // define token and the rest of the threads wait to return the
   117 // result the first thread gets.
   118 class SeenThread: public CHeapObj {
   119 private:
   120    Thread *_thread;
   121    SeenThread* _stnext;
   122    SeenThread* _stprev;
   123 public:
   124    SeenThread(Thread *thread) {
   125        _thread = thread;
   126        _stnext = NULL;
   127        _stprev = NULL;
   128    }
   129    Thread* thread()                const { return _thread;}
   130    void set_thread(Thread *thread) { _thread = thread; }
   132    SeenThread* next()              const { return _stnext;}
   133    void set_next(SeenThread *seen) { _stnext = seen; }
   134    void set_prev(SeenThread *seen) { _stprev = seen; }
   136 #ifndef PRODUCT
   137   void printActionQ() {
   138     SeenThread* seen = this;
   139     while (seen != NULL) {
   140       seen->thread()->print_value();
   141       tty->print(", ");
   142       seen = seen->next();
   143     }
   144   }
   145 #endif // PRODUCT
   146 };
   148 // Placeholder objects represent classes currently being loaded.
   149 // All threads examining the placeholder table must hold the
   150 // SystemDictionary_lock, so we don't need special precautions
   151 // on store ordering here.
   152 // The system dictionary is the only user of this class.
   154 class PlaceholderEntry : public HashtableEntry {
   155   friend class VMStructs;
   158  private:
   159   oop               _loader;        // initiating loader
   160   bool              _havesupername; // distinguish between null supername, and unknown
   161   symbolOop         _supername;
   162   Thread*           _definer;       // owner of define token
   163   klassOop          _instanceKlass; // instanceKlass from successful define
   164   SeenThread*       _superThreadQ;  // doubly-linked queue of Threads loading a superclass for this class
   165   SeenThread*       _loadInstanceThreadQ;  // loadInstance thread
   166                                     // can be multiple threads if classloader object lock broken by application
   167                                     // or if classloader supports parallel classloading
   169   SeenThread*       _defineThreadQ; // queue of Threads trying to define this class
   170                                     // including _definer
   171                                     // _definer owns token
   172                                     // queue waits for and returns results from _definer
   174  public:
   175   // Simple accessors, used only by SystemDictionary
   176   symbolOop          klass()               const { return (symbolOop)literal(); }
   177   symbolOop*         klass_addr()          { return (symbolOop*)literal_addr(); }
   179   oop                loader()              const { return _loader; }
   180   void               set_loader(oop loader) { _loader = loader; }
   181   oop*               loader_addr()         { return &_loader; }
   183   bool               havesupername()       const { return _havesupername; }
   184   void               set_havesupername(bool havesupername) { _havesupername = havesupername; }
   186   symbolOop          supername()           const { return _supername; }
   187   void               set_supername(symbolOop supername) { _supername = supername; }
   188   symbolOop*         supername_addr()      { return &_supername; }
   190   Thread*            definer()             const {return _definer; }
   191   void               set_definer(Thread* definer) { _definer = definer; }
   193   klassOop           instanceKlass()     const {return _instanceKlass; }
   194   void               set_instanceKlass(klassOop instanceKlass) { _instanceKlass = instanceKlass; }
   195   klassOop*          instanceKlass_addr()   { return &_instanceKlass; }
   197   SeenThread*        superThreadQ()        const { return _superThreadQ; }
   198   void               set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }
   200   SeenThread*        loadInstanceThreadQ() const { return _loadInstanceThreadQ; }
   201   void               set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }
   203   SeenThread*        defineThreadQ()        const { return _defineThreadQ; }
   204   void               set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
   206   PlaceholderEntry* next() const {
   207     return (PlaceholderEntry*)HashtableEntry::next();
   208   }
   210   PlaceholderEntry** next_addr() {
   211     return (PlaceholderEntry**)HashtableEntry::next_addr();
   212   }
   214   // Test for equality
   215   // Entries are unique for class/classloader name pair
   216   bool equals(symbolOop class_name, oop class_loader) const {
   217     return (klass() == class_name && loader() == class_loader);
   218   }
   220   SeenThread* actionToQueue(PlaceholderTable::classloadAction action) {
   221     SeenThread* queuehead;
   222     switch (action) {
   223       case PlaceholderTable::LOAD_INSTANCE:
   224          queuehead = _loadInstanceThreadQ;
   225          break;
   226       case PlaceholderTable::LOAD_SUPER:
   227          queuehead = _superThreadQ;
   228          break;
   229       case PlaceholderTable::DEFINE_CLASS:
   230          queuehead = _defineThreadQ;
   231          break;
   232       default: Unimplemented();
   233     }
   234     return queuehead;
   235   }
   237   void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
   238     switch (action) {
   239       case PlaceholderTable::LOAD_INSTANCE:
   240          _loadInstanceThreadQ = seenthread;
   241          break;
   242       case PlaceholderTable::LOAD_SUPER:
   243          _superThreadQ = seenthread;
   244          break;
   245       case PlaceholderTable::DEFINE_CLASS:
   246          _defineThreadQ = seenthread;
   247          break;
   248       default: Unimplemented();
   249     }
   250     return;
   251   }
   253   bool super_load_in_progress() {
   254      return (_superThreadQ != NULL);
   255   }
   257   bool instance_load_in_progress() {
   258     return (_loadInstanceThreadQ != NULL);
   259   }
   261   bool define_class_in_progress() {
   262     return (_defineThreadQ != NULL);
   263   }
   265 // Doubly-linked list of Threads per action for class/classloader pair
   266 // Class circularity support: links in thread before loading superclass
   267 // bootstrapsearchpath support: links in a thread before load_instance_class
   268 // definers: use as queue of define requestors, including owner of
   269 // define token. Appends for debugging of requestor order
   270   void add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
   271     assert_lock_strong(SystemDictionary_lock);
   272     SeenThread* threadEntry = new SeenThread(thread);
   273     SeenThread* seen = actionToQueue(action);
   275     if (seen == NULL) {
   276       set_threadQ(threadEntry, action);
   277       return;
   278     }
   279     SeenThread* next;
   280     while ((next = seen->next()) != NULL) {
   281       seen = next;
   282     }
   283     seen->set_next(threadEntry);
   284     threadEntry->set_prev(seen);
   285     return;
   286   }
   288   bool check_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
   289     assert_lock_strong(SystemDictionary_lock);
   290     SeenThread* threadQ = actionToQueue(action);
   291     SeenThread* seen = threadQ;
   292     while (seen) {
   293       if (thread == seen->thread()) {
   294         return true;
   295       }
   296       seen = seen->next();
   297     }
   298     return false;
   299   }
   301   // returns true if seenthreadQ is now empty
   302   // Note, caller must ensure probe still exists while holding
   303   // SystemDictionary_lock
   304   // ignores if cleanup has already been done
   305   // if found, deletes SeenThread
   306   bool remove_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
   307     assert_lock_strong(SystemDictionary_lock);
   308     SeenThread* threadQ = actionToQueue(action);
   309     SeenThread* seen = threadQ;
   310     SeenThread* prev = NULL;
   311     while (seen) {
   312       if (thread == seen->thread()) {
   313         if (prev) {
   314           prev->set_next(seen->next());
   315         } else {
   316           set_threadQ(seen->next(), action);
   317         }
   318         if (seen->next()) {
   319           seen->next()->set_prev(prev);
   320         }
   321         delete seen;
   322         break;
   323       }
   324       prev = seen;
   325       seen = seen->next();
   326     }
   327     return (actionToQueue(action) == NULL);
   328   }
   330   // GC support
   331   // Applies "f->do_oop" to all root oops in the placeholder table.
   332   void oops_do(OopClosure* blk);
   334   // Print method doesn't append a cr
   335   void print() const  PRODUCT_RETURN;
   336   void verify() const;
   337 };
   339 #endif // SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP

mercurial