diff src/share/vm/classfile/loaderConstraints.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 d2a62e0f25eb
children 070d523b96a7
line wrap: on
line diff
--- a/src/share/vm/classfile/loaderConstraints.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/src/share/vm/classfile/loaderConstraints.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/loaderConstraints.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
@@ -30,16 +31,20 @@
 #include "runtime/safepoint.hpp"
 #include "utilities/hashtable.inline.hpp"
 
+void LoaderConstraintEntry::set_loader(int i, oop p) {
+  set_loader_data(i, ClassLoaderData::class_loader_data(p));
+}
+
 LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
-  : Hashtable<klassOop, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
+  : Hashtable<Klass*, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
 
 
 LoaderConstraintEntry* LoaderConstraintTable::new_entry(
                                  unsigned int hash, Symbol* name,
-                                 klassOop klass, int num_loaders,
+                                 Klass* klass, int num_loaders,
                                  int max_loaders) {
   LoaderConstraintEntry* entry;
-  entry = (LoaderConstraintEntry*)Hashtable<klassOop, mtClass>::new_entry(hash, klass);
+  entry = (LoaderConstraintEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
   entry->set_name(name);
   entry->set_num_loaders(num_loaders);
   entry->set_max_loaders(max_loaders);
@@ -49,27 +54,21 @@
 void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) {
   // decrement name refcount before freeing
   entry->name()->decrement_refcount();
-  Hashtable<klassOop, mtClass>::free_entry(entry);
+  Hashtable<Klass*, mtClass>::free_entry(entry);
 }
 
-
-void LoaderConstraintTable::oops_do(OopClosure* f) {
+// Enhanced Class Redefinition support
+void LoaderConstraintTable::classes_do(KlassClosure* f) {
   for (int index = 0; index < table_size(); index++) {
     for (LoaderConstraintEntry* probe = bucket(index);
                                 probe != NULL;
                                 probe = probe->next()) {
       if (probe->klass() != NULL) {
-        f->do_oop((oop*)probe->klass_addr());
+        f->do_klass(probe->klass());
       }
-      for (int n = 0; n < probe->num_loaders(); n++) {
-        if (probe->loader(n) != NULL) {
-          f->do_oop(probe->loader_addr(n));
         }
       }
     }
-  }
-}
-
 
 // The loaderConstraintTable must always be accessed with the
 // SystemDictionary lock held. This is true even for readers as
@@ -81,12 +80,14 @@
   unsigned int hash = compute_hash(name);
   int index = hash_to_index(hash);
   LoaderConstraintEntry** pp = bucket_addr(index);
+  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(loader());
+
   while (*pp) {
     LoaderConstraintEntry* p = *pp;
     if (p->hash() == hash) {
       if (p->name() == name) {
         for (int i = p->num_loaders() - 1; i >= 0; i--) {
-          if (p->loader(i) == loader()) {
+          if (p->loader_data(i) == loader_data) {
             return pp;
           }
         }
@@ -98,16 +99,17 @@
 }
 
 
-void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) {
+void LoaderConstraintTable::purge_loader_constraints() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   // Remove unloaded entries from constraint table
   for (int index = 0; index < table_size(); index++) {
     LoaderConstraintEntry** p = bucket_addr(index);
     while(*p) {
       LoaderConstraintEntry* probe = *p;
-      klassOop klass = probe->klass();
+      Klass* klass = probe->klass();
       // Remove klass that is no longer alive
-      if (klass != NULL && !is_alive->do_object_b(klass)) {
+      if (klass != NULL &&
+          klass->class_loader_data()->is_unloading()) {
         probe->set_klass(NULL);
         if (TraceLoaderConstraints) {
           ResourceMark rm;
@@ -116,19 +118,18 @@
                      probe->name()->as_C_string());
           for (int i = 0; i < probe->num_loaders(); i++) {
             tty->print_cr("[   [%d]: %s", i,
-                          SystemDictionary::loader_name(probe->loader(i)));
+                          SystemDictionary::loader_name(probe->loader_data(i)));
           }
         }
       }
       // Remove entries no longer alive from loader array
       int n = 0;
       while (n < probe->num_loaders()) {
-        if (probe->loader(n) != NULL) {
-          if (!is_alive->do_object_b(probe->loader(n))) {
+        if (probe->loader_data(n)->is_unloading()) {
             if (TraceLoaderConstraints) {
               ResourceMark rm;
               tty->print_cr("[Purging loader %s from constraint for name %s",
-                            SystemDictionary::loader_name(probe->loader(n)),
+                          SystemDictionary::loader_name(probe->loader_data(n)),
                             probe->name()->as_C_string()
                             );
             }
@@ -136,22 +137,21 @@
             // Compact array
             int num = probe->num_loaders() - 1;
             probe->set_num_loaders(num);
-            probe->set_loader(n, probe->loader(num));
-            probe->set_loader(num, NULL);
+          probe->set_loader_data(n, probe->loader_data(num));
+          probe->set_loader_data(num, NULL);
 
             if (TraceLoaderConstraints) {
               ResourceMark rm;
               tty->print_cr("[New loader list:");
               for (int i = 0; i < probe->num_loaders(); i++) {
                 tty->print_cr("[   [%d]: %s", i,
-                              SystemDictionary::loader_name(probe->loader(i)));
+                            SystemDictionary::loader_name(probe->loader_data(i)));
               }
             }
 
             continue;  // current element replaced, so restart without
                        // incrementing n
           }
-        }
         n++;
       }
       // Check whether entry should be purged
@@ -169,12 +169,9 @@
       } else {
 #ifdef ASSERT
         if (probe->klass() != NULL) {
-          assert(is_alive->do_object_b(probe->klass()), "klass should be live");
-        }
-        for (n = 0; n < probe->num_loaders(); n++) {
-          if (probe->loader(n) != NULL) {
-            assert(is_alive->do_object_b(probe->loader(n)), "loader should be live");
-          }
+          ClassLoaderData* loader_data =
+            probe->klass()->class_loader_data();
+          assert(!loader_data->is_unloading(), "klass should be live");
         }
 #endif
         // Go to next entry
@@ -185,14 +182,14 @@
 }
 
 bool LoaderConstraintTable::add_entry(Symbol* class_name,
-                                      klassOop klass1, Handle class_loader1,
-                                      klassOop klass2, Handle class_loader2) {
+                                      Klass* klass1, Handle class_loader1,
+                                      Klass* klass2, Handle class_loader2) {
   int failure_code = 0; // encode different reasons for failing
 
   if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
     failure_code = 1;
   } else {
-    klassOop klass = klass1 != NULL ? klass1 : klass2;
+    Klass* klass = klass1 != NULL ? klass1 : klass2;
 
     LoaderConstraintEntry** pp1 = find_loader_constraint(class_name,
                                                          class_loader1);
@@ -224,7 +221,7 @@
         int index = hash_to_index(hash);
         LoaderConstraintEntry* p;
         p = new_entry(hash, class_name, klass, 2, 2);
-        p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2, mtClass));
+        p->set_loaders(NEW_C_HEAP_ARRAY(ClassLoaderData*, 2, mtClass));
         p->set_loader(0, class_loader1());
         p->set_loader(1, class_loader2());
         p->set_klass(klass);
@@ -319,11 +316,11 @@
   }
 }
 
-klassOop LoaderConstraintTable::find_constrained_klass(Symbol* name,
+Klass* LoaderConstraintTable::find_constrained_klass(Symbol* name,
                                                        Handle loader) {
   LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
   if (p != NULL && p->klass() != NULL) {
-    if (Klass::cast(p->klass())->oop_is_instance() && !instanceKlass::cast(p->klass())->is_loaded()) {
+    if (Klass::cast(p->klass())->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) {
       // Only return fully loaded classes.  Classes found through the
       // constraints might still be in the process of loading.
       return NULL;
@@ -340,10 +337,10 @@
                                                     int nfree) {
     if (p->max_loaders() - p->num_loaders() < nfree) {
         int n = nfree + p->num_loaders();
-        oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n, mtClass);
-        memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
+        ClassLoaderData** new_loaders = NEW_C_HEAP_ARRAY(ClassLoaderData*, n, mtClass);
+        memcpy(new_loaders, p->loaders(), sizeof(ClassLoaderData*) * p->num_loaders());
         p->set_max_loaders(n);
-        FREE_C_HEAP_ARRAY(oop, p->loaders(), mtClass);
+        FREE_C_HEAP_ARRAY(ClassLoaderData*, p->loaders(), mtClass);
         p->set_loaders(new_loaders);
     }
 }
@@ -351,7 +348,7 @@
 
 void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
                                                      Handle loader,
-                                                     klassOop klass) {
+                                                     Klass* klass) {
   ensure_loader_constraint_capacity(p, 1);
   int num = p->num_loaders();
   p->set_loader(num, loader());
@@ -376,7 +373,7 @@
 void LoaderConstraintTable::merge_loader_constraints(
                                                    LoaderConstraintEntry** pp1,
                                                    LoaderConstraintEntry** pp2,
-                                                   klassOop klass) {
+                                                   Klass* klass) {
   // make sure *pp1 has higher capacity
   if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
     LoaderConstraintEntry** tmp = pp2;
@@ -391,7 +388,7 @@
 
   for (int i = 0; i < p2->num_loaders(); i++) {
     int num = p1->num_loaders();
-    p1->set_loader(num, p2->loader(i));
+    p1->set_loader_data(num, p2->loader_data(i));
     p1->set_num_loaders(num + 1);
   }
 
@@ -403,7 +400,7 @@
 
     for (int i = 0; i < p1->num_loaders(); i++) {
       tty->print_cr("[   [%d]: %s", i,
-                    SystemDictionary::loader_name(p1->loader(i)));
+                    SystemDictionary::loader_name(p1->loader_data(i)));
     }
     if (p1->klass() == NULL) {
       tty->print_cr("[... and setting class object]");
@@ -439,33 +436,33 @@
                                 probe != NULL;
                                 probe = probe->next()) {
       if (probe->klass() != NULL) {
-        instanceKlass* ik = instanceKlass::cast(probe->klass());
+        InstanceKlass* ik = InstanceKlass::cast(probe->klass());
         guarantee(ik->name() == probe->name(), "name should match");
         Symbol* name = ik->name();
-        Handle loader(thread, ik->class_loader());
-        unsigned int d_hash = dictionary->compute_hash(name, loader);
+        ClassLoaderData* loader_data = ik->class_loader_data();
+        unsigned int d_hash = dictionary->compute_hash(name, loader_data);
         int d_index = dictionary->hash_to_index(d_hash);
-        klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
+        Klass* k = dictionary->find_class(d_index, d_hash, name, loader_data);
         if (k != NULL) {
           // We found the class in the system dictionary, so we should
-          // make sure that the klassOop matches what we already have.
+          // make sure that the Klass* matches what we already have.
           guarantee(k == probe->klass(), "klass should be in dictionary");
         } else {
           // If we don't find the class in the system dictionary, it
           // has to be in the placeholders table.
-          unsigned int p_hash = placeholders->compute_hash(name, loader);
+          unsigned int p_hash = placeholders->compute_hash(name, loader_data);
           int p_index = placeholders->hash_to_index(p_hash);
           PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
-                                                            name, loader);
+                                                            name, loader_data);
 
-          // The instanceKlass might not be on the entry, so the only
+          // The InstanceKlass might not be on the entry, so the only
           // thing we can check here is whether we were successful in
           // finding the class in the placeholders table.
           guarantee(entry != NULL, "klass should be in the placeholders");
         }
       }
       for (int n = 0; n< probe->num_loaders(); n++) {
-        guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
+        assert(ClassLoaderDataGraph::contains_loader_data(probe->loader_data(n)), "The loader is missing");
       }
     }
   }
@@ -487,7 +484,7 @@
       probe->name()->print();
       tty->print(" , loaders:");
       for (int n = 0; n < probe->num_loaders(); n++) {
-        probe->loader(n)->print_value();
+        probe->loader_data(n)->print_value();
         tty->print(", ");
       }
       tty->cr();