diff src/share/vm/oops/typeArrayKlass.cpp @ 6725:da91efe96a93

6964458: Reimplement class meta-data storage to use native memory Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author coleenp
date Sat, 01 Sep 2012 13:25:18 -0400
parents fc9d8850ab8b
children 86af3dacab81 d8ce2825b193
line wrap: on
line diff
--- a/src/share/vm/oops/typeArrayKlass.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -23,23 +23,25 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
+#include "memory/metadataFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/instanceKlass.hpp"
-#include "oops/klassOop.hpp"
-#include "oops/objArrayKlassKlass.hpp"
+#include "oops/klass.inline.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "runtime/handles.inline.hpp"
 
-bool typeArrayKlass::compute_is_subtype_of(klassOop k) {
-  if (!k->klass_part()->oop_is_typeArray()) {
+bool typeArrayKlass::compute_is_subtype_of(Klass* k) {
+  if (!k->oop_is_typeArray()) {
     return arrayKlass::compute_is_subtype_of(k);
   }
 
@@ -49,31 +51,46 @@
   return element_type() == tak->element_type();
 }
 
-klassOop typeArrayKlass::create_klass(BasicType type, int scale,
+typeArrayKlass* typeArrayKlass::create_klass(BasicType type,
                                       const char* name_str, TRAPS) {
-  typeArrayKlass o;
-
   Symbol* sym = NULL;
   if (name_str != NULL) {
     sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL);
   }
-  KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
+
+  ClassLoaderData* null_loader_data = ClassLoaderData::the_null_class_loader_data();
+
+  typeArrayKlass* ak = typeArrayKlass::allocate(null_loader_data, type, sym, CHECK_NULL);
 
-  arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL);
-  typeArrayKlass* ak = typeArrayKlass::cast(k());
-  ak->set_name(sym);
-  ak->set_layout_helper(array_layout_helper(type));
-  assert(scale == (1 << ak->log2_element_size()), "scale must check out");
-  assert(ak->oop_is_javaArray(), "sanity");
-  assert(ak->oop_is_typeArray(), "sanity");
-  ak->set_max_length(arrayOopDesc::max_array_length(type));
-  assert(k()->size() > header_size(), "bad size");
+  // Add all classes to our internal class loader list here,
+  // including classes in the bootstrap (NULL) class loader.
+  // GC walks these as strong roots.
+  null_loader_data->add_class(ak);
 
   // Call complete_create_array_klass after all instance variables have been initialized.
-  KlassHandle super (THREAD, k->super());
-  complete_create_array_klass(k, super, CHECK_NULL);
+  complete_create_array_klass(ak, ak->super(), CHECK_NULL);
+
+  return ak;
+}
+
+typeArrayKlass* typeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) {
+  assert(typeArrayKlass::header_size() <= InstanceKlass::header_size(),
+      "array klasses must be same size as InstanceKlass");
+
+  int size = arrayKlass::static_size(typeArrayKlass::header_size());
 
-  return k();
+  return new (loader_data, size, THREAD) typeArrayKlass(type, name);
+}
+
+typeArrayKlass::typeArrayKlass(BasicType type, Symbol* name) : arrayKlass(name) {
+  set_layout_helper(array_layout_helper(type));
+  assert(oop_is_array(), "sanity");
+  assert(oop_is_typeArray(), "sanity");
+
+  set_max_length(arrayOopDesc::max_array_length(type));
+  assert(size() >= typeArrayKlass::header_size(), "bad size");
+
+  set_class_loader_data(ClassLoaderData::the_null_class_loader_data());
 }
 
 typeArrayOop typeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) {
@@ -81,7 +98,7 @@
   if (length >= 0) {
     if (length <= max_length()) {
       size_t size = typeArrayOopDesc::object_size(layout_helper(), length);
-      KlassHandle h_k(THREAD, as_klassOop());
+      KlassHandle h_k(THREAD, this);
       typeArrayOop t;
       CollectedHeap* ch = Universe::heap();
       if (do_zero) {
@@ -89,7 +106,6 @@
       } else {
         t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL);
       }
-      assert(t->is_parsable(), "Don't publish unless parsable");
       return t;
     } else {
       report_java_out_of_memory("Requested array size exceeds VM limit");
@@ -101,16 +117,6 @@
   }
 }
 
-typeArrayOop typeArrayKlass::allocate_permanent(int length, TRAPS) {
-  if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
-  int size = typeArrayOopDesc::object_size(layout_helper(), length);
-  KlassHandle h_k(THREAD, as_klassOop());
-  typeArrayOop t = (typeArrayOop)
-    CollectedHeap::permanent_array_allocate(h_k, size, length, CHECK_NULL);
-  assert(t->is_parsable(), "Can't publish until parsable");
-  return t;
-}
-
 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
   // For typeArrays this is only called for the last dimension
   assert(rank == 1, "just checking");
