Sat, 01 Sep 2012 13:25:18 -0400
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>
coleenp@4037 | 1 | /* |
coleenp@4037 | 2 | * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
coleenp@4037 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
coleenp@4037 | 4 | * |
coleenp@4037 | 5 | * This code is free software; you can redistribute it and/or modify it |
coleenp@4037 | 6 | * under the terms of the GNU General Public License version 2 only, as |
coleenp@4037 | 7 | * published by the Free Software Foundation. |
coleenp@4037 | 8 | * |
coleenp@4037 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
coleenp@4037 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
coleenp@4037 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
coleenp@4037 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
coleenp@4037 | 13 | * accompanied this code). |
coleenp@4037 | 14 | * |
coleenp@4037 | 15 | * You should have received a copy of the GNU General Public License version |
coleenp@4037 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
coleenp@4037 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
coleenp@4037 | 18 | * |
coleenp@4037 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
coleenp@4037 | 20 | * or visit www.oracle.com if you need additional information or have any |
coleenp@4037 | 21 | * questions. |
coleenp@4037 | 22 | * |
coleenp@4037 | 23 | */ |
coleenp@4037 | 24 | |
coleenp@4037 | 25 | #include "precompiled.hpp" |
coleenp@4037 | 26 | #include "classfile/classLoaderData.hpp" |
coleenp@4037 | 27 | #include "memory/metadataFactory.hpp" |
coleenp@4037 | 28 | #include "memory/oopFactory.hpp" |
coleenp@4037 | 29 | #include "oops/annotations.hpp" |
coleenp@4037 | 30 | #include "oops/instanceKlass.hpp" |
coleenp@4037 | 31 | #include "utilities/ostream.hpp" |
coleenp@4037 | 32 | |
coleenp@4037 | 33 | // Allocate annotations in metadata area |
coleenp@4037 | 34 | Annotations* Annotations::allocate(ClassLoaderData* loader_data, TRAPS) { |
coleenp@4037 | 35 | return new (loader_data, size(), true, THREAD) Annotations(); |
coleenp@4037 | 36 | } |
coleenp@4037 | 37 | |
coleenp@4037 | 38 | Annotations* Annotations::allocate(ClassLoaderData* loader_data, |
coleenp@4037 | 39 | Array<AnnotationArray*>* fa, |
coleenp@4037 | 40 | Array<AnnotationArray*>* ma, |
coleenp@4037 | 41 | Array<AnnotationArray*>* mpa, |
coleenp@4037 | 42 | Array<AnnotationArray*>* mda, TRAPS) { |
coleenp@4037 | 43 | return new (loader_data, size(), true, THREAD) Annotations(fa, ma, mpa, mda); |
coleenp@4037 | 44 | } |
coleenp@4037 | 45 | |
coleenp@4037 | 46 | // helper |
coleenp@4037 | 47 | static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) { |
coleenp@4037 | 48 | if (p != NULL) { |
coleenp@4037 | 49 | for (int i = 0; i < p->length(); i++) { |
coleenp@4037 | 50 | MetadataFactory::free_array<u1>(loader_data, p->at(i)); |
coleenp@4037 | 51 | } |
coleenp@4037 | 52 | MetadataFactory::free_array<AnnotationArray*>(loader_data, p); |
coleenp@4037 | 53 | } |
coleenp@4037 | 54 | } |
coleenp@4037 | 55 | |
coleenp@4037 | 56 | void Annotations::deallocate_contents(ClassLoaderData* loader_data) { |
coleenp@4037 | 57 | if (class_annotations() != NULL) { |
coleenp@4037 | 58 | MetadataFactory::free_array<u1>(loader_data, class_annotations()); |
coleenp@4037 | 59 | } |
coleenp@4037 | 60 | free_contents(loader_data, fields_annotations()); |
coleenp@4037 | 61 | free_contents(loader_data, methods_annotations()); |
coleenp@4037 | 62 | free_contents(loader_data, methods_parameter_annotations()); |
coleenp@4037 | 63 | free_contents(loader_data, methods_default_annotations()); |
coleenp@4037 | 64 | } |
coleenp@4037 | 65 | |
coleenp@4037 | 66 | // Set the annotation at 'idnum' to 'anno'. |
coleenp@4037 | 67 | // We don't want to create or extend the array if 'anno' is NULL, since that is the |
coleenp@4037 | 68 | // default value. However, if the array exists and is long enough, we must set NULL values. |
coleenp@4037 | 69 | void Annotations::set_methods_annotations_of(instanceKlassHandle ik, |
coleenp@4037 | 70 | int idnum, AnnotationArray* anno, |
coleenp@4037 | 71 | Array<AnnotationArray*>** md_p, |
coleenp@4037 | 72 | TRAPS) { |
coleenp@4037 | 73 | Array<AnnotationArray*>* md = *md_p; |
coleenp@4037 | 74 | if (md != NULL && md->length() > idnum) { |
coleenp@4037 | 75 | md->at_put(idnum, anno); |
coleenp@4037 | 76 | } else if (anno != NULL) { |
coleenp@4037 | 77 | // create the array |
coleenp@4037 | 78 | int length = MAX2(idnum+1, (int)ik->idnum_allocated_count()); |
coleenp@4037 | 79 | md = MetadataFactory::new_array<AnnotationArray*>(ik->class_loader_data(), length, CHECK); |
coleenp@4037 | 80 | if (*md_p != NULL) { |
coleenp@4037 | 81 | // copy the existing entries |
coleenp@4037 | 82 | for (int index = 0; index < (*md_p)->length(); index++) { |
coleenp@4037 | 83 | md->at_put(index, (*md_p)->at(index)); |
coleenp@4037 | 84 | } |
coleenp@4037 | 85 | } |
coleenp@4037 | 86 | set_annotations(md, md_p); |
coleenp@4037 | 87 | md->at_put(idnum, anno); |
coleenp@4037 | 88 | } // if no array and idnum isn't included there is nothing to do |
coleenp@4037 | 89 | } |
coleenp@4037 | 90 | |
coleenp@4037 | 91 | // Keep created annotations in a global growable array (should be hashtable) |
coleenp@4037 | 92 | // need to add, search, delete when class is unloaded. |
coleenp@4037 | 93 | // Does it need a lock? yes. This sucks. |
coleenp@4037 | 94 | |
coleenp@4037 | 95 | // Copy annotations to JVM call or reflection to the java heap. |
coleenp@4037 | 96 | typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) { |
coleenp@4037 | 97 | if (annotations != NULL) { |
coleenp@4037 | 98 | int length = annotations->length(); |
coleenp@4037 | 99 | typeArrayOop copy = oopFactory::new_byteArray(length, CHECK_NULL); |
coleenp@4037 | 100 | for (int i = 0; i< length; i++) { |
coleenp@4037 | 101 | copy->byte_at_put(i, annotations->at(i)); |
coleenp@4037 | 102 | } |
coleenp@4037 | 103 | return copy; |
coleenp@4037 | 104 | } else { |
coleenp@4037 | 105 | return NULL; |
coleenp@4037 | 106 | } |
coleenp@4037 | 107 | } |
coleenp@4037 | 108 | |
coleenp@4037 | 109 | |
coleenp@4037 | 110 | void Annotations::print_value_on(outputStream* st) const { |
coleenp@4037 | 111 | st->print("Anotations(" INTPTR_FORMAT ")", this); |
coleenp@4037 | 112 | } |
coleenp@4037 | 113 | |
coleenp@4037 | 114 | #define BULLET " - " |
coleenp@4037 | 115 | |
coleenp@4037 | 116 | #ifndef PRODUCT |
coleenp@4037 | 117 | void Annotations::print_on(outputStream* st) const { |
coleenp@4037 | 118 | st->print(BULLET"class_annotations "); class_annotations()->print_value_on(st); |
coleenp@4037 | 119 | st->print(BULLET"fields_annotations "); fields_annotations()->print_value_on(st); |
coleenp@4037 | 120 | st->print(BULLET"methods_annotations "); methods_annotations()->print_value_on(st); |
coleenp@4037 | 121 | st->print(BULLET"methods_parameter_annotations"); methods_parameter_annotations()->print_value_on(st); |
coleenp@4037 | 122 | st->print(BULLET"methods_default_annotations "); methods_default_annotations()->print_value_on(st); |
coleenp@4037 | 123 | } |
coleenp@4037 | 124 | #endif // PRODUCT |