src/share/vm/oops/klassVtable.hpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2534
e5383553fd4e
child 2777
8ce625481709
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

     1 /*
     2  * Copyright (c) 1997, 2011, 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_OOPS_KLASSVTABLE_HPP
    26 #define SHARE_VM_OOPS_KLASSVTABLE_HPP
    28 #include "memory/allocation.hpp"
    29 #include "oops/oopsHierarchy.hpp"
    30 #include "runtime/handles.hpp"
    31 #include "utilities/growableArray.hpp"
    33 // A klassVtable abstracts the variable-length vtable that is embedded in instanceKlass
    34 // and arrayKlass.  klassVtable objects are used just as convenient transient accessors to the vtable,
    35 // not to actually hold the vtable data.
    36 // Note: the klassVtable should not be accessed before the class has been verified
    37 // (until that point, the vtable is uninitialized).
    39 // Currently a klassVtable contains a direct reference to the vtable data, and is therefore
    40 // not preserved across GCs.
    42 class vtableEntry;
    44 class klassVtable : public ResourceObj {
    45   KlassHandle  _klass;            // my klass
    46   int          _tableOffset;      // offset of start of vtable data within klass
    47   int          _length;           // length of vtable (number of entries)
    48 #ifndef PRODUCT
    49   int          _verify_count;     // to make verify faster
    50 #endif
    52   // Ordering important, so greater_than (>) can be used as an merge operator.
    53   enum AccessType {
    54     acc_private         = 0,
    55     acc_package_private = 1,
    56     acc_publicprotected = 2
    57   };
    59  public:
    60   klassVtable(KlassHandle h_klass, void* base, int length) : _klass(h_klass) {
    61     _tableOffset = (address)base - (address)h_klass(); _length = length;
    62   }
    64   // accessors
    65   vtableEntry* table() const      { return (vtableEntry*)(address(_klass()) + _tableOffset); }
    66   KlassHandle klass() const       { return _klass;  }
    67   int length() const              { return _length; }
    68   inline methodOop method_at(int i) const;
    69   inline methodOop unchecked_method_at(int i) const;
    70   inline oop*      adr_method_at(int i) const;
    72   // searching; all methods return -1 if not found
    73   int index_of(methodOop m) const                         { return index_of(m, _length); }
    74   int index_of_miranda(Symbol* name, Symbol* signature);
    76   void initialize_vtable(bool checkconstraints, TRAPS);   // initialize vtable of a new klass
    78   // conputes vtable length (in words) and the number of miranda methods
    79   static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods,
    80                                                    klassOop super, objArrayOop methods,
    81                                                    AccessFlags class_flags, Handle classloader,
    82                                                    Symbol* classname, objArrayOop local_interfaces,
    83                                                    TRAPS);
    85   // RedefineClasses() API support:
    86   // If any entry of this vtable points to any of old_methods,
    87   // replace it with the corresponding new_method.
    88   // trace_name_printed is set to true if the current call has
    89   // printed the klass name so that other routines in the adjust_*
    90   // group don't print the klass name.
    91   void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
    92                              int methods_length, bool * trace_name_printed);
    94   // Garbage collection
    95   void oop_follow_contents();
    96   void oop_adjust_pointers();
    98 #ifndef SERIALGC
    99   // Parallel Old
   100   void oop_follow_contents(ParCompactionManager* cm);
   101   void oop_update_pointers(ParCompactionManager* cm);
   102 #endif // SERIALGC
   104   // Iterators
   105   void oop_oop_iterate(OopClosure* blk);
   106   void oop_oop_iterate_m(OopClosure* blk, MemRegion mr);
   108   // Debugging code
   109   void print()                                              PRODUCT_RETURN;
   110   void verify(outputStream* st, bool force = false);
   111   static void print_statistics()                            PRODUCT_RETURN;
   113 #ifndef PRODUCT
   114   bool check_no_old_entries();
   115   void dump_vtable();
   116 #endif
   118  protected:
   119   friend class vtableEntry;
   120  private:
   121   enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ;
   122   void copy_vtable_to(vtableEntry* start);
   123   int  initialize_from_super(KlassHandle super);
   124   int  index_of(methodOop m, int len) const; // same as index_of, but search only up to len
   125   void put_method_at(methodOop m, int index);
   126   static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
   128   bool update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
   129  instanceKlass* find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, int vtable_index,
   130                                          Handle target_loader, Symbol* target_classname, Thread* THREAD);
   132   // support for miranda methods
   133   bool is_miranda_entry_at(int i);
   134   void fill_in_mirandas(int& initialized);
   135   static bool is_miranda(methodOop m, objArrayOop class_methods, klassOop super);
   136   static void add_new_mirandas_to_list(GrowableArray<methodOop>* list_of_current_mirandas, objArrayOop current_interface_methods, objArrayOop class_methods, klassOop super);
   137   static void get_mirandas(GrowableArray<methodOop>* mirandas, klassOop super, objArrayOop class_methods, objArrayOop local_interfaces);
   138   static int get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces);
   141   void verify_against(outputStream* st, klassVtable* vt, int index);
   142   inline instanceKlass* ik() const;
   143 };
   146 // private helper class for klassVtable
   147 // description of entry points:
   148 //    destination is interpreted:
   149 //      from_compiled_code_entry_point -> c2iadapter
   150 //      from_interpreter_entry_point   -> interpreter entry point
   151 //    destination is compiled:
   152 //      from_compiled_code_entry_point -> nmethod entry point
   153 //      from_interpreter_entry_point   -> i2cadapter
   154 class vtableEntry VALUE_OBJ_CLASS_SPEC {
   155  public:
   156   // size in words
   157   static int size() {
   158     return sizeof(vtableEntry) / sizeof(HeapWord);
   159   }
   160   static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); }
   161   methodOop method() const    { return _method; }
   163  private:
   164   methodOop _method;
   165   void set(methodOop method)  { assert(method != NULL, "use clear"); _method = method; }
   166   void clear()                { _method = NULL; }
   167   void print()                                        PRODUCT_RETURN;
   168   void verify(klassVtable* vt, outputStream* st);
   170   friend class klassVtable;
   171 };
   174 inline methodOop klassVtable::method_at(int i) const {
   175   assert(i >= 0 && i < _length, "index out of bounds");
   176   assert(table()[i].method() != NULL, "should not be null");
   177   assert(oop(table()[i].method())->is_method(), "should be method");
   178   return table()[i].method();
   179 }
   181 inline methodOop klassVtable::unchecked_method_at(int i) const {
   182   assert(i >= 0 && i < _length, "index out of bounds");
   183   return table()[i].method();
   184 }
   186 inline oop* klassVtable::adr_method_at(int i) const {
   187   // Allow one past the last entry to be referenced; useful for loop bounds.
   188   assert(i >= 0 && i <= _length, "index out of bounds");
   189   return (oop*)(address(table() + i) + vtableEntry::method_offset_in_bytes());
   190 }
   192 // --------------------------------------------------------------------------------
   193 class klassItable;
   194 class itableMethodEntry;
   196 class itableOffsetEntry VALUE_OBJ_CLASS_SPEC {
   197  private:
   198   klassOop _interface;
   199   int      _offset;
   200  public:
   201   klassOop interface_klass() const { return _interface; }
   202   int      offset() const          { return _offset; }
   204   static itableMethodEntry* method_entry(klassOop k, int offset) { return (itableMethodEntry*)(((address)k) + offset); }
   205   itableMethodEntry* first_method_entry(klassOop k)              { return method_entry(k, _offset); }
   207   void initialize(klassOop interf, int offset) { _interface = interf; _offset = offset; }
   209   // Static size and offset accessors
   210   static int size()                       { return sizeof(itableOffsetEntry) / HeapWordSize; }    // size in words
   211   static int interface_offset_in_bytes()  { return offset_of(itableOffsetEntry, _interface); }
   212   static int offset_offset_in_bytes()     { return offset_of(itableOffsetEntry, _offset); }
   214   friend class klassItable;
   215 };
   218 class itableMethodEntry VALUE_OBJ_CLASS_SPEC {
   219  private:
   220   methodOop _method;
   222  public:
   223   methodOop method() const { return _method; }
   225   void clear()             { _method = NULL; }
   227   void initialize(methodOop method);
   229   // Static size and offset accessors
   230   static int size()                         { return sizeof(itableMethodEntry) / HeapWordSize; }  // size in words
   231   static int method_offset_in_bytes()       { return offset_of(itableMethodEntry, _method); }
   233   friend class klassItable;
   234 };
   236 //
   237 // Format of an itable
   238 //
   239 //    ---- offset table ---
   240 //    klassOop of interface 1             \
   241 //    offset to vtable from start of oop  / offset table entry
   242 //    ...
   243 //    klassOop of interface n             \
   244 //    offset to vtable from start of oop  / offset table entry
   245 //    --- vtable for interface 1 ---
   246 //    methodOop                           \
   247 //    compiler entry point                / method table entry
   248 //    ...
   249 //    methodOop                           \
   250 //    compiler entry point                / method table entry
   251 //    -- vtable for interface 2 ---
   252 //    ...
   253 //
   254 class klassItable : public ResourceObj {
   255  private:
   256   instanceKlassHandle  _klass;             // my klass
   257   int                  _table_offset;      // offset of start of itable data within klass (in words)
   258   int                  _size_offset_table; // size of offset table (in itableOffset entries)
   259   int                  _size_method_table; // size of methodtable (in itableMethodEntry entries)
   261   void initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS);
   262  public:
   263   klassItable(instanceKlassHandle klass);
   265   itableOffsetEntry* offset_entry(int i) { assert(0 <= i && i <= _size_offset_table, "index out of bounds");
   266                                            return &((itableOffsetEntry*)vtable_start())[i]; }
   268   itableMethodEntry* method_entry(int i) { assert(0 <= i && i <= _size_method_table, "index out of bounds");
   269                                            return &((itableMethodEntry*)method_start())[i]; }
   271   int size_offset_table()                { return _size_offset_table; }
   273   // Initialization
   274   void initialize_itable(bool checkconstraints, TRAPS);
   276   // Updates
   277   void initialize_with_method(methodOop m);
   279   // RedefineClasses() API support:
   280   // if any entry of this itable points to any of old_methods,
   281   // replace it with the corresponding new_method.
   282   // trace_name_printed is set to true if the current call has
   283   // printed the klass name so that other routines in the adjust_*
   284   // group don't print the klass name.
   285   void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
   286                              int methods_length, bool * trace_name_printed);
   288   // Garbage collection
   289   void oop_follow_contents();
   290   void oop_adjust_pointers();
   292 #ifndef SERIALGC
   293   // Parallel Old
   294   void oop_follow_contents(ParCompactionManager* cm);
   295   void oop_update_pointers(ParCompactionManager* cm);
   296 #endif // SERIALGC
   298   // Iterators
   299   void oop_oop_iterate(OopClosure* blk);
   300   void oop_oop_iterate_m(OopClosure* blk, MemRegion mr);
   302   // Setup of itable
   303   static int compute_itable_size(objArrayHandle transitive_interfaces);
   304   static void setup_itable_offset_table(instanceKlassHandle klass);
   306   // Resolving of method to index
   307   static int compute_itable_index(methodOop m);
   308   // ...and back again:
   309   static methodOop method_for_itable_index(klassOop klass, int itable_index);
   311   // Debugging/Statistics
   312   static void print_statistics() PRODUCT_RETURN;
   313  private:
   314   intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; }
   315   intptr_t* method_start() const { return vtable_start() + _size_offset_table * itableOffsetEntry::size(); }
   317   // Helper methods
   318   static int  calc_itable_size(int num_interfaces, int num_methods) { return (num_interfaces * itableOffsetEntry::size()) + (num_methods * itableMethodEntry::size()); }
   320   // Statistics
   321   NOT_PRODUCT(static int  _total_classes;)   // Total no. of classes with itables
   322   NOT_PRODUCT(static long _total_size;)      // Total no. of bytes used for itables
   324   static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
   325 };
   327 #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP

mercurial