src/share/vm/oops/typeArrayKlass.cpp

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 2971
c9ca3f51cf41
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 #include "precompiled.hpp"
    26 #include "classfile/systemDictionary.hpp"
    27 #include "classfile/vmSymbols.hpp"
    28 #include "gc_interface/collectedHeap.hpp"
    29 #include "gc_interface/collectedHeap.inline.hpp"
    30 #include "memory/resourceArea.hpp"
    31 #include "memory/universe.hpp"
    32 #include "memory/universe.inline.hpp"
    33 #include "oops/instanceKlass.hpp"
    34 #include "oops/klassOop.hpp"
    35 #include "oops/objArrayKlassKlass.hpp"
    36 #include "oops/oop.inline.hpp"
    37 #include "oops/typeArrayKlass.hpp"
    38 #include "oops/typeArrayOop.hpp"
    39 #include "runtime/handles.inline.hpp"
    41 bool typeArrayKlass::compute_is_subtype_of(klassOop k) {
    42   if (!k->klass_part()->oop_is_typeArray()) {
    43     return arrayKlass::compute_is_subtype_of(k);
    44   }
    46   typeArrayKlass* tak = typeArrayKlass::cast(k);
    47   if (dimension() != tak->dimension()) return false;
    49   return element_type() == tak->element_type();
    50 }
    52 klassOop typeArrayKlass::create_klass(BasicType type, int scale,
    53                                       const char* name_str, TRAPS) {
    54   typeArrayKlass o;
    56   Symbol* sym = NULL;
    57   if (name_str != NULL) {
    58     sym = SymbolTable::new_symbol(name_str, CHECK_NULL);
    59   }
    60   KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
    62   arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL);
    63   typeArrayKlass* ak = typeArrayKlass::cast(k());
    64   ak->set_name(sym);
    65   ak->set_layout_helper(array_layout_helper(type));
    66   assert(scale == (1 << ak->log2_element_size()), "scale must check out");
    67   assert(ak->oop_is_javaArray(), "sanity");
    68   assert(ak->oop_is_typeArray(), "sanity");
    69   ak->set_max_length(arrayOopDesc::max_array_length(type));
    70   assert(k()->size() > header_size(), "bad size");
    72   // Call complete_create_array_klass after all instance variables have been initialized.
    73   KlassHandle super (THREAD, k->super());
    74   complete_create_array_klass(k, super, CHECK_NULL);
    76   return k();
    77 }
    79 typeArrayOop typeArrayKlass::allocate(int length, TRAPS) {
    80   assert(log2_element_size() >= 0, "bad scale");
    81   if (length >= 0) {
    82     if (length <= max_length()) {
    83       size_t size = typeArrayOopDesc::object_size(layout_helper(), length);
    84       KlassHandle h_k(THREAD, as_klassOop());
    85       typeArrayOop t;
    86       CollectedHeap* ch = Universe::heap();
    87       if (size < ch->large_typearray_limit()) {
    88         t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL);
    89       } else {
    90         t = (typeArrayOop)CollectedHeap::large_typearray_allocate(h_k, (int)size, length, CHECK_NULL);
    91       }
    92       assert(t->is_parsable(), "Don't publish unless parsable");
    93       return t;
    94     } else {
    95       report_java_out_of_memory("Requested array size exceeds VM limit");
    96       THROW_OOP_0(Universe::out_of_memory_error_array_size());
    97     }
    98   } else {
    99     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
   100   }
   101 }
   103 typeArrayOop typeArrayKlass::allocate_permanent(int length, TRAPS) {
   104   if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
   105   int size = typeArrayOopDesc::object_size(layout_helper(), length);
   106   KlassHandle h_k(THREAD, as_klassOop());
   107   typeArrayOop t = (typeArrayOop)
   108     CollectedHeap::permanent_array_allocate(h_k, size, length, CHECK_NULL);
   109   assert(t->is_parsable(), "Can't publish until parsable");
   110   return t;
   111 }
   113 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
   114   // For typeArrays this is only called for the last dimension
   115   assert(rank == 1, "just checking");
   116   int length = *last_size;
   117   return allocate(length, THREAD);
   118 }
   121 void typeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
   122   assert(s->is_typeArray(), "must be type array");
   124   // Check destination
   125   if (!d->is_typeArray() || element_type() != typeArrayKlass::cast(d->klass())->element_type()) {
   126     THROW(vmSymbols::java_lang_ArrayStoreException());
   127   }
   129   // Check is all offsets and lengths are non negative
   130   if (src_pos < 0 || dst_pos < 0 || length < 0) {
   131     THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
   132   }
   133   // Check if the ranges are valid
   134   if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
   135      || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
   136     THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
   137   }
   138   // Check zero copy
   139   if (length == 0)
   140     return;
   142   // This is an attempt to make the copy_array fast.
   143   int l2es = log2_element_size();
   144   int ihs = array_header_in_bytes() / wordSize;
   145   char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es);
   146   char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es);
   147   Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es);
   148 }
   151 // create a klass of array holding typeArrays
   152 klassOop typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
   153   typeArrayKlassHandle h_this(THREAD, as_klassOop());
   154   return array_klass_impl(h_this, or_null, n, THREAD);
   155 }
   157 klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_null, int n, TRAPS) {
   158   int dimension = h_this->dimension();
   159   assert(dimension <= n, "check order of chain");
   160     if (dimension == n)
   161       return h_this();
   163   objArrayKlassHandle  h_ak(THREAD, h_this->higher_dimension());
   164   if (h_ak.is_null()) {
   165     if (or_null)  return NULL;
   167     ResourceMark rm;
   168     JavaThread *jt = (JavaThread *)THREAD;
   169     {
   170       MutexLocker mc(Compile_lock, THREAD);   // for vtables
   171       // Atomic create higher dimension and link into list
   172       MutexLocker mu(MultiArray_lock, THREAD);
   174       h_ak = objArrayKlassHandle(THREAD, h_this->higher_dimension());
   175       if (h_ak.is_null()) {
   176         klassOop oak = objArrayKlassKlass::cast(
   177           Universe::objArrayKlassKlassObj())->allocate_objArray_klass(
   178           dimension + 1, h_this, CHECK_NULL);
   179         h_ak = objArrayKlassHandle(THREAD, oak);
   180         h_ak->set_lower_dimension(h_this());
   181         OrderAccess::storestore();
   182         h_this->set_higher_dimension(h_ak());
   183         assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
   184       }
   185     }
   186   } else {
   187     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   188   }
   189   if (or_null) {
   190     return h_ak->array_klass_or_null(n);
   191   }
   192   return h_ak->array_klass(n, CHECK_NULL);
   193 }
   195 klassOop typeArrayKlass::array_klass_impl(bool or_null, TRAPS) {
   196   return array_klass_impl(or_null, dimension() +  1, THREAD);
   197 }
   199 int typeArrayKlass::oop_size(oop obj) const {
   200   assert(obj->is_typeArray(),"must be a type array");
   201   typeArrayOop t = typeArrayOop(obj);
   202   return t->object_size();
   203 }
   205 void typeArrayKlass::oop_follow_contents(oop obj) {
   206   assert(obj->is_typeArray(),"must be a type array");
   207   // Performance tweak: We skip iterating over the klass pointer since we
   208   // know that Universe::typeArrayKlass never moves.
   209 }
   211 #ifndef SERIALGC
   212 void typeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) {
   213   assert(obj->is_typeArray(),"must be a type array");
   214   // Performance tweak: We skip iterating over the klass pointer since we
   215   // know that Universe::typeArrayKlass never moves.
   216 }
   217 #endif // SERIALGC
   219 int typeArrayKlass::oop_adjust_pointers(oop obj) {
   220   assert(obj->is_typeArray(),"must be a type array");
   221   typeArrayOop t = typeArrayOop(obj);
   222   // Performance tweak: We skip iterating over the klass pointer since we
   223   // know that Universe::typeArrayKlass never moves.
   224   return t->object_size();
   225 }
   227 int typeArrayKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
   228   assert(obj->is_typeArray(),"must be a type array");
   229   typeArrayOop t = typeArrayOop(obj);
   230   // Performance tweak: We skip iterating over the klass pointer since we
   231   // know that Universe::typeArrayKlass never moves.
   232   return t->object_size();
   233 }
   235 int typeArrayKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
   236   assert(obj->is_typeArray(),"must be a type array");
   237   typeArrayOop t = typeArrayOop(obj);
   238   // Performance tweak: We skip iterating over the klass pointer since we
   239   // know that Universe::typeArrayKlass never moves.
   240   return t->object_size();
   241 }
   243 #ifndef SERIALGC
   244 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   245   assert(obj->is_typeArray(),"must be a type array");
   246 }
   248 int
   249 typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
   250   assert(obj->is_typeArray(),"must be a type array");
   251   return typeArrayOop(obj)->object_size();
   252 }
   253 #endif // SERIALGC
   255 void typeArrayKlass::initialize(TRAPS) {
   256   // Nothing to do. Having this function is handy since objArrayKlasses can be
   257   // initialized by calling initialize on their bottom_klass, see objArrayKlass::initialize
   258 }
   260 const char* typeArrayKlass::external_name(BasicType type) {
   261   switch (type) {
   262     case T_BOOLEAN: return "[Z";
   263     case T_CHAR:    return "[C";
   264     case T_FLOAT:   return "[F";
   265     case T_DOUBLE:  return "[D";
   266     case T_BYTE:    return "[B";
   267     case T_SHORT:   return "[S";
   268     case T_INT:     return "[I";
   269     case T_LONG:    return "[J";
   270     default: ShouldNotReachHere();
   271   }
   272   return NULL;
   273 }
   275 #ifndef PRODUCT
   276 // Printing
   278 static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) {
   279   for (int index = 0; index < print_len; index++) {
   280     st->print_cr(" - %3d: %s", index, (ta->bool_at(index) == 0) ? "false" : "true");
   281   }
   282 }
   285 static void print_char_array(typeArrayOop ta, int print_len, outputStream* st) {
   286   for (int index = 0; index < print_len; index++) {
   287     jchar c = ta->char_at(index);
   288     st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' ');
   289   }
   290 }
   293 static void print_float_array(typeArrayOop ta, int print_len, outputStream* st) {
   294   for (int index = 0; index < print_len; index++) {
   295     st->print_cr(" - %3d: %g", index, ta->float_at(index));
   296   }
   297 }
   300 static void print_double_array(typeArrayOop ta, int print_len, outputStream* st) {
   301   for (int index = 0; index < print_len; index++) {
   302     st->print_cr(" - %3d: %g", index, ta->double_at(index));
   303   }
   304 }
   307 static void print_byte_array(typeArrayOop ta, int print_len, outputStream* st) {
   308   for (int index = 0; index < print_len; index++) {
   309     jbyte c = ta->byte_at(index);
   310     st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' ');
   311   }
   312 }
   315 static void print_short_array(typeArrayOop ta, int print_len, outputStream* st) {
   316   for (int index = 0; index < print_len; index++) {
   317     int v = ta->ushort_at(index);
   318     st->print_cr(" - %3d: 0x%x\t %d", index, v, v);
   319   }
   320 }
   323 static void print_int_array(typeArrayOop ta, int print_len, outputStream* st) {
   324   for (int index = 0; index < print_len; index++) {
   325     jint v = ta->int_at(index);
   326     st->print_cr(" - %3d: 0x%x %d", index, v, v);
   327   }
   328 }
   331 static void print_long_array(typeArrayOop ta, int print_len, outputStream* st) {
   332   for (int index = 0; index < print_len; index++) {
   333     jlong v = ta->long_at(index);
   334     st->print_cr(" - %3d: 0x%x 0x%x", index, high(v), low(v));
   335   }
   336 }
   339 void typeArrayKlass::oop_print_on(oop obj, outputStream* st) {
   340   arrayKlass::oop_print_on(obj, st);
   341   typeArrayOop ta = typeArrayOop(obj);
   342   int print_len = MIN2((intx) ta->length(), MaxElementPrintSize);
   343   switch (element_type()) {
   344     case T_BOOLEAN: print_boolean_array(ta, print_len, st); break;
   345     case T_CHAR:    print_char_array(ta, print_len, st);    break;
   346     case T_FLOAT:   print_float_array(ta, print_len, st);   break;
   347     case T_DOUBLE:  print_double_array(ta, print_len, st);  break;
   348     case T_BYTE:    print_byte_array(ta, print_len, st);    break;
   349     case T_SHORT:   print_short_array(ta, print_len, st);   break;
   350     case T_INT:     print_int_array(ta, print_len, st);     break;
   351     case T_LONG:    print_long_array(ta, print_len, st);    break;
   352     default: ShouldNotReachHere();
   353   }
   354   int remaining = ta->length() - print_len;
   355   if (remaining > 0) {
   356     tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
   357   }
   358 }
   360 #endif // PRODUCT
   362 const char* typeArrayKlass::internal_name() const {
   363   return Klass::external_name();
   364 }

mercurial