Mon, 10 Jan 2011 17:14:53 -0500
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
Summary: Make JvmtiGCMark safe to run non-safepoint and instrument CMS
Reviewed-by: ysr, dcubed
duke@435 | 1 | /* |
phh@2423 | 2 | * Copyright (c) 2003, 2011, 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 "classfile/vmSymbols.hpp" |
stefank@2314 | 28 | #include "interpreter/bytecodeStream.hpp" |
stefank@2314 | 29 | #include "interpreter/interpreter.hpp" |
stefank@2314 | 30 | #include "jvmtifiles/jvmtiEnv.hpp" |
stefank@2314 | 31 | #include "memory/resourceArea.hpp" |
stefank@2314 | 32 | #include "memory/universe.inline.hpp" |
stefank@2314 | 33 | #include "oops/cpCacheOop.hpp" |
stefank@2314 | 34 | #include "oops/instanceKlass.hpp" |
stefank@2314 | 35 | #include "prims/jniCheck.hpp" |
stefank@2314 | 36 | #include "prims/jvm_misc.hpp" |
stefank@2314 | 37 | #include "prims/jvmtiAgentThread.hpp" |
stefank@2314 | 38 | #include "prims/jvmtiClassFileReconstituter.hpp" |
stefank@2314 | 39 | #include "prims/jvmtiCodeBlobEvents.hpp" |
stefank@2314 | 40 | #include "prims/jvmtiExtensions.hpp" |
stefank@2314 | 41 | #include "prims/jvmtiGetLoadedClasses.hpp" |
stefank@2314 | 42 | #include "prims/jvmtiImpl.hpp" |
stefank@2314 | 43 | #include "prims/jvmtiManageCapabilities.hpp" |
stefank@2314 | 44 | #include "prims/jvmtiRawMonitor.hpp" |
stefank@2314 | 45 | #include "prims/jvmtiRedefineClasses.hpp" |
stefank@2314 | 46 | #include "prims/jvmtiTagMap.hpp" |
stefank@2314 | 47 | #include "prims/jvmtiThreadState.inline.hpp" |
stefank@2314 | 48 | #include "prims/jvmtiUtil.hpp" |
stefank@2314 | 49 | #include "runtime/arguments.hpp" |
stefank@2314 | 50 | #include "runtime/deoptimization.hpp" |
stefank@2314 | 51 | #include "runtime/interfaceSupport.hpp" |
stefank@2314 | 52 | #include "runtime/javaCalls.hpp" |
stefank@2314 | 53 | #include "runtime/jfieldIDWorkaround.hpp" |
stefank@2314 | 54 | #include "runtime/osThread.hpp" |
stefank@2314 | 55 | #include "runtime/reflectionUtils.hpp" |
stefank@2314 | 56 | #include "runtime/signature.hpp" |
stefank@2314 | 57 | #include "runtime/vframe.hpp" |
stefank@2314 | 58 | #include "runtime/vmThread.hpp" |
stefank@2314 | 59 | #include "services/threadService.hpp" |
stefank@2314 | 60 | #include "utilities/exceptions.hpp" |
stefank@2314 | 61 | #include "utilities/preserveException.hpp" |
stefank@2314 | 62 | #ifdef TARGET_OS_FAMILY_linux |
stefank@2314 | 63 | # include "thread_linux.inline.hpp" |
stefank@2314 | 64 | #endif |
stefank@2314 | 65 | #ifdef TARGET_OS_FAMILY_solaris |
stefank@2314 | 66 | # include "thread_solaris.inline.hpp" |
stefank@2314 | 67 | #endif |
stefank@2314 | 68 | #ifdef TARGET_OS_FAMILY_windows |
stefank@2314 | 69 | # include "thread_windows.inline.hpp" |
stefank@2314 | 70 | #endif |
stefank@2314 | 71 | |
duke@435 | 72 | |
duke@435 | 73 | |
duke@435 | 74 | #define FIXLATER 0 // REMOVE this when completed. |
duke@435 | 75 | |
duke@435 | 76 | // FIXLATER: hook into JvmtiTrace |
duke@435 | 77 | #define TraceJVMTICalls false |
duke@435 | 78 | |
dcubed@1556 | 79 | JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) { |
duke@435 | 80 | } |
duke@435 | 81 | |
duke@435 | 82 | JvmtiEnv::~JvmtiEnv() { |
duke@435 | 83 | } |
duke@435 | 84 | |
duke@435 | 85 | JvmtiEnv* |
dcubed@1556 | 86 | JvmtiEnv::create_a_jvmti(jint version) { |
dcubed@1556 | 87 | return new JvmtiEnv(version); |
duke@435 | 88 | } |
duke@435 | 89 | |
duke@435 | 90 | // VM operation class to copy jni function table at safepoint. |
duke@435 | 91 | // More than one java threads or jvmti agents may be reading/ |
duke@435 | 92 | // modifying jni function tables. To reduce the risk of bad |
duke@435 | 93 | // interaction b/w these threads it is copied at safepoint. |
duke@435 | 94 | class VM_JNIFunctionTableCopier : public VM_Operation { |
duke@435 | 95 | private: |
duke@435 | 96 | const struct JNINativeInterface_ *_function_table; |
duke@435 | 97 | public: |
duke@435 | 98 | VM_JNIFunctionTableCopier(const struct JNINativeInterface_ *func_tbl) { |
duke@435 | 99 | _function_table = func_tbl; |
duke@435 | 100 | }; |
duke@435 | 101 | |
duke@435 | 102 | VMOp_Type type() const { return VMOp_JNIFunctionTableCopier; } |
duke@435 | 103 | void doit() { |
duke@435 | 104 | copy_jni_function_table(_function_table); |
duke@435 | 105 | }; |
duke@435 | 106 | }; |
duke@435 | 107 | |
duke@435 | 108 | // |
duke@435 | 109 | // Do not change the "prefix" marker below, everything above it is copied |
duke@435 | 110 | // unchanged into the filled stub, everything below is controlled by the |
duke@435 | 111 | // stub filler (only method bodies are carried forward, and then only for |
duke@435 | 112 | // functionality still in the spec). |
duke@435 | 113 | // |
duke@435 | 114 | // end file prefix |
duke@435 | 115 | |
duke@435 | 116 | // |
duke@435 | 117 | // Memory Management functions |
duke@435 | 118 | // |
duke@435 | 119 | |
duke@435 | 120 | // mem_ptr - pre-checked for NULL |
duke@435 | 121 | jvmtiError |
duke@435 | 122 | JvmtiEnv::Allocate(jlong size, unsigned char** mem_ptr) { |
duke@435 | 123 | return allocate(size, mem_ptr); |
duke@435 | 124 | } /* end Allocate */ |
duke@435 | 125 | |
duke@435 | 126 | |
duke@435 | 127 | // mem - NULL is a valid value, must be checked |
duke@435 | 128 | jvmtiError |
duke@435 | 129 | JvmtiEnv::Deallocate(unsigned char* mem) { |
duke@435 | 130 | return deallocate(mem); |
duke@435 | 131 | } /* end Deallocate */ |
duke@435 | 132 | |
duke@435 | 133 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 134 | // java_thread - pre-checked |
duke@435 | 135 | // data - NULL is a valid value, must be checked |
duke@435 | 136 | jvmtiError |
duke@435 | 137 | JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) { |
duke@435 | 138 | JvmtiThreadState* state = java_thread->jvmti_thread_state(); |
duke@435 | 139 | if (state == NULL) { |
duke@435 | 140 | if (data == NULL) { |
duke@435 | 141 | // leaving state unset same as data set to NULL |
duke@435 | 142 | return JVMTI_ERROR_NONE; |
duke@435 | 143 | } |
duke@435 | 144 | // otherwise, create the state |
duke@435 | 145 | state = JvmtiThreadState::state_for(java_thread); |
dcubed@1044 | 146 | if (state == NULL) { |
dcubed@1044 | 147 | return JVMTI_ERROR_THREAD_NOT_ALIVE; |
dcubed@1044 | 148 | } |
duke@435 | 149 | } |
duke@435 | 150 | state->env_thread_state(this)->set_agent_thread_local_storage_data((void*)data); |
duke@435 | 151 | return JVMTI_ERROR_NONE; |
duke@435 | 152 | } /* end SetThreadLocalStorage */ |
duke@435 | 153 | |
duke@435 | 154 | |
duke@435 | 155 | // Threads_lock NOT held |
duke@435 | 156 | // thread - NOT pre-checked |
duke@435 | 157 | // data_ptr - pre-checked for NULL |
duke@435 | 158 | jvmtiError |
duke@435 | 159 | JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) { |
duke@435 | 160 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 161 | if (thread == NULL) { |
duke@435 | 162 | JvmtiThreadState* state = current_thread->jvmti_thread_state(); |
duke@435 | 163 | *data_ptr = (state == NULL) ? NULL : |
duke@435 | 164 | state->env_thread_state(this)->get_agent_thread_local_storage_data(); |
duke@435 | 165 | } else { |
duke@435 | 166 | |
duke@435 | 167 | // jvmti_GetThreadLocalStorage is "in native" and doesn't transition |
duke@435 | 168 | // the thread to _thread_in_vm. However, when the TLS for a thread |
duke@435 | 169 | // other than the current thread is required we need to transition |
duke@435 | 170 | // from native so as to resolve the jthread. |
duke@435 | 171 | |
duke@435 | 172 | ThreadInVMfromNative __tiv(current_thread); |
duke@435 | 173 | __ENTRY(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread) |
duke@435 | 174 | debug_only(VMNativeEntryWrapper __vew;) |
duke@435 | 175 | |
duke@435 | 176 | oop thread_oop = JNIHandles::resolve_external_guard(thread); |
duke@435 | 177 | if (thread_oop == NULL) { |
duke@435 | 178 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 179 | } |
never@1577 | 180 | if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { |
duke@435 | 181 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 182 | } |
duke@435 | 183 | JavaThread* java_thread = java_lang_Thread::thread(thread_oop); |
duke@435 | 184 | if (java_thread == NULL) { |
duke@435 | 185 | return JVMTI_ERROR_THREAD_NOT_ALIVE; |
duke@435 | 186 | } |
duke@435 | 187 | JvmtiThreadState* state = java_thread->jvmti_thread_state(); |
duke@435 | 188 | *data_ptr = (state == NULL) ? NULL : |
duke@435 | 189 | state->env_thread_state(this)->get_agent_thread_local_storage_data(); |
duke@435 | 190 | } |
duke@435 | 191 | return JVMTI_ERROR_NONE; |
duke@435 | 192 | } /* end GetThreadLocalStorage */ |
duke@435 | 193 | |
duke@435 | 194 | // |
duke@435 | 195 | // Class functions |
duke@435 | 196 | // |
duke@435 | 197 | |
duke@435 | 198 | // class_count_ptr - pre-checked for NULL |
duke@435 | 199 | // classes_ptr - pre-checked for NULL |
duke@435 | 200 | jvmtiError |
duke@435 | 201 | JvmtiEnv::GetLoadedClasses(jint* class_count_ptr, jclass** classes_ptr) { |
duke@435 | 202 | return JvmtiGetLoadedClasses::getLoadedClasses(this, class_count_ptr, classes_ptr); |
duke@435 | 203 | } /* end GetLoadedClasses */ |
duke@435 | 204 | |
duke@435 | 205 | |
duke@435 | 206 | // initiating_loader - NULL is a valid value, must be checked |
duke@435 | 207 | // class_count_ptr - pre-checked for NULL |
duke@435 | 208 | // classes_ptr - pre-checked for NULL |
duke@435 | 209 | jvmtiError |
duke@435 | 210 | JvmtiEnv::GetClassLoaderClasses(jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr) { |
duke@435 | 211 | return JvmtiGetLoadedClasses::getClassLoaderClasses(this, initiating_loader, |
duke@435 | 212 | class_count_ptr, classes_ptr); |
duke@435 | 213 | } /* end GetClassLoaderClasses */ |
duke@435 | 214 | |
duke@435 | 215 | // k_mirror - may be primitive, this must be checked |
duke@435 | 216 | // is_modifiable_class_ptr - pre-checked for NULL |
duke@435 | 217 | jvmtiError |
duke@435 | 218 | JvmtiEnv::IsModifiableClass(oop k_mirror, jboolean* is_modifiable_class_ptr) { |
duke@435 | 219 | *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? |
duke@435 | 220 | JNI_TRUE : JNI_FALSE; |
duke@435 | 221 | return JVMTI_ERROR_NONE; |
duke@435 | 222 | } /* end IsModifiableClass */ |
duke@435 | 223 | |
duke@435 | 224 | // class_count - pre-checked to be greater than or equal to 0 |
duke@435 | 225 | // classes - pre-checked for NULL |
duke@435 | 226 | jvmtiError |
duke@435 | 227 | JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { |
duke@435 | 228 | //TODO: add locking |
duke@435 | 229 | |
duke@435 | 230 | int index; |
duke@435 | 231 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 232 | ResourceMark rm(current_thread); |
duke@435 | 233 | |
duke@435 | 234 | jvmtiClassDefinition* class_definitions = |
duke@435 | 235 | NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count); |
duke@435 | 236 | NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY); |
duke@435 | 237 | |
duke@435 | 238 | for (index = 0; index < class_count; index++) { |
duke@435 | 239 | HandleMark hm(current_thread); |
duke@435 | 240 | |
duke@435 | 241 | jclass jcls = classes[index]; |
duke@435 | 242 | oop k_mirror = JNIHandles::resolve_external_guard(jcls); |
duke@435 | 243 | if (k_mirror == NULL) { |
duke@435 | 244 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 245 | } |
never@1577 | 246 | if (!k_mirror->is_a(SystemDictionary::Class_klass())) { |
duke@435 | 247 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 248 | } |
duke@435 | 249 | |
duke@435 | 250 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 251 | return JVMTI_ERROR_UNMODIFIABLE_CLASS; |
duke@435 | 252 | } |
duke@435 | 253 | |
duke@435 | 254 | klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 255 | KlassHandle klass(current_thread, k_oop); |
duke@435 | 256 | |
duke@435 | 257 | jint status = klass->jvmti_class_status(); |
duke@435 | 258 | if (status & (JVMTI_CLASS_STATUS_ERROR)) { |
duke@435 | 259 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 260 | } |
duke@435 | 261 | if (status & (JVMTI_CLASS_STATUS_ARRAY)) { |
duke@435 | 262 | return JVMTI_ERROR_UNMODIFIABLE_CLASS; |
duke@435 | 263 | } |
duke@435 | 264 | |
duke@435 | 265 | instanceKlassHandle ikh(current_thread, k_oop); |
duke@435 | 266 | if (ikh->get_cached_class_file_bytes() == NULL) { |
duke@435 | 267 | // not cached, we need to reconstitute the class file from VM representation |
duke@435 | 268 | constantPoolHandle constants(current_thread, ikh->constants()); |
duke@435 | 269 | ObjectLocker ol(constants, current_thread); // lock constant pool while we query it |
duke@435 | 270 | |
duke@435 | 271 | JvmtiClassFileReconstituter reconstituter(ikh); |
duke@435 | 272 | if (reconstituter.get_error() != JVMTI_ERROR_NONE) { |
duke@435 | 273 | return reconstituter.get_error(); |
duke@435 | 274 | } |
duke@435 | 275 | |
duke@435 | 276 | class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size(); |
duke@435 | 277 | class_definitions[index].class_bytes = (unsigned char*) |
duke@435 | 278 | reconstituter.class_file_bytes(); |
duke@435 | 279 | } else { |
duke@435 | 280 | // it is cached, get it from the cache |
duke@435 | 281 | class_definitions[index].class_byte_count = ikh->get_cached_class_file_len(); |
duke@435 | 282 | class_definitions[index].class_bytes = ikh->get_cached_class_file_bytes(); |
duke@435 | 283 | } |
duke@435 | 284 | class_definitions[index].klass = jcls; |
duke@435 | 285 | } |
duke@435 | 286 | VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); |
duke@435 | 287 | VMThread::execute(&op); |
duke@435 | 288 | return (op.check_error()); |
duke@435 | 289 | } /* end RetransformClasses */ |
duke@435 | 290 | |
duke@435 | 291 | |
duke@435 | 292 | // class_count - pre-checked to be greater than or equal to 0 |
duke@435 | 293 | // class_definitions - pre-checked for NULL |
duke@435 | 294 | jvmtiError |
duke@435 | 295 | JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) { |
duke@435 | 296 | //TODO: add locking |
duke@435 | 297 | VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); |
duke@435 | 298 | VMThread::execute(&op); |
duke@435 | 299 | return (op.check_error()); |
duke@435 | 300 | } /* end RedefineClasses */ |
duke@435 | 301 | |
duke@435 | 302 | |
duke@435 | 303 | // |
duke@435 | 304 | // Object functions |
duke@435 | 305 | // |
duke@435 | 306 | |
duke@435 | 307 | // size_ptr - pre-checked for NULL |
duke@435 | 308 | jvmtiError |
duke@435 | 309 | JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) { |
duke@435 | 310 | oop mirror = JNIHandles::resolve_external_guard(object); |
duke@435 | 311 | NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); |
duke@435 | 312 | |
never@1577 | 313 | if (mirror->klass() == SystemDictionary::Class_klass()) { |
duke@435 | 314 | if (!java_lang_Class::is_primitive(mirror)) { |
duke@435 | 315 | mirror = java_lang_Class::as_klassOop(mirror); |
duke@435 | 316 | assert(mirror != NULL, "class for non-primitive mirror must exist"); |
duke@435 | 317 | } |
duke@435 | 318 | } |
duke@435 | 319 | |
duke@435 | 320 | *size_ptr = mirror->size() * wordSize; |
duke@435 | 321 | return JVMTI_ERROR_NONE; |
duke@435 | 322 | } /* end GetObjectSize */ |
duke@435 | 323 | |
duke@435 | 324 | // |
duke@435 | 325 | // Method functions |
duke@435 | 326 | // |
duke@435 | 327 | |
duke@435 | 328 | // prefix - NULL is a valid value, must be checked |
duke@435 | 329 | jvmtiError |
duke@435 | 330 | JvmtiEnv::SetNativeMethodPrefix(const char* prefix) { |
duke@435 | 331 | return prefix == NULL? |
duke@435 | 332 | SetNativeMethodPrefixes(0, NULL) : |
duke@435 | 333 | SetNativeMethodPrefixes(1, (char**)&prefix); |
duke@435 | 334 | } /* end SetNativeMethodPrefix */ |
duke@435 | 335 | |
duke@435 | 336 | |
duke@435 | 337 | // prefix_count - pre-checked to be greater than or equal to 0 |
duke@435 | 338 | // prefixes - pre-checked for NULL |
duke@435 | 339 | jvmtiError |
duke@435 | 340 | JvmtiEnv::SetNativeMethodPrefixes(jint prefix_count, char** prefixes) { |
duke@435 | 341 | // Have to grab JVMTI thread state lock to be sure that some thread |
duke@435 | 342 | // isn't accessing the prefixes at the same time we are setting them. |
duke@435 | 343 | // No locks during VM bring-up. |
duke@435 | 344 | if (Threads::number_of_threads() == 0) { |
duke@435 | 345 | return set_native_method_prefixes(prefix_count, prefixes); |
duke@435 | 346 | } else { |
duke@435 | 347 | MutexLocker mu(JvmtiThreadState_lock); |
duke@435 | 348 | return set_native_method_prefixes(prefix_count, prefixes); |
duke@435 | 349 | } |
duke@435 | 350 | } /* end SetNativeMethodPrefixes */ |
duke@435 | 351 | |
duke@435 | 352 | // |
duke@435 | 353 | // Event Management functions |
duke@435 | 354 | // |
duke@435 | 355 | |
duke@435 | 356 | // callbacks - NULL is a valid value, must be checked |
duke@435 | 357 | // size_of_callbacks - pre-checked to be greater than or equal to 0 |
duke@435 | 358 | jvmtiError |
duke@435 | 359 | JvmtiEnv::SetEventCallbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks) { |
duke@435 | 360 | JvmtiEventController::set_event_callbacks(this, callbacks, size_of_callbacks); |
duke@435 | 361 | return JVMTI_ERROR_NONE; |
duke@435 | 362 | } /* end SetEventCallbacks */ |
duke@435 | 363 | |
duke@435 | 364 | |
duke@435 | 365 | // event_thread - NULL is a valid value, must be checked |
duke@435 | 366 | jvmtiError |
duke@435 | 367 | JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...) { |
duke@435 | 368 | JavaThread* java_thread = NULL; |
duke@435 | 369 | if (event_thread != NULL) { |
duke@435 | 370 | oop thread_oop = JNIHandles::resolve_external_guard(event_thread); |
duke@435 | 371 | if (thread_oop == NULL) { |
duke@435 | 372 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 373 | } |
never@1577 | 374 | if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { |
duke@435 | 375 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 376 | } |
duke@435 | 377 | java_thread = java_lang_Thread::thread(thread_oop); |
duke@435 | 378 | if (java_thread == NULL) { |
duke@435 | 379 | return JVMTI_ERROR_THREAD_NOT_ALIVE; |
duke@435 | 380 | } |
duke@435 | 381 | } |
duke@435 | 382 | |
duke@435 | 383 | // event_type must be valid |
duke@435 | 384 | if (!JvmtiEventController::is_valid_event_type(event_type)) { |
duke@435 | 385 | return JVMTI_ERROR_INVALID_EVENT_TYPE; |
duke@435 | 386 | } |
duke@435 | 387 | |
duke@435 | 388 | // global events cannot be controlled at thread level. |
duke@435 | 389 | if (java_thread != NULL && JvmtiEventController::is_global_event(event_type)) { |
duke@435 | 390 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 391 | } |
duke@435 | 392 | |
duke@435 | 393 | bool enabled = (mode == JVMTI_ENABLE); |
duke@435 | 394 | |
duke@435 | 395 | // assure that needed capabilities are present |
duke@435 | 396 | if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) { |
duke@435 | 397 | return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; |
duke@435 | 398 | } |
duke@435 | 399 | |
duke@435 | 400 | if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { |
duke@435 | 401 | record_class_file_load_hook_enabled(); |
duke@435 | 402 | } |
duke@435 | 403 | JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled); |
duke@435 | 404 | |
duke@435 | 405 | return JVMTI_ERROR_NONE; |
duke@435 | 406 | } /* end SetEventNotificationMode */ |
duke@435 | 407 | |
duke@435 | 408 | // |
duke@435 | 409 | // Capability functions |
duke@435 | 410 | // |
duke@435 | 411 | |
duke@435 | 412 | // capabilities_ptr - pre-checked for NULL |
duke@435 | 413 | jvmtiError |
duke@435 | 414 | JvmtiEnv::GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) { |
duke@435 | 415 | JvmtiManageCapabilities::get_potential_capabilities(get_capabilities(), |
duke@435 | 416 | get_prohibited_capabilities(), |
duke@435 | 417 | capabilities_ptr); |
duke@435 | 418 | return JVMTI_ERROR_NONE; |
duke@435 | 419 | } /* end GetPotentialCapabilities */ |
duke@435 | 420 | |
duke@435 | 421 | |
duke@435 | 422 | // capabilities_ptr - pre-checked for NULL |
duke@435 | 423 | jvmtiError |
duke@435 | 424 | JvmtiEnv::AddCapabilities(const jvmtiCapabilities* capabilities_ptr) { |
duke@435 | 425 | return JvmtiManageCapabilities::add_capabilities(get_capabilities(), |
duke@435 | 426 | get_prohibited_capabilities(), |
duke@435 | 427 | capabilities_ptr, |
duke@435 | 428 | get_capabilities()); |
duke@435 | 429 | } /* end AddCapabilities */ |
duke@435 | 430 | |
duke@435 | 431 | |
duke@435 | 432 | // capabilities_ptr - pre-checked for NULL |
duke@435 | 433 | jvmtiError |
duke@435 | 434 | JvmtiEnv::RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) { |
duke@435 | 435 | JvmtiManageCapabilities::relinquish_capabilities(get_capabilities(), capabilities_ptr, get_capabilities()); |
duke@435 | 436 | return JVMTI_ERROR_NONE; |
duke@435 | 437 | } /* end RelinquishCapabilities */ |
duke@435 | 438 | |
duke@435 | 439 | |
duke@435 | 440 | // capabilities_ptr - pre-checked for NULL |
duke@435 | 441 | jvmtiError |
duke@435 | 442 | JvmtiEnv::GetCapabilities(jvmtiCapabilities* capabilities_ptr) { |
duke@435 | 443 | JvmtiManageCapabilities::copy_capabilities(get_capabilities(), capabilities_ptr); |
duke@435 | 444 | return JVMTI_ERROR_NONE; |
duke@435 | 445 | } /* end GetCapabilities */ |
duke@435 | 446 | |
duke@435 | 447 | // |
duke@435 | 448 | // Class Loader Search functions |
duke@435 | 449 | // |
duke@435 | 450 | |
duke@435 | 451 | // segment - pre-checked for NULL |
duke@435 | 452 | jvmtiError |
duke@435 | 453 | JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) { |
duke@435 | 454 | jvmtiPhase phase = get_phase(); |
duke@435 | 455 | if (phase == JVMTI_PHASE_ONLOAD) { |
duke@435 | 456 | Arguments::append_sysclasspath(segment); |
duke@435 | 457 | return JVMTI_ERROR_NONE; |
dcubed@1556 | 458 | } else if (use_version_1_0_semantics()) { |
dcubed@1556 | 459 | // This JvmtiEnv requested version 1.0 semantics and this function |
dcubed@1556 | 460 | // is only allowed in the ONLOAD phase in version 1.0 so we need to |
dcubed@1556 | 461 | // return an error here. |
dcubed@1556 | 462 | return JVMTI_ERROR_WRONG_PHASE; |
dcubed@1555 | 463 | } else if (phase == JVMTI_PHASE_LIVE) { |
dcubed@1555 | 464 | // The phase is checked by the wrapper that called this function, |
dcubed@1555 | 465 | // but this thread could be racing with the thread that is |
dcubed@1555 | 466 | // terminating the VM so we check one more time. |
duke@435 | 467 | |
duke@435 | 468 | // create the zip entry |
duke@435 | 469 | ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); |
duke@435 | 470 | if (zip_entry == NULL) { |
duke@435 | 471 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 472 | } |
duke@435 | 473 | |
duke@435 | 474 | // lock the loader |
duke@435 | 475 | Thread* thread = Thread::current(); |
duke@435 | 476 | HandleMark hm; |
duke@435 | 477 | Handle loader_lock = Handle(thread, SystemDictionary::system_loader_lock()); |
duke@435 | 478 | |
duke@435 | 479 | ObjectLocker ol(loader_lock, thread); |
duke@435 | 480 | |
duke@435 | 481 | // add the jar file to the bootclasspath |
duke@435 | 482 | if (TraceClassLoading) { |
duke@435 | 483 | tty->print_cr("[Opened %s]", zip_entry->name()); |
duke@435 | 484 | } |
duke@435 | 485 | ClassLoader::add_to_list(zip_entry); |
duke@435 | 486 | return JVMTI_ERROR_NONE; |
dcubed@1555 | 487 | } else { |
dcubed@1555 | 488 | return JVMTI_ERROR_WRONG_PHASE; |
duke@435 | 489 | } |
duke@435 | 490 | |
duke@435 | 491 | } /* end AddToBootstrapClassLoaderSearch */ |
duke@435 | 492 | |
duke@435 | 493 | |
duke@435 | 494 | // segment - pre-checked for NULL |
duke@435 | 495 | jvmtiError |
duke@435 | 496 | JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) { |
duke@435 | 497 | jvmtiPhase phase = get_phase(); |
duke@435 | 498 | |
duke@435 | 499 | if (phase == JVMTI_PHASE_ONLOAD) { |
duke@435 | 500 | for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { |
duke@435 | 501 | if (strcmp("java.class.path", p->key()) == 0) { |
duke@435 | 502 | p->append_value(segment); |
duke@435 | 503 | break; |
duke@435 | 504 | } |
duke@435 | 505 | } |
duke@435 | 506 | return JVMTI_ERROR_NONE; |
dcubed@1555 | 507 | } else if (phase == JVMTI_PHASE_LIVE) { |
dcubed@1555 | 508 | // The phase is checked by the wrapper that called this function, |
dcubed@1555 | 509 | // but this thread could be racing with the thread that is |
dcubed@1555 | 510 | // terminating the VM so we check one more time. |
duke@435 | 511 | HandleMark hm; |
duke@435 | 512 | |
duke@435 | 513 | // create the zip entry (which will open the zip file and hence |
duke@435 | 514 | // check that the segment is indeed a zip file). |
duke@435 | 515 | ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); |
duke@435 | 516 | if (zip_entry == NULL) { |
duke@435 | 517 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 518 | } |
duke@435 | 519 | delete zip_entry; // no longer needed |
duke@435 | 520 | |
duke@435 | 521 | // lock the loader |
duke@435 | 522 | Thread* THREAD = Thread::current(); |
duke@435 | 523 | Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); |
duke@435 | 524 | |
duke@435 | 525 | ObjectLocker ol(loader, THREAD); |
duke@435 | 526 | |
duke@435 | 527 | // need the path as java.lang.String |
duke@435 | 528 | Handle path = java_lang_String::create_from_str(segment, THREAD); |
duke@435 | 529 | if (HAS_PENDING_EXCEPTION) { |
duke@435 | 530 | CLEAR_PENDING_EXCEPTION; |
duke@435 | 531 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 532 | } |
duke@435 | 533 | |
duke@435 | 534 | instanceKlassHandle loader_ik(THREAD, loader->klass()); |
duke@435 | 535 | |
duke@435 | 536 | // Invoke the appendToClassPathForInstrumentation method - if the method |
duke@435 | 537 | // is not found it means the loader doesn't support adding to the class path |
duke@435 | 538 | // in the live phase. |
duke@435 | 539 | { |
duke@435 | 540 | JavaValue res(T_VOID); |
duke@435 | 541 | JavaCalls::call_special(&res, |
duke@435 | 542 | loader, |
duke@435 | 543 | loader_ik, |
duke@435 | 544 | vmSymbolHandles::appendToClassPathForInstrumentation_name(), |
duke@435 | 545 | vmSymbolHandles::appendToClassPathForInstrumentation_signature(), |
duke@435 | 546 | path, |
duke@435 | 547 | THREAD); |
duke@435 | 548 | if (HAS_PENDING_EXCEPTION) { |
duke@435 | 549 | symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name(); |
duke@435 | 550 | CLEAR_PENDING_EXCEPTION; |
duke@435 | 551 | |
duke@435 | 552 | if (ex_name == vmSymbols::java_lang_NoSuchMethodError()) { |
duke@435 | 553 | return JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED; |
duke@435 | 554 | } else { |
duke@435 | 555 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 556 | } |
duke@435 | 557 | } |
duke@435 | 558 | } |
duke@435 | 559 | |
duke@435 | 560 | return JVMTI_ERROR_NONE; |
dcubed@1555 | 561 | } else { |
dcubed@1555 | 562 | return JVMTI_ERROR_WRONG_PHASE; |
duke@435 | 563 | } |
duke@435 | 564 | } /* end AddToSystemClassLoaderSearch */ |
duke@435 | 565 | |
duke@435 | 566 | // |
duke@435 | 567 | // General functions |
duke@435 | 568 | // |
duke@435 | 569 | |
duke@435 | 570 | // phase_ptr - pre-checked for NULL |
duke@435 | 571 | jvmtiError |
duke@435 | 572 | JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) { |
duke@435 | 573 | *phase_ptr = get_phase(); |
duke@435 | 574 | return JVMTI_ERROR_NONE; |
duke@435 | 575 | } /* end GetPhase */ |
duke@435 | 576 | |
duke@435 | 577 | |
duke@435 | 578 | jvmtiError |
duke@435 | 579 | JvmtiEnv::DisposeEnvironment() { |
duke@435 | 580 | dispose(); |
duke@435 | 581 | return JVMTI_ERROR_NONE; |
duke@435 | 582 | } /* end DisposeEnvironment */ |
duke@435 | 583 | |
duke@435 | 584 | |
duke@435 | 585 | // data - NULL is a valid value, must be checked |
duke@435 | 586 | jvmtiError |
duke@435 | 587 | JvmtiEnv::SetEnvironmentLocalStorage(const void* data) { |
duke@435 | 588 | set_env_local_storage(data); |
duke@435 | 589 | return JVMTI_ERROR_NONE; |
duke@435 | 590 | } /* end SetEnvironmentLocalStorage */ |
duke@435 | 591 | |
duke@435 | 592 | |
duke@435 | 593 | // data_ptr - pre-checked for NULL |
duke@435 | 594 | jvmtiError |
duke@435 | 595 | JvmtiEnv::GetEnvironmentLocalStorage(void** data_ptr) { |
duke@435 | 596 | *data_ptr = (void*)get_env_local_storage(); |
duke@435 | 597 | return JVMTI_ERROR_NONE; |
duke@435 | 598 | } /* end GetEnvironmentLocalStorage */ |
duke@435 | 599 | |
duke@435 | 600 | // version_ptr - pre-checked for NULL |
duke@435 | 601 | jvmtiError |
duke@435 | 602 | JvmtiEnv::GetVersionNumber(jint* version_ptr) { |
duke@435 | 603 | *version_ptr = JVMTI_VERSION; |
duke@435 | 604 | return JVMTI_ERROR_NONE; |
duke@435 | 605 | } /* end GetVersionNumber */ |
duke@435 | 606 | |
duke@435 | 607 | |
duke@435 | 608 | // name_ptr - pre-checked for NULL |
duke@435 | 609 | jvmtiError |
duke@435 | 610 | JvmtiEnv::GetErrorName(jvmtiError error, char** name_ptr) { |
duke@435 | 611 | if (error < JVMTI_ERROR_NONE || error > JVMTI_ERROR_MAX) { |
duke@435 | 612 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 613 | } |
duke@435 | 614 | const char *name = JvmtiUtil::error_name(error); |
duke@435 | 615 | if (name == NULL) { |
duke@435 | 616 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 617 | } |
duke@435 | 618 | size_t len = strlen(name) + 1; |
duke@435 | 619 | jvmtiError err = allocate(len, (unsigned char**)name_ptr); |
duke@435 | 620 | if (err == JVMTI_ERROR_NONE) { |
duke@435 | 621 | memcpy(*name_ptr, name, len); |
duke@435 | 622 | } |
duke@435 | 623 | return err; |
duke@435 | 624 | } /* end GetErrorName */ |
duke@435 | 625 | |
duke@435 | 626 | |
duke@435 | 627 | jvmtiError |
duke@435 | 628 | JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) { |
duke@435 | 629 | switch (flag) { |
duke@435 | 630 | case JVMTI_VERBOSE_OTHER: |
duke@435 | 631 | // ignore |
duke@435 | 632 | break; |
duke@435 | 633 | case JVMTI_VERBOSE_CLASS: |
duke@435 | 634 | TraceClassLoading = value != 0; |
duke@435 | 635 | TraceClassUnloading = value != 0; |
duke@435 | 636 | break; |
duke@435 | 637 | case JVMTI_VERBOSE_GC: |
duke@435 | 638 | PrintGC = value != 0; |
duke@435 | 639 | break; |
duke@435 | 640 | case JVMTI_VERBOSE_JNI: |
duke@435 | 641 | PrintJNIResolving = value != 0; |
duke@435 | 642 | break; |
duke@435 | 643 | default: |
duke@435 | 644 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 645 | }; |
duke@435 | 646 | return JVMTI_ERROR_NONE; |
duke@435 | 647 | } /* end SetVerboseFlag */ |
duke@435 | 648 | |
duke@435 | 649 | |
duke@435 | 650 | // format_ptr - pre-checked for NULL |
duke@435 | 651 | jvmtiError |
duke@435 | 652 | JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { |
duke@435 | 653 | *format_ptr = JVMTI_JLOCATION_JVMBCI; |
duke@435 | 654 | return JVMTI_ERROR_NONE; |
duke@435 | 655 | } /* end GetJLocationFormat */ |
duke@435 | 656 | |
duke@435 | 657 | #ifndef JVMTI_KERNEL |
duke@435 | 658 | |
duke@435 | 659 | // |
duke@435 | 660 | // Thread functions |
duke@435 | 661 | // |
duke@435 | 662 | |
duke@435 | 663 | // Threads_lock NOT held |
duke@435 | 664 | // thread - NOT pre-checked |
duke@435 | 665 | // thread_state_ptr - pre-checked for NULL |
duke@435 | 666 | jvmtiError |
duke@435 | 667 | JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) { |
duke@435 | 668 | jint state; |
duke@435 | 669 | oop thread_oop; |
duke@435 | 670 | JavaThread* thr; |
duke@435 | 671 | |
duke@435 | 672 | if (thread == NULL) { |
duke@435 | 673 | thread_oop = JavaThread::current()->threadObj(); |
duke@435 | 674 | } else { |
duke@435 | 675 | thread_oop = JNIHandles::resolve_external_guard(thread); |
duke@435 | 676 | } |
duke@435 | 677 | |
never@1577 | 678 | if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { |
duke@435 | 679 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 680 | } |
duke@435 | 681 | |
duke@435 | 682 | // get most state bits |
duke@435 | 683 | state = (jint)java_lang_Thread::get_thread_status(thread_oop); |
duke@435 | 684 | |
duke@435 | 685 | // add more state bits |
duke@435 | 686 | thr = java_lang_Thread::thread(thread_oop); |
duke@435 | 687 | if (thr != NULL) { |
duke@435 | 688 | JavaThreadState jts = thr->thread_state(); |
duke@435 | 689 | |
duke@435 | 690 | if (thr->is_being_ext_suspended()) { |
duke@435 | 691 | state |= JVMTI_THREAD_STATE_SUSPENDED; |
duke@435 | 692 | } |
duke@435 | 693 | if (jts == _thread_in_native) { |
duke@435 | 694 | state |= JVMTI_THREAD_STATE_IN_NATIVE; |
duke@435 | 695 | } |
duke@435 | 696 | OSThread* osThread = thr->osthread(); |
duke@435 | 697 | if (osThread != NULL && osThread->interrupted()) { |
duke@435 | 698 | state |= JVMTI_THREAD_STATE_INTERRUPTED; |
duke@435 | 699 | } |
duke@435 | 700 | } |
duke@435 | 701 | |
duke@435 | 702 | *thread_state_ptr = state; |
duke@435 | 703 | return JVMTI_ERROR_NONE; |
duke@435 | 704 | } /* end GetThreadState */ |
duke@435 | 705 | |
duke@435 | 706 | |
duke@435 | 707 | // thread_ptr - pre-checked for NULL |
duke@435 | 708 | jvmtiError |
duke@435 | 709 | JvmtiEnv::GetCurrentThread(jthread* thread_ptr) { |
duke@435 | 710 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 711 | *thread_ptr = (jthread)JNIHandles::make_local(current_thread, current_thread->threadObj()); |
duke@435 | 712 | return JVMTI_ERROR_NONE; |
duke@435 | 713 | } /* end GetCurrentThread */ |
duke@435 | 714 | |
duke@435 | 715 | |
duke@435 | 716 | // threads_count_ptr - pre-checked for NULL |
duke@435 | 717 | // threads_ptr - pre-checked for NULL |
duke@435 | 718 | jvmtiError |
duke@435 | 719 | JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) { |
duke@435 | 720 | int nthreads = 0; |
duke@435 | 721 | Handle *thread_objs = NULL; |
duke@435 | 722 | ResourceMark rm; |
duke@435 | 723 | HandleMark hm; |
duke@435 | 724 | |
duke@435 | 725 | // enumerate threads (including agent threads) |
duke@435 | 726 | ThreadsListEnumerator tle(Thread::current(), true); |
duke@435 | 727 | nthreads = tle.num_threads(); |
duke@435 | 728 | *threads_count_ptr = nthreads; |
duke@435 | 729 | |
duke@435 | 730 | if (nthreads == 0) { |
duke@435 | 731 | *threads_ptr = NULL; |
duke@435 | 732 | return JVMTI_ERROR_NONE; |
duke@435 | 733 | } |
duke@435 | 734 | |
duke@435 | 735 | thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads); |
duke@435 | 736 | NULL_CHECK(thread_objs, JVMTI_ERROR_OUT_OF_MEMORY); |
duke@435 | 737 | |
duke@435 | 738 | for (int i=0; i < nthreads; i++) { |
duke@435 | 739 | thread_objs[i] = Handle(tle.get_threadObj(i)); |
duke@435 | 740 | } |
duke@435 | 741 | |
duke@435 | 742 | // have to make global handles outside of Threads_lock |
duke@435 | 743 | jthread *jthreads = new_jthreadArray(nthreads, thread_objs); |
duke@435 | 744 | NULL_CHECK(jthreads, JVMTI_ERROR_OUT_OF_MEMORY); |
duke@435 | 745 | |
duke@435 | 746 | *threads_ptr = jthreads; |
duke@435 | 747 | return JVMTI_ERROR_NONE; |
duke@435 | 748 | } /* end GetAllThreads */ |
duke@435 | 749 | |
duke@435 | 750 | |
duke@435 | 751 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 752 | // java_thread - pre-checked |
duke@435 | 753 | jvmtiError |
duke@435 | 754 | JvmtiEnv::SuspendThread(JavaThread* java_thread) { |
duke@435 | 755 | // don't allow hidden thread suspend request. |
duke@435 | 756 | if (java_thread->is_hidden_from_external_view()) { |
duke@435 | 757 | return (JVMTI_ERROR_NONE); |
duke@435 | 758 | } |
duke@435 | 759 | |
duke@435 | 760 | { |
duke@435 | 761 | MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag); |
duke@435 | 762 | if (java_thread->is_external_suspend()) { |
duke@435 | 763 | // don't allow nested external suspend requests. |
duke@435 | 764 | return (JVMTI_ERROR_THREAD_SUSPENDED); |
duke@435 | 765 | } |
duke@435 | 766 | if (java_thread->is_exiting()) { // thread is in the process of exiting |
duke@435 | 767 | return (JVMTI_ERROR_THREAD_NOT_ALIVE); |
duke@435 | 768 | } |
duke@435 | 769 | java_thread->set_external_suspend(); |
duke@435 | 770 | } |
duke@435 | 771 | |
duke@435 | 772 | if (!JvmtiSuspendControl::suspend(java_thread)) { |
duke@435 | 773 | // the thread was in the process of exiting |
duke@435 | 774 | return (JVMTI_ERROR_THREAD_NOT_ALIVE); |
duke@435 | 775 | } |
duke@435 | 776 | return JVMTI_ERROR_NONE; |
duke@435 | 777 | } /* end SuspendThread */ |
duke@435 | 778 | |
duke@435 | 779 | |
duke@435 | 780 | // request_count - pre-checked to be greater than or equal to 0 |
duke@435 | 781 | // request_list - pre-checked for NULL |
duke@435 | 782 | // results - pre-checked for NULL |
duke@435 | 783 | jvmtiError |
duke@435 | 784 | JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { |
duke@435 | 785 | int needSafepoint = 0; // > 0 if we need a safepoint |
duke@435 | 786 | for (int i = 0; i < request_count; i++) { |
duke@435 | 787 | JavaThread *java_thread = get_JavaThread(request_list[i]); |
duke@435 | 788 | if (java_thread == NULL) { |
duke@435 | 789 | results[i] = JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 790 | continue; |
duke@435 | 791 | } |
duke@435 | 792 | // the thread has not yet run or has exited (not on threads list) |
duke@435 | 793 | if (java_thread->threadObj() == NULL) { |
duke@435 | 794 | results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; |
duke@435 | 795 | continue; |
duke@435 | 796 | } |
duke@435 | 797 | if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) { |
duke@435 | 798 | results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; |
duke@435 | 799 | continue; |
duke@435 | 800 | } |
duke@435 | 801 | // don't allow hidden thread suspend request. |
duke@435 | 802 | if (java_thread->is_hidden_from_external_view()) { |
duke@435 | 803 | results[i] = JVMTI_ERROR_NONE; // indicate successful suspend |
duke@435 | 804 | continue; |
duke@435 | 805 | } |
duke@435 | 806 | |
duke@435 | 807 | { |
duke@435 | 808 | MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag); |
duke@435 | 809 | if (java_thread->is_external_suspend()) { |
duke@435 | 810 | // don't allow nested external suspend requests. |
duke@435 | 811 | results[i] = JVMTI_ERROR_THREAD_SUSPENDED; |
duke@435 | 812 | continue; |
duke@435 | 813 | } |
duke@435 | 814 | if (java_thread->is_exiting()) { // thread is in the process of exiting |
duke@435 | 815 | results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; |
duke@435 | 816 | continue; |
duke@435 | 817 | } |
duke@435 | 818 | java_thread->set_external_suspend(); |
duke@435 | 819 | } |
duke@435 | 820 | if (java_thread->thread_state() == _thread_in_native) { |
duke@435 | 821 | // We need to try and suspend native threads here. Threads in |
duke@435 | 822 | // other states will self-suspend on their next transition. |
duke@435 | 823 | if (!JvmtiSuspendControl::suspend(java_thread)) { |
duke@435 | 824 | // The thread was in the process of exiting. Force another |
duke@435 | 825 | // safepoint to make sure that this thread transitions. |
duke@435 | 826 | needSafepoint++; |
duke@435 | 827 | results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; |
duke@435 | 828 | continue; |
duke@435 | 829 | } |
duke@435 | 830 | } else { |
duke@435 | 831 | needSafepoint++; |
duke@435 | 832 | } |
duke@435 | 833 | results[i] = JVMTI_ERROR_NONE; // indicate successful suspend |
duke@435 | 834 | } |
duke@435 | 835 | if (needSafepoint > 0) { |
duke@435 | 836 | VM_ForceSafepoint vfs; |
duke@435 | 837 | VMThread::execute(&vfs); |
duke@435 | 838 | } |
duke@435 | 839 | // per-thread suspend results returned via results parameter |
duke@435 | 840 | return JVMTI_ERROR_NONE; |
duke@435 | 841 | } /* end SuspendThreadList */ |
duke@435 | 842 | |
duke@435 | 843 | |
duke@435 | 844 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 845 | // java_thread - pre-checked |
duke@435 | 846 | jvmtiError |
duke@435 | 847 | JvmtiEnv::ResumeThread(JavaThread* java_thread) { |
duke@435 | 848 | // don't allow hidden thread resume request. |
duke@435 | 849 | if (java_thread->is_hidden_from_external_view()) { |
duke@435 | 850 | return JVMTI_ERROR_NONE; |
duke@435 | 851 | } |
duke@435 | 852 | |
duke@435 | 853 | if (!java_thread->is_being_ext_suspended()) { |
duke@435 | 854 | return JVMTI_ERROR_THREAD_NOT_SUSPENDED; |
duke@435 | 855 | } |
duke@435 | 856 | |
duke@435 | 857 | if (!JvmtiSuspendControl::resume(java_thread)) { |
duke@435 | 858 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 859 | } |
duke@435 | 860 | return JVMTI_ERROR_NONE; |
duke@435 | 861 | } /* end ResumeThread */ |
duke@435 | 862 | |
duke@435 | 863 | |
duke@435 | 864 | // request_count - pre-checked to be greater than or equal to 0 |
duke@435 | 865 | // request_list - pre-checked for NULL |
duke@435 | 866 | // results - pre-checked for NULL |
duke@435 | 867 | jvmtiError |
duke@435 | 868 | JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { |
duke@435 | 869 | for (int i = 0; i < request_count; i++) { |
duke@435 | 870 | JavaThread *java_thread = get_JavaThread(request_list[i]); |
duke@435 | 871 | if (java_thread == NULL) { |
duke@435 | 872 | results[i] = JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 873 | continue; |
duke@435 | 874 | } |
duke@435 | 875 | // don't allow hidden thread resume request. |
duke@435 | 876 | if (java_thread->is_hidden_from_external_view()) { |
duke@435 | 877 | results[i] = JVMTI_ERROR_NONE; // indicate successful resume |
duke@435 | 878 | continue; |
duke@435 | 879 | } |
duke@435 | 880 | if (!java_thread->is_being_ext_suspended()) { |
duke@435 | 881 | results[i] = JVMTI_ERROR_THREAD_NOT_SUSPENDED; |
duke@435 | 882 | continue; |
duke@435 | 883 | } |
duke@435 | 884 | |
duke@435 | 885 | if (!JvmtiSuspendControl::resume(java_thread)) { |
duke@435 | 886 | results[i] = JVMTI_ERROR_INTERNAL; |
duke@435 | 887 | continue; |
duke@435 | 888 | } |
duke@435 | 889 | |
duke@435 | 890 | results[i] = JVMTI_ERROR_NONE; // indicate successful suspend |
duke@435 | 891 | } |
duke@435 | 892 | // per-thread resume results returned via results parameter |
duke@435 | 893 | return JVMTI_ERROR_NONE; |
duke@435 | 894 | } /* end ResumeThreadList */ |
duke@435 | 895 | |
duke@435 | 896 | |
duke@435 | 897 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 898 | // java_thread - pre-checked |
duke@435 | 899 | jvmtiError |
duke@435 | 900 | JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) { |
duke@435 | 901 | oop e = JNIHandles::resolve_external_guard(exception); |
duke@435 | 902 | NULL_CHECK(e, JVMTI_ERROR_NULL_POINTER); |
duke@435 | 903 | |
duke@435 | 904 | JavaThread::send_async_exception(java_thread->threadObj(), e); |
duke@435 | 905 | |
duke@435 | 906 | return JVMTI_ERROR_NONE; |
duke@435 | 907 | |
duke@435 | 908 | } /* end StopThread */ |
duke@435 | 909 | |
duke@435 | 910 | |
duke@435 | 911 | // Threads_lock NOT held |
duke@435 | 912 | // thread - NOT pre-checked |
duke@435 | 913 | jvmtiError |
duke@435 | 914 | JvmtiEnv::InterruptThread(jthread thread) { |
duke@435 | 915 | oop thread_oop = JNIHandles::resolve_external_guard(thread); |
never@1577 | 916 | if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) |
duke@435 | 917 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 918 | |
duke@435 | 919 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 920 | |
duke@435 | 921 | // Todo: this is a duplicate of JVM_Interrupt; share code in future |
duke@435 | 922 | // Ensure that the C++ Thread and OSThread structures aren't freed before we operate |
duke@435 | 923 | MutexLockerEx ml(current_thread->threadObj() == thread_oop ? NULL : Threads_lock); |
duke@435 | 924 | // We need to re-resolve the java_thread, since a GC might have happened during the |
duke@435 | 925 | // acquire of the lock |
duke@435 | 926 | |
duke@435 | 927 | JavaThread* java_thread = java_lang_Thread::thread(JNIHandles::resolve_external_guard(thread)); |
duke@435 | 928 | NULL_CHECK(java_thread, JVMTI_ERROR_THREAD_NOT_ALIVE); |
duke@435 | 929 | |
duke@435 | 930 | Thread::interrupt(java_thread); |
duke@435 | 931 | |
duke@435 | 932 | return JVMTI_ERROR_NONE; |
duke@435 | 933 | } /* end InterruptThread */ |
duke@435 | 934 | |
duke@435 | 935 | |
duke@435 | 936 | // Threads_lock NOT held |
duke@435 | 937 | // thread - NOT pre-checked |
duke@435 | 938 | // info_ptr - pre-checked for NULL |
duke@435 | 939 | jvmtiError |
duke@435 | 940 | JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) { |
duke@435 | 941 | ResourceMark rm; |
duke@435 | 942 | HandleMark hm; |
duke@435 | 943 | |
duke@435 | 944 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 945 | |
duke@435 | 946 | // if thread is NULL the current thread is used |
duke@435 | 947 | oop thread_oop; |
duke@435 | 948 | if (thread == NULL) { |
duke@435 | 949 | thread_oop = current_thread->threadObj(); |
duke@435 | 950 | } else { |
duke@435 | 951 | thread_oop = JNIHandles::resolve_external_guard(thread); |
duke@435 | 952 | } |
never@1577 | 953 | if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) |
duke@435 | 954 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 955 | |
duke@435 | 956 | Handle thread_obj(current_thread, thread_oop); |
duke@435 | 957 | typeArrayHandle name; |
duke@435 | 958 | ThreadPriority priority; |
duke@435 | 959 | Handle thread_group; |
duke@435 | 960 | Handle context_class_loader; |
duke@435 | 961 | bool is_daemon; |
duke@435 | 962 | |
duke@435 | 963 | { MutexLocker mu(Threads_lock); |
duke@435 | 964 | |
duke@435 | 965 | name = typeArrayHandle(current_thread, java_lang_Thread::name(thread_obj())); |
duke@435 | 966 | priority = java_lang_Thread::priority(thread_obj()); |
duke@435 | 967 | thread_group = Handle(current_thread, java_lang_Thread::threadGroup(thread_obj())); |
duke@435 | 968 | is_daemon = java_lang_Thread::is_daemon(thread_obj()); |
duke@435 | 969 | |
duke@435 | 970 | oop loader = java_lang_Thread::context_class_loader(thread_obj()); |
duke@435 | 971 | context_class_loader = Handle(current_thread, loader); |
duke@435 | 972 | } |
duke@435 | 973 | { const char *n; |
duke@435 | 974 | |
duke@435 | 975 | if (name() != NULL) { |
duke@435 | 976 | n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); |
duke@435 | 977 | } else { |
duke@435 | 978 | n = UNICODE::as_utf8(NULL, 0); |
duke@435 | 979 | } |
duke@435 | 980 | |
duke@435 | 981 | info_ptr->name = (char *) jvmtiMalloc(strlen(n)+1); |
duke@435 | 982 | if (info_ptr->name == NULL) |
duke@435 | 983 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 984 | |
duke@435 | 985 | strcpy(info_ptr->name, n); |
duke@435 | 986 | } |
duke@435 | 987 | info_ptr->is_daemon = is_daemon; |
duke@435 | 988 | info_ptr->priority = priority; |
duke@435 | 989 | |
duke@435 | 990 | info_ptr->context_class_loader = (context_class_loader.is_null()) ? NULL : |
duke@435 | 991 | jni_reference(context_class_loader); |
duke@435 | 992 | info_ptr->thread_group = jni_reference(thread_group); |
duke@435 | 993 | |
duke@435 | 994 | return JVMTI_ERROR_NONE; |
duke@435 | 995 | } /* end GetThreadInfo */ |
duke@435 | 996 | |
duke@435 | 997 | |
duke@435 | 998 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 999 | // java_thread - pre-checked |
duke@435 | 1000 | // owned_monitor_count_ptr - pre-checked for NULL |
duke@435 | 1001 | // owned_monitors_ptr - pre-checked for NULL |
duke@435 | 1002 | jvmtiError |
duke@435 | 1003 | JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) { |
duke@435 | 1004 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1005 | JavaThread* calling_thread = JavaThread::current(); |
duke@435 | 1006 | |
duke@435 | 1007 | // growable array of jvmti monitors info on the C-heap |
duke@435 | 1008 | GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list = |
duke@435 | 1009 | new (ResourceObj::C_HEAP) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true); |
duke@435 | 1010 | |
duke@435 | 1011 | uint32_t debug_bits = 0; |
duke@435 | 1012 | if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1013 | err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); |
duke@435 | 1014 | } else { |
duke@435 | 1015 | // JVMTI get monitors info at safepoint. Do not require target thread to |
duke@435 | 1016 | // be suspended. |
duke@435 | 1017 | VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list); |
duke@435 | 1018 | VMThread::execute(&op); |
duke@435 | 1019 | err = op.result(); |
duke@435 | 1020 | } |
duke@435 | 1021 | jint owned_monitor_count = owned_monitors_list->length(); |
duke@435 | 1022 | if (err == JVMTI_ERROR_NONE) { |
duke@435 | 1023 | if ((err = allocate(owned_monitor_count * sizeof(jobject *), |
duke@435 | 1024 | (unsigned char**)owned_monitors_ptr)) == JVMTI_ERROR_NONE) { |
duke@435 | 1025 | // copy into the returned array |
duke@435 | 1026 | for (int i = 0; i < owned_monitor_count; i++) { |
duke@435 | 1027 | (*owned_monitors_ptr)[i] = |
duke@435 | 1028 | ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor; |
duke@435 | 1029 | } |
duke@435 | 1030 | *owned_monitor_count_ptr = owned_monitor_count; |
duke@435 | 1031 | } |
duke@435 | 1032 | } |
duke@435 | 1033 | // clean up. |
duke@435 | 1034 | for (int i = 0; i < owned_monitor_count; i++) { |
duke@435 | 1035 | deallocate((unsigned char*)owned_monitors_list->at(i)); |
duke@435 | 1036 | } |
duke@435 | 1037 | delete owned_monitors_list; |
duke@435 | 1038 | |
duke@435 | 1039 | return err; |
duke@435 | 1040 | } /* end GetOwnedMonitorInfo */ |
duke@435 | 1041 | |
duke@435 | 1042 | |
duke@435 | 1043 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1044 | // java_thread - pre-checked |
duke@435 | 1045 | // monitor_info_count_ptr - pre-checked for NULL |
duke@435 | 1046 | // monitor_info_ptr - pre-checked for NULL |
duke@435 | 1047 | jvmtiError |
duke@435 | 1048 | JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) { |
duke@435 | 1049 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1050 | JavaThread* calling_thread = JavaThread::current(); |
duke@435 | 1051 | |
duke@435 | 1052 | // growable array of jvmti monitors info on the C-heap |
duke@435 | 1053 | GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list = |
duke@435 | 1054 | new (ResourceObj::C_HEAP) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true); |
duke@435 | 1055 | |
duke@435 | 1056 | uint32_t debug_bits = 0; |
duke@435 | 1057 | if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1058 | err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); |
duke@435 | 1059 | } else { |
duke@435 | 1060 | // JVMTI get owned monitors info at safepoint. Do not require target thread to |
duke@435 | 1061 | // be suspended. |
duke@435 | 1062 | VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list); |
duke@435 | 1063 | VMThread::execute(&op); |
duke@435 | 1064 | err = op.result(); |
duke@435 | 1065 | } |
duke@435 | 1066 | |
duke@435 | 1067 | jint owned_monitor_count = owned_monitors_list->length(); |
duke@435 | 1068 | if (err == JVMTI_ERROR_NONE) { |
duke@435 | 1069 | if ((err = allocate(owned_monitor_count * sizeof(jvmtiMonitorStackDepthInfo), |
duke@435 | 1070 | (unsigned char**)monitor_info_ptr)) == JVMTI_ERROR_NONE) { |
duke@435 | 1071 | // copy to output array. |
duke@435 | 1072 | for (int i = 0; i < owned_monitor_count; i++) { |
duke@435 | 1073 | (*monitor_info_ptr)[i].monitor = |
duke@435 | 1074 | ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor; |
duke@435 | 1075 | (*monitor_info_ptr)[i].stack_depth = |
duke@435 | 1076 | ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->stack_depth; |
duke@435 | 1077 | } |
duke@435 | 1078 | } |
duke@435 | 1079 | *monitor_info_count_ptr = owned_monitor_count; |
duke@435 | 1080 | } |
duke@435 | 1081 | |
duke@435 | 1082 | // clean up. |
duke@435 | 1083 | for (int i = 0; i < owned_monitor_count; i++) { |
duke@435 | 1084 | deallocate((unsigned char*)owned_monitors_list->at(i)); |
duke@435 | 1085 | } |
duke@435 | 1086 | delete owned_monitors_list; |
duke@435 | 1087 | |
duke@435 | 1088 | return err; |
duke@435 | 1089 | } /* end GetOwnedMonitorStackDepthInfo */ |
duke@435 | 1090 | |
duke@435 | 1091 | |
duke@435 | 1092 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1093 | // java_thread - pre-checked |
duke@435 | 1094 | // monitor_ptr - pre-checked for NULL |
duke@435 | 1095 | jvmtiError |
duke@435 | 1096 | JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) { |
duke@435 | 1097 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1098 | uint32_t debug_bits = 0; |
duke@435 | 1099 | JavaThread* calling_thread = JavaThread::current(); |
duke@435 | 1100 | if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1101 | err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr); |
duke@435 | 1102 | } else { |
duke@435 | 1103 | // get contended monitor information at safepoint. |
duke@435 | 1104 | VM_GetCurrentContendedMonitor op(this, calling_thread, java_thread, monitor_ptr); |
duke@435 | 1105 | VMThread::execute(&op); |
duke@435 | 1106 | err = op.result(); |
duke@435 | 1107 | } |
duke@435 | 1108 | return err; |
duke@435 | 1109 | } /* end GetCurrentContendedMonitor */ |
duke@435 | 1110 | |
duke@435 | 1111 | |
duke@435 | 1112 | // Threads_lock NOT held |
duke@435 | 1113 | // thread - NOT pre-checked |
duke@435 | 1114 | // proc - pre-checked for NULL |
duke@435 | 1115 | // arg - NULL is a valid value, must be checked |
duke@435 | 1116 | jvmtiError |
duke@435 | 1117 | JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) { |
duke@435 | 1118 | oop thread_oop = JNIHandles::resolve_external_guard(thread); |
never@1577 | 1119 | if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { |
duke@435 | 1120 | return JVMTI_ERROR_INVALID_THREAD; |
duke@435 | 1121 | } |
duke@435 | 1122 | if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { |
duke@435 | 1123 | return JVMTI_ERROR_INVALID_PRIORITY; |
duke@435 | 1124 | } |
duke@435 | 1125 | |
duke@435 | 1126 | //Thread-self |
duke@435 | 1127 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 1128 | |
duke@435 | 1129 | Handle thread_hndl(current_thread, thread_oop); |
duke@435 | 1130 | { |
duke@435 | 1131 | MutexLocker mu(Threads_lock); // grab Threads_lock |
duke@435 | 1132 | |
duke@435 | 1133 | JvmtiAgentThread *new_thread = new JvmtiAgentThread(this, proc, arg); |
duke@435 | 1134 | |
duke@435 | 1135 | // At this point it may be possible that no osthread was created for the |
duke@435 | 1136 | // JavaThread due to lack of memory. |
duke@435 | 1137 | if (new_thread == NULL || new_thread->osthread() == NULL) { |
duke@435 | 1138 | if (new_thread) delete new_thread; |
duke@435 | 1139 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 1140 | } |
duke@435 | 1141 | |
duke@435 | 1142 | java_lang_Thread::set_thread(thread_hndl(), new_thread); |
duke@435 | 1143 | java_lang_Thread::set_priority(thread_hndl(), (ThreadPriority)priority); |
duke@435 | 1144 | java_lang_Thread::set_daemon(thread_hndl()); |
duke@435 | 1145 | |
duke@435 | 1146 | new_thread->set_threadObj(thread_hndl()); |
duke@435 | 1147 | Threads::add(new_thread); |
duke@435 | 1148 | Thread::start(new_thread); |
duke@435 | 1149 | } // unlock Threads_lock |
duke@435 | 1150 | |
duke@435 | 1151 | return JVMTI_ERROR_NONE; |
duke@435 | 1152 | } /* end RunAgentThread */ |
duke@435 | 1153 | |
duke@435 | 1154 | // |
duke@435 | 1155 | // Thread Group functions |
duke@435 | 1156 | // |
duke@435 | 1157 | |
duke@435 | 1158 | // group_count_ptr - pre-checked for NULL |
duke@435 | 1159 | // groups_ptr - pre-checked for NULL |
duke@435 | 1160 | jvmtiError |
duke@435 | 1161 | JvmtiEnv::GetTopThreadGroups(jint* group_count_ptr, jthreadGroup** groups_ptr) { |
duke@435 | 1162 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 1163 | |
duke@435 | 1164 | // Only one top level thread group now. |
duke@435 | 1165 | *group_count_ptr = 1; |
duke@435 | 1166 | |
duke@435 | 1167 | // Allocate memory to store global-refs to the thread groups. |
duke@435 | 1168 | // Assume this area is freed by caller. |
duke@435 | 1169 | *groups_ptr = (jthreadGroup *) jvmtiMalloc((sizeof(jthreadGroup)) * (*group_count_ptr)); |
duke@435 | 1170 | |
duke@435 | 1171 | NULL_CHECK(*groups_ptr, JVMTI_ERROR_OUT_OF_MEMORY); |
duke@435 | 1172 | |
duke@435 | 1173 | // Convert oop to Handle, then convert Handle to global-ref. |
duke@435 | 1174 | { |
duke@435 | 1175 | HandleMark hm(current_thread); |
duke@435 | 1176 | Handle system_thread_group(current_thread, Universe::system_thread_group()); |
duke@435 | 1177 | *groups_ptr[0] = jni_reference(system_thread_group); |
duke@435 | 1178 | } |
duke@435 | 1179 | |
duke@435 | 1180 | return JVMTI_ERROR_NONE; |
duke@435 | 1181 | } /* end GetTopThreadGroups */ |
duke@435 | 1182 | |
duke@435 | 1183 | |
duke@435 | 1184 | // info_ptr - pre-checked for NULL |
duke@435 | 1185 | jvmtiError |
duke@435 | 1186 | JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) { |
duke@435 | 1187 | ResourceMark rm; |
duke@435 | 1188 | HandleMark hm; |
duke@435 | 1189 | |
duke@435 | 1190 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 1191 | |
duke@435 | 1192 | Handle group_obj (current_thread, JNIHandles::resolve_external_guard(group)); |
duke@435 | 1193 | NULL_CHECK(group_obj(), JVMTI_ERROR_INVALID_THREAD_GROUP); |
duke@435 | 1194 | |
duke@435 | 1195 | typeArrayHandle name; |
duke@435 | 1196 | Handle parent_group; |
duke@435 | 1197 | bool is_daemon; |
duke@435 | 1198 | ThreadPriority max_priority; |
duke@435 | 1199 | |
duke@435 | 1200 | { MutexLocker mu(Threads_lock); |
duke@435 | 1201 | |
duke@435 | 1202 | name = typeArrayHandle(current_thread, |
duke@435 | 1203 | java_lang_ThreadGroup::name(group_obj())); |
duke@435 | 1204 | parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj())); |
duke@435 | 1205 | is_daemon = java_lang_ThreadGroup::is_daemon(group_obj()); |
duke@435 | 1206 | max_priority = java_lang_ThreadGroup::maxPriority(group_obj()); |
duke@435 | 1207 | } |
duke@435 | 1208 | |
duke@435 | 1209 | info_ptr->is_daemon = is_daemon; |
duke@435 | 1210 | info_ptr->max_priority = max_priority; |
duke@435 | 1211 | info_ptr->parent = jni_reference(parent_group); |
duke@435 | 1212 | |
duke@435 | 1213 | if (name() != NULL) { |
duke@435 | 1214 | const char* n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); |
duke@435 | 1215 | info_ptr->name = (char *)jvmtiMalloc(strlen(n)+1); |
duke@435 | 1216 | NULL_CHECK(info_ptr->name, JVMTI_ERROR_OUT_OF_MEMORY); |
duke@435 | 1217 | strcpy(info_ptr->name, n); |
duke@435 | 1218 | } else { |
duke@435 | 1219 | info_ptr->name = NULL; |
duke@435 | 1220 | } |
duke@435 | 1221 | |
duke@435 | 1222 | return JVMTI_ERROR_NONE; |
duke@435 | 1223 | } /* end GetThreadGroupInfo */ |
duke@435 | 1224 | |
duke@435 | 1225 | |
duke@435 | 1226 | // thread_count_ptr - pre-checked for NULL |
duke@435 | 1227 | // threads_ptr - pre-checked for NULL |
duke@435 | 1228 | // group_count_ptr - pre-checked for NULL |
duke@435 | 1229 | // groups_ptr - pre-checked for NULL |
duke@435 | 1230 | jvmtiError |
duke@435 | 1231 | JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr) { |
duke@435 | 1232 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 1233 | oop group_obj = (oop) JNIHandles::resolve_external_guard(group); |
duke@435 | 1234 | NULL_CHECK(group_obj, JVMTI_ERROR_INVALID_THREAD_GROUP); |
duke@435 | 1235 | |
duke@435 | 1236 | Handle *thread_objs = NULL; |
duke@435 | 1237 | Handle *group_objs = NULL; |
duke@435 | 1238 | int nthreads = 0; |
duke@435 | 1239 | int ngroups = 0; |
duke@435 | 1240 | int hidden_threads = 0; |
duke@435 | 1241 | |
duke@435 | 1242 | ResourceMark rm; |
duke@435 | 1243 | HandleMark hm; |
duke@435 | 1244 | |
duke@435 | 1245 | Handle group_hdl(current_thread, group_obj); |
duke@435 | 1246 | |
duke@435 | 1247 | { MutexLocker mu(Threads_lock); |
duke@435 | 1248 | |
duke@435 | 1249 | nthreads = java_lang_ThreadGroup::nthreads(group_hdl()); |
duke@435 | 1250 | ngroups = java_lang_ThreadGroup::ngroups(group_hdl()); |
duke@435 | 1251 | |
duke@435 | 1252 | if (nthreads > 0) { |
duke@435 | 1253 | objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl()); |
duke@435 | 1254 | assert(nthreads <= threads->length(), "too many threads"); |
duke@435 | 1255 | thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads); |
duke@435 | 1256 | for (int i=0, j=0; i<nthreads; i++) { |
duke@435 | 1257 | oop thread_obj = threads->obj_at(i); |
duke@435 | 1258 | assert(thread_obj != NULL, "thread_obj is NULL"); |
duke@435 | 1259 | JavaThread *javathread = java_lang_Thread::thread(thread_obj); |
duke@435 | 1260 | // Filter out hidden java threads. |
duke@435 | 1261 | if (javathread != NULL && javathread->is_hidden_from_external_view()) { |
duke@435 | 1262 | hidden_threads++; |
duke@435 | 1263 | continue; |
duke@435 | 1264 | } |
duke@435 | 1265 | thread_objs[j++] = Handle(current_thread, thread_obj); |
duke@435 | 1266 | } |
duke@435 | 1267 | nthreads -= hidden_threads; |
duke@435 | 1268 | } |
duke@435 | 1269 | if (ngroups > 0) { |
duke@435 | 1270 | objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl()); |
duke@435 | 1271 | assert(ngroups <= groups->length(), "too many threads"); |
duke@435 | 1272 | group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups); |
duke@435 | 1273 | for (int i=0; i<ngroups; i++) { |
duke@435 | 1274 | oop group_obj = groups->obj_at(i); |
duke@435 | 1275 | assert(group_obj != NULL, "group_obj != NULL"); |
duke@435 | 1276 | group_objs[i] = Handle(current_thread, group_obj); |
duke@435 | 1277 | } |
duke@435 | 1278 | } |
duke@435 | 1279 | } |
duke@435 | 1280 | |
duke@435 | 1281 | // have to make global handles outside of Threads_lock |
duke@435 | 1282 | *group_count_ptr = ngroups; |
duke@435 | 1283 | *thread_count_ptr = nthreads; |
duke@435 | 1284 | *threads_ptr = new_jthreadArray(nthreads, thread_objs); |
duke@435 | 1285 | *groups_ptr = new_jthreadGroupArray(ngroups, group_objs); |
duke@435 | 1286 | if ((nthreads > 0) && (*threads_ptr == NULL)) { |
duke@435 | 1287 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 1288 | } |
duke@435 | 1289 | if ((ngroups > 0) && (*groups_ptr == NULL)) { |
duke@435 | 1290 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 1291 | } |
duke@435 | 1292 | |
duke@435 | 1293 | return JVMTI_ERROR_NONE; |
duke@435 | 1294 | } /* end GetThreadGroupChildren */ |
duke@435 | 1295 | |
duke@435 | 1296 | |
duke@435 | 1297 | // |
duke@435 | 1298 | // Stack Frame functions |
duke@435 | 1299 | // |
duke@435 | 1300 | |
duke@435 | 1301 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1302 | // java_thread - pre-checked |
duke@435 | 1303 | // max_frame_count - pre-checked to be greater than or equal to 0 |
duke@435 | 1304 | // frame_buffer - pre-checked for NULL |
duke@435 | 1305 | // count_ptr - pre-checked for NULL |
duke@435 | 1306 | jvmtiError |
duke@435 | 1307 | JvmtiEnv::GetStackTrace(JavaThread* java_thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) { |
duke@435 | 1308 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1309 | uint32_t debug_bits = 0; |
duke@435 | 1310 | if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1311 | err = get_stack_trace(java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); |
duke@435 | 1312 | } else { |
duke@435 | 1313 | // JVMTI get stack trace at safepoint. Do not require target thread to |
duke@435 | 1314 | // be suspended. |
duke@435 | 1315 | VM_GetStackTrace op(this, java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); |
duke@435 | 1316 | VMThread::execute(&op); |
duke@435 | 1317 | err = op.result(); |
duke@435 | 1318 | } |
duke@435 | 1319 | |
duke@435 | 1320 | return err; |
duke@435 | 1321 | } /* end GetStackTrace */ |
duke@435 | 1322 | |
duke@435 | 1323 | |
duke@435 | 1324 | // max_frame_count - pre-checked to be greater than or equal to 0 |
duke@435 | 1325 | // stack_info_ptr - pre-checked for NULL |
duke@435 | 1326 | // thread_count_ptr - pre-checked for NULL |
duke@435 | 1327 | jvmtiError |
duke@435 | 1328 | JvmtiEnv::GetAllStackTraces(jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr) { |
duke@435 | 1329 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1330 | JavaThread* calling_thread = JavaThread::current(); |
duke@435 | 1331 | |
duke@435 | 1332 | // JVMTI get stack traces at safepoint. |
duke@435 | 1333 | VM_GetAllStackTraces op(this, calling_thread, max_frame_count); |
duke@435 | 1334 | VMThread::execute(&op); |
duke@435 | 1335 | *thread_count_ptr = op.final_thread_count(); |
duke@435 | 1336 | *stack_info_ptr = op.stack_info(); |
duke@435 | 1337 | err = op.result(); |
duke@435 | 1338 | return err; |
duke@435 | 1339 | } /* end GetAllStackTraces */ |
duke@435 | 1340 | |
duke@435 | 1341 | |
duke@435 | 1342 | // thread_count - pre-checked to be greater than or equal to 0 |
duke@435 | 1343 | // thread_list - pre-checked for NULL |
duke@435 | 1344 | // max_frame_count - pre-checked to be greater than or equal to 0 |
duke@435 | 1345 | // stack_info_ptr - pre-checked for NULL |
duke@435 | 1346 | jvmtiError |
duke@435 | 1347 | JvmtiEnv::GetThreadListStackTraces(jint thread_count, const jthread* thread_list, jint max_frame_count, jvmtiStackInfo** stack_info_ptr) { |
duke@435 | 1348 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1349 | // JVMTI get stack traces at safepoint. |
duke@435 | 1350 | VM_GetThreadListStackTraces op(this, thread_count, thread_list, max_frame_count); |
duke@435 | 1351 | VMThread::execute(&op); |
duke@435 | 1352 | err = op.result(); |
duke@435 | 1353 | if (err == JVMTI_ERROR_NONE) { |
duke@435 | 1354 | *stack_info_ptr = op.stack_info(); |
duke@435 | 1355 | } |
duke@435 | 1356 | return err; |
duke@435 | 1357 | } /* end GetThreadListStackTraces */ |
duke@435 | 1358 | |
duke@435 | 1359 | |
duke@435 | 1360 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1361 | // java_thread - pre-checked |
duke@435 | 1362 | // count_ptr - pre-checked for NULL |
duke@435 | 1363 | jvmtiError |
duke@435 | 1364 | JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) { |
duke@435 | 1365 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1366 | |
duke@435 | 1367 | // retrieve or create JvmtiThreadState. |
duke@435 | 1368 | JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); |
dcubed@1044 | 1369 | if (state == NULL) { |
dcubed@1044 | 1370 | return JVMTI_ERROR_THREAD_NOT_ALIVE; |
dcubed@1044 | 1371 | } |
duke@435 | 1372 | uint32_t debug_bits = 0; |
duke@435 | 1373 | if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1374 | err = get_frame_count(state, count_ptr); |
duke@435 | 1375 | } else { |
duke@435 | 1376 | // get java stack frame count at safepoint. |
duke@435 | 1377 | VM_GetFrameCount op(this, state, count_ptr); |
duke@435 | 1378 | VMThread::execute(&op); |
duke@435 | 1379 | err = op.result(); |
duke@435 | 1380 | } |
duke@435 | 1381 | return err; |
duke@435 | 1382 | } /* end GetFrameCount */ |
duke@435 | 1383 | |
duke@435 | 1384 | |
duke@435 | 1385 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1386 | // java_thread - pre-checked |
duke@435 | 1387 | jvmtiError |
duke@435 | 1388 | JvmtiEnv::PopFrame(JavaThread* java_thread) { |
duke@435 | 1389 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 1390 | HandleMark hm(current_thread); |
duke@435 | 1391 | uint32_t debug_bits = 0; |
duke@435 | 1392 | |
dcubed@1044 | 1393 | // retrieve or create the state |
dcubed@1044 | 1394 | JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); |
dcubed@1044 | 1395 | if (state == NULL) { |
dcubed@1044 | 1396 | return JVMTI_ERROR_THREAD_NOT_ALIVE; |
dcubed@1044 | 1397 | } |
dcubed@1044 | 1398 | |
duke@435 | 1399 | // Check if java_thread is fully suspended |
duke@435 | 1400 | if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) { |
duke@435 | 1401 | return JVMTI_ERROR_THREAD_NOT_SUSPENDED; |
duke@435 | 1402 | } |
duke@435 | 1403 | // Check to see if a PopFrame was already in progress |
duke@435 | 1404 | if (java_thread->popframe_condition() != JavaThread::popframe_inactive) { |
duke@435 | 1405 | // Probably possible for JVMTI clients to trigger this, but the |
duke@435 | 1406 | // JPDA backend shouldn't allow this to happen |
duke@435 | 1407 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 1408 | } |
duke@435 | 1409 | |
duke@435 | 1410 | { |
duke@435 | 1411 | // Was workaround bug |
duke@435 | 1412 | // 4812902: popFrame hangs if the method is waiting at a synchronize |
duke@435 | 1413 | // Catch this condition and return an error to avoid hanging. |
duke@435 | 1414 | // Now JVMTI spec allows an implementation to bail out with an opaque frame error. |
duke@435 | 1415 | OSThread* osThread = java_thread->osthread(); |
duke@435 | 1416 | if (osThread->get_state() == MONITOR_WAIT) { |
duke@435 | 1417 | return JVMTI_ERROR_OPAQUE_FRAME; |
duke@435 | 1418 | } |
duke@435 | 1419 | } |
duke@435 | 1420 | |
duke@435 | 1421 | { |
duke@435 | 1422 | ResourceMark rm(current_thread); |
duke@435 | 1423 | // Check if there are more than one Java frame in this thread, that the top two frames |
duke@435 | 1424 | // are Java (not native) frames, and that there is no intervening VM frame |
duke@435 | 1425 | int frame_count = 0; |
duke@435 | 1426 | bool is_interpreted[2]; |
duke@435 | 1427 | intptr_t *frame_sp[2]; |
duke@435 | 1428 | // The 2-nd arg of constructor is needed to stop iterating at java entry frame. |
duke@435 | 1429 | for (vframeStream vfs(java_thread, true); !vfs.at_end(); vfs.next()) { |
duke@435 | 1430 | methodHandle mh(current_thread, vfs.method()); |
duke@435 | 1431 | if (mh->is_native()) return(JVMTI_ERROR_OPAQUE_FRAME); |
duke@435 | 1432 | is_interpreted[frame_count] = vfs.is_interpreted_frame(); |
duke@435 | 1433 | frame_sp[frame_count] = vfs.frame_id(); |
duke@435 | 1434 | if (++frame_count > 1) break; |
duke@435 | 1435 | } |
duke@435 | 1436 | if (frame_count < 2) { |
duke@435 | 1437 | // We haven't found two adjacent non-native Java frames on the top. |
duke@435 | 1438 | // There can be two situations here: |
duke@435 | 1439 | // 1. There are no more java frames |
duke@435 | 1440 | // 2. Two top java frames are separated by non-java native frames |
duke@435 | 1441 | if(vframeFor(java_thread, 1) == NULL) { |
duke@435 | 1442 | return JVMTI_ERROR_NO_MORE_FRAMES; |
duke@435 | 1443 | } else { |
duke@435 | 1444 | // Intervening non-java native or VM frames separate java frames. |
duke@435 | 1445 | // Current implementation does not support this. See bug #5031735. |
duke@435 | 1446 | // In theory it is possible to pop frames in such cases. |
duke@435 | 1447 | return JVMTI_ERROR_OPAQUE_FRAME; |
duke@435 | 1448 | } |
duke@435 | 1449 | } |
duke@435 | 1450 | |
duke@435 | 1451 | // If any of the top 2 frames is a compiled one, need to deoptimize it |
duke@435 | 1452 | for (int i = 0; i < 2; i++) { |
duke@435 | 1453 | if (!is_interpreted[i]) { |
never@2260 | 1454 | Deoptimization::deoptimize_frame(java_thread, frame_sp[i]); |
duke@435 | 1455 | } |
duke@435 | 1456 | } |
duke@435 | 1457 | |
duke@435 | 1458 | // Update the thread state to reflect that the top frame is popped |
duke@435 | 1459 | // so that cur_stack_depth is maintained properly and all frameIDs |
duke@435 | 1460 | // are invalidated. |
duke@435 | 1461 | // The current frame will be popped later when the suspended thread |
duke@435 | 1462 | // is resumed and right before returning from VM to Java. |
duke@435 | 1463 | // (see call_VM_base() in assembler_<cpu>.cpp). |
duke@435 | 1464 | |
duke@435 | 1465 | // It's fine to update the thread state here because no JVMTI events |
duke@435 | 1466 | // shall be posted for this PopFrame. |
duke@435 | 1467 | |
duke@435 | 1468 | state->update_for_pop_top_frame(); |
duke@435 | 1469 | java_thread->set_popframe_condition(JavaThread::popframe_pending_bit); |
duke@435 | 1470 | // Set pending step flag for this popframe and it is cleared when next |
duke@435 | 1471 | // step event is posted. |
duke@435 | 1472 | state->set_pending_step_for_popframe(); |
duke@435 | 1473 | } |
duke@435 | 1474 | |
duke@435 | 1475 | return JVMTI_ERROR_NONE; |
duke@435 | 1476 | } /* end PopFrame */ |
duke@435 | 1477 | |
duke@435 | 1478 | |
duke@435 | 1479 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1480 | // java_thread - pre-checked |
duke@435 | 1481 | // java_thread - unchecked |
duke@435 | 1482 | // depth - pre-checked as non-negative |
duke@435 | 1483 | // method_ptr - pre-checked for NULL |
duke@435 | 1484 | // location_ptr - pre-checked for NULL |
duke@435 | 1485 | jvmtiError |
duke@435 | 1486 | JvmtiEnv::GetFrameLocation(JavaThread* java_thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) { |
duke@435 | 1487 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 1488 | uint32_t debug_bits = 0; |
duke@435 | 1489 | |
duke@435 | 1490 | if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1491 | err = get_frame_location(java_thread, depth, method_ptr, location_ptr); |
duke@435 | 1492 | } else { |
duke@435 | 1493 | // JVMTI get java stack frame location at safepoint. |
duke@435 | 1494 | VM_GetFrameLocation op(this, java_thread, depth, method_ptr, location_ptr); |
duke@435 | 1495 | VMThread::execute(&op); |
duke@435 | 1496 | err = op.result(); |
duke@435 | 1497 | } |
duke@435 | 1498 | return err; |
duke@435 | 1499 | } /* end GetFrameLocation */ |
duke@435 | 1500 | |
duke@435 | 1501 | |
duke@435 | 1502 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1503 | // java_thread - pre-checked |
duke@435 | 1504 | // java_thread - unchecked |
duke@435 | 1505 | // depth - pre-checked as non-negative |
duke@435 | 1506 | jvmtiError |
duke@435 | 1507 | JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) { |
duke@435 | 1508 | ResourceMark rm; |
duke@435 | 1509 | uint32_t debug_bits = 0; |
duke@435 | 1510 | |
dcubed@1044 | 1511 | JvmtiThreadState *state = JvmtiThreadState::state_for(java_thread); |
dcubed@1044 | 1512 | if (state == NULL) { |
dcubed@1044 | 1513 | return JVMTI_ERROR_THREAD_NOT_ALIVE; |
dcubed@1044 | 1514 | } |
dcubed@1044 | 1515 | |
duke@435 | 1516 | if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
duke@435 | 1517 | return JVMTI_ERROR_THREAD_NOT_SUSPENDED; |
duke@435 | 1518 | } |
duke@435 | 1519 | |
duke@435 | 1520 | if (TraceJVMTICalls) { |
duke@435 | 1521 | JvmtiSuspendControl::print(); |
duke@435 | 1522 | } |
duke@435 | 1523 | |
duke@435 | 1524 | vframe *vf = vframeFor(java_thread, depth); |
duke@435 | 1525 | if (vf == NULL) { |
duke@435 | 1526 | return JVMTI_ERROR_NO_MORE_FRAMES; |
duke@435 | 1527 | } |
duke@435 | 1528 | |
duke@435 | 1529 | if (!vf->is_java_frame() || ((javaVFrame*) vf)->method()->is_native()) { |
duke@435 | 1530 | return JVMTI_ERROR_OPAQUE_FRAME; |
duke@435 | 1531 | } |
duke@435 | 1532 | |
duke@435 | 1533 | assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL"); |
duke@435 | 1534 | |
duke@435 | 1535 | int frame_number = state->count_frames() - depth; |
duke@435 | 1536 | state->env_thread_state(this)->set_frame_pop(frame_number); |
duke@435 | 1537 | |
duke@435 | 1538 | return JVMTI_ERROR_NONE; |
duke@435 | 1539 | } /* end NotifyFramePop */ |
duke@435 | 1540 | |
duke@435 | 1541 | |
duke@435 | 1542 | // |
duke@435 | 1543 | // Force Early Return functions |
duke@435 | 1544 | // |
duke@435 | 1545 | |
duke@435 | 1546 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1547 | // java_thread - pre-checked |
duke@435 | 1548 | jvmtiError |
duke@435 | 1549 | JvmtiEnv::ForceEarlyReturnObject(JavaThread* java_thread, jobject value) { |
duke@435 | 1550 | jvalue val; |
duke@435 | 1551 | val.l = value; |
duke@435 | 1552 | return force_early_return(java_thread, val, atos); |
duke@435 | 1553 | } /* end ForceEarlyReturnObject */ |
duke@435 | 1554 | |
duke@435 | 1555 | |
duke@435 | 1556 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1557 | // java_thread - pre-checked |
duke@435 | 1558 | jvmtiError |
duke@435 | 1559 | JvmtiEnv::ForceEarlyReturnInt(JavaThread* java_thread, jint value) { |
duke@435 | 1560 | jvalue val; |
duke@435 | 1561 | val.i = value; |
duke@435 | 1562 | return force_early_return(java_thread, val, itos); |
duke@435 | 1563 | } /* end ForceEarlyReturnInt */ |
duke@435 | 1564 | |
duke@435 | 1565 | |
duke@435 | 1566 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1567 | // java_thread - pre-checked |
duke@435 | 1568 | jvmtiError |
duke@435 | 1569 | JvmtiEnv::ForceEarlyReturnLong(JavaThread* java_thread, jlong value) { |
duke@435 | 1570 | jvalue val; |
duke@435 | 1571 | val.j = value; |
duke@435 | 1572 | return force_early_return(java_thread, val, ltos); |
duke@435 | 1573 | } /* end ForceEarlyReturnLong */ |
duke@435 | 1574 | |
duke@435 | 1575 | |
duke@435 | 1576 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1577 | // java_thread - pre-checked |
duke@435 | 1578 | jvmtiError |
duke@435 | 1579 | JvmtiEnv::ForceEarlyReturnFloat(JavaThread* java_thread, jfloat value) { |
duke@435 | 1580 | jvalue val; |
duke@435 | 1581 | val.f = value; |
duke@435 | 1582 | return force_early_return(java_thread, val, ftos); |
duke@435 | 1583 | } /* end ForceEarlyReturnFloat */ |
duke@435 | 1584 | |
duke@435 | 1585 | |
duke@435 | 1586 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1587 | // java_thread - pre-checked |
duke@435 | 1588 | jvmtiError |
duke@435 | 1589 | JvmtiEnv::ForceEarlyReturnDouble(JavaThread* java_thread, jdouble value) { |
duke@435 | 1590 | jvalue val; |
duke@435 | 1591 | val.d = value; |
duke@435 | 1592 | return force_early_return(java_thread, val, dtos); |
duke@435 | 1593 | } /* end ForceEarlyReturnDouble */ |
duke@435 | 1594 | |
duke@435 | 1595 | |
duke@435 | 1596 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1597 | // java_thread - pre-checked |
duke@435 | 1598 | jvmtiError |
duke@435 | 1599 | JvmtiEnv::ForceEarlyReturnVoid(JavaThread* java_thread) { |
duke@435 | 1600 | jvalue val; |
duke@435 | 1601 | val.j = 0L; |
duke@435 | 1602 | return force_early_return(java_thread, val, vtos); |
duke@435 | 1603 | } /* end ForceEarlyReturnVoid */ |
duke@435 | 1604 | |
duke@435 | 1605 | |
duke@435 | 1606 | // |
duke@435 | 1607 | // Heap functions |
duke@435 | 1608 | // |
duke@435 | 1609 | |
duke@435 | 1610 | // klass - NULL is a valid value, must be checked |
duke@435 | 1611 | // initial_object - NULL is a valid value, must be checked |
duke@435 | 1612 | // callbacks - pre-checked for NULL |
duke@435 | 1613 | // user_data - NULL is a valid value, must be checked |
duke@435 | 1614 | jvmtiError |
duke@435 | 1615 | JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data) { |
duke@435 | 1616 | // check klass if provided |
duke@435 | 1617 | klassOop k_oop = NULL; |
duke@435 | 1618 | if (klass != NULL) { |
duke@435 | 1619 | oop k_mirror = JNIHandles::resolve_external_guard(klass); |
duke@435 | 1620 | if (k_mirror == NULL) { |
duke@435 | 1621 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 1622 | } |
duke@435 | 1623 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 1624 | return JVMTI_ERROR_NONE; |
duke@435 | 1625 | } |
duke@435 | 1626 | k_oop = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 1627 | if (k_oop == NULL) { |
duke@435 | 1628 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 1629 | } |
duke@435 | 1630 | } |
duke@435 | 1631 | |
duke@435 | 1632 | Thread *thread = Thread::current(); |
duke@435 | 1633 | HandleMark hm(thread); |
duke@435 | 1634 | KlassHandle kh (thread, k_oop); |
duke@435 | 1635 | |
duke@435 | 1636 | TraceTime t("FollowReferences", TraceJVMTIObjectTagging); |
duke@435 | 1637 | JvmtiTagMap::tag_map_for(this)->follow_references(heap_filter, kh, initial_object, callbacks, user_data); |
duke@435 | 1638 | return JVMTI_ERROR_NONE; |
duke@435 | 1639 | } /* end FollowReferences */ |
duke@435 | 1640 | |
duke@435 | 1641 | |
duke@435 | 1642 | // klass - NULL is a valid value, must be checked |
duke@435 | 1643 | // callbacks - pre-checked for NULL |
duke@435 | 1644 | // user_data - NULL is a valid value, must be checked |
duke@435 | 1645 | jvmtiError |
duke@435 | 1646 | JvmtiEnv::IterateThroughHeap(jint heap_filter, jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) { |
duke@435 | 1647 | // check klass if provided |
duke@435 | 1648 | klassOop k_oop = NULL; |
duke@435 | 1649 | if (klass != NULL) { |
duke@435 | 1650 | oop k_mirror = JNIHandles::resolve_external_guard(klass); |
duke@435 | 1651 | if (k_mirror == NULL) { |
duke@435 | 1652 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 1653 | } |
duke@435 | 1654 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 1655 | return JVMTI_ERROR_NONE; |
duke@435 | 1656 | } |
duke@435 | 1657 | k_oop = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 1658 | if (k_oop == NULL) { |
duke@435 | 1659 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 1660 | } |
duke@435 | 1661 | } |
duke@435 | 1662 | |
duke@435 | 1663 | Thread *thread = Thread::current(); |
duke@435 | 1664 | HandleMark hm(thread); |
duke@435 | 1665 | KlassHandle kh (thread, k_oop); |
duke@435 | 1666 | |
duke@435 | 1667 | TraceTime t("IterateThroughHeap", TraceJVMTIObjectTagging); |
duke@435 | 1668 | JvmtiTagMap::tag_map_for(this)->iterate_through_heap(heap_filter, kh, callbacks, user_data); |
duke@435 | 1669 | return JVMTI_ERROR_NONE; |
duke@435 | 1670 | } /* end IterateThroughHeap */ |
duke@435 | 1671 | |
duke@435 | 1672 | |
duke@435 | 1673 | // tag_ptr - pre-checked for NULL |
duke@435 | 1674 | jvmtiError |
duke@435 | 1675 | JvmtiEnv::GetTag(jobject object, jlong* tag_ptr) { |
duke@435 | 1676 | oop o = JNIHandles::resolve_external_guard(object); |
duke@435 | 1677 | NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); |
duke@435 | 1678 | *tag_ptr = JvmtiTagMap::tag_map_for(this)->get_tag(object); |
duke@435 | 1679 | return JVMTI_ERROR_NONE; |
duke@435 | 1680 | } /* end GetTag */ |
duke@435 | 1681 | |
duke@435 | 1682 | |
duke@435 | 1683 | jvmtiError |
duke@435 | 1684 | JvmtiEnv::SetTag(jobject object, jlong tag) { |
duke@435 | 1685 | oop o = JNIHandles::resolve_external_guard(object); |
duke@435 | 1686 | NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); |
duke@435 | 1687 | JvmtiTagMap::tag_map_for(this)->set_tag(object, tag); |
duke@435 | 1688 | return JVMTI_ERROR_NONE; |
duke@435 | 1689 | } /* end SetTag */ |
duke@435 | 1690 | |
duke@435 | 1691 | |
duke@435 | 1692 | // tag_count - pre-checked to be greater than or equal to 0 |
duke@435 | 1693 | // tags - pre-checked for NULL |
duke@435 | 1694 | // count_ptr - pre-checked for NULL |
duke@435 | 1695 | // object_result_ptr - NULL is a valid value, must be checked |
duke@435 | 1696 | // tag_result_ptr - NULL is a valid value, must be checked |
duke@435 | 1697 | jvmtiError |
duke@435 | 1698 | JvmtiEnv::GetObjectsWithTags(jint tag_count, const jlong* tags, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { |
duke@435 | 1699 | TraceTime t("GetObjectsWithTags", TraceJVMTIObjectTagging); |
duke@435 | 1700 | return JvmtiTagMap::tag_map_for(this)->get_objects_with_tags((jlong*)tags, tag_count, count_ptr, object_result_ptr, tag_result_ptr); |
duke@435 | 1701 | } /* end GetObjectsWithTags */ |
duke@435 | 1702 | |
duke@435 | 1703 | |
duke@435 | 1704 | jvmtiError |
duke@435 | 1705 | JvmtiEnv::ForceGarbageCollection() { |
duke@435 | 1706 | Universe::heap()->collect(GCCause::_jvmti_force_gc); |
duke@435 | 1707 | return JVMTI_ERROR_NONE; |
duke@435 | 1708 | } /* end ForceGarbageCollection */ |
duke@435 | 1709 | |
duke@435 | 1710 | |
duke@435 | 1711 | // |
duke@435 | 1712 | // Heap (1.0) functions |
duke@435 | 1713 | // |
duke@435 | 1714 | |
duke@435 | 1715 | // object_reference_callback - pre-checked for NULL |
duke@435 | 1716 | // user_data - NULL is a valid value, must be checked |
duke@435 | 1717 | jvmtiError |
duke@435 | 1718 | JvmtiEnv::IterateOverObjectsReachableFromObject(jobject object, jvmtiObjectReferenceCallback object_reference_callback, const void* user_data) { |
duke@435 | 1719 | oop o = JNIHandles::resolve_external_guard(object); |
duke@435 | 1720 | NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); |
duke@435 | 1721 | JvmtiTagMap::tag_map_for(this)->iterate_over_objects_reachable_from_object(object, object_reference_callback, user_data); |
duke@435 | 1722 | return JVMTI_ERROR_NONE; |
duke@435 | 1723 | } /* end IterateOverObjectsReachableFromObject */ |
duke@435 | 1724 | |
duke@435 | 1725 | |
duke@435 | 1726 | // heap_root_callback - NULL is a valid value, must be checked |
duke@435 | 1727 | // stack_ref_callback - NULL is a valid value, must be checked |
duke@435 | 1728 | // object_ref_callback - NULL is a valid value, must be checked |
duke@435 | 1729 | // user_data - NULL is a valid value, must be checked |
duke@435 | 1730 | jvmtiError |
duke@435 | 1731 | JvmtiEnv::IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, const void* user_data) { |
duke@435 | 1732 | TraceTime t("IterateOverReachableObjects", TraceJVMTIObjectTagging); |
duke@435 | 1733 | JvmtiTagMap::tag_map_for(this)->iterate_over_reachable_objects(heap_root_callback, stack_ref_callback, object_ref_callback, user_data); |
duke@435 | 1734 | return JVMTI_ERROR_NONE; |
duke@435 | 1735 | } /* end IterateOverReachableObjects */ |
duke@435 | 1736 | |
duke@435 | 1737 | |
duke@435 | 1738 | // heap_object_callback - pre-checked for NULL |
duke@435 | 1739 | // user_data - NULL is a valid value, must be checked |
duke@435 | 1740 | jvmtiError |
duke@435 | 1741 | JvmtiEnv::IterateOverHeap(jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { |
duke@435 | 1742 | TraceTime t("IterateOverHeap", TraceJVMTIObjectTagging); |
duke@435 | 1743 | Thread *thread = Thread::current(); |
duke@435 | 1744 | HandleMark hm(thread); |
duke@435 | 1745 | JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, KlassHandle(), heap_object_callback, user_data); |
duke@435 | 1746 | return JVMTI_ERROR_NONE; |
duke@435 | 1747 | } /* end IterateOverHeap */ |
duke@435 | 1748 | |
duke@435 | 1749 | |
duke@435 | 1750 | // k_mirror - may be primitive, this must be checked |
duke@435 | 1751 | // heap_object_callback - pre-checked for NULL |
duke@435 | 1752 | // user_data - NULL is a valid value, must be checked |
duke@435 | 1753 | jvmtiError |
duke@435 | 1754 | JvmtiEnv::IterateOverInstancesOfClass(oop k_mirror, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { |
duke@435 | 1755 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 1756 | // DO PRIMITIVE CLASS PROCESSING |
duke@435 | 1757 | return JVMTI_ERROR_NONE; |
duke@435 | 1758 | } |
duke@435 | 1759 | klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 1760 | if (k_oop == NULL) { |
duke@435 | 1761 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 1762 | } |
duke@435 | 1763 | Thread *thread = Thread::current(); |
duke@435 | 1764 | HandleMark hm(thread); |
duke@435 | 1765 | KlassHandle klass (thread, k_oop); |
duke@435 | 1766 | TraceTime t("IterateOverInstancesOfClass", TraceJVMTIObjectTagging); |
duke@435 | 1767 | JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, klass, heap_object_callback, user_data); |
duke@435 | 1768 | return JVMTI_ERROR_NONE; |
duke@435 | 1769 | } /* end IterateOverInstancesOfClass */ |
duke@435 | 1770 | |
duke@435 | 1771 | |
duke@435 | 1772 | // |
duke@435 | 1773 | // Local Variable functions |
duke@435 | 1774 | // |
duke@435 | 1775 | |
duke@435 | 1776 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1777 | // java_thread - pre-checked |
duke@435 | 1778 | // java_thread - unchecked |
duke@435 | 1779 | // depth - pre-checked as non-negative |
duke@435 | 1780 | // value_ptr - pre-checked for NULL |
duke@435 | 1781 | jvmtiError |
duke@435 | 1782 | JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject* value_ptr) { |
duke@435 | 1783 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 1784 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1785 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1786 | ResourceMark rm(current_thread); |
duke@435 | 1787 | |
duke@435 | 1788 | VM_GetOrSetLocal op(java_thread, current_thread, depth, slot); |
duke@435 | 1789 | VMThread::execute(&op); |
duke@435 | 1790 | jvmtiError err = op.result(); |
duke@435 | 1791 | if (err != JVMTI_ERROR_NONE) { |
duke@435 | 1792 | return err; |
duke@435 | 1793 | } else { |
duke@435 | 1794 | *value_ptr = op.value().l; |
duke@435 | 1795 | return JVMTI_ERROR_NONE; |
duke@435 | 1796 | } |
duke@435 | 1797 | } /* end GetLocalObject */ |
duke@435 | 1798 | |
kamg@2361 | 1799 | // Threads_lock NOT held, java_thread not protected by lock |
kamg@2361 | 1800 | // java_thread - pre-checked |
kamg@2361 | 1801 | // java_thread - unchecked |
kamg@2361 | 1802 | // depth - pre-checked as non-negative |
kamg@2361 | 1803 | // value - pre-checked for NULL |
kamg@2361 | 1804 | jvmtiError |
phh@2423 | 1805 | JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value_ptr){ |
kamg@2361 | 1806 | JavaThread* current_thread = JavaThread::current(); |
kamg@2361 | 1807 | // rm object is created to clean up the javaVFrame created in |
kamg@2361 | 1808 | // doit_prologue(), but after doit() is finished with it. |
kamg@2361 | 1809 | ResourceMark rm(current_thread); |
kamg@2361 | 1810 | |
kamg@2361 | 1811 | VM_GetReceiver op(java_thread, current_thread, depth); |
kamg@2361 | 1812 | VMThread::execute(&op); |
kamg@2361 | 1813 | jvmtiError err = op.result(); |
kamg@2361 | 1814 | if (err != JVMTI_ERROR_NONE) { |
kamg@2361 | 1815 | return err; |
kamg@2361 | 1816 | } else { |
phh@2423 | 1817 | *value_ptr = op.value().l; |
kamg@2361 | 1818 | return JVMTI_ERROR_NONE; |
kamg@2361 | 1819 | } |
kamg@2361 | 1820 | } /* end GetLocalInstance */ |
kamg@2361 | 1821 | |
duke@435 | 1822 | |
duke@435 | 1823 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1824 | // java_thread - pre-checked |
duke@435 | 1825 | // java_thread - unchecked |
duke@435 | 1826 | // depth - pre-checked as non-negative |
duke@435 | 1827 | // value_ptr - pre-checked for NULL |
duke@435 | 1828 | jvmtiError |
duke@435 | 1829 | JvmtiEnv::GetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint* value_ptr) { |
duke@435 | 1830 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1831 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1832 | ResourceMark rm; |
duke@435 | 1833 | |
duke@435 | 1834 | VM_GetOrSetLocal op(java_thread, depth, slot, T_INT); |
duke@435 | 1835 | VMThread::execute(&op); |
duke@435 | 1836 | *value_ptr = op.value().i; |
duke@435 | 1837 | return op.result(); |
duke@435 | 1838 | } /* end GetLocalInt */ |
duke@435 | 1839 | |
duke@435 | 1840 | |
duke@435 | 1841 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1842 | // java_thread - pre-checked |
duke@435 | 1843 | // java_thread - unchecked |
duke@435 | 1844 | // depth - pre-checked as non-negative |
duke@435 | 1845 | // value_ptr - pre-checked for NULL |
duke@435 | 1846 | jvmtiError |
duke@435 | 1847 | JvmtiEnv::GetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong* value_ptr) { |
duke@435 | 1848 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1849 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1850 | ResourceMark rm; |
duke@435 | 1851 | |
duke@435 | 1852 | VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG); |
duke@435 | 1853 | VMThread::execute(&op); |
duke@435 | 1854 | *value_ptr = op.value().j; |
duke@435 | 1855 | return op.result(); |
duke@435 | 1856 | } /* end GetLocalLong */ |
duke@435 | 1857 | |
duke@435 | 1858 | |
duke@435 | 1859 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1860 | // java_thread - pre-checked |
duke@435 | 1861 | // java_thread - unchecked |
duke@435 | 1862 | // depth - pre-checked as non-negative |
duke@435 | 1863 | // value_ptr - pre-checked for NULL |
duke@435 | 1864 | jvmtiError |
duke@435 | 1865 | JvmtiEnv::GetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat* value_ptr) { |
duke@435 | 1866 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1867 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1868 | ResourceMark rm; |
duke@435 | 1869 | |
duke@435 | 1870 | VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT); |
duke@435 | 1871 | VMThread::execute(&op); |
duke@435 | 1872 | *value_ptr = op.value().f; |
duke@435 | 1873 | return op.result(); |
duke@435 | 1874 | } /* end GetLocalFloat */ |
duke@435 | 1875 | |
duke@435 | 1876 | |
duke@435 | 1877 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1878 | // java_thread - pre-checked |
duke@435 | 1879 | // java_thread - unchecked |
duke@435 | 1880 | // depth - pre-checked as non-negative |
duke@435 | 1881 | // value_ptr - pre-checked for NULL |
duke@435 | 1882 | jvmtiError |
duke@435 | 1883 | JvmtiEnv::GetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble* value_ptr) { |
duke@435 | 1884 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1885 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1886 | ResourceMark rm; |
duke@435 | 1887 | |
duke@435 | 1888 | VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE); |
duke@435 | 1889 | VMThread::execute(&op); |
duke@435 | 1890 | *value_ptr = op.value().d; |
duke@435 | 1891 | return op.result(); |
duke@435 | 1892 | } /* end GetLocalDouble */ |
duke@435 | 1893 | |
duke@435 | 1894 | |
duke@435 | 1895 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1896 | // java_thread - pre-checked |
duke@435 | 1897 | // java_thread - unchecked |
duke@435 | 1898 | // depth - pre-checked as non-negative |
duke@435 | 1899 | jvmtiError |
duke@435 | 1900 | JvmtiEnv::SetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject value) { |
duke@435 | 1901 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1902 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1903 | ResourceMark rm; |
duke@435 | 1904 | jvalue val; |
duke@435 | 1905 | val.l = value; |
duke@435 | 1906 | VM_GetOrSetLocal op(java_thread, depth, slot, T_OBJECT, val); |
duke@435 | 1907 | VMThread::execute(&op); |
duke@435 | 1908 | return op.result(); |
duke@435 | 1909 | } /* end SetLocalObject */ |
duke@435 | 1910 | |
duke@435 | 1911 | |
duke@435 | 1912 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1913 | // java_thread - pre-checked |
duke@435 | 1914 | // java_thread - unchecked |
duke@435 | 1915 | // depth - pre-checked as non-negative |
duke@435 | 1916 | jvmtiError |
duke@435 | 1917 | JvmtiEnv::SetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint value) { |
duke@435 | 1918 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1919 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1920 | ResourceMark rm; |
duke@435 | 1921 | jvalue val; |
duke@435 | 1922 | val.i = value; |
duke@435 | 1923 | VM_GetOrSetLocal op(java_thread, depth, slot, T_INT, val); |
duke@435 | 1924 | VMThread::execute(&op); |
duke@435 | 1925 | return op.result(); |
duke@435 | 1926 | } /* end SetLocalInt */ |
duke@435 | 1927 | |
duke@435 | 1928 | |
duke@435 | 1929 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1930 | // java_thread - pre-checked |
duke@435 | 1931 | // java_thread - unchecked |
duke@435 | 1932 | // depth - pre-checked as non-negative |
duke@435 | 1933 | jvmtiError |
duke@435 | 1934 | JvmtiEnv::SetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong value) { |
duke@435 | 1935 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1936 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1937 | ResourceMark rm; |
duke@435 | 1938 | jvalue val; |
duke@435 | 1939 | val.j = value; |
duke@435 | 1940 | VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG, val); |
duke@435 | 1941 | VMThread::execute(&op); |
duke@435 | 1942 | return op.result(); |
duke@435 | 1943 | } /* end SetLocalLong */ |
duke@435 | 1944 | |
duke@435 | 1945 | |
duke@435 | 1946 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1947 | // java_thread - pre-checked |
duke@435 | 1948 | // java_thread - unchecked |
duke@435 | 1949 | // depth - pre-checked as non-negative |
duke@435 | 1950 | jvmtiError |
duke@435 | 1951 | JvmtiEnv::SetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat value) { |
duke@435 | 1952 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1953 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1954 | ResourceMark rm; |
duke@435 | 1955 | jvalue val; |
duke@435 | 1956 | val.f = value; |
duke@435 | 1957 | VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT, val); |
duke@435 | 1958 | VMThread::execute(&op); |
duke@435 | 1959 | return op.result(); |
duke@435 | 1960 | } /* end SetLocalFloat */ |
duke@435 | 1961 | |
duke@435 | 1962 | |
duke@435 | 1963 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 1964 | // java_thread - pre-checked |
duke@435 | 1965 | // java_thread - unchecked |
duke@435 | 1966 | // depth - pre-checked as non-negative |
duke@435 | 1967 | jvmtiError |
duke@435 | 1968 | JvmtiEnv::SetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble value) { |
duke@435 | 1969 | // rm object is created to clean up the javaVFrame created in |
duke@435 | 1970 | // doit_prologue(), but after doit() is finished with it. |
duke@435 | 1971 | ResourceMark rm; |
duke@435 | 1972 | jvalue val; |
duke@435 | 1973 | val.d = value; |
duke@435 | 1974 | VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE, val); |
duke@435 | 1975 | VMThread::execute(&op); |
duke@435 | 1976 | return op.result(); |
duke@435 | 1977 | } /* end SetLocalDouble */ |
duke@435 | 1978 | |
duke@435 | 1979 | |
duke@435 | 1980 | // |
duke@435 | 1981 | // Breakpoint functions |
duke@435 | 1982 | // |
duke@435 | 1983 | |
duke@435 | 1984 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 1985 | jvmtiError |
duke@435 | 1986 | JvmtiEnv::SetBreakpoint(methodOop method_oop, jlocation location) { |
duke@435 | 1987 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 1988 | if (location < 0) { // simple invalid location check first |
duke@435 | 1989 | return JVMTI_ERROR_INVALID_LOCATION; |
duke@435 | 1990 | } |
duke@435 | 1991 | // verify that the breakpoint is not past the end of the method |
duke@435 | 1992 | if (location >= (jlocation) method_oop->code_size()) { |
duke@435 | 1993 | return JVMTI_ERROR_INVALID_LOCATION; |
duke@435 | 1994 | } |
duke@435 | 1995 | |
duke@435 | 1996 | ResourceMark rm; |
duke@435 | 1997 | JvmtiBreakpoint bp(method_oop, location); |
duke@435 | 1998 | JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); |
duke@435 | 1999 | if (jvmti_breakpoints.set(bp) == JVMTI_ERROR_DUPLICATE) |
duke@435 | 2000 | return JVMTI_ERROR_DUPLICATE; |
duke@435 | 2001 | |
duke@435 | 2002 | if (TraceJVMTICalls) { |
duke@435 | 2003 | jvmti_breakpoints.print(); |
duke@435 | 2004 | } |
duke@435 | 2005 | |
duke@435 | 2006 | return JVMTI_ERROR_NONE; |
duke@435 | 2007 | } /* end SetBreakpoint */ |
duke@435 | 2008 | |
duke@435 | 2009 | |
duke@435 | 2010 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2011 | jvmtiError |
duke@435 | 2012 | JvmtiEnv::ClearBreakpoint(methodOop method_oop, jlocation location) { |
duke@435 | 2013 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2014 | |
duke@435 | 2015 | if (location < 0) { // simple invalid location check first |
duke@435 | 2016 | return JVMTI_ERROR_INVALID_LOCATION; |
duke@435 | 2017 | } |
duke@435 | 2018 | |
duke@435 | 2019 | // verify that the breakpoint is not past the end of the method |
duke@435 | 2020 | if (location >= (jlocation) method_oop->code_size()) { |
duke@435 | 2021 | return JVMTI_ERROR_INVALID_LOCATION; |
duke@435 | 2022 | } |
duke@435 | 2023 | |
duke@435 | 2024 | JvmtiBreakpoint bp(method_oop, location); |
duke@435 | 2025 | |
duke@435 | 2026 | JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); |
duke@435 | 2027 | if (jvmti_breakpoints.clear(bp) == JVMTI_ERROR_NOT_FOUND) |
duke@435 | 2028 | return JVMTI_ERROR_NOT_FOUND; |
duke@435 | 2029 | |
duke@435 | 2030 | if (TraceJVMTICalls) { |
duke@435 | 2031 | jvmti_breakpoints.print(); |
duke@435 | 2032 | } |
duke@435 | 2033 | |
duke@435 | 2034 | return JVMTI_ERROR_NONE; |
duke@435 | 2035 | } /* end ClearBreakpoint */ |
duke@435 | 2036 | |
duke@435 | 2037 | |
duke@435 | 2038 | // |
duke@435 | 2039 | // Watched Field functions |
duke@435 | 2040 | // |
duke@435 | 2041 | |
duke@435 | 2042 | jvmtiError |
duke@435 | 2043 | JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) { |
duke@435 | 2044 | // make sure we haven't set this watch before |
duke@435 | 2045 | if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; |
duke@435 | 2046 | fdesc_ptr->set_is_field_access_watched(true); |
duke@435 | 2047 | update_klass_field_access_flag(fdesc_ptr); |
duke@435 | 2048 | |
duke@435 | 2049 | JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true); |
duke@435 | 2050 | |
duke@435 | 2051 | return JVMTI_ERROR_NONE; |
duke@435 | 2052 | } /* end SetFieldAccessWatch */ |
duke@435 | 2053 | |
duke@435 | 2054 | |
duke@435 | 2055 | jvmtiError |
duke@435 | 2056 | JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) { |
duke@435 | 2057 | // make sure we have a watch to clear |
duke@435 | 2058 | if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; |
duke@435 | 2059 | fdesc_ptr->set_is_field_access_watched(false); |
duke@435 | 2060 | update_klass_field_access_flag(fdesc_ptr); |
duke@435 | 2061 | |
duke@435 | 2062 | JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false); |
duke@435 | 2063 | |
duke@435 | 2064 | return JVMTI_ERROR_NONE; |
duke@435 | 2065 | } /* end ClearFieldAccessWatch */ |
duke@435 | 2066 | |
duke@435 | 2067 | |
duke@435 | 2068 | jvmtiError |
duke@435 | 2069 | JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) { |
duke@435 | 2070 | // make sure we haven't set this watch before |
duke@435 | 2071 | if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; |
duke@435 | 2072 | fdesc_ptr->set_is_field_modification_watched(true); |
duke@435 | 2073 | update_klass_field_access_flag(fdesc_ptr); |
duke@435 | 2074 | |
duke@435 | 2075 | JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true); |
duke@435 | 2076 | |
duke@435 | 2077 | return JVMTI_ERROR_NONE; |
duke@435 | 2078 | } /* end SetFieldModificationWatch */ |
duke@435 | 2079 | |
duke@435 | 2080 | |
duke@435 | 2081 | jvmtiError |
duke@435 | 2082 | JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) { |
duke@435 | 2083 | // make sure we have a watch to clear |
duke@435 | 2084 | if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; |
duke@435 | 2085 | fdesc_ptr->set_is_field_modification_watched(false); |
duke@435 | 2086 | update_klass_field_access_flag(fdesc_ptr); |
duke@435 | 2087 | |
duke@435 | 2088 | JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false); |
duke@435 | 2089 | |
duke@435 | 2090 | return JVMTI_ERROR_NONE; |
duke@435 | 2091 | } /* end ClearFieldModificationWatch */ |
duke@435 | 2092 | |
duke@435 | 2093 | // |
duke@435 | 2094 | // Class functions |
duke@435 | 2095 | // |
duke@435 | 2096 | |
duke@435 | 2097 | |
duke@435 | 2098 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2099 | // signature_ptr - NULL is a valid value, must be checked |
duke@435 | 2100 | // generic_ptr - NULL is a valid value, must be checked |
duke@435 | 2101 | jvmtiError |
duke@435 | 2102 | JvmtiEnv::GetClassSignature(oop k_mirror, char** signature_ptr, char** generic_ptr) { |
duke@435 | 2103 | ResourceMark rm; |
duke@435 | 2104 | bool isPrimitive = java_lang_Class::is_primitive(k_mirror); |
duke@435 | 2105 | klassOop k = NULL; |
duke@435 | 2106 | if (!isPrimitive) { |
duke@435 | 2107 | k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2108 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2109 | } |
duke@435 | 2110 | if (signature_ptr != NULL) { |
duke@435 | 2111 | char* result = NULL; |
duke@435 | 2112 | if (isPrimitive) { |
duke@435 | 2113 | char tchar = type2char(java_lang_Class::primitive_type(k_mirror)); |
duke@435 | 2114 | result = (char*) jvmtiMalloc(2); |
duke@435 | 2115 | result[0] = tchar; |
duke@435 | 2116 | result[1] = '\0'; |
duke@435 | 2117 | } else { |
duke@435 | 2118 | const char* class_sig = Klass::cast(k)->signature_name(); |
duke@435 | 2119 | result = (char *) jvmtiMalloc(strlen(class_sig)+1); |
duke@435 | 2120 | strcpy(result, class_sig); |
duke@435 | 2121 | } |
duke@435 | 2122 | *signature_ptr = result; |
duke@435 | 2123 | } |
duke@435 | 2124 | if (generic_ptr != NULL) { |
duke@435 | 2125 | *generic_ptr = NULL; |
duke@435 | 2126 | if (!isPrimitive && Klass::cast(k)->oop_is_instance()) { |
duke@435 | 2127 | symbolOop soo = instanceKlass::cast(k)->generic_signature(); |
duke@435 | 2128 | if (soo != NULL) { |
duke@435 | 2129 | const char *gen_sig = soo->as_C_string(); |
duke@435 | 2130 | if (gen_sig != NULL) { |
duke@435 | 2131 | char* gen_result; |
duke@435 | 2132 | jvmtiError err = allocate(strlen(gen_sig) + 1, |
duke@435 | 2133 | (unsigned char **)&gen_result); |
duke@435 | 2134 | if (err != JVMTI_ERROR_NONE) { |
duke@435 | 2135 | return err; |
duke@435 | 2136 | } |
duke@435 | 2137 | strcpy(gen_result, gen_sig); |
duke@435 | 2138 | *generic_ptr = gen_result; |
duke@435 | 2139 | } |
duke@435 | 2140 | } |
duke@435 | 2141 | } |
duke@435 | 2142 | } |
duke@435 | 2143 | return JVMTI_ERROR_NONE; |
duke@435 | 2144 | } /* end GetClassSignature */ |
duke@435 | 2145 | |
duke@435 | 2146 | |
duke@435 | 2147 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2148 | // status_ptr - pre-checked for NULL |
duke@435 | 2149 | jvmtiError |
duke@435 | 2150 | JvmtiEnv::GetClassStatus(oop k_mirror, jint* status_ptr) { |
duke@435 | 2151 | jint result = 0; |
duke@435 | 2152 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2153 | result |= JVMTI_CLASS_STATUS_PRIMITIVE; |
duke@435 | 2154 | } else { |
duke@435 | 2155 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2156 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2157 | result = Klass::cast(k)->jvmti_class_status(); |
duke@435 | 2158 | } |
duke@435 | 2159 | *status_ptr = result; |
duke@435 | 2160 | |
duke@435 | 2161 | return JVMTI_ERROR_NONE; |
duke@435 | 2162 | } /* end GetClassStatus */ |
duke@435 | 2163 | |
duke@435 | 2164 | |
duke@435 | 2165 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2166 | // source_name_ptr - pre-checked for NULL |
duke@435 | 2167 | jvmtiError |
duke@435 | 2168 | JvmtiEnv::GetSourceFileName(oop k_mirror, char** source_name_ptr) { |
duke@435 | 2169 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2170 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2171 | } |
duke@435 | 2172 | klassOop k_klass = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2173 | NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2174 | |
duke@435 | 2175 | if (!Klass::cast(k_klass)->oop_is_instance()) { |
duke@435 | 2176 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2177 | } |
duke@435 | 2178 | |
duke@435 | 2179 | symbolOop sfnOop = instanceKlass::cast(k_klass)->source_file_name(); |
duke@435 | 2180 | NULL_CHECK(sfnOop, JVMTI_ERROR_ABSENT_INFORMATION); |
duke@435 | 2181 | { |
duke@435 | 2182 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2183 | ResourceMark rm(current_thread); |
duke@435 | 2184 | const char* sfncp = (const char*) sfnOop->as_C_string(); |
duke@435 | 2185 | *source_name_ptr = (char *) jvmtiMalloc(strlen(sfncp)+1); |
duke@435 | 2186 | strcpy(*source_name_ptr, sfncp); |
duke@435 | 2187 | } |
duke@435 | 2188 | |
duke@435 | 2189 | return JVMTI_ERROR_NONE; |
duke@435 | 2190 | } /* end GetSourceFileName */ |
duke@435 | 2191 | |
duke@435 | 2192 | |
duke@435 | 2193 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2194 | // modifiers_ptr - pre-checked for NULL |
duke@435 | 2195 | jvmtiError |
duke@435 | 2196 | JvmtiEnv::GetClassModifiers(oop k_mirror, jint* modifiers_ptr) { |
duke@435 | 2197 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2198 | jint result = 0; |
duke@435 | 2199 | if (!java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2200 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2201 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2202 | assert((Klass::cast(k)->oop_is_instance() || Klass::cast(k)->oop_is_array()), "should be an instance or an array klass"); |
duke@435 | 2203 | result = Klass::cast(k)->compute_modifier_flags(current_thread); |
duke@435 | 2204 | JavaThread* THREAD = current_thread; // pass to macros |
duke@435 | 2205 | if (HAS_PENDING_EXCEPTION) { |
duke@435 | 2206 | CLEAR_PENDING_EXCEPTION; |
duke@435 | 2207 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 2208 | }; |
duke@435 | 2209 | |
duke@435 | 2210 | // Reset the deleted ACC_SUPER bit ( deleted in compute_modifier_flags()). |
duke@435 | 2211 | if(Klass::cast(k)->is_super()) { |
duke@435 | 2212 | result |= JVM_ACC_SUPER; |
duke@435 | 2213 | } |
duke@435 | 2214 | } else { |
duke@435 | 2215 | result = (JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); |
duke@435 | 2216 | } |
duke@435 | 2217 | *modifiers_ptr = result; |
duke@435 | 2218 | |
duke@435 | 2219 | return JVMTI_ERROR_NONE; |
duke@435 | 2220 | } /* end GetClassModifiers */ |
duke@435 | 2221 | |
duke@435 | 2222 | |
duke@435 | 2223 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2224 | // method_count_ptr - pre-checked for NULL |
duke@435 | 2225 | // methods_ptr - pre-checked for NULL |
duke@435 | 2226 | jvmtiError |
duke@435 | 2227 | JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** methods_ptr) { |
duke@435 | 2228 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2229 | HandleMark hm(current_thread); |
duke@435 | 2230 | |
duke@435 | 2231 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2232 | *method_count_ptr = 0; |
duke@435 | 2233 | *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); |
duke@435 | 2234 | return JVMTI_ERROR_NONE; |
duke@435 | 2235 | } |
duke@435 | 2236 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2237 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2238 | |
duke@435 | 2239 | // Return CLASS_NOT_PREPARED error as per JVMTI spec. |
duke@435 | 2240 | if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { |
duke@435 | 2241 | return JVMTI_ERROR_CLASS_NOT_PREPARED; |
duke@435 | 2242 | } |
duke@435 | 2243 | |
duke@435 | 2244 | if (!Klass::cast(k)->oop_is_instance()) { |
duke@435 | 2245 | *method_count_ptr = 0; |
duke@435 | 2246 | *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); |
duke@435 | 2247 | return JVMTI_ERROR_NONE; |
duke@435 | 2248 | } |
duke@435 | 2249 | instanceKlassHandle instanceK_h(current_thread, k); |
duke@435 | 2250 | // Allocate the result and fill it in |
duke@435 | 2251 | int result_length = instanceK_h->methods()->length(); |
duke@435 | 2252 | jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID)); |
duke@435 | 2253 | int index; |
duke@435 | 2254 | if (JvmtiExport::can_maintain_original_method_order()) { |
duke@435 | 2255 | // Use the original method ordering indices stored in the class, so we can emit |
duke@435 | 2256 | // jmethodIDs in the order they appeared in the class file |
duke@435 | 2257 | for (index = 0; index < result_length; index++) { |
duke@435 | 2258 | methodOop m = methodOop(instanceK_h->methods()->obj_at(index)); |
duke@435 | 2259 | int original_index = instanceK_h->method_ordering()->int_at(index); |
duke@435 | 2260 | assert(original_index >= 0 && original_index < result_length, "invalid original method index"); |
duke@435 | 2261 | jmethodID id = m->jmethod_id(); |
duke@435 | 2262 | result_list[original_index] = id; |
duke@435 | 2263 | } |
duke@435 | 2264 | } else { |
duke@435 | 2265 | // otherwise just copy in any order |
duke@435 | 2266 | for (index = 0; index < result_length; index++) { |
duke@435 | 2267 | methodOop m = methodOop(instanceK_h->methods()->obj_at(index)); |
duke@435 | 2268 | jmethodID id = m->jmethod_id(); |
duke@435 | 2269 | result_list[index] = id; |
duke@435 | 2270 | } |
duke@435 | 2271 | } |
duke@435 | 2272 | // Fill in return value. |
duke@435 | 2273 | *method_count_ptr = result_length; |
duke@435 | 2274 | *methods_ptr = result_list; |
duke@435 | 2275 | |
duke@435 | 2276 | return JVMTI_ERROR_NONE; |
duke@435 | 2277 | } /* end GetClassMethods */ |
duke@435 | 2278 | |
duke@435 | 2279 | |
duke@435 | 2280 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2281 | // field_count_ptr - pre-checked for NULL |
duke@435 | 2282 | // fields_ptr - pre-checked for NULL |
duke@435 | 2283 | jvmtiError |
duke@435 | 2284 | JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ptr) { |
duke@435 | 2285 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2286 | *field_count_ptr = 0; |
duke@435 | 2287 | *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); |
duke@435 | 2288 | return JVMTI_ERROR_NONE; |
duke@435 | 2289 | } |
duke@435 | 2290 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2291 | HandleMark hm(current_thread); |
duke@435 | 2292 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2293 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2294 | |
duke@435 | 2295 | // Return CLASS_NOT_PREPARED error as per JVMTI spec. |
duke@435 | 2296 | if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { |
duke@435 | 2297 | return JVMTI_ERROR_CLASS_NOT_PREPARED; |
duke@435 | 2298 | } |
duke@435 | 2299 | |
duke@435 | 2300 | if (!Klass::cast(k)->oop_is_instance()) { |
duke@435 | 2301 | *field_count_ptr = 0; |
duke@435 | 2302 | *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); |
duke@435 | 2303 | return JVMTI_ERROR_NONE; |
duke@435 | 2304 | } |
duke@435 | 2305 | |
duke@435 | 2306 | |
duke@435 | 2307 | instanceKlassHandle instanceK_h(current_thread, k); |
duke@435 | 2308 | |
duke@435 | 2309 | int result_count = 0; |
duke@435 | 2310 | // First, count the fields. |
duke@435 | 2311 | FilteredFieldStream flds(instanceK_h, true, true); |
duke@435 | 2312 | result_count = flds.field_count(); |
duke@435 | 2313 | |
duke@435 | 2314 | // Allocate the result and fill it in |
duke@435 | 2315 | jfieldID* result_list = (jfieldID*) jvmtiMalloc(result_count * sizeof(jfieldID)); |
duke@435 | 2316 | // The JVMTI spec requires fields in the order they occur in the class file, |
duke@435 | 2317 | // this is the reverse order of what FieldStream hands out. |
duke@435 | 2318 | int id_index = (result_count - 1); |
duke@435 | 2319 | |
duke@435 | 2320 | for (FilteredFieldStream src_st(instanceK_h, true, true); !src_st.eos(); src_st.next()) { |
duke@435 | 2321 | result_list[id_index--] = jfieldIDWorkaround::to_jfieldID( |
duke@435 | 2322 | instanceK_h, src_st.offset(), |
duke@435 | 2323 | src_st.access_flags().is_static()); |
duke@435 | 2324 | } |
duke@435 | 2325 | assert(id_index == -1, "just checking"); |
duke@435 | 2326 | // Fill in the results |
duke@435 | 2327 | *field_count_ptr = result_count; |
duke@435 | 2328 | *fields_ptr = result_list; |
duke@435 | 2329 | |
duke@435 | 2330 | return JVMTI_ERROR_NONE; |
duke@435 | 2331 | } /* end GetClassFields */ |
duke@435 | 2332 | |
duke@435 | 2333 | |
duke@435 | 2334 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2335 | // interface_count_ptr - pre-checked for NULL |
duke@435 | 2336 | // interfaces_ptr - pre-checked for NULL |
duke@435 | 2337 | jvmtiError |
duke@435 | 2338 | JvmtiEnv::GetImplementedInterfaces(oop k_mirror, jint* interface_count_ptr, jclass** interfaces_ptr) { |
duke@435 | 2339 | { |
duke@435 | 2340 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2341 | *interface_count_ptr = 0; |
duke@435 | 2342 | *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); |
duke@435 | 2343 | return JVMTI_ERROR_NONE; |
duke@435 | 2344 | } |
duke@435 | 2345 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2346 | HandleMark hm(current_thread); |
duke@435 | 2347 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2348 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2349 | |
duke@435 | 2350 | // Return CLASS_NOT_PREPARED error as per JVMTI spec. |
duke@435 | 2351 | if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) |
duke@435 | 2352 | return JVMTI_ERROR_CLASS_NOT_PREPARED; |
duke@435 | 2353 | |
duke@435 | 2354 | if (!Klass::cast(k)->oop_is_instance()) { |
duke@435 | 2355 | *interface_count_ptr = 0; |
duke@435 | 2356 | *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); |
duke@435 | 2357 | return JVMTI_ERROR_NONE; |
duke@435 | 2358 | } |
duke@435 | 2359 | |
duke@435 | 2360 | objArrayHandle interface_list(current_thread, instanceKlass::cast(k)->local_interfaces()); |
duke@435 | 2361 | const int result_length = (interface_list.is_null() ? 0 : interface_list->length()); |
duke@435 | 2362 | jclass* result_list = (jclass*) jvmtiMalloc(result_length * sizeof(jclass)); |
duke@435 | 2363 | for (int i_index = 0; i_index < result_length; i_index += 1) { |
duke@435 | 2364 | oop oop_at = interface_list->obj_at(i_index); |
duke@435 | 2365 | assert(oop_at->is_klass(), "interfaces must be klassOops"); |
duke@435 | 2366 | klassOop klassOop_at = klassOop(oop_at); // ???: is there a better way? |
duke@435 | 2367 | assert(Klass::cast(klassOop_at)->is_interface(), "interfaces must be interfaces"); |
duke@435 | 2368 | oop mirror_at = Klass::cast(klassOop_at)->java_mirror(); |
duke@435 | 2369 | Handle handle_at = Handle(current_thread, mirror_at); |
duke@435 | 2370 | result_list[i_index] = (jclass) jni_reference(handle_at); |
duke@435 | 2371 | } |
duke@435 | 2372 | *interface_count_ptr = result_length; |
duke@435 | 2373 | *interfaces_ptr = result_list; |
duke@435 | 2374 | } |
duke@435 | 2375 | |
duke@435 | 2376 | return JVMTI_ERROR_NONE; |
duke@435 | 2377 | } /* end GetImplementedInterfaces */ |
duke@435 | 2378 | |
duke@435 | 2379 | |
duke@435 | 2380 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2381 | // minor_version_ptr - pre-checked for NULL |
duke@435 | 2382 | // major_version_ptr - pre-checked for NULL |
duke@435 | 2383 | jvmtiError |
duke@435 | 2384 | JvmtiEnv::GetClassVersionNumbers(oop k_mirror, jint* minor_version_ptr, jint* major_version_ptr) { |
duke@435 | 2385 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2386 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2387 | } |
duke@435 | 2388 | klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2389 | Thread *thread = Thread::current(); |
duke@435 | 2390 | HandleMark hm(thread); |
duke@435 | 2391 | KlassHandle klass(thread, k_oop); |
duke@435 | 2392 | |
duke@435 | 2393 | jint status = klass->jvmti_class_status(); |
duke@435 | 2394 | if (status & (JVMTI_CLASS_STATUS_ERROR)) { |
duke@435 | 2395 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 2396 | } |
duke@435 | 2397 | if (status & (JVMTI_CLASS_STATUS_ARRAY)) { |
duke@435 | 2398 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2399 | } |
duke@435 | 2400 | |
duke@435 | 2401 | instanceKlassHandle ik(thread, k_oop); |
duke@435 | 2402 | *minor_version_ptr = ik->minor_version(); |
duke@435 | 2403 | *major_version_ptr = ik->major_version(); |
duke@435 | 2404 | |
duke@435 | 2405 | return JVMTI_ERROR_NONE; |
duke@435 | 2406 | } /* end GetClassVersionNumbers */ |
duke@435 | 2407 | |
duke@435 | 2408 | |
duke@435 | 2409 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2410 | // constant_pool_count_ptr - pre-checked for NULL |
duke@435 | 2411 | // constant_pool_byte_count_ptr - pre-checked for NULL |
duke@435 | 2412 | // constant_pool_bytes_ptr - pre-checked for NULL |
duke@435 | 2413 | jvmtiError |
duke@435 | 2414 | JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* constant_pool_byte_count_ptr, unsigned char** constant_pool_bytes_ptr) { |
duke@435 | 2415 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2416 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2417 | } |
duke@435 | 2418 | |
duke@435 | 2419 | klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2420 | Thread *thread = Thread::current(); |
duke@435 | 2421 | HandleMark hm(thread); |
duke@435 | 2422 | ResourceMark rm(thread); |
duke@435 | 2423 | KlassHandle klass(thread, k_oop); |
duke@435 | 2424 | |
duke@435 | 2425 | jint status = klass->jvmti_class_status(); |
duke@435 | 2426 | if (status & (JVMTI_CLASS_STATUS_ERROR)) { |
duke@435 | 2427 | return JVMTI_ERROR_INVALID_CLASS; |
duke@435 | 2428 | } |
duke@435 | 2429 | if (status & (JVMTI_CLASS_STATUS_ARRAY)) { |
duke@435 | 2430 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2431 | } |
duke@435 | 2432 | |
duke@435 | 2433 | instanceKlassHandle ikh(thread, k_oop); |
duke@435 | 2434 | constantPoolHandle constants(thread, ikh->constants()); |
duke@435 | 2435 | ObjectLocker ol(constants, thread); // lock constant pool while we query it |
duke@435 | 2436 | |
duke@435 | 2437 | JvmtiConstantPoolReconstituter reconstituter(ikh); |
duke@435 | 2438 | if (reconstituter.get_error() != JVMTI_ERROR_NONE) { |
duke@435 | 2439 | return reconstituter.get_error(); |
duke@435 | 2440 | } |
duke@435 | 2441 | |
duke@435 | 2442 | unsigned char *cpool_bytes; |
duke@435 | 2443 | int cpool_size = reconstituter.cpool_size(); |
duke@435 | 2444 | if (reconstituter.get_error() != JVMTI_ERROR_NONE) { |
duke@435 | 2445 | return reconstituter.get_error(); |
duke@435 | 2446 | } |
duke@435 | 2447 | jvmtiError res = allocate(cpool_size, &cpool_bytes); |
duke@435 | 2448 | if (res != JVMTI_ERROR_NONE) { |
duke@435 | 2449 | return res; |
duke@435 | 2450 | } |
duke@435 | 2451 | reconstituter.copy_cpool_bytes(cpool_bytes); |
duke@435 | 2452 | if (reconstituter.get_error() != JVMTI_ERROR_NONE) { |
duke@435 | 2453 | return reconstituter.get_error(); |
duke@435 | 2454 | } |
duke@435 | 2455 | |
duke@435 | 2456 | *constant_pool_count_ptr = constants->length(); |
duke@435 | 2457 | *constant_pool_byte_count_ptr = cpool_size; |
duke@435 | 2458 | *constant_pool_bytes_ptr = cpool_bytes; |
duke@435 | 2459 | |
duke@435 | 2460 | return JVMTI_ERROR_NONE; |
duke@435 | 2461 | } /* end GetConstantPool */ |
duke@435 | 2462 | |
duke@435 | 2463 | |
duke@435 | 2464 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2465 | // is_interface_ptr - pre-checked for NULL |
duke@435 | 2466 | jvmtiError |
duke@435 | 2467 | JvmtiEnv::IsInterface(oop k_mirror, jboolean* is_interface_ptr) { |
duke@435 | 2468 | { |
duke@435 | 2469 | bool result = false; |
duke@435 | 2470 | if (!java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2471 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2472 | if (k != NULL && Klass::cast(k)->is_interface()) { |
duke@435 | 2473 | result = true; |
duke@435 | 2474 | } |
duke@435 | 2475 | } |
duke@435 | 2476 | *is_interface_ptr = result; |
duke@435 | 2477 | } |
duke@435 | 2478 | |
duke@435 | 2479 | return JVMTI_ERROR_NONE; |
duke@435 | 2480 | } /* end IsInterface */ |
duke@435 | 2481 | |
duke@435 | 2482 | |
duke@435 | 2483 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2484 | // is_array_class_ptr - pre-checked for NULL |
duke@435 | 2485 | jvmtiError |
duke@435 | 2486 | JvmtiEnv::IsArrayClass(oop k_mirror, jboolean* is_array_class_ptr) { |
duke@435 | 2487 | { |
duke@435 | 2488 | bool result = false; |
duke@435 | 2489 | if (!java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2490 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2491 | if (k != NULL && Klass::cast(k)->oop_is_array()) { |
duke@435 | 2492 | result = true; |
duke@435 | 2493 | } |
duke@435 | 2494 | } |
duke@435 | 2495 | *is_array_class_ptr = result; |
duke@435 | 2496 | } |
duke@435 | 2497 | |
duke@435 | 2498 | return JVMTI_ERROR_NONE; |
duke@435 | 2499 | } /* end IsArrayClass */ |
duke@435 | 2500 | |
duke@435 | 2501 | |
duke@435 | 2502 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2503 | // classloader_ptr - pre-checked for NULL |
duke@435 | 2504 | jvmtiError |
duke@435 | 2505 | JvmtiEnv::GetClassLoader(oop k_mirror, jobject* classloader_ptr) { |
duke@435 | 2506 | { |
duke@435 | 2507 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2508 | *classloader_ptr = (jclass) jni_reference(Handle()); |
duke@435 | 2509 | return JVMTI_ERROR_NONE; |
duke@435 | 2510 | } |
duke@435 | 2511 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2512 | HandleMark hm(current_thread); |
duke@435 | 2513 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2514 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2515 | |
duke@435 | 2516 | oop result_oop = Klass::cast(k)->class_loader(); |
duke@435 | 2517 | if (result_oop == NULL) { |
duke@435 | 2518 | *classloader_ptr = (jclass) jni_reference(Handle()); |
duke@435 | 2519 | return JVMTI_ERROR_NONE; |
duke@435 | 2520 | } |
duke@435 | 2521 | Handle result_handle = Handle(current_thread, result_oop); |
duke@435 | 2522 | jclass result_jnihandle = (jclass) jni_reference(result_handle); |
duke@435 | 2523 | *classloader_ptr = result_jnihandle; |
duke@435 | 2524 | } |
duke@435 | 2525 | return JVMTI_ERROR_NONE; |
duke@435 | 2526 | } /* end GetClassLoader */ |
duke@435 | 2527 | |
duke@435 | 2528 | |
duke@435 | 2529 | // k_mirror - may be primitive, this must be checked |
duke@435 | 2530 | // source_debug_extension_ptr - pre-checked for NULL |
duke@435 | 2531 | jvmtiError |
duke@435 | 2532 | JvmtiEnv::GetSourceDebugExtension(oop k_mirror, char** source_debug_extension_ptr) { |
duke@435 | 2533 | { |
duke@435 | 2534 | if (java_lang_Class::is_primitive(k_mirror)) { |
duke@435 | 2535 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2536 | } |
duke@435 | 2537 | klassOop k = java_lang_Class::as_klassOop(k_mirror); |
duke@435 | 2538 | NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); |
duke@435 | 2539 | if (!Klass::cast(k)->oop_is_instance()) { |
duke@435 | 2540 | return JVMTI_ERROR_ABSENT_INFORMATION; |
duke@435 | 2541 | } |
duke@435 | 2542 | symbolOop sdeOop = instanceKlass::cast(k)->source_debug_extension(); |
duke@435 | 2543 | NULL_CHECK(sdeOop, JVMTI_ERROR_ABSENT_INFORMATION); |
duke@435 | 2544 | |
duke@435 | 2545 | { |
duke@435 | 2546 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2547 | ResourceMark rm(current_thread); |
duke@435 | 2548 | const char* sdecp = (const char*) sdeOop->as_C_string(); |
duke@435 | 2549 | *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sdecp)+1); |
duke@435 | 2550 | strcpy(*source_debug_extension_ptr, sdecp); |
duke@435 | 2551 | } |
duke@435 | 2552 | } |
duke@435 | 2553 | |
duke@435 | 2554 | return JVMTI_ERROR_NONE; |
duke@435 | 2555 | } /* end GetSourceDebugExtension */ |
duke@435 | 2556 | |
duke@435 | 2557 | // |
duke@435 | 2558 | // Object functions |
duke@435 | 2559 | // |
duke@435 | 2560 | |
duke@435 | 2561 | // hash_code_ptr - pre-checked for NULL |
duke@435 | 2562 | jvmtiError |
duke@435 | 2563 | JvmtiEnv::GetObjectHashCode(jobject object, jint* hash_code_ptr) { |
duke@435 | 2564 | oop mirror = JNIHandles::resolve_external_guard(object); |
duke@435 | 2565 | NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); |
duke@435 | 2566 | NULL_CHECK(hash_code_ptr, JVMTI_ERROR_NULL_POINTER); |
duke@435 | 2567 | |
duke@435 | 2568 | { |
duke@435 | 2569 | jint result = (jint) mirror->identity_hash(); |
duke@435 | 2570 | *hash_code_ptr = result; |
duke@435 | 2571 | } |
duke@435 | 2572 | return JVMTI_ERROR_NONE; |
duke@435 | 2573 | } /* end GetObjectHashCode */ |
duke@435 | 2574 | |
duke@435 | 2575 | |
duke@435 | 2576 | // info_ptr - pre-checked for NULL |
duke@435 | 2577 | jvmtiError |
duke@435 | 2578 | JvmtiEnv::GetObjectMonitorUsage(jobject object, jvmtiMonitorUsage* info_ptr) { |
duke@435 | 2579 | JavaThread* calling_thread = JavaThread::current(); |
duke@435 | 2580 | jvmtiError err = get_object_monitor_usage(calling_thread, object, info_ptr); |
duke@435 | 2581 | if (err == JVMTI_ERROR_THREAD_NOT_SUSPENDED) { |
duke@435 | 2582 | // Some of the critical threads were not suspended. go to a safepoint and try again |
duke@435 | 2583 | VM_GetObjectMonitorUsage op(this, calling_thread, object, info_ptr); |
duke@435 | 2584 | VMThread::execute(&op); |
duke@435 | 2585 | err = op.result(); |
duke@435 | 2586 | } |
duke@435 | 2587 | return err; |
duke@435 | 2588 | } /* end GetObjectMonitorUsage */ |
duke@435 | 2589 | |
duke@435 | 2590 | |
duke@435 | 2591 | // |
duke@435 | 2592 | // Field functions |
duke@435 | 2593 | // |
duke@435 | 2594 | |
duke@435 | 2595 | // name_ptr - NULL is a valid value, must be checked |
duke@435 | 2596 | // signature_ptr - NULL is a valid value, must be checked |
duke@435 | 2597 | // generic_ptr - NULL is a valid value, must be checked |
duke@435 | 2598 | jvmtiError |
duke@435 | 2599 | JvmtiEnv::GetFieldName(fieldDescriptor* fdesc_ptr, char** name_ptr, char** signature_ptr, char** generic_ptr) { |
duke@435 | 2600 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2601 | ResourceMark rm(current_thread); |
duke@435 | 2602 | if (name_ptr == NULL) { |
duke@435 | 2603 | // just don't return the name |
duke@435 | 2604 | } else { |
duke@435 | 2605 | const char* fieldName = fdesc_ptr->name()->as_C_string(); |
duke@435 | 2606 | *name_ptr = (char*) jvmtiMalloc(strlen(fieldName) + 1); |
duke@435 | 2607 | if (*name_ptr == NULL) |
duke@435 | 2608 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 2609 | strcpy(*name_ptr, fieldName); |
duke@435 | 2610 | } |
duke@435 | 2611 | if (signature_ptr== NULL) { |
duke@435 | 2612 | // just don't return the signature |
duke@435 | 2613 | } else { |
duke@435 | 2614 | const char* fieldSignature = fdesc_ptr->signature()->as_C_string(); |
duke@435 | 2615 | *signature_ptr = (char*) jvmtiMalloc(strlen(fieldSignature) + 1); |
duke@435 | 2616 | if (*signature_ptr == NULL) |
duke@435 | 2617 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 2618 | strcpy(*signature_ptr, fieldSignature); |
duke@435 | 2619 | } |
duke@435 | 2620 | if (generic_ptr != NULL) { |
duke@435 | 2621 | *generic_ptr = NULL; |
duke@435 | 2622 | symbolOop soop = fdesc_ptr->generic_signature(); |
duke@435 | 2623 | if (soop != NULL) { |
duke@435 | 2624 | const char* gen_sig = soop->as_C_string(); |
duke@435 | 2625 | if (gen_sig != NULL) { |
duke@435 | 2626 | jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr); |
duke@435 | 2627 | if (err != JVMTI_ERROR_NONE) { |
duke@435 | 2628 | return err; |
duke@435 | 2629 | } |
duke@435 | 2630 | strcpy(*generic_ptr, gen_sig); |
duke@435 | 2631 | } |
duke@435 | 2632 | } |
duke@435 | 2633 | } |
duke@435 | 2634 | return JVMTI_ERROR_NONE; |
duke@435 | 2635 | } /* end GetFieldName */ |
duke@435 | 2636 | |
duke@435 | 2637 | |
duke@435 | 2638 | // declaring_class_ptr - pre-checked for NULL |
duke@435 | 2639 | jvmtiError |
duke@435 | 2640 | JvmtiEnv::GetFieldDeclaringClass(fieldDescriptor* fdesc_ptr, jclass* declaring_class_ptr) { |
duke@435 | 2641 | |
duke@435 | 2642 | *declaring_class_ptr = get_jni_class_non_null(fdesc_ptr->field_holder()); |
duke@435 | 2643 | return JVMTI_ERROR_NONE; |
duke@435 | 2644 | } /* end GetFieldDeclaringClass */ |
duke@435 | 2645 | |
duke@435 | 2646 | |
duke@435 | 2647 | // modifiers_ptr - pre-checked for NULL |
duke@435 | 2648 | jvmtiError |
duke@435 | 2649 | JvmtiEnv::GetFieldModifiers(fieldDescriptor* fdesc_ptr, jint* modifiers_ptr) { |
duke@435 | 2650 | |
duke@435 | 2651 | AccessFlags resultFlags = fdesc_ptr->access_flags(); |
duke@435 | 2652 | jint result = resultFlags.as_int(); |
duke@435 | 2653 | *modifiers_ptr = result; |
duke@435 | 2654 | |
duke@435 | 2655 | return JVMTI_ERROR_NONE; |
duke@435 | 2656 | } /* end GetFieldModifiers */ |
duke@435 | 2657 | |
duke@435 | 2658 | |
duke@435 | 2659 | // is_synthetic_ptr - pre-checked for NULL |
duke@435 | 2660 | jvmtiError |
duke@435 | 2661 | JvmtiEnv::IsFieldSynthetic(fieldDescriptor* fdesc_ptr, jboolean* is_synthetic_ptr) { |
duke@435 | 2662 | *is_synthetic_ptr = fdesc_ptr->is_synthetic(); |
duke@435 | 2663 | return JVMTI_ERROR_NONE; |
duke@435 | 2664 | } /* end IsFieldSynthetic */ |
duke@435 | 2665 | |
duke@435 | 2666 | |
duke@435 | 2667 | // |
duke@435 | 2668 | // Method functions |
duke@435 | 2669 | // |
duke@435 | 2670 | |
duke@435 | 2671 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2672 | // name_ptr - NULL is a valid value, must be checked |
duke@435 | 2673 | // signature_ptr - NULL is a valid value, must be checked |
duke@435 | 2674 | // generic_ptr - NULL is a valid value, must be checked |
duke@435 | 2675 | jvmtiError |
duke@435 | 2676 | JvmtiEnv::GetMethodName(methodOop method_oop, char** name_ptr, char** signature_ptr, char** generic_ptr) { |
duke@435 | 2677 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2678 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2679 | |
duke@435 | 2680 | ResourceMark rm(current_thread); // get the utf8 name and signature |
duke@435 | 2681 | if (name_ptr == NULL) { |
duke@435 | 2682 | // just don't return the name |
duke@435 | 2683 | } else { |
duke@435 | 2684 | const char* utf8_name = (const char *) method_oop->name()->as_utf8(); |
duke@435 | 2685 | *name_ptr = (char *) jvmtiMalloc(strlen(utf8_name)+1); |
duke@435 | 2686 | strcpy(*name_ptr, utf8_name); |
duke@435 | 2687 | } |
duke@435 | 2688 | if (signature_ptr == NULL) { |
duke@435 | 2689 | // just don't return the signature |
duke@435 | 2690 | } else { |
duke@435 | 2691 | const char* utf8_signature = (const char *) method_oop->signature()->as_utf8(); |
duke@435 | 2692 | *signature_ptr = (char *) jvmtiMalloc(strlen(utf8_signature) + 1); |
duke@435 | 2693 | strcpy(*signature_ptr, utf8_signature); |
duke@435 | 2694 | } |
duke@435 | 2695 | |
duke@435 | 2696 | if (generic_ptr != NULL) { |
duke@435 | 2697 | *generic_ptr = NULL; |
duke@435 | 2698 | symbolOop soop = method_oop->generic_signature(); |
duke@435 | 2699 | if (soop != NULL) { |
duke@435 | 2700 | const char* gen_sig = soop->as_C_string(); |
duke@435 | 2701 | if (gen_sig != NULL) { |
duke@435 | 2702 | jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr); |
duke@435 | 2703 | if (err != JVMTI_ERROR_NONE) { |
duke@435 | 2704 | return err; |
duke@435 | 2705 | } |
duke@435 | 2706 | strcpy(*generic_ptr, gen_sig); |
duke@435 | 2707 | } |
duke@435 | 2708 | } |
duke@435 | 2709 | } |
duke@435 | 2710 | return JVMTI_ERROR_NONE; |
duke@435 | 2711 | } /* end GetMethodName */ |
duke@435 | 2712 | |
duke@435 | 2713 | |
duke@435 | 2714 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2715 | // declaring_class_ptr - pre-checked for NULL |
duke@435 | 2716 | jvmtiError |
duke@435 | 2717 | JvmtiEnv::GetMethodDeclaringClass(methodOop method_oop, jclass* declaring_class_ptr) { |
duke@435 | 2718 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2719 | (*declaring_class_ptr) = get_jni_class_non_null(method_oop->method_holder()); |
duke@435 | 2720 | return JVMTI_ERROR_NONE; |
duke@435 | 2721 | } /* end GetMethodDeclaringClass */ |
duke@435 | 2722 | |
duke@435 | 2723 | |
duke@435 | 2724 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2725 | // modifiers_ptr - pre-checked for NULL |
duke@435 | 2726 | jvmtiError |
duke@435 | 2727 | JvmtiEnv::GetMethodModifiers(methodOop method_oop, jint* modifiers_ptr) { |
duke@435 | 2728 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2729 | (*modifiers_ptr) = method_oop->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; |
duke@435 | 2730 | return JVMTI_ERROR_NONE; |
duke@435 | 2731 | } /* end GetMethodModifiers */ |
duke@435 | 2732 | |
duke@435 | 2733 | |
duke@435 | 2734 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2735 | // max_ptr - pre-checked for NULL |
duke@435 | 2736 | jvmtiError |
duke@435 | 2737 | JvmtiEnv::GetMaxLocals(methodOop method_oop, jint* max_ptr) { |
duke@435 | 2738 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2739 | // get max stack |
duke@435 | 2740 | (*max_ptr) = method_oop->max_locals(); |
duke@435 | 2741 | return JVMTI_ERROR_NONE; |
duke@435 | 2742 | } /* end GetMaxLocals */ |
duke@435 | 2743 | |
duke@435 | 2744 | |
duke@435 | 2745 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2746 | // size_ptr - pre-checked for NULL |
duke@435 | 2747 | jvmtiError |
duke@435 | 2748 | JvmtiEnv::GetArgumentsSize(methodOop method_oop, jint* size_ptr) { |
duke@435 | 2749 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2750 | // get size of arguments |
duke@435 | 2751 | |
duke@435 | 2752 | (*size_ptr) = method_oop->size_of_parameters(); |
duke@435 | 2753 | return JVMTI_ERROR_NONE; |
duke@435 | 2754 | } /* end GetArgumentsSize */ |
duke@435 | 2755 | |
duke@435 | 2756 | |
duke@435 | 2757 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2758 | // entry_count_ptr - pre-checked for NULL |
duke@435 | 2759 | // table_ptr - pre-checked for NULL |
duke@435 | 2760 | jvmtiError |
duke@435 | 2761 | JvmtiEnv::GetLineNumberTable(methodOop method_oop, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) { |
duke@435 | 2762 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2763 | if (!method_oop->has_linenumber_table()) { |
duke@435 | 2764 | return (JVMTI_ERROR_ABSENT_INFORMATION); |
duke@435 | 2765 | } |
duke@435 | 2766 | |
duke@435 | 2767 | // The line number table is compressed so we don't know how big it is until decompressed. |
duke@435 | 2768 | // Decompression is really fast so we just do it twice. |
duke@435 | 2769 | |
duke@435 | 2770 | // Compute size of table |
duke@435 | 2771 | jint num_entries = 0; |
duke@435 | 2772 | CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table()); |
duke@435 | 2773 | while (stream.read_pair()) { |
duke@435 | 2774 | num_entries++; |
duke@435 | 2775 | } |
duke@435 | 2776 | jvmtiLineNumberEntry *jvmti_table = |
duke@435 | 2777 | (jvmtiLineNumberEntry *)jvmtiMalloc(num_entries * (sizeof(jvmtiLineNumberEntry))); |
duke@435 | 2778 | |
duke@435 | 2779 | // Fill jvmti table |
duke@435 | 2780 | if (num_entries > 0) { |
duke@435 | 2781 | int index = 0; |
duke@435 | 2782 | CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table()); |
duke@435 | 2783 | while (stream.read_pair()) { |
duke@435 | 2784 | jvmti_table[index].start_location = (jlocation) stream.bci(); |
duke@435 | 2785 | jvmti_table[index].line_number = (jint) stream.line(); |
duke@435 | 2786 | index++; |
duke@435 | 2787 | } |
duke@435 | 2788 | assert(index == num_entries, "sanity check"); |
duke@435 | 2789 | } |
duke@435 | 2790 | |
duke@435 | 2791 | // Set up results |
duke@435 | 2792 | (*entry_count_ptr) = num_entries; |
duke@435 | 2793 | (*table_ptr) = jvmti_table; |
duke@435 | 2794 | |
duke@435 | 2795 | return JVMTI_ERROR_NONE; |
duke@435 | 2796 | } /* end GetLineNumberTable */ |
duke@435 | 2797 | |
duke@435 | 2798 | |
duke@435 | 2799 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2800 | // start_location_ptr - pre-checked for NULL |
duke@435 | 2801 | // end_location_ptr - pre-checked for NULL |
duke@435 | 2802 | jvmtiError |
duke@435 | 2803 | JvmtiEnv::GetMethodLocation(methodOop method_oop, jlocation* start_location_ptr, jlocation* end_location_ptr) { |
duke@435 | 2804 | |
duke@435 | 2805 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2806 | // get start and end location |
duke@435 | 2807 | (*end_location_ptr) = (jlocation) (method_oop->code_size() - 1); |
duke@435 | 2808 | if (method_oop->code_size() == 0) { |
duke@435 | 2809 | // there is no code so there is no start location |
duke@435 | 2810 | (*start_location_ptr) = (jlocation)(-1); |
duke@435 | 2811 | } else { |
duke@435 | 2812 | (*start_location_ptr) = (jlocation)(0); |
duke@435 | 2813 | } |
duke@435 | 2814 | |
duke@435 | 2815 | return JVMTI_ERROR_NONE; |
duke@435 | 2816 | } /* end GetMethodLocation */ |
duke@435 | 2817 | |
duke@435 | 2818 | |
duke@435 | 2819 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2820 | // entry_count_ptr - pre-checked for NULL |
duke@435 | 2821 | // table_ptr - pre-checked for NULL |
duke@435 | 2822 | jvmtiError |
duke@435 | 2823 | JvmtiEnv::GetLocalVariableTable(methodOop method_oop, jint* entry_count_ptr, jvmtiLocalVariableEntry** table_ptr) { |
duke@435 | 2824 | |
duke@435 | 2825 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2826 | JavaThread* current_thread = JavaThread::current(); |
duke@435 | 2827 | |
duke@435 | 2828 | // does the klass have any local variable information? |
duke@435 | 2829 | instanceKlass* ik = instanceKlass::cast(method_oop->method_holder()); |
duke@435 | 2830 | if (!ik->access_flags().has_localvariable_table()) { |
duke@435 | 2831 | return (JVMTI_ERROR_ABSENT_INFORMATION); |
duke@435 | 2832 | } |
duke@435 | 2833 | |
duke@435 | 2834 | constantPoolOop constants = method_oop->constants(); |
duke@435 | 2835 | NULL_CHECK(constants, JVMTI_ERROR_ABSENT_INFORMATION); |
duke@435 | 2836 | |
duke@435 | 2837 | // in the vm localvariable table representation, 6 consecutive elements in the table |
duke@435 | 2838 | // represent a 6-tuple of shorts |
duke@435 | 2839 | // [start_pc, length, name_index, descriptor_index, signature_index, index] |
duke@435 | 2840 | jint num_entries = method_oop->localvariable_table_length(); |
duke@435 | 2841 | jvmtiLocalVariableEntry *jvmti_table = (jvmtiLocalVariableEntry *) |
duke@435 | 2842 | jvmtiMalloc(num_entries * (sizeof(jvmtiLocalVariableEntry))); |
duke@435 | 2843 | |
duke@435 | 2844 | if (num_entries > 0) { |
duke@435 | 2845 | LocalVariableTableElement* table = method_oop->localvariable_table_start(); |
duke@435 | 2846 | for (int i = 0; i < num_entries; i++) { |
duke@435 | 2847 | // get the 5 tuple information from the vm table |
duke@435 | 2848 | jlocation start_location = (jlocation) table[i].start_bci; |
duke@435 | 2849 | jint length = (jint) table[i].length; |
duke@435 | 2850 | int name_index = (int) table[i].name_cp_index; |
duke@435 | 2851 | int signature_index = (int) table[i].descriptor_cp_index; |
duke@435 | 2852 | int generic_signature_index = (int) table[i].signature_cp_index; |
duke@435 | 2853 | jint slot = (jint) table[i].slot; |
duke@435 | 2854 | |
duke@435 | 2855 | // get utf8 name and signature |
duke@435 | 2856 | char *name_buf = NULL; |
duke@435 | 2857 | char *sig_buf = NULL; |
duke@435 | 2858 | char *gen_sig_buf = NULL; |
duke@435 | 2859 | { |
duke@435 | 2860 | ResourceMark rm(current_thread); |
duke@435 | 2861 | |
duke@435 | 2862 | const char *utf8_name = (const char *) constants->symbol_at(name_index)->as_utf8(); |
duke@435 | 2863 | name_buf = (char *) jvmtiMalloc(strlen(utf8_name)+1); |
duke@435 | 2864 | strcpy(name_buf, utf8_name); |
duke@435 | 2865 | |
duke@435 | 2866 | const char *utf8_signature = (const char *) constants->symbol_at(signature_index)->as_utf8(); |
duke@435 | 2867 | sig_buf = (char *) jvmtiMalloc(strlen(utf8_signature)+1); |
duke@435 | 2868 | strcpy(sig_buf, utf8_signature); |
duke@435 | 2869 | |
duke@435 | 2870 | if (generic_signature_index > 0) { |
duke@435 | 2871 | const char *utf8_gen_sign = (const char *) |
duke@435 | 2872 | constants->symbol_at(generic_signature_index)->as_utf8(); |
duke@435 | 2873 | gen_sig_buf = (char *) jvmtiMalloc(strlen(utf8_gen_sign)+1); |
duke@435 | 2874 | strcpy(gen_sig_buf, utf8_gen_sign); |
duke@435 | 2875 | } |
duke@435 | 2876 | } |
duke@435 | 2877 | |
duke@435 | 2878 | // fill in the jvmti local variable table |
duke@435 | 2879 | jvmti_table[i].start_location = start_location; |
duke@435 | 2880 | jvmti_table[i].length = length; |
duke@435 | 2881 | jvmti_table[i].name = name_buf; |
duke@435 | 2882 | jvmti_table[i].signature = sig_buf; |
duke@435 | 2883 | jvmti_table[i].generic_signature = gen_sig_buf; |
duke@435 | 2884 | jvmti_table[i].slot = slot; |
duke@435 | 2885 | } |
duke@435 | 2886 | } |
duke@435 | 2887 | |
duke@435 | 2888 | // set results |
duke@435 | 2889 | (*entry_count_ptr) = num_entries; |
duke@435 | 2890 | (*table_ptr) = jvmti_table; |
duke@435 | 2891 | |
duke@435 | 2892 | return JVMTI_ERROR_NONE; |
duke@435 | 2893 | } /* end GetLocalVariableTable */ |
duke@435 | 2894 | |
duke@435 | 2895 | |
duke@435 | 2896 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2897 | // bytecode_count_ptr - pre-checked for NULL |
duke@435 | 2898 | // bytecodes_ptr - pre-checked for NULL |
duke@435 | 2899 | jvmtiError |
duke@435 | 2900 | JvmtiEnv::GetBytecodes(methodOop method_oop, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) { |
duke@435 | 2901 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2902 | |
duke@435 | 2903 | HandleMark hm; |
duke@435 | 2904 | methodHandle method(method_oop); |
duke@435 | 2905 | jint size = (jint)method->code_size(); |
duke@435 | 2906 | jvmtiError err = allocate(size, bytecodes_ptr); |
duke@435 | 2907 | if (err != JVMTI_ERROR_NONE) { |
duke@435 | 2908 | return err; |
duke@435 | 2909 | } |
duke@435 | 2910 | |
duke@435 | 2911 | (*bytecode_count_ptr) = size; |
duke@435 | 2912 | // get byte codes |
duke@435 | 2913 | JvmtiClassFileReconstituter::copy_bytecodes(method, *bytecodes_ptr); |
duke@435 | 2914 | |
duke@435 | 2915 | return JVMTI_ERROR_NONE; |
duke@435 | 2916 | } /* end GetBytecodes */ |
duke@435 | 2917 | |
duke@435 | 2918 | |
duke@435 | 2919 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2920 | // is_native_ptr - pre-checked for NULL |
duke@435 | 2921 | jvmtiError |
duke@435 | 2922 | JvmtiEnv::IsMethodNative(methodOop method_oop, jboolean* is_native_ptr) { |
duke@435 | 2923 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2924 | (*is_native_ptr) = method_oop->is_native(); |
duke@435 | 2925 | return JVMTI_ERROR_NONE; |
duke@435 | 2926 | } /* end IsMethodNative */ |
duke@435 | 2927 | |
duke@435 | 2928 | |
duke@435 | 2929 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2930 | // is_synthetic_ptr - pre-checked for NULL |
duke@435 | 2931 | jvmtiError |
duke@435 | 2932 | JvmtiEnv::IsMethodSynthetic(methodOop method_oop, jboolean* is_synthetic_ptr) { |
duke@435 | 2933 | NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); |
duke@435 | 2934 | (*is_synthetic_ptr) = method_oop->is_synthetic(); |
duke@435 | 2935 | return JVMTI_ERROR_NONE; |
duke@435 | 2936 | } /* end IsMethodSynthetic */ |
duke@435 | 2937 | |
duke@435 | 2938 | |
duke@435 | 2939 | // method_oop - pre-checked for validity, but may be NULL meaning obsolete method |
duke@435 | 2940 | // is_obsolete_ptr - pre-checked for NULL |
duke@435 | 2941 | jvmtiError |
duke@435 | 2942 | JvmtiEnv::IsMethodObsolete(methodOop method_oop, jboolean* is_obsolete_ptr) { |
dcubed@1556 | 2943 | if (use_version_1_0_semantics() && |
dcubed@1556 | 2944 | get_capabilities()->can_redefine_classes == 0) { |
dcubed@1556 | 2945 | // This JvmtiEnv requested version 1.0 semantics and this function |
dcubed@1556 | 2946 | // requires the can_redefine_classes capability in version 1.0 so |
dcubed@1556 | 2947 | // we need to return an error here. |
dcubed@1556 | 2948 | return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; |
dcubed@1556 | 2949 | } |
dcubed@1556 | 2950 | |
duke@435 | 2951 | if (method_oop == NULL || method_oop->is_obsolete()) { |
duke@435 | 2952 | *is_obsolete_ptr = true; |
duke@435 | 2953 | } else { |
duke@435 | 2954 | *is_obsolete_ptr = false; |
duke@435 | 2955 | } |
duke@435 | 2956 | return JVMTI_ERROR_NONE; |
duke@435 | 2957 | } /* end IsMethodObsolete */ |
duke@435 | 2958 | |
duke@435 | 2959 | // |
duke@435 | 2960 | // Raw Monitor functions |
duke@435 | 2961 | // |
duke@435 | 2962 | |
duke@435 | 2963 | // name - pre-checked for NULL |
duke@435 | 2964 | // monitor_ptr - pre-checked for NULL |
duke@435 | 2965 | jvmtiError |
duke@435 | 2966 | JvmtiEnv::CreateRawMonitor(const char* name, jrawMonitorID* monitor_ptr) { |
duke@435 | 2967 | JvmtiRawMonitor* rmonitor = new JvmtiRawMonitor(name); |
duke@435 | 2968 | NULL_CHECK(rmonitor, JVMTI_ERROR_OUT_OF_MEMORY); |
duke@435 | 2969 | |
duke@435 | 2970 | *monitor_ptr = (jrawMonitorID)rmonitor; |
duke@435 | 2971 | |
duke@435 | 2972 | return JVMTI_ERROR_NONE; |
duke@435 | 2973 | } /* end CreateRawMonitor */ |
duke@435 | 2974 | |
duke@435 | 2975 | |
duke@435 | 2976 | // rmonitor - pre-checked for validity |
duke@435 | 2977 | jvmtiError |
duke@435 | 2978 | JvmtiEnv::DestroyRawMonitor(JvmtiRawMonitor * rmonitor) { |
duke@435 | 2979 | if (Threads::number_of_threads() == 0) { |
duke@435 | 2980 | // Remove this monitor from pending raw monitors list |
duke@435 | 2981 | // if it has entered in onload or start phase. |
duke@435 | 2982 | JvmtiPendingMonitors::destroy(rmonitor); |
duke@435 | 2983 | } else { |
duke@435 | 2984 | Thread* thread = Thread::current(); |
duke@435 | 2985 | if (rmonitor->is_entered(thread)) { |
duke@435 | 2986 | // The caller owns this monitor which we are about to destroy. |
duke@435 | 2987 | // We exit the underlying synchronization object so that the |
duke@435 | 2988 | // "delete monitor" call below can work without an assertion |
duke@435 | 2989 | // failure on systems that don't like destroying synchronization |
duke@435 | 2990 | // objects that are locked. |
duke@435 | 2991 | int r; |
duke@435 | 2992 | intptr_t recursion = rmonitor->recursions(); |
duke@435 | 2993 | for (intptr_t i=0; i <= recursion; i++) { |
duke@435 | 2994 | r = rmonitor->raw_exit(thread); |
duke@435 | 2995 | assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked"); |
duke@435 | 2996 | if (r != ObjectMonitor::OM_OK) { // robustness |
duke@435 | 2997 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 2998 | } |
duke@435 | 2999 | } |
duke@435 | 3000 | } |
duke@435 | 3001 | if (rmonitor->owner() != NULL) { |
duke@435 | 3002 | // The caller is trying to destroy a monitor that is locked by |
duke@435 | 3003 | // someone else. While this is not forbidden by the JVMTI |
duke@435 | 3004 | // spec, it will cause an assertion failure on systems that don't |
duke@435 | 3005 | // like destroying synchronization objects that are locked. |
duke@435 | 3006 | // We indicate a problem with the error return (and leak the |
duke@435 | 3007 | // monitor's memory). |
duke@435 | 3008 | return JVMTI_ERROR_NOT_MONITOR_OWNER; |
duke@435 | 3009 | } |
duke@435 | 3010 | } |
duke@435 | 3011 | |
duke@435 | 3012 | delete rmonitor; |
duke@435 | 3013 | |
duke@435 | 3014 | return JVMTI_ERROR_NONE; |
duke@435 | 3015 | } /* end DestroyRawMonitor */ |
duke@435 | 3016 | |
duke@435 | 3017 | |
duke@435 | 3018 | // rmonitor - pre-checked for validity |
duke@435 | 3019 | jvmtiError |
duke@435 | 3020 | JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) { |
duke@435 | 3021 | if (Threads::number_of_threads() == 0) { |
duke@435 | 3022 | // No JavaThreads exist so ObjectMonitor enter cannot be |
duke@435 | 3023 | // used, add this raw monitor to the pending list. |
duke@435 | 3024 | // The pending monitors will be actually entered when |
duke@435 | 3025 | // the VM is setup. |
duke@435 | 3026 | // See transition_pending_raw_monitors in create_vm() |
duke@435 | 3027 | // in thread.cpp. |
duke@435 | 3028 | JvmtiPendingMonitors::enter(rmonitor); |
duke@435 | 3029 | } else { |
duke@435 | 3030 | int r; |
duke@435 | 3031 | Thread* thread = Thread::current(); |
duke@435 | 3032 | |
duke@435 | 3033 | if (thread->is_Java_thread()) { |
duke@435 | 3034 | JavaThread* current_thread = (JavaThread*)thread; |
duke@435 | 3035 | |
duke@435 | 3036 | #ifdef PROPER_TRANSITIONS |
duke@435 | 3037 | // Not really unknown but ThreadInVMfromNative does more than we want |
duke@435 | 3038 | ThreadInVMfromUnknown __tiv; |
duke@435 | 3039 | { |
duke@435 | 3040 | ThreadBlockInVM __tbivm(current_thread); |
duke@435 | 3041 | r = rmonitor->raw_enter(current_thread); |
duke@435 | 3042 | } |
duke@435 | 3043 | #else |
duke@435 | 3044 | /* Transition to thread_blocked without entering vm state */ |
duke@435 | 3045 | /* This is really evil. Normally you can't undo _thread_blocked */ |
duke@435 | 3046 | /* transitions like this because it would cause us to miss a */ |
duke@435 | 3047 | /* safepoint but since the thread was already in _thread_in_native */ |
duke@435 | 3048 | /* the thread is not leaving a safepoint safe state and it will */ |
duke@435 | 3049 | /* block when it tries to return from native. We can't safepoint */ |
duke@435 | 3050 | /* block in here because we could deadlock the vmthread. Blech. */ |
duke@435 | 3051 | |
duke@435 | 3052 | JavaThreadState state = current_thread->thread_state(); |
duke@435 | 3053 | assert(state == _thread_in_native, "Must be _thread_in_native"); |
duke@435 | 3054 | // frame should already be walkable since we are in native |
duke@435 | 3055 | assert(!current_thread->has_last_Java_frame() || |
duke@435 | 3056 | current_thread->frame_anchor()->walkable(), "Must be walkable"); |
duke@435 | 3057 | current_thread->set_thread_state(_thread_blocked); |
duke@435 | 3058 | |
duke@435 | 3059 | r = rmonitor->raw_enter(current_thread); |
duke@435 | 3060 | // restore state, still at a safepoint safe state |
duke@435 | 3061 | current_thread->set_thread_state(state); |
duke@435 | 3062 | |
duke@435 | 3063 | #endif /* PROPER_TRANSITIONS */ |
duke@435 | 3064 | assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked"); |
duke@435 | 3065 | } else { |
duke@435 | 3066 | if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { |
duke@435 | 3067 | r = rmonitor->raw_enter(thread); |
duke@435 | 3068 | } else { |
duke@435 | 3069 | ShouldNotReachHere(); |
duke@435 | 3070 | } |
duke@435 | 3071 | } |
duke@435 | 3072 | |
duke@435 | 3073 | if (r != ObjectMonitor::OM_OK) { // robustness |
duke@435 | 3074 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 3075 | } |
duke@435 | 3076 | } |
duke@435 | 3077 | return JVMTI_ERROR_NONE; |
duke@435 | 3078 | } /* end RawMonitorEnter */ |
duke@435 | 3079 | |
duke@435 | 3080 | |
duke@435 | 3081 | // rmonitor - pre-checked for validity |
duke@435 | 3082 | jvmtiError |
duke@435 | 3083 | JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) { |
duke@435 | 3084 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 3085 | |
duke@435 | 3086 | if (Threads::number_of_threads() == 0) { |
duke@435 | 3087 | // No JavaThreads exist so just remove this monitor from the pending list. |
duke@435 | 3088 | // Bool value from exit is false if rmonitor is not in the list. |
duke@435 | 3089 | if (!JvmtiPendingMonitors::exit(rmonitor)) { |
duke@435 | 3090 | err = JVMTI_ERROR_NOT_MONITOR_OWNER; |
duke@435 | 3091 | } |
duke@435 | 3092 | } else { |
duke@435 | 3093 | int r; |
duke@435 | 3094 | Thread* thread = Thread::current(); |
duke@435 | 3095 | |
duke@435 | 3096 | if (thread->is_Java_thread()) { |
duke@435 | 3097 | JavaThread* current_thread = (JavaThread*)thread; |
duke@435 | 3098 | #ifdef PROPER_TRANSITIONS |
duke@435 | 3099 | // Not really unknown but ThreadInVMfromNative does more than we want |
duke@435 | 3100 | ThreadInVMfromUnknown __tiv; |
duke@435 | 3101 | #endif /* PROPER_TRANSITIONS */ |
duke@435 | 3102 | r = rmonitor->raw_exit(current_thread); |
duke@435 | 3103 | } else { |
duke@435 | 3104 | if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { |
duke@435 | 3105 | r = rmonitor->raw_exit(thread); |
duke@435 | 3106 | } else { |
duke@435 | 3107 | ShouldNotReachHere(); |
duke@435 | 3108 | } |
duke@435 | 3109 | } |
duke@435 | 3110 | |
duke@435 | 3111 | if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { |
duke@435 | 3112 | err = JVMTI_ERROR_NOT_MONITOR_OWNER; |
duke@435 | 3113 | } else { |
duke@435 | 3114 | assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked"); |
duke@435 | 3115 | if (r != ObjectMonitor::OM_OK) { // robustness |
duke@435 | 3116 | err = JVMTI_ERROR_INTERNAL; |
duke@435 | 3117 | } |
duke@435 | 3118 | } |
duke@435 | 3119 | } |
duke@435 | 3120 | return err; |
duke@435 | 3121 | } /* end RawMonitorExit */ |
duke@435 | 3122 | |
duke@435 | 3123 | |
duke@435 | 3124 | // rmonitor - pre-checked for validity |
duke@435 | 3125 | jvmtiError |
duke@435 | 3126 | JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) { |
duke@435 | 3127 | int r; |
duke@435 | 3128 | Thread* thread = Thread::current(); |
duke@435 | 3129 | |
duke@435 | 3130 | if (thread->is_Java_thread()) { |
duke@435 | 3131 | JavaThread* current_thread = (JavaThread*)thread; |
duke@435 | 3132 | #ifdef PROPER_TRANSITIONS |
duke@435 | 3133 | // Not really unknown but ThreadInVMfromNative does more than we want |
duke@435 | 3134 | ThreadInVMfromUnknown __tiv; |
duke@435 | 3135 | { |
duke@435 | 3136 | ThreadBlockInVM __tbivm(current_thread); |
duke@435 | 3137 | r = rmonitor->raw_wait(millis, true, current_thread); |
duke@435 | 3138 | } |
duke@435 | 3139 | #else |
duke@435 | 3140 | /* Transition to thread_blocked without entering vm state */ |
duke@435 | 3141 | /* This is really evil. Normally you can't undo _thread_blocked */ |
duke@435 | 3142 | /* transitions like this because it would cause us to miss a */ |
duke@435 | 3143 | /* safepoint but since the thread was already in _thread_in_native */ |
duke@435 | 3144 | /* the thread is not leaving a safepoint safe state and it will */ |
duke@435 | 3145 | /* block when it tries to return from native. We can't safepoint */ |
duke@435 | 3146 | /* block in here because we could deadlock the vmthread. Blech. */ |
duke@435 | 3147 | |
duke@435 | 3148 | JavaThreadState state = current_thread->thread_state(); |
duke@435 | 3149 | assert(state == _thread_in_native, "Must be _thread_in_native"); |
duke@435 | 3150 | // frame should already be walkable since we are in native |
duke@435 | 3151 | assert(!current_thread->has_last_Java_frame() || |
duke@435 | 3152 | current_thread->frame_anchor()->walkable(), "Must be walkable"); |
duke@435 | 3153 | current_thread->set_thread_state(_thread_blocked); |
duke@435 | 3154 | |
duke@435 | 3155 | r = rmonitor->raw_wait(millis, true, current_thread); |
duke@435 | 3156 | // restore state, still at a safepoint safe state |
duke@435 | 3157 | current_thread->set_thread_state(state); |
duke@435 | 3158 | |
duke@435 | 3159 | #endif /* PROPER_TRANSITIONS */ |
duke@435 | 3160 | } else { |
duke@435 | 3161 | if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { |
duke@435 | 3162 | r = rmonitor->raw_wait(millis, true, thread); |
duke@435 | 3163 | } else { |
duke@435 | 3164 | ShouldNotReachHere(); |
duke@435 | 3165 | } |
duke@435 | 3166 | } |
duke@435 | 3167 | |
duke@435 | 3168 | switch (r) { |
duke@435 | 3169 | case ObjectMonitor::OM_INTERRUPTED: |
duke@435 | 3170 | return JVMTI_ERROR_INTERRUPT; |
duke@435 | 3171 | case ObjectMonitor::OM_ILLEGAL_MONITOR_STATE: |
duke@435 | 3172 | return JVMTI_ERROR_NOT_MONITOR_OWNER; |
duke@435 | 3173 | } |
duke@435 | 3174 | assert(r == ObjectMonitor::OM_OK, "raw_wait should have worked"); |
duke@435 | 3175 | if (r != ObjectMonitor::OM_OK) { // robustness |
duke@435 | 3176 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 3177 | } |
duke@435 | 3178 | |
duke@435 | 3179 | return JVMTI_ERROR_NONE; |
duke@435 | 3180 | } /* end RawMonitorWait */ |
duke@435 | 3181 | |
duke@435 | 3182 | |
duke@435 | 3183 | // rmonitor - pre-checked for validity |
duke@435 | 3184 | jvmtiError |
duke@435 | 3185 | JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) { |
duke@435 | 3186 | int r; |
duke@435 | 3187 | Thread* thread = Thread::current(); |
duke@435 | 3188 | |
duke@435 | 3189 | if (thread->is_Java_thread()) { |
duke@435 | 3190 | JavaThread* current_thread = (JavaThread*)thread; |
duke@435 | 3191 | // Not really unknown but ThreadInVMfromNative does more than we want |
duke@435 | 3192 | ThreadInVMfromUnknown __tiv; |
duke@435 | 3193 | r = rmonitor->raw_notify(current_thread); |
duke@435 | 3194 | } else { |
duke@435 | 3195 | if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { |
duke@435 | 3196 | r = rmonitor->raw_notify(thread); |
duke@435 | 3197 | } else { |
duke@435 | 3198 | ShouldNotReachHere(); |
duke@435 | 3199 | } |
duke@435 | 3200 | } |
duke@435 | 3201 | |
duke@435 | 3202 | if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { |
duke@435 | 3203 | return JVMTI_ERROR_NOT_MONITOR_OWNER; |
duke@435 | 3204 | } |
duke@435 | 3205 | assert(r == ObjectMonitor::OM_OK, "raw_notify should have worked"); |
duke@435 | 3206 | if (r != ObjectMonitor::OM_OK) { // robustness |
duke@435 | 3207 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 3208 | } |
duke@435 | 3209 | |
duke@435 | 3210 | return JVMTI_ERROR_NONE; |
duke@435 | 3211 | } /* end RawMonitorNotify */ |
duke@435 | 3212 | |
duke@435 | 3213 | |
duke@435 | 3214 | // rmonitor - pre-checked for validity |
duke@435 | 3215 | jvmtiError |
duke@435 | 3216 | JvmtiEnv::RawMonitorNotifyAll(JvmtiRawMonitor * rmonitor) { |
duke@435 | 3217 | int r; |
duke@435 | 3218 | Thread* thread = Thread::current(); |
duke@435 | 3219 | |
duke@435 | 3220 | if (thread->is_Java_thread()) { |
duke@435 | 3221 | JavaThread* current_thread = (JavaThread*)thread; |
duke@435 | 3222 | ThreadInVMfromUnknown __tiv; |
duke@435 | 3223 | r = rmonitor->raw_notifyAll(current_thread); |
duke@435 | 3224 | } else { |
duke@435 | 3225 | if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { |
duke@435 | 3226 | r = rmonitor->raw_notifyAll(thread); |
duke@435 | 3227 | } else { |
duke@435 | 3228 | ShouldNotReachHere(); |
duke@435 | 3229 | } |
duke@435 | 3230 | } |
duke@435 | 3231 | |
duke@435 | 3232 | if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { |
duke@435 | 3233 | return JVMTI_ERROR_NOT_MONITOR_OWNER; |
duke@435 | 3234 | } |
duke@435 | 3235 | assert(r == ObjectMonitor::OM_OK, "raw_notifyAll should have worked"); |
duke@435 | 3236 | if (r != ObjectMonitor::OM_OK) { // robustness |
duke@435 | 3237 | return JVMTI_ERROR_INTERNAL; |
duke@435 | 3238 | } |
duke@435 | 3239 | |
duke@435 | 3240 | return JVMTI_ERROR_NONE; |
duke@435 | 3241 | } /* end RawMonitorNotifyAll */ |
duke@435 | 3242 | |
duke@435 | 3243 | |
duke@435 | 3244 | // |
duke@435 | 3245 | // JNI Function Interception functions |
duke@435 | 3246 | // |
duke@435 | 3247 | |
duke@435 | 3248 | |
duke@435 | 3249 | // function_table - pre-checked for NULL |
duke@435 | 3250 | jvmtiError |
duke@435 | 3251 | JvmtiEnv::SetJNIFunctionTable(const jniNativeInterface* function_table) { |
duke@435 | 3252 | // Copy jni function table at safepoint. |
duke@435 | 3253 | VM_JNIFunctionTableCopier copier(function_table); |
duke@435 | 3254 | VMThread::execute(&copier); |
duke@435 | 3255 | |
duke@435 | 3256 | return JVMTI_ERROR_NONE; |
duke@435 | 3257 | } /* end SetJNIFunctionTable */ |
duke@435 | 3258 | |
duke@435 | 3259 | |
duke@435 | 3260 | // function_table - pre-checked for NULL |
duke@435 | 3261 | jvmtiError |
duke@435 | 3262 | JvmtiEnv::GetJNIFunctionTable(jniNativeInterface** function_table) { |
duke@435 | 3263 | *function_table=(jniNativeInterface*)jvmtiMalloc(sizeof(jniNativeInterface)); |
duke@435 | 3264 | if (*function_table == NULL) |
duke@435 | 3265 | return JVMTI_ERROR_OUT_OF_MEMORY; |
duke@435 | 3266 | memcpy(*function_table,(JavaThread::current())->get_jni_functions(),sizeof(jniNativeInterface)); |
duke@435 | 3267 | return JVMTI_ERROR_NONE; |
duke@435 | 3268 | } /* end GetJNIFunctionTable */ |
duke@435 | 3269 | |
duke@435 | 3270 | |
duke@435 | 3271 | // |
duke@435 | 3272 | // Event Management functions |
duke@435 | 3273 | // |
duke@435 | 3274 | |
duke@435 | 3275 | jvmtiError |
duke@435 | 3276 | JvmtiEnv::GenerateEvents(jvmtiEvent event_type) { |
duke@435 | 3277 | // can only generate two event types |
duke@435 | 3278 | if (event_type != JVMTI_EVENT_COMPILED_METHOD_LOAD && |
duke@435 | 3279 | event_type != JVMTI_EVENT_DYNAMIC_CODE_GENERATED) { |
duke@435 | 3280 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; |
duke@435 | 3281 | } |
duke@435 | 3282 | |
duke@435 | 3283 | // for compiled_method_load events we must check that the environment |
duke@435 | 3284 | // has the can_generate_compiled_method_load_events capability. |
duke@435 | 3285 | if (event_type == JVMTI_EVENT_COMPILED_METHOD_LOAD) { |
duke@435 | 3286 | if (get_capabilities()->can_generate_compiled_method_load_events == 0) { |
duke@435 | 3287 | return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; |
duke@435 | 3288 | } |
duke@435 | 3289 | return JvmtiCodeBlobEvents::generate_compiled_method_load_events(this); |
duke@435 | 3290 | } else { |
duke@435 | 3291 | return JvmtiCodeBlobEvents::generate_dynamic_code_events(this); |
duke@435 | 3292 | } |
duke@435 | 3293 | |
duke@435 | 3294 | } /* end GenerateEvents */ |
duke@435 | 3295 | |
duke@435 | 3296 | |
duke@435 | 3297 | // |
duke@435 | 3298 | // Extension Mechanism functions |
duke@435 | 3299 | // |
duke@435 | 3300 | |
duke@435 | 3301 | // extension_count_ptr - pre-checked for NULL |
duke@435 | 3302 | // extensions - pre-checked for NULL |
duke@435 | 3303 | jvmtiError |
duke@435 | 3304 | JvmtiEnv::GetExtensionFunctions(jint* extension_count_ptr, jvmtiExtensionFunctionInfo** extensions) { |
duke@435 | 3305 | return JvmtiExtensions::get_functions(this, extension_count_ptr, extensions); |
duke@435 | 3306 | } /* end GetExtensionFunctions */ |
duke@435 | 3307 | |
duke@435 | 3308 | |
duke@435 | 3309 | // extension_count_ptr - pre-checked for NULL |
duke@435 | 3310 | // extensions - pre-checked for NULL |
duke@435 | 3311 | jvmtiError |
duke@435 | 3312 | JvmtiEnv::GetExtensionEvents(jint* extension_count_ptr, jvmtiExtensionEventInfo** extensions) { |
duke@435 | 3313 | return JvmtiExtensions::get_events(this, extension_count_ptr, extensions); |
duke@435 | 3314 | } /* end GetExtensionEvents */ |
duke@435 | 3315 | |
duke@435 | 3316 | |
duke@435 | 3317 | // callback - NULL is a valid value, must be checked |
duke@435 | 3318 | jvmtiError |
duke@435 | 3319 | JvmtiEnv::SetExtensionEventCallback(jint extension_event_index, jvmtiExtensionEvent callback) { |
duke@435 | 3320 | return JvmtiExtensions::set_event_callback(this, extension_event_index, callback); |
duke@435 | 3321 | } /* end SetExtensionEventCallback */ |
duke@435 | 3322 | |
duke@435 | 3323 | // |
duke@435 | 3324 | // Timers functions |
duke@435 | 3325 | // |
duke@435 | 3326 | |
duke@435 | 3327 | // info_ptr - pre-checked for NULL |
duke@435 | 3328 | jvmtiError |
duke@435 | 3329 | JvmtiEnv::GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { |
duke@435 | 3330 | os::current_thread_cpu_time_info(info_ptr); |
duke@435 | 3331 | return JVMTI_ERROR_NONE; |
duke@435 | 3332 | } /* end GetCurrentThreadCpuTimerInfo */ |
duke@435 | 3333 | |
duke@435 | 3334 | |
duke@435 | 3335 | // nanos_ptr - pre-checked for NULL |
duke@435 | 3336 | jvmtiError |
duke@435 | 3337 | JvmtiEnv::GetCurrentThreadCpuTime(jlong* nanos_ptr) { |
duke@435 | 3338 | *nanos_ptr = os::current_thread_cpu_time(); |
duke@435 | 3339 | return JVMTI_ERROR_NONE; |
duke@435 | 3340 | } /* end GetCurrentThreadCpuTime */ |
duke@435 | 3341 | |
duke@435 | 3342 | |
duke@435 | 3343 | // info_ptr - pre-checked for NULL |
duke@435 | 3344 | jvmtiError |
duke@435 | 3345 | JvmtiEnv::GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { |
duke@435 | 3346 | os::thread_cpu_time_info(info_ptr); |
duke@435 | 3347 | return JVMTI_ERROR_NONE; |
duke@435 | 3348 | } /* end GetThreadCpuTimerInfo */ |
duke@435 | 3349 | |
duke@435 | 3350 | |
duke@435 | 3351 | // Threads_lock NOT held, java_thread not protected by lock |
duke@435 | 3352 | // java_thread - pre-checked |
duke@435 | 3353 | // nanos_ptr - pre-checked for NULL |
duke@435 | 3354 | jvmtiError |
duke@435 | 3355 | JvmtiEnv::GetThreadCpuTime(JavaThread* java_thread, jlong* nanos_ptr) { |
duke@435 | 3356 | *nanos_ptr = os::thread_cpu_time(java_thread); |
duke@435 | 3357 | return JVMTI_ERROR_NONE; |
duke@435 | 3358 | } /* end GetThreadCpuTime */ |
duke@435 | 3359 | |
duke@435 | 3360 | |
duke@435 | 3361 | // info_ptr - pre-checked for NULL |
duke@435 | 3362 | jvmtiError |
duke@435 | 3363 | JvmtiEnv::GetTimerInfo(jvmtiTimerInfo* info_ptr) { |
duke@435 | 3364 | os::javaTimeNanos_info(info_ptr); |
duke@435 | 3365 | return JVMTI_ERROR_NONE; |
duke@435 | 3366 | } /* end GetTimerInfo */ |
duke@435 | 3367 | |
duke@435 | 3368 | |
duke@435 | 3369 | // nanos_ptr - pre-checked for NULL |
duke@435 | 3370 | jvmtiError |
duke@435 | 3371 | JvmtiEnv::GetTime(jlong* nanos_ptr) { |
duke@435 | 3372 | *nanos_ptr = os::javaTimeNanos(); |
duke@435 | 3373 | return JVMTI_ERROR_NONE; |
duke@435 | 3374 | } /* end GetTime */ |
duke@435 | 3375 | |
duke@435 | 3376 | |
duke@435 | 3377 | // processor_count_ptr - pre-checked for NULL |
duke@435 | 3378 | jvmtiError |
duke@435 | 3379 | JvmtiEnv::GetAvailableProcessors(jint* processor_count_ptr) { |
duke@435 | 3380 | *processor_count_ptr = os::active_processor_count(); |
duke@435 | 3381 | return JVMTI_ERROR_NONE; |
duke@435 | 3382 | } /* end GetAvailableProcessors */ |
duke@435 | 3383 | |
duke@435 | 3384 | // |
duke@435 | 3385 | // System Properties functions |
duke@435 | 3386 | // |
duke@435 | 3387 | |
duke@435 | 3388 | // count_ptr - pre-checked for NULL |
duke@435 | 3389 | // property_ptr - pre-checked for NULL |
duke@435 | 3390 | jvmtiError |
duke@435 | 3391 | JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) { |
duke@435 | 3392 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 3393 | |
duke@435 | 3394 | *count_ptr = Arguments::PropertyList_count(Arguments::system_properties()); |
duke@435 | 3395 | |
duke@435 | 3396 | err = allocate(*count_ptr * sizeof(char *), (unsigned char **)property_ptr); |
duke@435 | 3397 | if (err != JVMTI_ERROR_NONE) { |
duke@435 | 3398 | return err; |
duke@435 | 3399 | } |
duke@435 | 3400 | int i = 0 ; |
duke@435 | 3401 | for (SystemProperty* p = Arguments::system_properties(); p != NULL && i < *count_ptr; p = p->next(), i++) { |
duke@435 | 3402 | const char *key = p->key(); |
duke@435 | 3403 | char **tmp_value = *property_ptr+i; |
duke@435 | 3404 | err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value); |
duke@435 | 3405 | if (err == JVMTI_ERROR_NONE) { |
duke@435 | 3406 | strcpy(*tmp_value, key); |
duke@435 | 3407 | } else { |
duke@435 | 3408 | // clean up previously allocated memory. |
duke@435 | 3409 | for (int j=0; j<i; j++) { |
duke@435 | 3410 | Deallocate((unsigned char*)*property_ptr+j); |
duke@435 | 3411 | } |
duke@435 | 3412 | Deallocate((unsigned char*)property_ptr); |
duke@435 | 3413 | break; |
duke@435 | 3414 | } |
duke@435 | 3415 | } |
duke@435 | 3416 | return err; |
duke@435 | 3417 | } /* end GetSystemProperties */ |
duke@435 | 3418 | |
duke@435 | 3419 | |
duke@435 | 3420 | // property - pre-checked for NULL |
duke@435 | 3421 | // value_ptr - pre-checked for NULL |
duke@435 | 3422 | jvmtiError |
duke@435 | 3423 | JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) { |
duke@435 | 3424 | jvmtiError err = JVMTI_ERROR_NONE; |
duke@435 | 3425 | const char *value; |
duke@435 | 3426 | |
duke@435 | 3427 | value = Arguments::PropertyList_get_value(Arguments::system_properties(), property); |
duke@435 | 3428 | if (value == NULL) { |
duke@435 | 3429 | err = JVMTI_ERROR_NOT_AVAILABLE; |
duke@435 | 3430 | } else { |
duke@435 | 3431 | err = allocate((strlen(value)+1) * sizeof(char), (unsigned char **)value_ptr); |
duke@435 | 3432 | if (err == JVMTI_ERROR_NONE) { |
duke@435 | 3433 | strcpy(*value_ptr, value); |
duke@435 | 3434 | } |
duke@435 | 3435 | } |
duke@435 | 3436 | return err; |
duke@435 | 3437 | } /* end GetSystemProperty */ |
duke@435 | 3438 | |
duke@435 | 3439 | |
duke@435 | 3440 | // property - pre-checked for NULL |
duke@435 | 3441 | // value - NULL is a valid value, must be checked |
duke@435 | 3442 | jvmtiError |
phh@2423 | 3443 | JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { |
duke@435 | 3444 | jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE; |
duke@435 | 3445 | |
duke@435 | 3446 | for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { |
duke@435 | 3447 | if (strcmp(property, p->key()) == 0) { |
phh@2423 | 3448 | if (p->set_value((char *)value_ptr)) { |
duke@435 | 3449 | err = JVMTI_ERROR_NONE; |
duke@435 | 3450 | } |
duke@435 | 3451 | } |
duke@435 | 3452 | } |
duke@435 | 3453 | return err; |
duke@435 | 3454 | } /* end SetSystemProperty */ |
duke@435 | 3455 | |
duke@435 | 3456 | #endif // !JVMTI_KERNEL |