@@ -150,19 +156,13 @@
 
 
 // create a klass of array holding typeArrays
-klassOop typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
-  typeArrayKlassHandle h_this(THREAD, as_klassOop());
-  return array_klass_impl(h_this, or_null, n, THREAD);
-}
+Klass* typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
+  int dim = dimension();
+  assert(dim <= n, "check order of chain");
+    if (dim == n)
+      return this;
 
-klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_null, int n, TRAPS) {
-  int dimension = h_this->dimension();
-  assert(dimension <= n, "check order of chain");
-    if (dimension == n)
-      return h_this();
-
-  objArrayKlassHandle  h_ak(THREAD, h_this->higher_dimension());
-  if (h_ak.is_null()) {
+  if (higher_dimension() == NULL) {
     if (or_null)  return NULL;
 
     ResourceMark rm;
@@ -172,28 +172,27 @@
       // Atomic create higher dimension and link into list
       MutexLocker mu(MultiArray_lock, THREAD);
 
-      h_ak = objArrayKlassHandle(THREAD, h_this->higher_dimension());
-      if (h_ak.is_null()) {
-        klassOop oak = objArrayKlassKlass::cast(
-          Universe::objArrayKlassKlassObj())->allocate_objArray_klass(
-          dimension + 1, h_this, CHECK_NULL);
-        h_ak = objArrayKlassHandle(THREAD, oak);
-        h_ak->set_lower_dimension(h_this());
+      if (higher_dimension() == NULL) {
+        Klass* oak = objArrayKlass::allocate_objArray_klass(
+              class_loader_data(), dim + 1, this, CHECK_NULL);
+        objArrayKlass* h_ak = objArrayKlass::cast(oak);
+        h_ak->set_lower_dimension(this);
         OrderAccess::storestore();
-        h_this->set_higher_dimension(h_ak());
+        set_higher_dimension(h_ak);
         assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
       }
     }
   } else {
     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   }
+  objArrayKlass* h_ak = objArrayKlass::cast(higher_dimension());
   if (or_null) {
     return h_ak->array_klass_or_null(n);
   }
   return h_ak->array_klass(n, CHECK_NULL);
 }
 
-klassOop typeArrayKlass::array_klass_impl(bool or_null, TRAPS) {
+Klass* typeArrayKlass::array_klass_impl(bool or_null, TRAPS) {
   return array_klass_impl(or_null, dimension() +  1, THREAD);
 }
 
@@ -225,7 +224,7 @@
   return t->object_size();
 }
 
-int typeArrayKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
+int typeArrayKlass::oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
   assert(obj->is_typeArray(),"must be a type array");
   typeArrayOop t = typeArrayOop(obj);
   // Performance tweak: We skip iterating over the klass pointer since we
@@ -233,7 +232,7 @@
   return t->object_size();
 }
 
-int typeArrayKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
+int typeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
   assert(obj->is_typeArray(),"must be a type array");
   typeArrayOop t = typeArrayOop(obj);
   // Performance tweak: We skip iterating over the klass pointer since we
@@ -243,6 +242,7 @@
 
 #ifndef SERIALGC
 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
+  ShouldNotReachHere();
   assert(obj->is_typeArray(),"must be a type array");
 }
 
@@ -273,8 +273,35 @@
   return NULL;
 }
 
+
+// Printing
+
+void typeArrayKlass::print_on(outputStream* st) const {
 #ifndef PRODUCT
-// Printing
+  assert(is_klass(), "must be klass");
+  print_value_on(st);
+  Klass::print_on(st);
+#endif //PRODUCT
+}
+
+void typeArrayKlass::print_value_on(outputStream* st) const {
+  assert(is_klass(), "must be klass");
+  st->print("{type array ");
+  switch (element_type()) {
+    case T_BOOLEAN: st->print("bool");    break;
+    case T_CHAR:    st->print("char");    break;
+    case T_FLOAT:   st->print("float");   break;
+    case T_DOUBLE:  st->print("double");  break;
+    case T_BYTE:    st->print("byte");    break;
+    case T_SHORT:   st->print("short");   break;
+    case T_INT:     st->print("int");     break;
+    case T_LONG:    st->print("long");    break;
+    default: ShouldNotReachHere();
+  }
+  st->print("}");
+}
+
+#ifndef PRODUCT
 
 static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) {
   for (int index = 0; index < print_len; index++) {