src/share/vm/prims/jvmtiGetLoadedClasses.cpp

Sun, 15 Sep 2013 15:28:58 +0200

author
goetz
date
Sun, 15 Sep 2013 15:28:58 +0200
changeset 6470
abe03600372a
parent 4278
070d523b96a7
child 6024
e64f1fe9756b
permissions
-rw-r--r--

8024468: PPC64 (part 201): cppInterpreter: implement bytecode profiling
Summary: Implement profiling for c2 jit compilation. Also enable new cppInterpreter features.
Reviewed-by: kvn

duke@435 1 /*
coleenp@4037 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "classfile/systemDictionary.hpp"
stefank@2314 27 #include "memory/universe.inline.hpp"
stefank@2314 28 #include "prims/jvmtiGetLoadedClasses.hpp"
stefank@2314 29 #include "runtime/thread.hpp"
duke@435 30
duke@435 31
duke@435 32
duke@435 33 // The closure for GetLoadedClasses and GetClassLoaderClasses
duke@435 34 class JvmtiGetLoadedClassesClosure : public StackObj {
duke@435 35 // Since the SystemDictionary::classes_do callback
duke@435 36 // doesn't pass a closureData pointer,
duke@435 37 // we use a thread-local slot to hold a pointer to
duke@435 38 // a stack allocated instance of this structure.
duke@435 39 private:
duke@435 40 jobject _initiatingLoader;
duke@435 41 int _count;
duke@435 42 Handle* _list;
duke@435 43 int _index;
duke@435 44
duke@435 45 private:
duke@435 46 // Getting and setting the thread local pointer
duke@435 47 static JvmtiGetLoadedClassesClosure* get_this() {
duke@435 48 JvmtiGetLoadedClassesClosure* result = NULL;
duke@435 49 JavaThread* thread = JavaThread::current();
duke@435 50 result = thread->get_jvmti_get_loaded_classes_closure();
duke@435 51 return result;
duke@435 52 }
duke@435 53 static void set_this(JvmtiGetLoadedClassesClosure* that) {
duke@435 54 JavaThread* thread = JavaThread::current();
duke@435 55 thread->set_jvmti_get_loaded_classes_closure(that);
duke@435 56 }
duke@435 57
duke@435 58 public:
duke@435 59 // Constructor/Destructor
duke@435 60 JvmtiGetLoadedClassesClosure() {
duke@435 61 JvmtiGetLoadedClassesClosure* that = get_this();
duke@435 62 assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
duke@435 63 _initiatingLoader = NULL;
duke@435 64 _count = 0;
duke@435 65 _list = NULL;
duke@435 66 _index = 0;
duke@435 67 set_this(this);
duke@435 68 }
duke@435 69
duke@435 70 JvmtiGetLoadedClassesClosure(jobject initiatingLoader) {
duke@435 71 JvmtiGetLoadedClassesClosure* that = get_this();
duke@435 72 assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
duke@435 73 _initiatingLoader = initiatingLoader;
duke@435 74 _count = 0;
duke@435 75 _list = NULL;
duke@435 76 _index = 0;
duke@435 77 set_this(this);
duke@435 78 }
duke@435 79
duke@435 80 ~JvmtiGetLoadedClassesClosure() {
duke@435 81 JvmtiGetLoadedClassesClosure* that = get_this();
duke@435 82 assert(that != NULL, "JvmtiGetLoadedClassesClosure not found");
duke@435 83 set_this(NULL);
duke@435 84 _initiatingLoader = NULL;
duke@435 85 _count = 0;
duke@435 86 if (_list != NULL) {
duke@435 87 FreeHeap(_list);
duke@435 88 _list = NULL;
duke@435 89 }
duke@435 90 _index = 0;
duke@435 91 }
duke@435 92
duke@435 93 // Accessors.
duke@435 94 jobject get_initiatingLoader() {
duke@435 95 return _initiatingLoader;
duke@435 96 }
duke@435 97
duke@435 98 int get_count() {
duke@435 99 return _count;
duke@435 100 }
duke@435 101
duke@435 102 void set_count(int value) {
duke@435 103 _count = value;
duke@435 104 }
duke@435 105
duke@435 106 Handle* get_list() {
duke@435 107 return _list;
duke@435 108 }
duke@435 109
duke@435 110 void set_list(Handle* value) {
duke@435 111 _list = value;
duke@435 112 }
duke@435 113
duke@435 114 int get_index() {
duke@435 115 return _index;
duke@435 116 }
duke@435 117
duke@435 118 void set_index(int value) {
duke@435 119 _index = value;
duke@435 120 }
duke@435 121
duke@435 122 Handle get_element(int index) {
duke@435 123 if ((_list != NULL) && (index < _count)) {
duke@435 124 return _list[index];
duke@435 125 } else {
duke@435 126 assert(false, "empty get_element");
duke@435 127 return Handle();
duke@435 128 }
duke@435 129 }
duke@435 130
duke@435 131 void set_element(int index, Handle value) {
duke@435 132 if ((_list != NULL) && (index < _count)) {
duke@435 133 _list[index] = value;
duke@435 134 } else {
duke@435 135 assert(false, "bad set_element");
duke@435 136 }
duke@435 137 }
duke@435 138
duke@435 139 // Other predicates
duke@435 140 bool available() {
duke@435 141 return (_list != NULL);
duke@435 142 }
duke@435 143
duke@435 144 #ifdef ASSERT
duke@435 145 // For debugging.
duke@435 146 void check(int limit) {
duke@435 147 for (int i = 0; i < limit; i += 1) {
duke@435 148 assert(Universe::heap()->is_in(get_element(i)()), "check fails");
duke@435 149 }
duke@435 150 }
duke@435 151 #endif
duke@435 152
duke@435 153 // Public methods that get called within the scope of the closure
duke@435 154 void allocate() {
zgu@3900 155 _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
duke@435 156 assert(_list != NULL, "Out of memory");
duke@435 157 if (_list == NULL) {
duke@435 158 _count = 0;
duke@435 159 }
duke@435 160 }
duke@435 161
duke@435 162 void extract(JvmtiEnv *env, jclass* result) {
duke@435 163 for (int index = 0; index < _count; index += 1) {
duke@435 164 result[index] = (jclass) env->jni_reference(get_element(index));
duke@435 165 }
duke@435 166 }
duke@435 167
duke@435 168 // Finally, the static methods that are the callbacks
coleenp@4037 169 static void increment(Klass* k) {
duke@435 170 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
duke@435 171 if (that->get_initiatingLoader() == NULL) {
hseigel@4278 172 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
duke@435 173 that->set_count(that->get_count() + 1);
duke@435 174 }
duke@435 175 } else if (k != NULL) {
duke@435 176 // if initiating loader not null, just include the instance with 1 dimension
duke@435 177 that->set_count(that->get_count() + 1);
duke@435 178 }
duke@435 179 }
duke@435 180
coleenp@4037 181 static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
duke@435 182 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
coleenp@4037 183 oop class_loader = loader_data->class_loader();
coleenp@4037 184 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
hseigel@4278 185 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
duke@435 186 that->set_count(that->get_count() + 1);
duke@435 187 }
duke@435 188 }
duke@435 189 }
duke@435 190
coleenp@4037 191 static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) {
duke@435 192 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
coleenp@4037 193 oop class_loader = loader_data->class_loader();
coleenp@4037 194 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
duke@435 195 that->set_count(that->get_count() + 1);
duke@435 196 }
duke@435 197 }
duke@435 198
coleenp@4037 199 static void add(Klass* k) {
duke@435 200 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
duke@435 201 if (that->available()) {
duke@435 202 if (that->get_initiatingLoader() == NULL) {
hseigel@4278 203 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
hseigel@4278 204 oop mirror = l->java_mirror();
duke@435 205 that->set_element(that->get_index(), mirror);
duke@435 206 that->set_index(that->get_index() + 1);
duke@435 207 }
duke@435 208 } else if (k != NULL) {
duke@435 209 // if initiating loader not null, just include the instance with 1 dimension
hseigel@4278 210 oop mirror = k->java_mirror();
duke@435 211 that->set_element(that->get_index(), mirror);
duke@435 212 that->set_index(that->get_index() + 1);
duke@435 213 }
duke@435 214 }
duke@435 215 }
duke@435 216
coleenp@4037 217 static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
duke@435 218 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
duke@435 219 if (that->available()) {
coleenp@4037 220 oop class_loader = loader_data->class_loader();
coleenp@4037 221 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
hseigel@4278 222 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
hseigel@4278 223 oop mirror = l->java_mirror();
duke@435 224 that->set_element(that->get_index(), mirror);
duke@435 225 that->set_index(that->get_index() + 1);
duke@435 226 }
duke@435 227 }
duke@435 228 }
duke@435 229 }
duke@435 230
duke@435 231 // increment the count for the given basic type array class (and any
duke@435 232 // multi-dimensional arrays). For example, for [B we check for
duke@435 233 // [[B, [[[B, .. and the count is incremented for each one that exists.
coleenp@4037 234 static void increment_for_basic_type_arrays(Klass* k) {
duke@435 235 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
duke@435 236 assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
hseigel@4278 237 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
duke@435 238 that->set_count(that->get_count() + 1);
duke@435 239 }
duke@435 240 }
duke@435 241
duke@435 242 // add the basic type array class and its multi-dimensional array classes to the list
coleenp@4037 243 static void add_for_basic_type_arrays(Klass* k) {
duke@435 244 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
duke@435 245 assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
duke@435 246 assert(that->available(), "no list");
hseigel@4278 247 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
hseigel@4278 248 oop mirror = l->java_mirror();
duke@435 249 that->set_element(that->get_index(), mirror);
duke@435 250 that->set_index(that->get_index() + 1);
duke@435 251 }
duke@435 252 }
duke@435 253 };
duke@435 254
duke@435 255
duke@435 256 jvmtiError
duke@435 257 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
duke@435 258 // Since SystemDictionary::classes_do only takes a function pointer
duke@435 259 // and doesn't call back with a closure data pointer,
duke@435 260 // we can only pass static methods.
duke@435 261
duke@435 262 JvmtiGetLoadedClassesClosure closure;
duke@435 263 {
duke@435 264 // To get a consistent list of classes we need MultiArray_lock to ensure
duke@435 265 // array classes aren't created, and SystemDictionary_lock to ensure that
duke@435 266 // classes aren't added to the system dictionary,
duke@435 267 MutexLocker ma(MultiArray_lock);
duke@435 268 MutexLocker sd(SystemDictionary_lock);
duke@435 269
duke@435 270 // First, count the classes
duke@435 271 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment);
duke@435 272 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment);
duke@435 273 // Next, fill in the classes
duke@435 274 closure.allocate();
duke@435 275 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add);
duke@435 276 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add);
duke@435 277 // Drop the SystemDictionary_lock, so the results could be wrong from here,
duke@435 278 // but we still have a snapshot.
duke@435 279 }
duke@435 280 // Post results
duke@435 281 jclass* result_list;
duke@435 282 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
duke@435 283 (unsigned char**)&result_list);
duke@435 284 if (err != JVMTI_ERROR_NONE) {
duke@435 285 return err;
duke@435 286 }
duke@435 287 closure.extract(env, result_list);
duke@435 288 *classCountPtr = closure.get_count();
duke@435 289 *classesPtr = result_list;
duke@435 290 return JVMTI_ERROR_NONE;
duke@435 291 }
duke@435 292
duke@435 293 jvmtiError
duke@435 294 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
duke@435 295 jint* classCountPtr, jclass** classesPtr) {
duke@435 296 // Since SystemDictionary::classes_do only takes a function pointer
duke@435 297 // and doesn't call back with a closure data pointer,
duke@435 298 // we can only pass static methods.
duke@435 299 JvmtiGetLoadedClassesClosure closure(initiatingLoader);
duke@435 300 {
duke@435 301 // To get a consistent list of classes we need MultiArray_lock to ensure
duke@435 302 // array classes aren't created, and SystemDictionary_lock to ensure that
duke@435 303 // classes aren't added to the system dictionary,
duke@435 304 MutexLocker ma(MultiArray_lock);
duke@435 305 MutexLocker sd(SystemDictionary_lock);
duke@435 306 // First, count the classes in the system dictionary which have this loader recorded
duke@435 307 // as an initiating loader. For basic type arrays this information is not recorded
duke@435 308 // so GetClassLoaderClasses will return all of the basic type arrays. This is okay
duke@435 309 // because the defining loader for basic type arrays is always the boot class loader
duke@435 310 // and these classes are "visible" to all loaders.
duke@435 311 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
duke@435 312 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
duke@435 313 // Next, fill in the classes
duke@435 314 closure.allocate();
duke@435 315 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
duke@435 316 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
duke@435 317 // Drop the SystemDictionary_lock, so the results could be wrong from here,
duke@435 318 // but we still have a snapshot.
duke@435 319 }
duke@435 320 // Post results
duke@435 321 jclass* result_list;
duke@435 322 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
duke@435 323 (unsigned char**)&result_list);
duke@435 324 if (err != JVMTI_ERROR_NONE) {
duke@435 325 return err;
duke@435 326 }
duke@435 327 closure.extract(env, result_list);
duke@435 328 *classCountPtr = closure.get_count();
duke@435 329 *classesPtr = result_list;
duke@435 330 return JVMTI_ERROR_NONE;
duke@435 331 }

mercurial