| 1 | /* | 
| 2 |  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. | 
| 3 |  * Copyright (c) 2012 Red Hat, Inc. | 
| 4 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
| 5 |  * | 
| 6 |  * This code is free software; you can redistribute it and/or modify it | 
| 7 |  * under the terms of the GNU General Public License version 2 only, as | 
| 8 |  * published by the Free Software Foundation. | 
| 9 |  * | 
| 10 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
| 11 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
| 12 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
| 13 |  * version 2 for more details (a copy is included in the LICENSE file that | 
| 14 |  * accompanied this code). | 
| 15 |  * | 
| 16 |  * You should have received a copy of the GNU General Public License version | 
| 17 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
| 18 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
| 19 |  * | 
| 20 |  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
| 21 |  * or visit www.oracle.com if you need additional information or have any | 
| 22 |  * questions. | 
| 23 |  * | 
| 24 |  */ | 
| 25 |  | 
| 26 | #include "precompiled.hpp" | 
| 27 | #include "jni.h" | 
| 28 | #include "jvm.h" | 
| 29 | #include "ci/ciReplay.hpp" | 
| 30 | #include "classfile/altHashing.hpp" | 
| 31 | #include "classfile/classFileStream.hpp" | 
| 32 | #include "classfile/classLoader.hpp" | 
| 33 | #include "classfile/javaClasses.hpp" | 
| 34 | #include "classfile/javaClasses.inline.hpp" | 
| 35 | #include "classfile/modules.hpp" | 
| 36 | #include "classfile/symbolTable.hpp" | 
| 37 | #include "classfile/systemDictionary.hpp" | 
| 38 | #include "classfile/vmSymbols.hpp" | 
| 39 | #include "gc/shared/gcLocker.inline.hpp" | 
| 40 | #include "interpreter/linkResolver.hpp" | 
| 41 | #include "jfr/jfrEvents.hpp" | 
| 42 | #include "jfr/support/jfrThreadId.hpp" | 
| 43 | #include "logging/log.hpp" | 
| 44 | #include "memory/allocation.hpp" | 
| 45 | #include "memory/allocation.inline.hpp" | 
| 46 | #include "memory/oopFactory.hpp" | 
| 47 | #include "memory/resourceArea.hpp" | 
| 48 | #include "memory/universe.hpp" | 
| 49 | #include "oops/access.inline.hpp" | 
| 50 | #include "oops/arrayOop.inline.hpp" | 
| 51 | #include "oops/instanceKlass.hpp" | 
| 52 | #include "oops/instanceOop.hpp" | 
| 53 | #include "oops/markOop.hpp" | 
| 54 | #include "oops/method.hpp" | 
| 55 | #include "oops/objArrayKlass.hpp" | 
| 56 | #include "oops/objArrayOop.inline.hpp" | 
| 57 | #include "oops/oop.inline.hpp" | 
| 58 | #include "oops/symbol.hpp" | 
| 59 | #include "oops/typeArrayKlass.hpp" | 
| 60 | #include "oops/typeArrayOop.inline.hpp" | 
| 61 | #include "prims/jniCheck.hpp" | 
| 62 | #include "prims/jniExport.hpp" | 
| 63 | #include "prims/jniFastGetField.hpp" | 
| 64 | #include "prims/jvm_misc.hpp" | 
| 65 | #include "prims/jvmtiExport.hpp" | 
| 66 | #include "prims/jvmtiThreadState.hpp" | 
| 67 | #include "runtime/atomic.hpp" | 
| 68 | #include "runtime/compilationPolicy.hpp" | 
| 69 | #include "runtime/fieldDescriptor.inline.hpp" | 
| 70 | #include "runtime/handles.inline.hpp" | 
| 71 | #include "runtime/interfaceSupport.inline.hpp" | 
| 72 | #include "runtime/java.hpp" | 
| 73 | #include "runtime/javaCalls.hpp" | 
| 74 | #include "runtime/jfieldIDWorkaround.hpp" | 
| 75 | #include "runtime/jniHandles.inline.hpp" | 
| 76 | #include "runtime/orderAccess.hpp" | 
| 77 | #include "runtime/reflection.hpp" | 
| 78 | #include "runtime/safepointVerifiers.hpp" | 
| 79 | #include "runtime/sharedRuntime.hpp" | 
| 80 | #include "runtime/signature.hpp" | 
| 81 | #include "runtime/thread.inline.hpp" | 
| 82 | #include "runtime/vmOperations.hpp" | 
| 83 | #include "services/memTracker.hpp" | 
| 84 | #include "services/runtimeService.hpp" | 
| 85 | #include "utilities/defaultStream.hpp" | 
| 86 | #include "utilities/dtrace.hpp" | 
| 87 | #include "utilities/events.hpp" | 
| 88 | #include "utilities/histogram.hpp" | 
| 89 | #include "utilities/macros.hpp" | 
| 90 | #include "utilities/vmError.hpp" | 
| 91 |  | 
| 92 | static jint CurrentVersion = JNI_VERSION_10; | 
| 93 |  | 
| 94 | #ifdef _WIN32 | 
| 95 | extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); | 
| 96 | #endif | 
| 97 |  | 
| 98 | // The DT_RETURN_MARK macros create a scoped object to fire the dtrace | 
| 99 | // '-return' probe regardless of the return path is taken out of the function. | 
| 100 | // Methods that have multiple return paths use this to avoid having to | 
| 101 | // instrument each return path.  Methods that use CHECK or THROW must use this | 
| 102 | // since those macros can cause an immedate uninstrumented return. | 
| 103 | // | 
| 104 | // In order to get the return value, a reference to the variable containing | 
| 105 | // the return value must be passed to the contructor of the object, and | 
| 106 | // the return value must be set before return (since the mark object has | 
| 107 | // a reference to it). | 
| 108 | // | 
| 109 | // Example: | 
| 110 | // DT_RETURN_MARK_DECL(SomeFunc, int); | 
| 111 | // JNI_ENTRY(int, SomeFunc, ...) | 
| 112 | //   int return_value = 0; | 
| 113 | //   DT_RETURN_MARK(SomeFunc, int, (const int&)return_value); | 
| 114 | //   foo(CHECK_0) | 
| 115 | //   return_value = 5; | 
| 116 | //   return return_value; | 
| 117 | // JNI_END | 
| 118 | #define DT_RETURN_MARK_DECL(name, type, probe)                             \ | 
| 119 |   DTRACE_ONLY(                                                             \ | 
| 120 |     class DTraceReturnProbeMark_##name {                                   \ | 
| 121 |      public:                                                               \ | 
| 122 |       const type& _ret_ref;                                                \ | 
| 123 |       DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {}         \ | 
| 124 |       ~DTraceReturnProbeMark_##name() {                                    \ | 
| 125 |         probe;                                                             \ | 
| 126 |       }                                                                    \ | 
| 127 |     }                                                                      \ | 
| 128 |   ) | 
| 129 | // Void functions are simpler since there's no return value | 
| 130 | #define DT_VOID_RETURN_MARK_DECL(name, probe)                              \ | 
| 131 |   DTRACE_ONLY(                                                             \ | 
| 132 |     class DTraceReturnProbeMark_##name {                                   \ | 
| 133 |      public:                                                               \ | 
| 134 |       ~DTraceReturnProbeMark_##name() {                                    \ | 
| 135 |         probe;                                                             \ | 
| 136 |       }                                                                    \ | 
| 137 |     }                                                                      \ | 
| 138 |   ) | 
| 139 |  | 
| 140 | // Place these macros in the function to mark the return.  Non-void | 
| 141 | // functions need the type and address of the return value. | 
| 142 | #define DT_RETURN_MARK(name, type, ref) \ | 
| 143 |   DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark(ref) ) | 
| 144 | #define DT_VOID_RETURN_MARK(name) \ | 
| 145 |   DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark ) | 
| 146 |  | 
| 147 |  | 
| 148 | // Use these to select distinct code for floating-point vs. non-floating point | 
| 149 | // situations.  Used from within common macros where we need slightly | 
| 150 | // different behavior for Float/Double | 
| 151 | #define FP_SELECT_Boolean(intcode, fpcode) intcode | 
| 152 | #define FP_SELECT_Byte(intcode, fpcode)    intcode | 
| 153 | #define FP_SELECT_Char(intcode, fpcode)    intcode | 
| 154 | #define FP_SELECT_Short(intcode, fpcode)   intcode | 
| 155 | #define FP_SELECT_Object(intcode, fpcode)  intcode | 
| 156 | #define FP_SELECT_Int(intcode, fpcode)     intcode | 
| 157 | #define FP_SELECT_Long(intcode, fpcode)    intcode | 
| 158 | #define FP_SELECT_Float(intcode, fpcode)   fpcode | 
| 159 | #define FP_SELECT_Double(intcode, fpcode)  fpcode | 
| 160 | #define FP_SELECT(TypeName, intcode, fpcode) \ | 
| 161 |   FP_SELECT_##TypeName(intcode, fpcode) | 
| 162 |  | 
| 163 | // Choose DT_RETURN_MARK macros  based on the type: float/double -> void | 
| 164 | // (dtrace doesn't do FP yet) | 
| 165 | #define DT_RETURN_MARK_DECL_FOR(TypeName, name, type, probe)    \ | 
| 166 |   FP_SELECT(TypeName, \ | 
| 167 |     DT_RETURN_MARK_DECL(name, type, probe), DT_VOID_RETURN_MARK_DECL(name, probe) ) | 
| 168 | #define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \ | 
| 169 |   FP_SELECT(TypeName, \ | 
| 170 |     DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) ) | 
| 171 |  | 
| 172 |  | 
| 173 | // out-of-line helpers for class jfieldIDWorkaround: | 
| 174 |  | 
| 175 | bool jfieldIDWorkaround::is_valid_jfieldID(Klass* k, jfieldID id) { | 
| 176 |   if (jfieldIDWorkaround::is_instance_jfieldID(k, id)) { | 
| 177 |     uintptr_t as_uint = (uintptr_t) id; | 
| 178 |     intptr_t offset = raw_instance_offset(id); | 
| 179 |     if (is_checked_jfieldID(id)) { | 
| 180 |       if (!klass_hash_ok(k, id)) { | 
| 181 |         return false; | 
| 182 |       } | 
| 183 |     } | 
| 184 |     return InstanceKlass::cast(k)->contains_field_offset(offset); | 
| 185 |   } else { | 
| 186 |     JNIid* result = (JNIid*) id; | 
| 187 | #ifdef ASSERT | 
| 188 |     return result != NULL && result->is_static_field_id(); | 
| 189 | #else | 
| 190 |     return result != NULL; | 
| 191 | #endif | 
| 192 |   } | 
| 193 | } | 
| 194 |  | 
| 195 |  | 
| 196 | intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, intptr_t offset) { | 
| 197 |   if (offset <= small_offset_mask) { | 
| 198 |     Klass* field_klass = k; | 
| 199 |     Klass* super_klass = field_klass->super(); | 
| 200 |     // With compressed oops the most super class with nonstatic fields would | 
| 201 |     // be the owner of fields embedded in the header. | 
| 202 |     while (InstanceKlass::cast(super_klass)->has_nonstatic_fields() && | 
| 203 |            InstanceKlass::cast(super_klass)->contains_field_offset(offset)) { | 
| 204 |       field_klass = super_klass;   // super contains the field also | 
| 205 |       super_klass = field_klass->super(); | 
| 206 |     } | 
| 207 |     debug_only(NoSafepointVerifier nosafepoint;) | 
| 208 |     uintptr_t klass_hash = field_klass->identity_hash(); | 
| 209 |     return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place; | 
| 210 |   } else { | 
| 211 | #if 0 | 
| 212 |     #ifndef PRODUCT | 
| 213 |     { | 
| 214 |       ResourceMark rm; | 
| 215 |       warning("VerifyJNIFields: long offset %d in %s" , offset, k->external_name()); | 
| 216 |     } | 
| 217 |     #endif | 
| 218 | #endif | 
| 219 |     return 0; | 
| 220 |   } | 
| 221 | } | 
| 222 |  | 
| 223 | bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) { | 
| 224 |   uintptr_t as_uint = (uintptr_t) id; | 
| 225 |   intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask; | 
| 226 |   do { | 
| 227 |     debug_only(NoSafepointVerifier nosafepoint;) | 
| 228 |     // Could use a non-blocking query for identity_hash here... | 
| 229 |     if ((k->identity_hash() & klass_mask) == klass_hash) | 
| 230 |       return true; | 
| 231 |     k = k->super(); | 
| 232 |   } while (k != NULL); | 
| 233 |   return false; | 
| 234 | } | 
| 235 |  | 
| 236 | void jfieldIDWorkaround::verify_instance_jfieldID(Klass* k, jfieldID id) { | 
| 237 |   guarantee(jfieldIDWorkaround::is_instance_jfieldID(k, id), "must be an instance field"  ); | 
| 238 |   uintptr_t as_uint = (uintptr_t) id; | 
| 239 |   intptr_t offset = raw_instance_offset(id); | 
| 240 |   if (VerifyJNIFields) { | 
| 241 |     if (is_checked_jfieldID(id)) { | 
| 242 |       guarantee(klass_hash_ok(k, id), | 
| 243 |     "Bug in native code: jfieldID class must match object" ); | 
| 244 |     } else { | 
| 245 | #if 0 | 
| 246 |       #ifndef PRODUCT | 
| 247 |       if (Verbose) { | 
| 248 |   ResourceMark rm; | 
| 249 |   warning("VerifyJNIFields: unverified offset %d for %s" , offset, k->external_name()); | 
| 250 |       } | 
| 251 |       #endif | 
| 252 | #endif | 
| 253 |     } | 
| 254 |   } | 
| 255 |   guarantee(InstanceKlass::cast(k)->contains_field_offset(offset), | 
| 256 |       "Bug in native code: jfieldID offset must address interior of object" ); | 
| 257 | } | 
| 258 |  | 
| 259 | // Wrapper to trace JNI functions | 
| 260 |  | 
| 261 | #ifdef ASSERT | 
| 262 |   Histogram* JNIHistogram; | 
| 263 |   static volatile int JNIHistogram_lock = 0; | 
| 264 |  | 
| 265 |   class JNIHistogramElement : public HistogramElement { | 
| 266 |     public: | 
| 267 |      JNIHistogramElement(const char* name); | 
| 268 |   }; | 
| 269 |  | 
| 270 |   JNIHistogramElement::JNIHistogramElement(const char* elementName) { | 
| 271 |     _name = elementName; | 
| 272 |     uintx count = 0; | 
| 273 |  | 
| 274 |     while (Atomic::cmpxchg(1, &JNIHistogram_lock, 0) != 0) { | 
| 275 |       while (OrderAccess::load_acquire(&JNIHistogram_lock) != 0) { | 
| 276 |         count +=1; | 
| 277 |         if ( (WarnOnStalledSpinLock > 0) | 
| 278 |           && (count % WarnOnStalledSpinLock == 0)) { | 
| 279 |           warning("JNIHistogram_lock seems to be stalled" ); | 
| 280 |         } | 
| 281 |       } | 
| 282 |      } | 
| 283 |  | 
| 284 |  | 
| 285 |     if(JNIHistogram == NULL) | 
| 286 |       JNIHistogram = new Histogram("JNI Call Counts" ,100); | 
| 287 |  | 
| 288 |     JNIHistogram->add_element(this); | 
| 289 |     Atomic::dec(&JNIHistogram_lock); | 
| 290 |   } | 
| 291 |  | 
| 292 |   #define JNICountWrapper(arg)                                     \ | 
| 293 |      static JNIHistogramElement* e = new JNIHistogramElement(arg); \ | 
| 294 |       /* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \ | 
| 295 |      if (e != NULL) e->increment_count() | 
| 296 |   #define JNIWrapper(arg) JNICountWrapper(arg); | 
| 297 | #else | 
| 298 |   #define JNIWrapper(arg) | 
| 299 | #endif | 
| 300 |  | 
| 301 |  | 
| 302 | // Implementation of JNI entries | 
| 303 |  | 
| 304 | DT_RETURN_MARK_DECL(DefineClass, jclass | 
| 305 |                     , HOTSPOT_JNI_DEFINECLASS_RETURN(_ret_ref)); | 
| 306 |  | 
| 307 | JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef, | 
| 308 |                                   const jbyte *buf, jsize bufLen)) | 
| 309 |   JNIWrapper("DefineClass" ); | 
| 310 |  | 
| 311 |   HOTSPOT_JNI_DEFINECLASS_ENTRY( | 
| 312 |     env, (char*) name, loaderRef, (char*) buf, bufLen); | 
| 313 |  | 
| 314 |   jclass cls = NULL; | 
| 315 |   DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls); | 
| 316 |  | 
| 317 |   TempNewSymbol class_name = NULL; | 
| 318 |   // Since exceptions can be thrown, class initialization can take place | 
| 319 |   // if name is NULL no check for class name in .class stream has to be made. | 
| 320 |   if (name != NULL) { | 
| 321 |     const int str_len = (int)strlen(name); | 
| 322 |     if (str_len > Symbol::max_length()) { | 
| 323 |       // It's impossible to create this class;  the name cannot fit | 
| 324 |       // into the constant pool. | 
| 325 |       Exceptions::fthrow(THREAD_AND_LOCATION, | 
| 326 |                          vmSymbols::java_lang_NoClassDefFoundError(), | 
| 327 |                          "Class name exceeds maximum length of %d: %s" , | 
| 328 |                          Symbol::max_length(), | 
| 329 |                          name); | 
| 330 |       return 0; | 
| 331 |     } | 
| 332 |     class_name = SymbolTable::new_symbol(name); | 
| 333 |   } | 
| 334 |   ResourceMark rm(THREAD); | 
| 335 |   ClassFileStream st((u1*)buf, bufLen, NULL, ClassFileStream::verify); | 
| 336 |   Handle class_loader (THREAD, JNIHandles::resolve(loaderRef)); | 
| 337 |  | 
| 338 |   if (UsePerfData && !class_loader.is_null()) { | 
| 339 |     // check whether the current caller thread holds the lock or not. | 
| 340 |     // If not, increment the corresponding counter | 
| 341 |     if (ObjectSynchronizer:: | 
| 342 |         query_lock_ownership((JavaThread*)THREAD, class_loader) != | 
| 343 |         ObjectSynchronizer::owner_self) { | 
| 344 |       ClassLoader::sync_JNIDefineClassLockFreeCounter()->inc(); | 
| 345 |     } | 
| 346 |   } | 
| 347 |   Klass* k = SystemDictionary::resolve_from_stream(class_name, | 
| 348 |                                                    class_loader, | 
| 349 |                                                    Handle(), | 
| 350 |                                                    &st, | 
| 351 |                                                    CHECK_NULL); | 
| 352 |  | 
| 353 |   if (log_is_enabled(Debug, class, resolve) && k != NULL) { | 
| 354 |     trace_class_resolution(k); | 
| 355 |   } | 
| 356 |  | 
| 357 |   cls = (jclass)JNIHandles::make_local( | 
| 358 |     env, k->java_mirror()); | 
| 359 |   return cls; | 
| 360 | JNI_END | 
| 361 |  | 
| 362 |  | 
| 363 |  | 
| 364 | DT_RETURN_MARK_DECL(FindClass, jclass | 
| 365 |                     , HOTSPOT_JNI_FINDCLASS_RETURN(_ret_ref)); | 
| 366 |  | 
| 367 | JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) | 
| 368 |   JNIWrapper("FindClass" ); | 
| 369 |  | 
| 370 |   HOTSPOT_JNI_FINDCLASS_ENTRY(env, (char *)name); | 
| 371 |  | 
| 372 |   jclass result = NULL; | 
| 373 |   DT_RETURN_MARK(FindClass, jclass, (const jclass&)result); | 
| 374 |  | 
| 375 |   // Sanity check the name:  it cannot be null or larger than the maximum size | 
| 376 |   // name we can fit in the constant pool. | 
| 377 |   if (name == NULL) { | 
| 378 |     THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), "No class name given" ); | 
| 379 |   } | 
| 380 |   if ((int)strlen(name) > Symbol::max_length()) { | 
| 381 |     Exceptions::fthrow(THREAD_AND_LOCATION, | 
| 382 |                        vmSymbols::java_lang_NoClassDefFoundError(), | 
| 383 |                        "Class name exceeds maximum length of %d: %s" , | 
| 384 |                        Symbol::max_length(), | 
| 385 |                        name); | 
| 386 |     return 0; | 
| 387 |   } | 
| 388 |  | 
| 389 |   //%note jni_3 | 
| 390 |   Handle protection_domain; | 
| 391 |   // Find calling class | 
| 392 |   Klass* k = thread->security_get_caller_class(0); | 
| 393 |   // default to the system loader when no context | 
| 394 |   Handle loader(THREAD, SystemDictionary::java_system_loader()); | 
| 395 |   if (k != NULL) { | 
| 396 |     // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed | 
| 397 |     // in the correct class context. | 
| 398 |     if (k->class_loader() == NULL && | 
| 399 |         k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) { | 
| 400 |       JavaValue result(T_OBJECT); | 
| 401 |       JavaCalls::call_static(&result, k, | 
| 402 |                              vmSymbols::getFromClass_name(), | 
| 403 |                              vmSymbols::void_class_signature(), | 
| 404 |                              CHECK_NULL); | 
| 405 |       // When invoked from JNI_OnLoad, NativeLibrary::getFromClass returns | 
| 406 |       // a non-NULL Class object.  When invoked from JNI_OnUnload, | 
| 407 |       // it will return NULL to indicate no context. | 
| 408 |       oop mirror = (oop) result.get_jobject(); | 
| 409 |       if (mirror != NULL) { | 
| 410 |         Klass* fromClass = java_lang_Class::as_Klass(mirror); | 
| 411 |         loader = Handle(THREAD, fromClass->class_loader()); | 
| 412 |         protection_domain = Handle(THREAD, fromClass->protection_domain()); | 
| 413 |       } | 
| 414 |     } else { | 
| 415 |       loader = Handle(THREAD, k->class_loader()); | 
| 416 |     } | 
| 417 |   } | 
| 418 |  | 
| 419 |   TempNewSymbol sym = SymbolTable::new_symbol(name); | 
| 420 |   result = find_class_from_class_loader(env, sym, true, loader, | 
| 421 |                                         protection_domain, true, thread); | 
| 422 |  | 
| 423 |   if (log_is_enabled(Debug, class, resolve) && result != NULL) { | 
| 424 |     trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); | 
| 425 |   } | 
| 426 |  | 
| 427 |   return result; | 
| 428 | JNI_END | 
| 429 |  | 
| 430 | DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID | 
| 431 |                     , HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN((uintptr_t)_ret_ref)); | 
| 432 |  | 
| 433 | JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) | 
| 434 |   JNIWrapper("FromReflectedMethod" ); | 
| 435 |  | 
| 436 |   HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY(env, method); | 
| 437 |  | 
| 438 |   jmethodID ret = NULL; | 
| 439 |   DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret); | 
| 440 |  | 
| 441 |   // method is a handle to a java.lang.reflect.Method object | 
| 442 |   oop reflected  = JNIHandles::resolve_non_null(method); | 
| 443 |   oop mirror     = NULL; | 
| 444 |   int slot       = 0; | 
| 445 |  | 
| 446 |   if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { | 
| 447 |     mirror = java_lang_reflect_Constructor::clazz(reflected); | 
| 448 |     slot   = java_lang_reflect_Constructor::slot(reflected); | 
| 449 |   } else { | 
| 450 |     assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type" ); | 
| 451 |     mirror = java_lang_reflect_Method::clazz(reflected); | 
| 452 |     slot   = java_lang_reflect_Method::slot(reflected); | 
| 453 |   } | 
| 454 |   Klass* k1 = java_lang_Class::as_Klass(mirror); | 
| 455 |  | 
| 456 |   // Make sure class is initialized before handing id's out to methods | 
| 457 |   k1->initialize(CHECK_NULL); | 
| 458 |   Method* m = InstanceKlass::cast(k1)->method_with_idnum(slot); | 
| 459 |   ret = m==NULL? NULL : m->jmethod_id();  // return NULL if reflected method deleted | 
| 460 |   return ret; | 
| 461 | JNI_END | 
| 462 |  | 
| 463 | DT_RETURN_MARK_DECL(FromReflectedField, jfieldID | 
| 464 |                     , HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN((uintptr_t)_ret_ref)); | 
| 465 |  | 
| 466 | JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) | 
| 467 |   JNIWrapper("FromReflectedField" ); | 
| 468 |  | 
| 469 |   HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY(env, field); | 
| 470 |  | 
| 471 |   jfieldID ret = NULL; | 
| 472 |   DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret); | 
| 473 |  | 
| 474 |   // field is a handle to a java.lang.reflect.Field object | 
| 475 |   oop reflected   = JNIHandles::resolve_non_null(field); | 
| 476 |   oop mirror      = java_lang_reflect_Field::clazz(reflected); | 
| 477 |   Klass* k1       = java_lang_Class::as_Klass(mirror); | 
| 478 |   int slot        = java_lang_reflect_Field::slot(reflected); | 
| 479 |   int modifiers   = java_lang_reflect_Field::modifiers(reflected); | 
| 480 |  | 
| 481 |   // Make sure class is initialized before handing id's out to fields | 
| 482 |   k1->initialize(CHECK_NULL); | 
| 483 |  | 
| 484 |   // First check if this is a static field | 
| 485 |   if (modifiers & JVM_ACC_STATIC) { | 
| 486 |     intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot ); | 
| 487 |     JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset); | 
| 488 |     assert(id != NULL, "corrupt Field object" ); | 
| 489 |     debug_only(id->set_is_static_field_id();) | 
| 490 |     // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass* | 
| 491 |     ret = jfieldIDWorkaround::to_static_jfieldID(id); | 
| 492 |     return ret; | 
| 493 |   } | 
| 494 |  | 
| 495 |   // The slot is the index of the field description in the field-array | 
| 496 |   // The jfieldID is the offset of the field within the object | 
| 497 |   // It may also have hash bits for k, if VerifyJNIFields is turned on. | 
| 498 |   intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot ); | 
| 499 |   assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object" ); | 
| 500 |   ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset); | 
| 501 |   return ret; | 
| 502 | JNI_END | 
| 503 |  | 
| 504 |  | 
| 505 | DT_RETURN_MARK_DECL(ToReflectedMethod, jobject | 
| 506 |                     , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref)); | 
| 507 |  | 
| 508 | JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic)) | 
| 509 |   JNIWrapper("ToReflectedMethod" ); | 
| 510 |  | 
| 511 |   HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic); | 
| 512 |  | 
| 513 |   jobject ret = NULL; | 
| 514 |   DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret); | 
| 515 |  | 
| 516 |   methodHandle m (THREAD, Method::resolve_jmethod_id(method_id)); | 
| 517 |   assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match" ); | 
| 518 |   oop reflection_method; | 
| 519 |   if (m->is_initializer()) { | 
| 520 |     reflection_method = Reflection::new_constructor(m, CHECK_NULL); | 
| 521 |   } else { | 
| 522 |     reflection_method = Reflection::new_method(m, false, CHECK_NULL); | 
| 523 |   } | 
| 524 |   ret = JNIHandles::make_local(env, reflection_method); | 
| 525 |   return ret; | 
| 526 | JNI_END | 
| 527 |  | 
| 528 | DT_RETURN_MARK_DECL(GetSuperclass, jclass | 
| 529 |                     , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref)); | 
| 530 |  | 
| 531 | JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub)) | 
| 532 |   JNIWrapper("GetSuperclass" ); | 
| 533 |  | 
| 534 |   HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub); | 
| 535 |  | 
| 536 |   jclass obj = NULL; | 
| 537 |   DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj); | 
| 538 |  | 
| 539 |   oop mirror = JNIHandles::resolve_non_null(sub); | 
| 540 |   // primitive classes return NULL | 
| 541 |   if (java_lang_Class::is_primitive(mirror)) return NULL; | 
| 542 |  | 
| 543 |   // Rules of Class.getSuperClass as implemented by KLass::java_super: | 
| 544 |   // arrays return Object | 
| 545 |   // interfaces return NULL | 
| 546 |   // proper classes return Klass::super() | 
| 547 |   Klass* k = java_lang_Class::as_Klass(mirror); | 
| 548 |   if (k->is_interface()) return NULL; | 
| 549 |  | 
| 550 |   // return mirror for superclass | 
| 551 |   Klass* super = k->java_super(); | 
| 552 |   // super2 is the value computed by the compiler's getSuperClass intrinsic: | 
| 553 |   debug_only(Klass* super2 = ( k->is_array_klass() | 
| 554 |                                  ? SystemDictionary::Object_klass() | 
| 555 |                                  : k->super() ) ); | 
| 556 |   assert(super == super2, | 
| 557 |          "java_super computation depends on interface, array, other super" ); | 
| 558 |   obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(super->java_mirror()); | 
| 559 |   return obj; | 
| 560 | JNI_END | 
| 561 |  | 
| 562 | JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super)) | 
| 563 |   JNIWrapper("IsSubclassOf" ); | 
| 564 |  | 
| 565 |   HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super); | 
| 566 |  | 
| 567 |   oop sub_mirror   = JNIHandles::resolve_non_null(sub); | 
| 568 |   oop super_mirror = JNIHandles::resolve_non_null(super); | 
| 569 |   if (java_lang_Class::is_primitive(sub_mirror) || | 
| 570 |       java_lang_Class::is_primitive(super_mirror)) { | 
| 571 |     jboolean ret = oopDesc::equals(sub_mirror, super_mirror); | 
| 572 |  | 
| 573 |     HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret); | 
| 574 |     return ret; | 
| 575 |   } | 
| 576 |   Klass* sub_klass   = java_lang_Class::as_Klass(sub_mirror); | 
| 577 |   Klass* super_klass = java_lang_Class::as_Klass(super_mirror); | 
| 578 |   assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom" ); | 
| 579 |   jboolean ret = sub_klass->is_subtype_of(super_klass) ? | 
| 580 |                    JNI_TRUE : JNI_FALSE; | 
| 581 |  | 
| 582 |   HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret); | 
| 583 |   return ret; | 
| 584 | JNI_END | 
| 585 |  | 
| 586 |  | 
| 587 | DT_RETURN_MARK_DECL(Throw, jint | 
| 588 |                     , HOTSPOT_JNI_THROW_RETURN(_ret_ref)); | 
| 589 |  | 
| 590 | JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj)) | 
| 591 |   JNIWrapper("Throw" ); | 
| 592 |  | 
| 593 |   HOTSPOT_JNI_THROW_ENTRY(env, obj); | 
| 594 |  | 
| 595 |   jint ret = JNI_OK; | 
| 596 |   DT_RETURN_MARK(Throw, jint, (const jint&)ret); | 
| 597 |  | 
| 598 |   THROW_OOP_(JNIHandles::resolve(obj), JNI_OK); | 
| 599 |   ShouldNotReachHere(); | 
| 600 |   return 0;  // Mute compiler. | 
| 601 | JNI_END | 
| 602 |  | 
| 603 |  | 
| 604 | DT_RETURN_MARK_DECL(ThrowNew, jint | 
| 605 |                     , HOTSPOT_JNI_THROWNEW_RETURN(_ret_ref)); | 
| 606 |  | 
| 607 | JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message)) | 
| 608 |   JNIWrapper("ThrowNew" ); | 
| 609 |  | 
| 610 |   HOTSPOT_JNI_THROWNEW_ENTRY(env, clazz, (char *) message); | 
| 611 |  | 
| 612 |   jint ret = JNI_OK; | 
| 613 |   DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret); | 
| 614 |  | 
| 615 |   InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); | 
| 616 |   Symbol*  name = k->name(); | 
| 617 |   Handle class_loader (THREAD,  k->class_loader()); | 
| 618 |   Handle protection_domain (THREAD, k->protection_domain()); | 
| 619 |   THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK); | 
| 620 |   ShouldNotReachHere(); | 
| 621 |   return 0;  // Mute compiler. | 
| 622 | JNI_END | 
| 623 |  | 
| 624 |  | 
| 625 | // JNI functions only transform a pending async exception to a synchronous | 
| 626 | // exception in ExceptionOccurred and ExceptionCheck calls, since | 
| 627 | // delivering an async exception in other places won't change the native | 
| 628 | // code's control flow and would be harmful when native code further calls | 
| 629 | // JNI functions with a pending exception. Async exception is also checked | 
| 630 | // during the call, so ExceptionOccurred/ExceptionCheck won't return | 
| 631 | // false but deliver the async exception at the very end during | 
| 632 | // state transition. | 
| 633 |  | 
| 634 | static void jni_check_async_exceptions(JavaThread *thread) { | 
| 635 |   assert(thread == Thread::current(), "must be itself" ); | 
| 636 |   thread->check_and_handle_async_exceptions(); | 
| 637 | } | 
| 638 |  | 
| 639 | JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env)) | 
| 640 |   JNIWrapper("ExceptionOccurred" ); | 
| 641 |  | 
| 642 |   HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY(env); | 
| 643 |  | 
| 644 |   jni_check_async_exceptions(thread); | 
| 645 |   oop exception = thread->pending_exception(); | 
| 646 |   jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception); | 
| 647 |  | 
| 648 |   HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(ret); | 
| 649 |   return ret; | 
| 650 | JNI_END | 
| 651 |  | 
| 652 |  | 
| 653 | JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) | 
| 654 |   JNIWrapper("ExceptionDescribe" ); | 
| 655 |  | 
| 656 |   HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY(env); | 
| 657 |  | 
| 658 |   if (thread->has_pending_exception()) { | 
| 659 |     Handle ex(thread, thread->pending_exception()); | 
| 660 |     thread->clear_pending_exception(); | 
| 661 |     if (ex->is_a(SystemDictionary::ThreadDeath_klass())) { | 
| 662 |       // Don't print anything if we are being killed. | 
| 663 |     } else { | 
| 664 |       jio_fprintf(defaultStream::error_stream(), "Exception " ); | 
| 665 |       if (thread != NULL && thread->threadObj() != NULL) { | 
| 666 |         ResourceMark rm(THREAD); | 
| 667 |         jio_fprintf(defaultStream::error_stream(), | 
| 668 |         "in thread \"%s\" " , thread->get_thread_name()); | 
| 669 |       } | 
| 670 |       if (ex->is_a(SystemDictionary::Throwable_klass())) { | 
| 671 |         JavaValue result(T_VOID); | 
| 672 |         JavaCalls::call_virtual(&result, | 
| 673 |                                 ex, | 
| 674 |                                 SystemDictionary::Throwable_klass(), | 
| 675 |                                 vmSymbols::printStackTrace_name(), | 
| 676 |                                 vmSymbols::void_method_signature(), | 
| 677 |                                 THREAD); | 
| 678 |         // If an exception is thrown in the call it gets thrown away. Not much | 
| 679 |         // we can do with it. The native code that calls this, does not check | 
| 680 |         // for the exception - hence, it might still be in the thread when DestroyVM gets | 
| 681 |         // called, potentially causing a few asserts to trigger - since no pending exception | 
| 682 |         // is expected. | 
| 683 |         CLEAR_PENDING_EXCEPTION; | 
| 684 |       } else { | 
| 685 |         ResourceMark rm(THREAD); | 
| 686 |         jio_fprintf(defaultStream::error_stream(), | 
| 687 |         ". Uncaught exception of type %s." , | 
| 688 |         ex->klass()->external_name()); | 
| 689 |       } | 
| 690 |     } | 
| 691 |   } | 
| 692 |  | 
| 693 |   HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN(); | 
| 694 | JNI_END | 
| 695 |  | 
| 696 |  | 
| 697 | JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env)) | 
| 698 |   JNIWrapper("ExceptionClear" ); | 
| 699 |  | 
| 700 |   HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY(env); | 
| 701 |  | 
| 702 |   // The jni code might be using this API to clear java thrown exception. | 
| 703 |   // So just mark jvmti thread exception state as exception caught. | 
| 704 |   JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state(); | 
| 705 |   if (state != NULL && state->is_exception_detected()) { | 
| 706 |     state->set_exception_caught(); | 
| 707 |   } | 
| 708 |   thread->clear_pending_exception(); | 
| 709 |  | 
| 710 |   HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN(); | 
| 711 | JNI_END | 
| 712 |  | 
| 713 |  | 
| 714 | JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg)) | 
| 715 |   JNIWrapper("FatalError" ); | 
| 716 |  | 
| 717 |   HOTSPOT_JNI_FATALERROR_ENTRY(env, (char *) msg); | 
| 718 |  | 
| 719 |   tty->print_cr("FATAL ERROR in native method: %s" , msg); | 
| 720 |   thread->print_stack(); | 
| 721 |   os::abort(); // Dump core and abort | 
| 722 | JNI_END | 
| 723 |  | 
| 724 |  | 
| 725 | JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity)) | 
| 726 |   JNIWrapper("PushLocalFrame" ); | 
| 727 |  | 
| 728 |   HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY(env, capacity); | 
| 729 |  | 
| 730 |   //%note jni_11 | 
| 731 |   if (capacity < 0 || | 
| 732 |       ((MaxJNILocalCapacity > 0) && (capacity > MaxJNILocalCapacity))) { | 
| 733 |     HOTSPOT_JNI_PUSHLOCALFRAME_RETURN((uint32_t)JNI_ERR); | 
| 734 |     return JNI_ERR; | 
| 735 |   } | 
| 736 |   JNIHandleBlock* old_handles = thread->active_handles(); | 
| 737 |   JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread); | 
| 738 |   assert(new_handles != NULL, "should not be NULL" ); | 
| 739 |   new_handles->set_pop_frame_link(old_handles); | 
| 740 |   thread->set_active_handles(new_handles); | 
| 741 |   jint ret = JNI_OK; | 
| 742 |   HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(ret); | 
| 743 |   return ret; | 
| 744 | JNI_END | 
| 745 |  | 
| 746 |  | 
| 747 | JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result)) | 
| 748 |   JNIWrapper("PopLocalFrame" ); | 
| 749 |  | 
| 750 |   HOTSPOT_JNI_POPLOCALFRAME_ENTRY(env, result); | 
| 751 |  | 
| 752 |   //%note jni_11 | 
| 753 |   Handle result_handle(thread, JNIHandles::resolve(result)); | 
| 754 |   JNIHandleBlock* old_handles = thread->active_handles(); | 
| 755 |   JNIHandleBlock* new_handles = old_handles->pop_frame_link(); | 
| 756 |   if (new_handles != NULL) { | 
| 757 |     // As a sanity check we only release the handle blocks if the pop_frame_link is not NULL. | 
| 758 |     // This way code will still work if PopLocalFrame is called without a corresponding | 
| 759 |     // PushLocalFrame call. Note that we set the pop_frame_link to NULL explicitly, otherwise | 
| 760 |     // the release_block call will release the blocks. | 
| 761 |     thread->set_active_handles(new_handles); | 
| 762 |     old_handles->set_pop_frame_link(NULL);              // clear link we won't release new_handles below | 
| 763 |     JNIHandleBlock::release_block(old_handles, thread); // may block | 
| 764 |     result = JNIHandles::make_local(thread, result_handle()); | 
| 765 |   } | 
| 766 |   HOTSPOT_JNI_POPLOCALFRAME_RETURN(result); | 
| 767 |   return result; | 
| 768 | JNI_END | 
| 769 |  | 
| 770 |  | 
| 771 | JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref)) | 
| 772 |   JNIWrapper("NewGlobalRef" ); | 
| 773 |  | 
| 774 |   HOTSPOT_JNI_NEWGLOBALREF_ENTRY(env, ref); | 
| 775 |  | 
| 776 |   Handle ref_handle(thread, JNIHandles::resolve(ref)); | 
| 777 |   jobject ret = JNIHandles::make_global(ref_handle); | 
| 778 |  | 
| 779 |   HOTSPOT_JNI_NEWGLOBALREF_RETURN(ret); | 
| 780 |   return ret; | 
| 781 | JNI_END | 
| 782 |  | 
| 783 | // Must be JNI_ENTRY (with HandleMark) | 
| 784 | JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref)) | 
| 785 |   JNIWrapper("DeleteGlobalRef" ); | 
| 786 |  | 
| 787 |   HOTSPOT_JNI_DELETEGLOBALREF_ENTRY(env, ref); | 
| 788 |  | 
| 789 |   JNIHandles::destroy_global(ref); | 
| 790 |  | 
| 791 |   HOTSPOT_JNI_DELETEGLOBALREF_RETURN(); | 
| 792 | JNI_END | 
| 793 |  | 
| 794 | JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj)) | 
| 795 |   JNIWrapper("DeleteLocalRef" ); | 
| 796 |  | 
| 797 |   HOTSPOT_JNI_DELETELOCALREF_ENTRY(env, obj); | 
| 798 |  | 
| 799 |   JNIHandles::destroy_local(obj); | 
| 800 |  | 
| 801 |   HOTSPOT_JNI_DELETELOCALREF_RETURN(); | 
| 802 | JNI_END | 
| 803 |  | 
| 804 | JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2)) | 
| 805 |   JNIWrapper("IsSameObject" ); | 
| 806 |  | 
| 807 |   HOTSPOT_JNI_ISSAMEOBJECT_ENTRY(env, r1, r2); | 
| 808 |  | 
| 809 |   jboolean ret = JNIHandles::is_same_object(r1, r2) ? JNI_TRUE : JNI_FALSE; | 
| 810 |  | 
| 811 |   HOTSPOT_JNI_ISSAMEOBJECT_RETURN(ret); | 
| 812 |   return ret; | 
| 813 | JNI_END | 
| 814 |  | 
| 815 |  | 
| 816 | JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref)) | 
| 817 |   JNIWrapper("NewLocalRef" ); | 
| 818 |  | 
| 819 |   HOTSPOT_JNI_NEWLOCALREF_ENTRY(env, ref); | 
| 820 |  | 
| 821 |   jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref)); | 
| 822 |  | 
| 823 |   HOTSPOT_JNI_NEWLOCALREF_RETURN(ret); | 
| 824 |   return ret; | 
| 825 | JNI_END | 
| 826 |  | 
| 827 | JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity)) | 
| 828 |   JNIWrapper("EnsureLocalCapacity" ); | 
| 829 |  | 
| 830 |   HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY(env, capacity); | 
| 831 |  | 
| 832 |   jint ret; | 
| 833 |   if (capacity >= 0 && | 
| 834 |       ((MaxJNILocalCapacity <= 0) || (capacity <= MaxJNILocalCapacity))) { | 
| 835 |     ret = JNI_OK; | 
| 836 |   } else { | 
| 837 |     ret = JNI_ERR; | 
| 838 |   } | 
| 839 |  | 
| 840 |   HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN(ret); | 
| 841 |   return ret; | 
| 842 | JNI_END | 
| 843 |  | 
| 844 | // Return the Handle Type | 
| 845 | JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj)) | 
| 846 |   JNIWrapper("GetObjectRefType" ); | 
| 847 |  | 
| 848 |   HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY(env, obj); | 
| 849 |  | 
| 850 |   jobjectRefType ret = JNIInvalidRefType; | 
| 851 |   if (obj != NULL) { | 
| 852 |     ret = JNIHandles::handle_type(thread, obj); | 
| 853 |   } | 
| 854 |  | 
| 855 |   HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN((void *) ret); | 
| 856 |   return ret; | 
| 857 | JNI_END | 
| 858 |  | 
| 859 |  | 
| 860 | class JNI_ArgumentPusher : public SignatureIterator { | 
| 861 |  protected: | 
| 862 |   JavaCallArguments*  _arguments; | 
| 863 |  | 
| 864 |   virtual void get_bool   () = 0; | 
| 865 |   virtual void get_char   () = 0; | 
| 866 |   virtual void get_short  () = 0; | 
| 867 |   virtual void get_byte   () = 0; | 
| 868 |   virtual void get_int    () = 0; | 
| 869 |   virtual void get_long   () = 0; | 
| 870 |   virtual void get_float  () = 0; | 
| 871 |   virtual void get_double () = 0; | 
| 872 |   virtual void get_object () = 0; | 
| 873 |  | 
| 874 |   JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) { | 
| 875 |     this->_return_type = T_ILLEGAL; | 
| 876 |     _arguments = NULL; | 
| 877 |   } | 
| 878 |  | 
| 879 |  public: | 
| 880 |   virtual void iterate( uint64_t fingerprint ) = 0; | 
| 881 |  | 
| 882 |   void set_java_argument_object(JavaCallArguments *arguments) { _arguments = arguments; } | 
| 883 |  | 
| 884 |   inline void do_bool()                     { if (!is_return_type()) get_bool();   } | 
| 885 |   inline void do_char()                     { if (!is_return_type()) get_char();   } | 
| 886 |   inline void do_short()                    { if (!is_return_type()) get_short();  } | 
| 887 |   inline void do_byte()                     { if (!is_return_type()) get_byte();   } | 
| 888 |   inline void do_int()                      { if (!is_return_type()) get_int();    } | 
| 889 |   inline void do_long()                     { if (!is_return_type()) get_long();   } | 
| 890 |   inline void do_float()                    { if (!is_return_type()) get_float();  } | 
| 891 |   inline void do_double()                   { if (!is_return_type()) get_double(); } | 
| 892 |   inline void do_object(int begin, int end) { if (!is_return_type()) get_object(); } | 
| 893 |   inline void do_array(int begin, int end)  { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array | 
| 894 |   inline void do_void()                     { } | 
| 895 |  | 
| 896 |   JavaCallArguments* arguments()     { return _arguments; } | 
| 897 |   void push_receiver(Handle h)       { _arguments->push_oop(h); } | 
| 898 | }; | 
| 899 |  | 
| 900 |  | 
| 901 | class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { | 
| 902 |  protected: | 
| 903 |   va_list _ap; | 
| 904 |  | 
| 905 |   inline void get_bool()   { | 
| 906 |     // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and | 
| 907 |     // 0 to JNI_FALSE.  Boolean return values from native are normalized the same in | 
| 908 |     // TemplateInterpreterGenerator::generate_result_handler_for and | 
| 909 |     // SharedRuntime::generate_native_wrapper. | 
| 910 |     jboolean b = va_arg(_ap, jint); | 
| 911 |     _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); | 
| 912 |   } | 
| 913 |   inline void get_char()   { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg | 
| 914 |   inline void get_short()  { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg | 
| 915 |   inline void get_byte()   { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg | 
| 916 |   inline void get_int()    { _arguments->push_int(va_arg(_ap, jint)); } | 
| 917 |  | 
| 918 |   // each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests | 
| 919 |  | 
| 920 |   inline void get_long()   { _arguments->push_long(va_arg(_ap, jlong)); } | 
| 921 |   inline void get_float()  { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg | 
| 922 |   inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); } | 
| 923 |   inline void get_object() { _arguments->push_jobject(va_arg(_ap, jobject)); } | 
| 924 |  | 
| 925 |   inline void set_ap(va_list rap) { | 
| 926 |     va_copy(_ap, rap); | 
| 927 |   } | 
| 928 |  | 
| 929 |  public: | 
| 930 |   JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap) | 
| 931 |        : JNI_ArgumentPusher(signature) { | 
| 932 |     set_ap(rap); | 
| 933 |   } | 
| 934 |   JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap) | 
| 935 |       : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) { | 
| 936 |     set_ap(rap); | 
| 937 |   } | 
| 938 |  | 
| 939 |   // Optimized path if we have the bitvector form of signature | 
| 940 |   void iterate( uint64_t fingerprint ) { | 
| 941 |     if (fingerprint == (uint64_t)CONST64(-1)) { | 
| 942 |       SignatureIterator::iterate(); // Must be too many arguments | 
| 943 |     } else { | 
| 944 |       _return_type = (BasicType)((fingerprint >> static_feature_size) & | 
| 945 |                                   result_feature_mask); | 
| 946 |  | 
| 947 |       assert(fingerprint, "Fingerprint should not be 0" ); | 
| 948 |       fingerprint = fingerprint >> (static_feature_size + result_feature_size); | 
| 949 |       while ( 1 ) { | 
| 950 |         switch ( fingerprint & parameter_feature_mask ) { | 
| 951 |           case bool_parm: | 
| 952 |             get_bool(); | 
| 953 |             break; | 
| 954 |           case char_parm: | 
| 955 |             get_char(); | 
| 956 |             break; | 
| 957 |           case short_parm: | 
| 958 |             get_short(); | 
| 959 |             break; | 
| 960 |           case byte_parm: | 
| 961 |             get_byte(); | 
| 962 |             break; | 
| 963 |           case int_parm: | 
| 964 |             get_int(); | 
| 965 |             break; | 
| 966 |           case obj_parm: | 
| 967 |             get_object(); | 
| 968 |             break; | 
| 969 |           case long_parm: | 
| 970 |             get_long(); | 
| 971 |             break; | 
| 972 |           case float_parm: | 
| 973 |             get_float(); | 
| 974 |             break; | 
| 975 |           case double_parm: | 
| 976 |             get_double(); | 
| 977 |             break; | 
| 978 |           case done_parm: | 
| 979 |             return; | 
| 980 |             break; | 
| 981 |           default: | 
| 982 |             ShouldNotReachHere(); | 
| 983 |             break; | 
| 984 |         } | 
| 985 |         fingerprint >>= parameter_feature_size; | 
| 986 |       } | 
| 987 |     } | 
| 988 |   } | 
| 989 | }; | 
| 990 |  | 
| 991 |  | 
| 992 | class JNI_ArgumentPusherArray : public JNI_ArgumentPusher { | 
| 993 |  protected: | 
| 994 |   const jvalue *_ap; | 
| 995 |  | 
| 996 |   inline void get_bool()   { | 
| 997 |     // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and | 
| 998 |     // 0 to JNI_FALSE.  Boolean return values from native are normalized the same in | 
| 999 |     // TemplateInterpreterGenerator::generate_result_handler_for and | 
| 1000 |     // SharedRuntime::generate_native_wrapper. | 
| 1001 |     jboolean b = (_ap++)->z; | 
| 1002 |     _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); | 
| 1003 |   } | 
| 1004 |   inline void get_char()   { _arguments->push_int((jint)(_ap++)->c); } | 
| 1005 |   inline void get_short()  { _arguments->push_int((jint)(_ap++)->s); } | 
| 1006 |   inline void get_byte()   { _arguments->push_int((jint)(_ap++)->b); } | 
| 1007 |   inline void get_int()    { _arguments->push_int((jint)(_ap++)->i); } | 
| 1008 |  | 
| 1009 |   inline void get_long()   { _arguments->push_long((_ap++)->j);  } | 
| 1010 |   inline void get_float()  { _arguments->push_float((_ap++)->f); } | 
| 1011 |   inline void get_double() { _arguments->push_double((_ap++)->d);} | 
| 1012 |   inline void get_object() { _arguments->push_jobject((_ap++)->l); } | 
| 1013 |  | 
| 1014 |   inline void set_ap(const jvalue *rap) { _ap = rap; } | 
| 1015 |  | 
| 1016 |  public: | 
| 1017 |   JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap) | 
| 1018 |        : JNI_ArgumentPusher(signature) { | 
| 1019 |     set_ap(rap); | 
| 1020 |   } | 
| 1021 |   JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap) | 
| 1022 |       : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) { | 
| 1023 |     set_ap(rap); | 
| 1024 |   } | 
| 1025 |  | 
| 1026 |   // Optimized path if we have the bitvector form of signature | 
| 1027 |   void iterate( uint64_t fingerprint ) { | 
| 1028 |     if (fingerprint == (uint64_t)CONST64(-1)) { | 
| 1029 |       SignatureIterator::iterate(); // Must be too many arguments | 
| 1030 |     } else { | 
| 1031 |       _return_type = (BasicType)((fingerprint >> static_feature_size) & | 
| 1032 |                                   result_feature_mask); | 
| 1033 |       assert(fingerprint, "Fingerprint should not be 0" ); | 
| 1034 |       fingerprint = fingerprint >> (static_feature_size + result_feature_size); | 
| 1035 |       while ( 1 ) { | 
| 1036 |         switch ( fingerprint & parameter_feature_mask ) { | 
| 1037 |           case bool_parm: | 
| 1038 |             get_bool(); | 
| 1039 |             break; | 
| 1040 |           case char_parm: | 
| 1041 |             get_char(); | 
| 1042 |             break; | 
| 1043 |           case short_parm: | 
| 1044 |             get_short(); | 
| 1045 |             break; | 
| 1046 |           case byte_parm: | 
| 1047 |             get_byte(); | 
| 1048 |             break; | 
| 1049 |           case int_parm: | 
| 1050 |             get_int(); | 
| 1051 |             break; | 
| 1052 |           case obj_parm: | 
| 1053 |             get_object(); | 
| 1054 |             break; | 
| 1055 |           case long_parm: | 
| 1056 |             get_long(); | 
| 1057 |             break; | 
| 1058 |           case float_parm: | 
| 1059 |             get_float(); | 
| 1060 |             break; | 
| 1061 |           case double_parm: | 
| 1062 |             get_double(); | 
| 1063 |             break; | 
| 1064 |           case done_parm: | 
| 1065 |             return; | 
| 1066 |             break; | 
| 1067 |           default: | 
| 1068 |             ShouldNotReachHere(); | 
| 1069 |             break; | 
| 1070 |         } | 
| 1071 |         fingerprint >>= parameter_feature_size; | 
| 1072 |       } | 
| 1073 |     } | 
| 1074 |   } | 
| 1075 | }; | 
| 1076 |  | 
| 1077 |  | 
| 1078 | enum JNICallType { | 
| 1079 |   JNI_STATIC, | 
| 1080 |   JNI_VIRTUAL, | 
| 1081 |   JNI_NONVIRTUAL | 
| 1082 | }; | 
| 1083 |  | 
| 1084 |  | 
| 1085 |  | 
| 1086 | static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { | 
| 1087 |   methodHandle method(THREAD, Method::resolve_jmethod_id(method_id)); | 
| 1088 |  | 
| 1089 |   // Create object to hold arguments for the JavaCall, and associate it with | 
| 1090 |   // the jni parser | 
| 1091 |   ResourceMark rm(THREAD); | 
| 1092 |   int number_of_parameters = method->size_of_parameters(); | 
| 1093 |   JavaCallArguments java_args(number_of_parameters); | 
| 1094 |   args->set_java_argument_object(&java_args); | 
| 1095 |  | 
| 1096 |   assert(method->is_static(), "method should be static" ); | 
| 1097 |  | 
| 1098 |   // Fill out JavaCallArguments object | 
| 1099 |   args->iterate( Fingerprinter(method).fingerprint() ); | 
| 1100 |   // Initialize result type | 
| 1101 |   result->set_type(args->get_ret_type()); | 
| 1102 |  | 
| 1103 |   // Invoke the method. Result is returned as oop. | 
| 1104 |   JavaCalls::call(result, method, &java_args, CHECK); | 
| 1105 |  | 
| 1106 |   // Convert result | 
| 1107 |   if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) { | 
| 1108 |     result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); | 
| 1109 |   } | 
| 1110 | } | 
| 1111 |  | 
| 1112 |  | 
| 1113 | static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { | 
| 1114 |   oop recv = JNIHandles::resolve(receiver); | 
| 1115 |   if (recv == NULL) { | 
| 1116 |     THROW(vmSymbols::java_lang_NullPointerException()); | 
| 1117 |   } | 
| 1118 |   Handle h_recv(THREAD, recv); | 
| 1119 |  | 
| 1120 |   int number_of_parameters; | 
| 1121 |   Method* selected_method; | 
| 1122 |   { | 
| 1123 |     Method* m = Method::resolve_jmethod_id(method_id); | 
| 1124 |     number_of_parameters = m->size_of_parameters(); | 
| 1125 |     Klass* holder = m->method_holder(); | 
| 1126 |     if (call_type != JNI_VIRTUAL) { | 
| 1127 |         selected_method = m; | 
| 1128 |     } else if (!m->has_itable_index()) { | 
| 1129 |       // non-interface call -- for that little speed boost, don't handlize | 
| 1130 |       debug_only(NoSafepointVerifier nosafepoint;) | 
| 1131 |       // jni_GetMethodID makes sure class is linked and initialized | 
| 1132 |       // so m should have a valid vtable index. | 
| 1133 |       assert(m->valid_vtable_index(), "no valid vtable index" ); | 
| 1134 |       int vtbl_index = m->vtable_index(); | 
| 1135 |       if (vtbl_index != Method::nonvirtual_vtable_index) { | 
| 1136 |         selected_method = h_recv->klass()->method_at_vtable(vtbl_index); | 
| 1137 |       } else { | 
| 1138 |         // final method | 
| 1139 |         selected_method = m; | 
| 1140 |       } | 
| 1141 |     } else { | 
| 1142 |       // interface call | 
| 1143 |       int itbl_index = m->itable_index(); | 
| 1144 |       Klass* k = h_recv->klass(); | 
| 1145 |       selected_method = InstanceKlass::cast(k)->method_at_itable(holder, itbl_index, CHECK); | 
| 1146 |     } | 
| 1147 |   } | 
| 1148 |  | 
| 1149 |   methodHandle method(THREAD, selected_method); | 
| 1150 |  | 
| 1151 |   // Create object to hold arguments for the JavaCall, and associate it with | 
| 1152 |   // the jni parser | 
| 1153 |   ResourceMark rm(THREAD); | 
| 1154 |   JavaCallArguments java_args(number_of_parameters); | 
| 1155 |   args->set_java_argument_object(&java_args); | 
| 1156 |  | 
| 1157 |   // handle arguments | 
| 1158 |   assert(!method->is_static(), "method %s should not be static" , method->name_and_sig_as_C_string()); | 
| 1159 |   args->push_receiver(h_recv); // Push jobject handle | 
| 1160 |  | 
| 1161 |   // Fill out JavaCallArguments object | 
| 1162 |   args->iterate( Fingerprinter(method).fingerprint() ); | 
| 1163 |   // Initialize result type | 
| 1164 |   result->set_type(args->get_ret_type()); | 
| 1165 |  | 
| 1166 |   // Invoke the method. Result is returned as oop. | 
| 1167 |   JavaCalls::call(result, method, &java_args, CHECK); | 
| 1168 |  | 
| 1169 |   // Convert result | 
| 1170 |   if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) { | 
| 1171 |     result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); | 
| 1172 |   } | 
| 1173 | } | 
| 1174 |  | 
| 1175 |  | 
| 1176 | static instanceOop alloc_object(jclass clazz, TRAPS) { | 
| 1177 |   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); | 
| 1178 |   if (k == NULL) { | 
| 1179 |     ResourceMark rm(THREAD); | 
| 1180 |     THROW_(vmSymbols::java_lang_InstantiationException(), NULL); | 
| 1181 |   } | 
| 1182 |   k->check_valid_for_instantiation(false, CHECK_NULL); | 
| 1183 |   k->initialize(CHECK_NULL); | 
| 1184 |   instanceOop ih = InstanceKlass::cast(k)->allocate_instance(THREAD); | 
| 1185 |   return ih; | 
| 1186 | } | 
| 1187 |  | 
| 1188 | DT_RETURN_MARK_DECL(AllocObject, jobject | 
| 1189 |                     , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref)); | 
| 1190 |  | 
| 1191 | JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz)) | 
| 1192 |   JNIWrapper("AllocObject" ); | 
| 1193 |  | 
| 1194 |   HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz); | 
| 1195 |  | 
| 1196 |   jobject ret = NULL; | 
| 1197 |   DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret); | 
| 1198 |  | 
| 1199 |   instanceOop i = alloc_object(clazz, CHECK_NULL); | 
| 1200 |   ret = JNIHandles::make_local(env, i); | 
| 1201 |   return ret; | 
| 1202 | JNI_END | 
| 1203 |  | 
| 1204 | DT_RETURN_MARK_DECL(NewObjectA, jobject | 
| 1205 |                     , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref)); | 
| 1206 |  | 
| 1207 | JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args)) | 
| 1208 |   JNIWrapper("NewObjectA" ); | 
| 1209 |  | 
| 1210 |   HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID); | 
| 1211 |  | 
| 1212 |   jobject obj = NULL; | 
| 1213 |   DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj); | 
| 1214 |  | 
| 1215 |   instanceOop i = alloc_object(clazz, CHECK_NULL); | 
| 1216 |   obj = JNIHandles::make_local(env, i); | 
| 1217 |   JavaValue jvalue(T_VOID); | 
| 1218 |   JNI_ArgumentPusherArray ap(methodID, args); | 
| 1219 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); | 
| 1220 |   return obj; | 
| 1221 | JNI_END | 
| 1222 |  | 
| 1223 |  | 
| 1224 | DT_RETURN_MARK_DECL(NewObjectV, jobject | 
| 1225 |                     , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref)); | 
| 1226 |  | 
| 1227 | JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)) | 
| 1228 |   JNIWrapper("NewObjectV" ); | 
| 1229 |  | 
| 1230 |   HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID); | 
| 1231 |  | 
| 1232 |   jobject obj = NULL; | 
| 1233 |   DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj); | 
| 1234 |  | 
| 1235 |   instanceOop i = alloc_object(clazz, CHECK_NULL); | 
| 1236 |   obj = JNIHandles::make_local(env, i); | 
| 1237 |   JavaValue jvalue(T_VOID); | 
| 1238 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1239 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); | 
| 1240 |   return obj; | 
| 1241 | JNI_END | 
| 1242 |  | 
| 1243 |  | 
| 1244 | DT_RETURN_MARK_DECL(NewObject, jobject | 
| 1245 |                     , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref)); | 
| 1246 |  | 
| 1247 | JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)) | 
| 1248 |   JNIWrapper("NewObject" ); | 
| 1249 |  | 
| 1250 |   HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID); | 
| 1251 |  | 
| 1252 |   jobject obj = NULL; | 
| 1253 |   DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj); | 
| 1254 |  | 
| 1255 |   instanceOop i = alloc_object(clazz, CHECK_NULL); | 
| 1256 |   obj = JNIHandles::make_local(env, i); | 
| 1257 |   va_list args; | 
| 1258 |   va_start(args, methodID); | 
| 1259 |   JavaValue jvalue(T_VOID); | 
| 1260 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1261 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); | 
| 1262 |   va_end(args); | 
| 1263 |   return obj; | 
| 1264 | JNI_END | 
| 1265 |  | 
| 1266 |  | 
| 1267 | JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj)) | 
| 1268 |   JNIWrapper("GetObjectClass" ); | 
| 1269 |  | 
| 1270 |   HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj); | 
| 1271 |  | 
| 1272 |   Klass* k = JNIHandles::resolve_non_null(obj)->klass(); | 
| 1273 |   jclass ret = | 
| 1274 |     (jclass) JNIHandles::make_local(env, k->java_mirror()); | 
| 1275 |  | 
| 1276 |   HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret); | 
| 1277 |   return ret; | 
| 1278 | JNI_END | 
| 1279 |  | 
| 1280 | JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)) | 
| 1281 |   JNIWrapper("IsInstanceOf" ); | 
| 1282 |  | 
| 1283 |   HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz); | 
| 1284 |  | 
| 1285 |   jboolean ret = JNI_TRUE; | 
| 1286 |   if (obj != NULL) { | 
| 1287 |     ret = JNI_FALSE; | 
| 1288 |     Klass* k = java_lang_Class::as_Klass( | 
| 1289 |       JNIHandles::resolve_non_null(clazz)); | 
| 1290 |     if (k != NULL) { | 
| 1291 |       ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE; | 
| 1292 |     } | 
| 1293 |   } | 
| 1294 |  | 
| 1295 |   HOTSPOT_JNI_ISINSTANCEOF_RETURN(ret); | 
| 1296 |   return ret; | 
| 1297 | JNI_END | 
| 1298 |  | 
| 1299 |  | 
| 1300 | static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, | 
| 1301 |                                const char *sig, bool is_static, TRAPS) { | 
| 1302 |   // %%%% This code should probably just call into a method in the LinkResolver | 
| 1303 |   // | 
| 1304 |   // The class should have been loaded (we have an instance of the class | 
| 1305 |   // passed in) so the method and signature should already be in the symbol | 
| 1306 |   // table.  If they're not there, the method doesn't exist. | 
| 1307 |   const char *name_to_probe = (name_str == NULL) | 
| 1308 |                         ? vmSymbols::object_initializer_name()->as_C_string() | 
| 1309 |                         : name_str; | 
| 1310 |   TempNewSymbol name = SymbolTable::probe(name_to_probe, (int)strlen(name_to_probe)); | 
| 1311 |   TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig)); | 
| 1312 |  | 
| 1313 |   if (name == NULL || signature == NULL) { | 
| 1314 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str); | 
| 1315 |   } | 
| 1316 |  | 
| 1317 |   Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); | 
| 1318 |  | 
| 1319 |   // Throw a NoSuchMethodError exception if we have an instance of a | 
| 1320 |   // primitive java.lang.Class | 
| 1321 |   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) { | 
| 1322 |     ResourceMark rm; | 
| 1323 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s" , is_static ? "static "  : "" , klass->signature_name(), name_str, sig)); | 
| 1324 |   } | 
| 1325 |  | 
| 1326 |   // Make sure class is linked and initialized before handing id's out to | 
| 1327 |   // Method*s. | 
| 1328 |   klass->initialize(CHECK_NULL); | 
| 1329 |  | 
| 1330 |   Method* m; | 
| 1331 |   if (name == vmSymbols::object_initializer_name() || | 
| 1332 |       name == vmSymbols::class_initializer_name()) { | 
| 1333 |     // Never search superclasses for constructors | 
| 1334 |     if (klass->is_instance_klass()) { | 
| 1335 |       m = InstanceKlass::cast(klass)->find_method(name, signature); | 
| 1336 |     } else { | 
| 1337 |       m = NULL; | 
| 1338 |     } | 
| 1339 |   } else { | 
| 1340 |     m = klass->lookup_method(name, signature); | 
| 1341 |     if (m == NULL &&  klass->is_instance_klass()) { | 
| 1342 |       m = InstanceKlass::cast(klass)->lookup_method_in_ordered_interfaces(name, signature); | 
| 1343 |     } | 
| 1344 |   } | 
| 1345 |   if (m == NULL || (m->is_static() != is_static)) { | 
| 1346 |     ResourceMark rm; | 
| 1347 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s" , is_static ? "static "  : "" , klass->signature_name(), name_str, sig)); | 
| 1348 |   } | 
| 1349 |   return m->jmethod_id(); | 
| 1350 | } | 
| 1351 |  | 
| 1352 |  | 
| 1353 | JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz, | 
| 1354 |           const char *name, const char *sig)) | 
| 1355 |   JNIWrapper("GetMethodID" ); | 
| 1356 |   HOTSPOT_JNI_GETMETHODID_ENTRY(env, clazz, (char *) name, (char *) sig); | 
| 1357 |   jmethodID ret = get_method_id(env, clazz, name, sig, false, thread); | 
| 1358 |   HOTSPOT_JNI_GETMETHODID_RETURN((uintptr_t) ret); | 
| 1359 |   return ret; | 
| 1360 | JNI_END | 
| 1361 |  | 
| 1362 |  | 
| 1363 | JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz, | 
| 1364 |           const char *name, const char *sig)) | 
| 1365 |   JNIWrapper("GetStaticMethodID" ); | 
| 1366 |   HOTSPOT_JNI_GETSTATICMETHODID_ENTRY(env, (char *) clazz, (char *) name, (char *)sig); | 
| 1367 |   jmethodID ret = get_method_id(env, clazz, name, sig, true, thread); | 
| 1368 |   HOTSPOT_JNI_GETSTATICMETHODID_RETURN((uintptr_t) ret); | 
| 1369 |   return ret; | 
| 1370 | JNI_END | 
| 1371 |  | 
| 1372 |  | 
| 1373 |  | 
| 1374 | // | 
| 1375 | // Calling Methods | 
| 1376 | // | 
| 1377 |  | 
| 1378 |  | 
| 1379 | #define DEFINE_CALLMETHOD(ResultType, Result, Tag \ | 
| 1380 |                           , EntryProbe, ReturnProbe)    \ | 
| 1381 | \ | 
| 1382 |   DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType \ | 
| 1383 |                           , ReturnProbe);                          \ | 
| 1384 | \ | 
| 1385 | JNI_ENTRY(ResultType, \ | 
| 1386 |           jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \ | 
| 1387 |   JNIWrapper("Call" XSTR(Result) "Method"); \ | 
| 1388 | \ | 
| 1389 |   EntryProbe; \ | 
| 1390 |   ResultType ret = 0;\ | 
| 1391 |   DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \ | 
| 1392 |                      (const ResultType&)ret);\ | 
| 1393 | \ | 
| 1394 |   va_list args; \ | 
| 1395 |   va_start(args, methodID); \ | 
| 1396 |   JavaValue jvalue(Tag); \ | 
| 1397 |   JNI_ArgumentPusherVaArg ap(methodID, args); \ | 
| 1398 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ | 
| 1399 |   va_end(args); \ | 
| 1400 |   ret = jvalue.get_##ResultType(); \ | 
| 1401 |   return ret;\ | 
| 1402 | JNI_END | 
| 1403 |  | 
| 1404 | // the runtime type of subword integral basic types is integer | 
| 1405 | DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN | 
| 1406 |                   , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1407 |                   HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref)) | 
| 1408 | DEFINE_CALLMETHOD(jbyte,    Byte,    T_BYTE | 
| 1409 |                   , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1410 |                   HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref)) | 
| 1411 | DEFINE_CALLMETHOD(jchar,    Char,    T_CHAR | 
| 1412 |                   , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1413 |                   HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref)) | 
| 1414 | DEFINE_CALLMETHOD(jshort,   Short,   T_SHORT | 
| 1415 |                   , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1416 |                   HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref)) | 
| 1417 |  | 
| 1418 | DEFINE_CALLMETHOD(jobject,  Object,  T_OBJECT | 
| 1419 |                   , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1420 |                   HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref)) | 
| 1421 | DEFINE_CALLMETHOD(jint,     Int,     T_INT, | 
| 1422 |                   HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1423 |                   HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref)) | 
| 1424 | DEFINE_CALLMETHOD(jlong,    Long,    T_LONG | 
| 1425 |                   , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1426 |                   HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref)) | 
| 1427 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1428 | DEFINE_CALLMETHOD(jfloat,   Float,   T_FLOAT | 
| 1429 |                   , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1430 |                   HOTSPOT_JNI_CALLFLOATMETHOD_RETURN()) | 
| 1431 | DEFINE_CALLMETHOD(jdouble,  Double,  T_DOUBLE | 
| 1432 |                   , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1433 |                   HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN()) | 
| 1434 |  | 
| 1435 | #define DEFINE_CALLMETHODV(ResultType, Result, Tag \ | 
| 1436 |                           , EntryProbe, ReturnProbe)    \ | 
| 1437 | \ | 
| 1438 |   DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType \ | 
| 1439 |                           , ReturnProbe);                          \ | 
| 1440 | \ | 
| 1441 | JNI_ENTRY(ResultType, \ | 
| 1442 |           jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \ | 
| 1443 |   JNIWrapper("Call" XSTR(Result) "MethodV"); \ | 
| 1444 | \ | 
| 1445 |   EntryProbe;\ | 
| 1446 |   ResultType ret = 0;\ | 
| 1447 |   DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \ | 
| 1448 |                      (const ResultType&)ret);\ | 
| 1449 | \ | 
| 1450 |   JavaValue jvalue(Tag); \ | 
| 1451 |   JNI_ArgumentPusherVaArg ap(methodID, args); \ | 
| 1452 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ | 
| 1453 |   ret = jvalue.get_##ResultType(); \ | 
| 1454 |   return ret;\ | 
| 1455 | JNI_END | 
| 1456 |  | 
| 1457 | // the runtime type of subword integral basic types is integer | 
| 1458 | DEFINE_CALLMETHODV(jboolean, Boolean, T_BOOLEAN | 
| 1459 |                   , HOTSPOT_JNI_CALLBOOLEANMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1460 |                   HOTSPOT_JNI_CALLBOOLEANMETHODV_RETURN(_ret_ref)) | 
| 1461 | DEFINE_CALLMETHODV(jbyte,    Byte,    T_BYTE | 
| 1462 |                   , HOTSPOT_JNI_CALLBYTEMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1463 |                   HOTSPOT_JNI_CALLBYTEMETHODV_RETURN(_ret_ref)) | 
| 1464 | DEFINE_CALLMETHODV(jchar,    Char,    T_CHAR | 
| 1465 |                   , HOTSPOT_JNI_CALLCHARMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1466 |                   HOTSPOT_JNI_CALLCHARMETHODV_RETURN(_ret_ref)) | 
| 1467 | DEFINE_CALLMETHODV(jshort,   Short,   T_SHORT | 
| 1468 |                   , HOTSPOT_JNI_CALLSHORTMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1469 |                   HOTSPOT_JNI_CALLSHORTMETHODV_RETURN(_ret_ref)) | 
| 1470 |  | 
| 1471 | DEFINE_CALLMETHODV(jobject,  Object,  T_OBJECT | 
| 1472 |                   , HOTSPOT_JNI_CALLOBJECTMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1473 |                   HOTSPOT_JNI_CALLOBJECTMETHODV_RETURN(_ret_ref)) | 
| 1474 | DEFINE_CALLMETHODV(jint,     Int,     T_INT, | 
| 1475 |                   HOTSPOT_JNI_CALLINTMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1476 |                   HOTSPOT_JNI_CALLINTMETHODV_RETURN(_ret_ref)) | 
| 1477 | DEFINE_CALLMETHODV(jlong,    Long,    T_LONG | 
| 1478 |                   , HOTSPOT_JNI_CALLLONGMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1479 |                   HOTSPOT_JNI_CALLLONGMETHODV_RETURN(_ret_ref)) | 
| 1480 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1481 | DEFINE_CALLMETHODV(jfloat,   Float,   T_FLOAT | 
| 1482 |                   , HOTSPOT_JNI_CALLFLOATMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1483 |                   HOTSPOT_JNI_CALLFLOATMETHODV_RETURN()) | 
| 1484 | DEFINE_CALLMETHODV(jdouble,  Double,  T_DOUBLE | 
| 1485 |                   , HOTSPOT_JNI_CALLDOUBLEMETHODV_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1486 |                   HOTSPOT_JNI_CALLDOUBLEMETHODV_RETURN()) | 
| 1487 |  | 
| 1488 | #define DEFINE_CALLMETHODA(ResultType, Result, Tag \ | 
| 1489 |                           , EntryProbe, ReturnProbe)    \ | 
| 1490 | \ | 
| 1491 |   DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType \ | 
| 1492 |                           , ReturnProbe);                          \ | 
| 1493 | \ | 
| 1494 | JNI_ENTRY(ResultType, \ | 
| 1495 |           jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \ | 
| 1496 |   JNIWrapper("Call" XSTR(Result) "MethodA"); \ | 
| 1497 |   EntryProbe; \ | 
| 1498 |   ResultType ret = 0;\ | 
| 1499 |   DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \ | 
| 1500 |                      (const ResultType&)ret);\ | 
| 1501 | \ | 
| 1502 |   JavaValue jvalue(Tag); \ | 
| 1503 |   JNI_ArgumentPusherArray ap(methodID, args); \ | 
| 1504 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ | 
| 1505 |   ret = jvalue.get_##ResultType(); \ | 
| 1506 |   return ret;\ | 
| 1507 | JNI_END | 
| 1508 |  | 
| 1509 | // the runtime type of subword integral basic types is integer | 
| 1510 | DEFINE_CALLMETHODA(jboolean, Boolean, T_BOOLEAN | 
| 1511 |                   , HOTSPOT_JNI_CALLBOOLEANMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1512 |                   HOTSPOT_JNI_CALLBOOLEANMETHODA_RETURN(_ret_ref)) | 
| 1513 | DEFINE_CALLMETHODA(jbyte,    Byte,    T_BYTE | 
| 1514 |                   , HOTSPOT_JNI_CALLBYTEMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1515 |                   HOTSPOT_JNI_CALLBYTEMETHODA_RETURN(_ret_ref)) | 
| 1516 | DEFINE_CALLMETHODA(jchar,    Char,    T_CHAR | 
| 1517 |                   , HOTSPOT_JNI_CALLCHARMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1518 |                   HOTSPOT_JNI_CALLCHARMETHODA_RETURN(_ret_ref)) | 
| 1519 | DEFINE_CALLMETHODA(jshort,   Short,   T_SHORT | 
| 1520 |                   , HOTSPOT_JNI_CALLSHORTMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1521 |                   HOTSPOT_JNI_CALLSHORTMETHODA_RETURN(_ret_ref)) | 
| 1522 |  | 
| 1523 | DEFINE_CALLMETHODA(jobject,  Object,  T_OBJECT | 
| 1524 |                   , HOTSPOT_JNI_CALLOBJECTMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1525 |                   HOTSPOT_JNI_CALLOBJECTMETHODA_RETURN(_ret_ref)) | 
| 1526 | DEFINE_CALLMETHODA(jint,     Int,     T_INT, | 
| 1527 |                   HOTSPOT_JNI_CALLINTMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1528 |                   HOTSPOT_JNI_CALLINTMETHODA_RETURN(_ret_ref)) | 
| 1529 | DEFINE_CALLMETHODA(jlong,    Long,    T_LONG | 
| 1530 |                   , HOTSPOT_JNI_CALLLONGMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1531 |                   HOTSPOT_JNI_CALLLONGMETHODA_RETURN(_ret_ref)) | 
| 1532 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1533 | DEFINE_CALLMETHODA(jfloat,   Float,   T_FLOAT | 
| 1534 |                   , HOTSPOT_JNI_CALLFLOATMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1535 |                   HOTSPOT_JNI_CALLFLOATMETHODA_RETURN()) | 
| 1536 | DEFINE_CALLMETHODA(jdouble,  Double,  T_DOUBLE | 
| 1537 |                   , HOTSPOT_JNI_CALLDOUBLEMETHODA_ENTRY(env, obj, (uintptr_t)methodID), | 
| 1538 |                   HOTSPOT_JNI_CALLDOUBLEMETHODA_RETURN()) | 
| 1539 |  | 
| 1540 | DT_VOID_RETURN_MARK_DECL(CallVoidMethod, HOTSPOT_JNI_CALLVOIDMETHOD_RETURN()); | 
| 1541 | DT_VOID_RETURN_MARK_DECL(CallVoidMethodV, HOTSPOT_JNI_CALLVOIDMETHODV_RETURN()); | 
| 1542 | DT_VOID_RETURN_MARK_DECL(CallVoidMethodA, HOTSPOT_JNI_CALLVOIDMETHODA_RETURN()); | 
| 1543 |  | 
| 1544 |  | 
| 1545 | JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)) | 
| 1546 |   JNIWrapper("CallVoidMethod" ); | 
| 1547 |   HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY(env, obj, (uintptr_t) methodID); | 
| 1548 |   DT_VOID_RETURN_MARK(CallVoidMethod); | 
| 1549 |  | 
| 1550 |   va_list args; | 
| 1551 |   va_start(args, methodID); | 
| 1552 |   JavaValue jvalue(T_VOID); | 
| 1553 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1554 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK); | 
| 1555 |   va_end(args); | 
| 1556 | JNI_END | 
| 1557 |  | 
| 1558 |  | 
| 1559 | JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) | 
| 1560 |   JNIWrapper("CallVoidMethodV" ); | 
| 1561 |   HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY(env, obj, (uintptr_t) methodID); | 
| 1562 |   DT_VOID_RETURN_MARK(CallVoidMethodV); | 
| 1563 |  | 
| 1564 |   JavaValue jvalue(T_VOID); | 
| 1565 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1566 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK); | 
| 1567 | JNI_END | 
| 1568 |  | 
| 1569 |  | 
| 1570 | JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) | 
| 1571 |   JNIWrapper("CallVoidMethodA" ); | 
| 1572 |   HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY(env, obj, (uintptr_t) methodID); | 
| 1573 |   DT_VOID_RETURN_MARK(CallVoidMethodA); | 
| 1574 |  | 
| 1575 |   JavaValue jvalue(T_VOID); | 
| 1576 |   JNI_ArgumentPusherArray ap(methodID, args); | 
| 1577 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK); | 
| 1578 | JNI_END | 
| 1579 |  | 
| 1580 |  | 
| 1581 |  | 
| 1582 | #define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag \ | 
| 1583 |                                     , EntryProbe, ReturnProbe)      \ | 
| 1584 | \ | 
| 1585 |   DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType \ | 
| 1586 |                           , ReturnProbe);\ | 
| 1587 | \ | 
| 1588 | JNI_ENTRY(ResultType, \ | 
| 1589 |           jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \ | 
| 1590 |   JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \ | 
| 1591 | \ | 
| 1592 |   EntryProbe;\ | 
| 1593 |   ResultType ret;\ | 
| 1594 |   DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \ | 
| 1595 |                      (const ResultType&)ret);\ | 
| 1596 | \ | 
| 1597 |   va_list args; \ | 
| 1598 |   va_start(args, methodID); \ | 
| 1599 |   JavaValue jvalue(Tag); \ | 
| 1600 |   JNI_ArgumentPusherVaArg ap(methodID, args); \ | 
| 1601 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ | 
| 1602 |   va_end(args); \ | 
| 1603 |   ret = jvalue.get_##ResultType(); \ | 
| 1604 |   return ret;\ | 
| 1605 | JNI_END | 
| 1606 |  | 
| 1607 | // the runtime type of subword integral basic types is integer | 
| 1608 | DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN | 
| 1609 |                             , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1610 |                             HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN(_ret_ref)) | 
| 1611 | DEFINE_CALLNONVIRTUALMETHOD(jbyte,    Byte,    T_BYTE | 
| 1612 |                             , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1613 |                             HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN(_ret_ref)) | 
| 1614 | DEFINE_CALLNONVIRTUALMETHOD(jchar,    Char,    T_CHAR | 
| 1615 |                             , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1616 |                             HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN(_ret_ref)) | 
| 1617 | DEFINE_CALLNONVIRTUALMETHOD(jshort,   Short,   T_SHORT | 
| 1618 |                             , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1619 |                             HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN(_ret_ref)) | 
| 1620 |  | 
| 1621 | DEFINE_CALLNONVIRTUALMETHOD(jobject,  Object,  T_OBJECT | 
| 1622 |                             , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1623 |                             HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN(_ret_ref)) | 
| 1624 | DEFINE_CALLNONVIRTUALMETHOD(jint,     Int,     T_INT | 
| 1625 |                             , HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1626 |                             HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN(_ret_ref)) | 
| 1627 | DEFINE_CALLNONVIRTUALMETHOD(jlong,    Long,    T_LONG | 
| 1628 |                             , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1629 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1630 |                             HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN(_ret_ref)) | 
| 1631 | DEFINE_CALLNONVIRTUALMETHOD(jfloat,   Float,   T_FLOAT | 
| 1632 |                             , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1633 |                             HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN()) | 
| 1634 | DEFINE_CALLNONVIRTUALMETHOD(jdouble,  Double,  T_DOUBLE | 
| 1635 |                             , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1636 |                             HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN()) | 
| 1637 |  | 
| 1638 | #define DEFINE_CALLNONVIRTUALMETHODV(ResultType, Result, Tag \ | 
| 1639 |                                     , EntryProbe, ReturnProbe)      \ | 
| 1640 | \ | 
| 1641 |   DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType \ | 
| 1642 |                           , ReturnProbe);\ | 
| 1643 | \ | 
| 1644 | JNI_ENTRY(ResultType, \ | 
| 1645 |           jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \ | 
| 1646 |   JNIWrapper("CallNonvitual" XSTR(Result) "MethodV"); \ | 
| 1647 | \ | 
| 1648 |   EntryProbe;\ | 
| 1649 |   ResultType ret;\ | 
| 1650 |   DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \ | 
| 1651 |                      (const ResultType&)ret);\ | 
| 1652 | \ | 
| 1653 |   JavaValue jvalue(Tag); \ | 
| 1654 |   JNI_ArgumentPusherVaArg ap(methodID, args); \ | 
| 1655 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ | 
| 1656 |   ret = jvalue.get_##ResultType(); \ | 
| 1657 |   return ret;\ | 
| 1658 | JNI_END | 
| 1659 |  | 
| 1660 | // the runtime type of subword integral basic types is integer | 
| 1661 | DEFINE_CALLNONVIRTUALMETHODV(jboolean, Boolean, T_BOOLEAN | 
| 1662 |                             , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1663 |                             HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN(_ret_ref)) | 
| 1664 | DEFINE_CALLNONVIRTUALMETHODV(jbyte,    Byte,    T_BYTE | 
| 1665 |                             , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1666 |                             HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN(_ret_ref)) | 
| 1667 | DEFINE_CALLNONVIRTUALMETHODV(jchar,    Char,    T_CHAR | 
| 1668 |                             , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1669 |                             HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN(_ret_ref)) | 
| 1670 | DEFINE_CALLNONVIRTUALMETHODV(jshort,   Short,   T_SHORT | 
| 1671 |                             , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1672 |                             HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN(_ret_ref)) | 
| 1673 |  | 
| 1674 | DEFINE_CALLNONVIRTUALMETHODV(jobject,  Object,  T_OBJECT | 
| 1675 |                             , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1676 |                             HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN(_ret_ref)) | 
| 1677 | DEFINE_CALLNONVIRTUALMETHODV(jint,     Int,     T_INT | 
| 1678 |                             , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1679 |                             HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN(_ret_ref)) | 
| 1680 | DEFINE_CALLNONVIRTUALMETHODV(jlong,    Long,    T_LONG | 
| 1681 |                             , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1682 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1683 |                             HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN(_ret_ref)) | 
| 1684 | DEFINE_CALLNONVIRTUALMETHODV(jfloat,   Float,   T_FLOAT | 
| 1685 |                             , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1686 |                             HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN()) | 
| 1687 | DEFINE_CALLNONVIRTUALMETHODV(jdouble,  Double,  T_DOUBLE | 
| 1688 |                             , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1689 |                             HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN()) | 
| 1690 |  | 
| 1691 | #define DEFINE_CALLNONVIRTUALMETHODA(ResultType, Result, Tag \ | 
| 1692 |                                     , EntryProbe, ReturnProbe)      \ | 
| 1693 | \ | 
| 1694 |   DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType \ | 
| 1695 |                           , ReturnProbe);\ | 
| 1696 | \ | 
| 1697 | JNI_ENTRY(ResultType, \ | 
| 1698 |           jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \ | 
| 1699 |   JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \ | 
| 1700 | \ | 
| 1701 |   EntryProbe;\ | 
| 1702 |   ResultType ret;\ | 
| 1703 |   DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \ | 
| 1704 |                      (const ResultType&)ret);\ | 
| 1705 | \ | 
| 1706 |   JavaValue jvalue(Tag); \ | 
| 1707 |   JNI_ArgumentPusherArray ap(methodID, args); \ | 
| 1708 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ | 
| 1709 |   ret = jvalue.get_##ResultType(); \ | 
| 1710 |   return ret;\ | 
| 1711 | JNI_END | 
| 1712 |  | 
| 1713 | // the runtime type of subword integral basic types is integer | 
| 1714 | DEFINE_CALLNONVIRTUALMETHODA(jboolean, Boolean, T_BOOLEAN | 
| 1715 |                             , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1716 |                             HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN(_ret_ref)) | 
| 1717 | DEFINE_CALLNONVIRTUALMETHODA(jbyte,    Byte,    T_BYTE | 
| 1718 |                             , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1719 |                             HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN(_ret_ref)) | 
| 1720 | DEFINE_CALLNONVIRTUALMETHODA(jchar,    Char,    T_CHAR | 
| 1721 |                             , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1722 |                             HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN(_ret_ref)) | 
| 1723 | DEFINE_CALLNONVIRTUALMETHODA(jshort,   Short,   T_SHORT | 
| 1724 |                             , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1725 |                             HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN(_ret_ref)) | 
| 1726 |  | 
| 1727 | DEFINE_CALLNONVIRTUALMETHODA(jobject,  Object,  T_OBJECT | 
| 1728 |                             , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1729 |                             HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN(_ret_ref)) | 
| 1730 | DEFINE_CALLNONVIRTUALMETHODA(jint,     Int,     T_INT | 
| 1731 |                             , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1732 |                             HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN(_ret_ref)) | 
| 1733 | DEFINE_CALLNONVIRTUALMETHODA(jlong,    Long,    T_LONG | 
| 1734 |                             , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1735 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1736 |                             HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN(_ret_ref)) | 
| 1737 | DEFINE_CALLNONVIRTUALMETHODA(jfloat,   Float,   T_FLOAT | 
| 1738 |                             , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1739 |                             HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN()) | 
| 1740 | DEFINE_CALLNONVIRTUALMETHODA(jdouble,  Double,  T_DOUBLE | 
| 1741 |                             , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), | 
| 1742 |                             HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN()) | 
| 1743 |  | 
| 1744 | DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod | 
| 1745 |                          , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN()); | 
| 1746 | DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV | 
| 1747 |                          , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN()); | 
| 1748 | DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA | 
| 1749 |                          , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN()); | 
| 1750 |  | 
| 1751 | JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) | 
| 1752 |   JNIWrapper("CallNonvirtualVoidMethod" ); | 
| 1753 |  | 
| 1754 |   HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY(env, obj, cls, (uintptr_t) methodID); | 
| 1755 |   DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod); | 
| 1756 |  | 
| 1757 |   va_list args; | 
| 1758 |   va_start(args, methodID); | 
| 1759 |   JavaValue jvalue(T_VOID); | 
| 1760 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1761 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK); | 
| 1762 |   va_end(args); | 
| 1763 | JNI_END | 
| 1764 |  | 
| 1765 |  | 
| 1766 | JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) | 
| 1767 |   JNIWrapper("CallNonvirtualVoidMethodV" ); | 
| 1768 |  | 
| 1769 |   HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY( | 
| 1770 |                env, obj, cls, (uintptr_t) methodID); | 
| 1771 |   DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV); | 
| 1772 |  | 
| 1773 |   JavaValue jvalue(T_VOID); | 
| 1774 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1775 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK); | 
| 1776 | JNI_END | 
| 1777 |  | 
| 1778 |  | 
| 1779 | JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) | 
| 1780 |   JNIWrapper("CallNonvirtualVoidMethodA" ); | 
| 1781 |   HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY( | 
| 1782 |                 env, obj, cls, (uintptr_t) methodID); | 
| 1783 |   DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA); | 
| 1784 |   JavaValue jvalue(T_VOID); | 
| 1785 |   JNI_ArgumentPusherArray ap(methodID, args); | 
| 1786 |   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK); | 
| 1787 | JNI_END | 
| 1788 |  | 
| 1789 |  | 
| 1790 |  | 
| 1791 | #define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag \ | 
| 1792 |                                 , EntryProbe, ResultProbe) \ | 
| 1793 | \ | 
| 1794 |   DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType \ | 
| 1795 |                           , ResultProbe);                               \ | 
| 1796 | \ | 
| 1797 | JNI_ENTRY(ResultType, \ | 
| 1798 |           jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \ | 
| 1799 |   JNIWrapper("CallStatic" XSTR(Result) "Method"); \ | 
| 1800 | \ | 
| 1801 |   EntryProbe; \ | 
| 1802 |   ResultType ret = 0;\ | 
| 1803 |   DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \ | 
| 1804 |                      (const ResultType&)ret);\ | 
| 1805 | \ | 
| 1806 |   va_list args; \ | 
| 1807 |   va_start(args, methodID); \ | 
| 1808 |   JavaValue jvalue(Tag); \ | 
| 1809 |   JNI_ArgumentPusherVaArg ap(methodID, args); \ | 
| 1810 |   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ | 
| 1811 |   va_end(args); \ | 
| 1812 |   ret = jvalue.get_##ResultType(); \ | 
| 1813 |   return ret;\ | 
| 1814 | JNI_END | 
| 1815 |  | 
| 1816 | // the runtime type of subword integral basic types is integer | 
| 1817 | DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN | 
| 1818 |                         , HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1819 |                         HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN(_ret_ref)); | 
| 1820 | DEFINE_CALLSTATICMETHOD(jbyte,    Byte,    T_BYTE | 
| 1821 |                         , HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1822 |                         HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN(_ret_ref)); | 
| 1823 | DEFINE_CALLSTATICMETHOD(jchar,    Char,    T_CHAR | 
| 1824 |                         , HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1825 |                         HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN(_ret_ref)); | 
| 1826 | DEFINE_CALLSTATICMETHOD(jshort,   Short,   T_SHORT | 
| 1827 |                         , HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1828 |                         HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN(_ret_ref)); | 
| 1829 |  | 
| 1830 | DEFINE_CALLSTATICMETHOD(jobject,  Object,  T_OBJECT | 
| 1831 |                         , HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1832 |                         HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN(_ret_ref)); | 
| 1833 | DEFINE_CALLSTATICMETHOD(jint,     Int,     T_INT | 
| 1834 |                         , HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1835 |                         HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN(_ret_ref)); | 
| 1836 | DEFINE_CALLSTATICMETHOD(jlong,    Long,    T_LONG | 
| 1837 |                         , HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1838 |                         HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN(_ret_ref)); | 
| 1839 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1840 | DEFINE_CALLSTATICMETHOD(jfloat,   Float,   T_FLOAT | 
| 1841 |                         , HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1842 |                         HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN()); | 
| 1843 | DEFINE_CALLSTATICMETHOD(jdouble,  Double,  T_DOUBLE | 
| 1844 |                         , HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1845 |                         HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN()); | 
| 1846 |  | 
| 1847 | #define DEFINE_CALLSTATICMETHODV(ResultType, Result, Tag \ | 
| 1848 |                                 , EntryProbe, ResultProbe) \ | 
| 1849 | \ | 
| 1850 |   DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType \ | 
| 1851 |                           , ResultProbe);                               \ | 
| 1852 | \ | 
| 1853 | JNI_ENTRY(ResultType, \ | 
| 1854 |           jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \ | 
| 1855 |   JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \ | 
| 1856 | \ | 
| 1857 |   EntryProbe; \ | 
| 1858 |   ResultType ret = 0;\ | 
| 1859 |   DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \ | 
| 1860 |                      (const ResultType&)ret);\ | 
| 1861 | \ | 
| 1862 |   JavaValue jvalue(Tag); \ | 
| 1863 |   JNI_ArgumentPusherVaArg ap(methodID, args); \ | 
| 1864 |   /* Make sure class is initialized before trying to invoke its method */ \ | 
| 1865 |   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); \ | 
| 1866 |   k->initialize(CHECK_0); \ | 
| 1867 |   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ | 
| 1868 |   va_end(args); \ | 
| 1869 |   ret = jvalue.get_##ResultType(); \ | 
| 1870 |   return ret;\ | 
| 1871 | JNI_END | 
| 1872 |  | 
| 1873 | // the runtime type of subword integral basic types is integer | 
| 1874 | DEFINE_CALLSTATICMETHODV(jboolean, Boolean, T_BOOLEAN | 
| 1875 |                         , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1876 |                         HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN(_ret_ref)); | 
| 1877 | DEFINE_CALLSTATICMETHODV(jbyte,    Byte,    T_BYTE | 
| 1878 |                         , HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1879 |                         HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN(_ret_ref)); | 
| 1880 | DEFINE_CALLSTATICMETHODV(jchar,    Char,    T_CHAR | 
| 1881 |                         , HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1882 |                         HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN(_ret_ref)); | 
| 1883 | DEFINE_CALLSTATICMETHODV(jshort,   Short,   T_SHORT | 
| 1884 |                         , HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1885 |                         HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN(_ret_ref)); | 
| 1886 |  | 
| 1887 | DEFINE_CALLSTATICMETHODV(jobject,  Object,  T_OBJECT | 
| 1888 |                         , HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1889 |                         HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN(_ret_ref)); | 
| 1890 | DEFINE_CALLSTATICMETHODV(jint,     Int,     T_INT | 
| 1891 |                         , HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1892 |                         HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN(_ret_ref)); | 
| 1893 | DEFINE_CALLSTATICMETHODV(jlong,    Long,    T_LONG | 
| 1894 |                         , HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1895 |                         HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN(_ret_ref)); | 
| 1896 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1897 | DEFINE_CALLSTATICMETHODV(jfloat,   Float,   T_FLOAT | 
| 1898 |                         , HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1899 |                         HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN()); | 
| 1900 | DEFINE_CALLSTATICMETHODV(jdouble,  Double,  T_DOUBLE | 
| 1901 |                         , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1902 |                         HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN()); | 
| 1903 |  | 
| 1904 | #define DEFINE_CALLSTATICMETHODA(ResultType, Result, Tag \ | 
| 1905 |                                 , EntryProbe, ResultProbe) \ | 
| 1906 | \ | 
| 1907 |   DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType \ | 
| 1908 |                           , ResultProbe);                               \ | 
| 1909 | \ | 
| 1910 | JNI_ENTRY(ResultType, \ | 
| 1911 |           jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \ | 
| 1912 |   JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \ | 
| 1913 | \ | 
| 1914 |   EntryProbe; \ | 
| 1915 |   ResultType ret = 0;\ | 
| 1916 |   DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \ | 
| 1917 |                      (const ResultType&)ret);\ | 
| 1918 | \ | 
| 1919 |   JavaValue jvalue(Tag); \ | 
| 1920 |   JNI_ArgumentPusherArray ap(methodID, args); \ | 
| 1921 |   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ | 
| 1922 |   ret = jvalue.get_##ResultType(); \ | 
| 1923 |   return ret;\ | 
| 1924 | JNI_END | 
| 1925 |  | 
| 1926 | // the runtime type of subword integral basic types is integer | 
| 1927 | DEFINE_CALLSTATICMETHODA(jboolean, Boolean, T_BOOLEAN | 
| 1928 |                         , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1929 |                         HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN(_ret_ref)); | 
| 1930 | DEFINE_CALLSTATICMETHODA(jbyte,    Byte,    T_BYTE | 
| 1931 |                         , HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1932 |                         HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN(_ret_ref)); | 
| 1933 | DEFINE_CALLSTATICMETHODA(jchar,    Char,    T_CHAR | 
| 1934 |                         , HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1935 |                         HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN(_ret_ref)); | 
| 1936 | DEFINE_CALLSTATICMETHODA(jshort,   Short,   T_SHORT | 
| 1937 |                         , HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1938 |                         HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN(_ret_ref)); | 
| 1939 |  | 
| 1940 | DEFINE_CALLSTATICMETHODA(jobject,  Object,  T_OBJECT | 
| 1941 |                         , HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1942 |                         HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN(_ret_ref)); | 
| 1943 | DEFINE_CALLSTATICMETHODA(jint,     Int,     T_INT | 
| 1944 |                         , HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1945 |                         HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN(_ret_ref)); | 
| 1946 | DEFINE_CALLSTATICMETHODA(jlong,    Long,    T_LONG | 
| 1947 |                         , HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1948 |                         HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN(_ret_ref)); | 
| 1949 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 1950 | DEFINE_CALLSTATICMETHODA(jfloat,   Float,   T_FLOAT | 
| 1951 |                         , HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1952 |                         HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN()); | 
| 1953 | DEFINE_CALLSTATICMETHODA(jdouble,  Double,  T_DOUBLE | 
| 1954 |                         , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY(env, cls, (uintptr_t)methodID), | 
| 1955 |                         HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN()); | 
| 1956 |  | 
| 1957 | DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod | 
| 1958 |                          , HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN()); | 
| 1959 | DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV | 
| 1960 |                          , HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN()); | 
| 1961 | DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA | 
| 1962 |                          , HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN()); | 
| 1963 |  | 
| 1964 | JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)) | 
| 1965 |   JNIWrapper("CallStaticVoidMethod" ); | 
| 1966 |   HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY(env, cls, (uintptr_t) methodID); | 
| 1967 |   DT_VOID_RETURN_MARK(CallStaticVoidMethod); | 
| 1968 |  | 
| 1969 |   va_list args; | 
| 1970 |   va_start(args, methodID); | 
| 1971 |   JavaValue jvalue(T_VOID); | 
| 1972 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1973 |   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK); | 
| 1974 |   va_end(args); | 
| 1975 | JNI_END | 
| 1976 |  | 
| 1977 |  | 
| 1978 | JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) | 
| 1979 |   JNIWrapper("CallStaticVoidMethodV" ); | 
| 1980 |   HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY(env, cls, (uintptr_t) methodID); | 
| 1981 |   DT_VOID_RETURN_MARK(CallStaticVoidMethodV); | 
| 1982 |  | 
| 1983 |   JavaValue jvalue(T_VOID); | 
| 1984 |   JNI_ArgumentPusherVaArg ap(methodID, args); | 
| 1985 |   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK); | 
| 1986 | JNI_END | 
| 1987 |  | 
| 1988 |  | 
| 1989 | JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) | 
| 1990 |   JNIWrapper("CallStaticVoidMethodA" ); | 
| 1991 |   HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY(env, cls, (uintptr_t) methodID); | 
| 1992 |   DT_VOID_RETURN_MARK(CallStaticVoidMethodA); | 
| 1993 |  | 
| 1994 |   JavaValue jvalue(T_VOID); | 
| 1995 |   JNI_ArgumentPusherArray ap(methodID, args); | 
| 1996 |   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK); | 
| 1997 | JNI_END | 
| 1998 |  | 
| 1999 |  | 
| 2000 | // | 
| 2001 | // Accessing Fields | 
| 2002 | // | 
| 2003 |  | 
| 2004 |  | 
| 2005 | DT_RETURN_MARK_DECL(GetFieldID, jfieldID | 
| 2006 |                     , HOTSPOT_JNI_GETFIELDID_RETURN((uintptr_t)_ret_ref)); | 
| 2007 |  | 
| 2008 | JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, | 
| 2009 |           const char *name, const char *sig)) | 
| 2010 |   JNIWrapper("GetFieldID" ); | 
| 2011 |   HOTSPOT_JNI_GETFIELDID_ENTRY(env, clazz, (char *) name, (char *) sig); | 
| 2012 |   jfieldID ret = 0; | 
| 2013 |   DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret); | 
| 2014 |  | 
| 2015 |   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); | 
| 2016 |  | 
| 2017 |   // The class should have been loaded (we have an instance of the class | 
| 2018 |   // passed in) so the field and signature should already be in the symbol | 
| 2019 |   // table.  If they're not there, the field doesn't exist. | 
| 2020 |   TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name)); | 
| 2021 |   TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig)); | 
| 2022 |   if (fieldname == NULL || signame == NULL) { | 
| 2023 |     ResourceMark rm; | 
| 2024 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s" , k->external_name(), name, sig)); | 
| 2025 |   } | 
| 2026 |  | 
| 2027 |   // Make sure class is initialized before handing id's out to fields | 
| 2028 |   k->initialize(CHECK_NULL); | 
| 2029 |  | 
| 2030 |   fieldDescriptor fd; | 
| 2031 |   if (!k->is_instance_klass() || | 
| 2032 |       !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) { | 
| 2033 |     ResourceMark rm; | 
| 2034 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s" , k->external_name(), name, sig)); | 
| 2035 |   } | 
| 2036 |  | 
| 2037 |   // A jfieldID for a non-static field is simply the offset of the field within the instanceOop | 
| 2038 |   // It may also have hash bits for k, if VerifyJNIFields is turned on. | 
| 2039 |   ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset()); | 
| 2040 |   return ret; | 
| 2041 | JNI_END | 
| 2042 |  | 
| 2043 |  | 
| 2044 | JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)) | 
| 2045 |   JNIWrapper("GetObjectField" ); | 
| 2046 |   HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID); | 
| 2047 |   oop o = JNIHandles::resolve_non_null(obj); | 
| 2048 |   Klass* k = o->klass(); | 
| 2049 |   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); | 
| 2050 |   // Keep JVMTI addition small and only check enabled flag here. | 
| 2051 |   // jni_GetField_probe() assumes that is okay to create handles. | 
| 2052 |   if (JvmtiExport::should_post_field_access()) { | 
| 2053 |     o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); | 
| 2054 |   } | 
| 2055 |   oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset); | 
| 2056 |   jobject ret = JNIHandles::make_local(env, loaded_obj); | 
| 2057 |   HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret); | 
| 2058 |   return ret; | 
| 2059 | JNI_END | 
| 2060 |  | 
| 2061 |  | 
| 2062 |  | 
| 2063 | #define DEFINE_GETFIELD(Return,Fieldname,Result \ | 
| 2064 |   , EntryProbe, ReturnProbe) \ | 
| 2065 | \ | 
| 2066 |   DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \ | 
| 2067 |   , ReturnProbe); \ | 
| 2068 | \ | 
| 2069 | JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \ | 
| 2070 |   JNIWrapper("Get" XSTR(Result) "Field"); \ | 
| 2071 | \ | 
| 2072 |   EntryProbe; \ | 
| 2073 |   Return ret = 0;\ | 
| 2074 |   DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\ | 
| 2075 | \ | 
| 2076 |   oop o = JNIHandles::resolve_non_null(obj); \ | 
| 2077 |   Klass* k = o->klass(); \ | 
| 2078 |   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);  \ | 
| 2079 |   /* Keep JVMTI addition small and only check enabled flag here.       */ \ | 
| 2080 |   /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \ | 
| 2081 |   /* and creates a ResetNoHandleMark.                                   */ \ | 
| 2082 |   if (JvmtiExport::should_post_field_access()) { \ | 
| 2083 |     o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \ | 
| 2084 |   } \ | 
| 2085 |   ret = o->Fieldname##_field(offset); \ | 
| 2086 |   return ret; \ | 
| 2087 | JNI_END | 
| 2088 |  | 
| 2089 | DEFINE_GETFIELD(jboolean, bool,   Boolean | 
| 2090 |                 , HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2091 |                 HOTSPOT_JNI_GETBOOLEANFIELD_RETURN(_ret_ref)) | 
| 2092 | DEFINE_GETFIELD(jbyte,    byte,   Byte | 
| 2093 |                 , HOTSPOT_JNI_GETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2094 |                 HOTSPOT_JNI_GETBYTEFIELD_RETURN(_ret_ref)) | 
| 2095 | DEFINE_GETFIELD(jchar,    char,   Char | 
| 2096 |                 , HOTSPOT_JNI_GETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2097 |                 HOTSPOT_JNI_GETCHARFIELD_RETURN(_ret_ref)) | 
| 2098 | DEFINE_GETFIELD(jshort,   short,  Short | 
| 2099 |                 , HOTSPOT_JNI_GETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2100 |                 HOTSPOT_JNI_GETSHORTFIELD_RETURN(_ret_ref)) | 
| 2101 | DEFINE_GETFIELD(jint,     int,    Int | 
| 2102 |                 , HOTSPOT_JNI_GETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2103 |                 HOTSPOT_JNI_GETINTFIELD_RETURN(_ret_ref)) | 
| 2104 | DEFINE_GETFIELD(jlong,    long,   Long | 
| 2105 |                 , HOTSPOT_JNI_GETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2106 |                 HOTSPOT_JNI_GETLONGFIELD_RETURN(_ret_ref)) | 
| 2107 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 2108 | DEFINE_GETFIELD(jfloat,   float,  Float | 
| 2109 |                 , HOTSPOT_JNI_GETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2110 |                 HOTSPOT_JNI_GETFLOATFIELD_RETURN()) | 
| 2111 | DEFINE_GETFIELD(jdouble,  double, Double | 
| 2112 |                 , HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2113 |                 HOTSPOT_JNI_GETDOUBLEFIELD_RETURN()) | 
| 2114 |  | 
| 2115 | address jni_GetBooleanField_addr() { | 
| 2116 |   return (address)jni_GetBooleanField; | 
| 2117 | } | 
| 2118 | address jni_GetByteField_addr() { | 
| 2119 |   return (address)jni_GetByteField; | 
| 2120 | } | 
| 2121 | address jni_GetCharField_addr() { | 
| 2122 |   return (address)jni_GetCharField; | 
| 2123 | } | 
| 2124 | address jni_GetShortField_addr() { | 
| 2125 |   return (address)jni_GetShortField; | 
| 2126 | } | 
| 2127 | address jni_GetIntField_addr() { | 
| 2128 |   return (address)jni_GetIntField; | 
| 2129 | } | 
| 2130 | address jni_GetLongField_addr() { | 
| 2131 |   return (address)jni_GetLongField; | 
| 2132 | } | 
| 2133 | address jni_GetFloatField_addr() { | 
| 2134 |   return (address)jni_GetFloatField; | 
| 2135 | } | 
| 2136 | address jni_GetDoubleField_addr() { | 
| 2137 |   return (address)jni_GetDoubleField; | 
| 2138 | } | 
| 2139 |  | 
| 2140 | JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)) | 
| 2141 |   JNIWrapper("SetObjectField" ); | 
| 2142 |   HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value); | 
| 2143 |   oop o = JNIHandles::resolve_non_null(obj); | 
| 2144 |   Klass* k = o->klass(); | 
| 2145 |   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); | 
| 2146 |   // Keep JVMTI addition small and only check enabled flag here. | 
| 2147 |   // jni_SetField_probe_nh() assumes that is not okay to create handles | 
| 2148 |   // and creates a ResetNoHandleMark. | 
| 2149 |   if (JvmtiExport::should_post_field_modification()) { | 
| 2150 |     jvalue field_value; | 
| 2151 |     field_value.l = value; | 
| 2152 |     o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value); | 
| 2153 |   } | 
| 2154 |   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value)); | 
| 2155 |   HOTSPOT_JNI_SETOBJECTFIELD_RETURN(); | 
| 2156 | JNI_END | 
| 2157 |  | 
| 2158 |  | 
| 2159 | #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \ | 
| 2160 |                         , EntryProbe, ReturnProbe) \ | 
| 2161 | \ | 
| 2162 | JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \ | 
| 2163 |   JNIWrapper("Set" XSTR(Result) "Field"); \ | 
| 2164 | \ | 
| 2165 |   EntryProbe; \ | 
| 2166 | \ | 
| 2167 |   oop o = JNIHandles::resolve_non_null(obj); \ | 
| 2168 |   Klass* k = o->klass(); \ | 
| 2169 |   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);  \ | 
| 2170 |   /* Keep JVMTI addition small and only check enabled flag here.       */ \ | 
| 2171 |   /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \ | 
| 2172 |   /* and creates a ResetNoHandleMark.                                   */ \ | 
| 2173 |   if (JvmtiExport::should_post_field_modification()) { \ | 
| 2174 |     jvalue field_value; \ | 
| 2175 |     field_value.unionType = value; \ | 
| 2176 |     o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ | 
| 2177 |   } \ | 
| 2178 |   if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ | 
| 2179 |   o->Fieldname##_field_put(offset, value); \ | 
| 2180 |   ReturnProbe; \ | 
| 2181 | JNI_END | 
| 2182 |  | 
| 2183 | DEFINE_SETFIELD(jboolean, bool,   Boolean, 'Z', z | 
| 2184 |                 , HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), | 
| 2185 |                 HOTSPOT_JNI_SETBOOLEANFIELD_RETURN()) | 
| 2186 | DEFINE_SETFIELD(jbyte,    byte,   Byte,    'B', b | 
| 2187 |                 , HOTSPOT_JNI_SETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), | 
| 2188 |                 HOTSPOT_JNI_SETBYTEFIELD_RETURN()) | 
| 2189 | DEFINE_SETFIELD(jchar,    char,   Char,    'C', c | 
| 2190 |                 , HOTSPOT_JNI_SETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), | 
| 2191 |                 HOTSPOT_JNI_SETCHARFIELD_RETURN()) | 
| 2192 | DEFINE_SETFIELD(jshort,   short,  Short,   'S', s | 
| 2193 |                 , HOTSPOT_JNI_SETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), | 
| 2194 |                 HOTSPOT_JNI_SETSHORTFIELD_RETURN()) | 
| 2195 | DEFINE_SETFIELD(jint,     int,    Int,     'I', i | 
| 2196 |                 , HOTSPOT_JNI_SETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), | 
| 2197 |                 HOTSPOT_JNI_SETINTFIELD_RETURN()) | 
| 2198 | DEFINE_SETFIELD(jlong,    long,   Long,    'J', j | 
| 2199 |                 , HOTSPOT_JNI_SETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), | 
| 2200 |                 HOTSPOT_JNI_SETLONGFIELD_RETURN()) | 
| 2201 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 2202 | DEFINE_SETFIELD(jfloat,   float,  Float,   'F', f | 
| 2203 |                 , HOTSPOT_JNI_SETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2204 |                 HOTSPOT_JNI_SETFLOATFIELD_RETURN()) | 
| 2205 | DEFINE_SETFIELD(jdouble,  double, Double,  'D', d | 
| 2206 |                 , HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), | 
| 2207 |                 HOTSPOT_JNI_SETDOUBLEFIELD_RETURN()) | 
| 2208 |  | 
| 2209 | DT_RETURN_MARK_DECL(ToReflectedField, jobject | 
| 2210 |                     , HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(_ret_ref)); | 
| 2211 |  | 
| 2212 | JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic)) | 
| 2213 |   JNIWrapper("ToReflectedField" ); | 
| 2214 |   HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY(env, cls, (uintptr_t) fieldID, isStatic); | 
| 2215 |   jobject ret = NULL; | 
| 2216 |   DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret); | 
| 2217 |  | 
| 2218 |   fieldDescriptor fd; | 
| 2219 |   bool found = false; | 
| 2220 |   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); | 
| 2221 |  | 
| 2222 |   assert(jfieldIDWorkaround::is_static_jfieldID(fieldID) == (isStatic != 0), "invalid fieldID" ); | 
| 2223 |  | 
| 2224 |   if (isStatic) { | 
| 2225 |     // Static field. The fieldID a JNIid specifying the field holder and the offset within the Klass*. | 
| 2226 |     JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); | 
| 2227 |     assert(id->is_static_field_id(), "invalid static field id" ); | 
| 2228 |     found = id->find_local_field(&fd); | 
| 2229 |   } else { | 
| 2230 |     // Non-static field. The fieldID is really the offset of the field within the instanceOop. | 
| 2231 |     int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); | 
| 2232 |     found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, &fd); | 
| 2233 |   } | 
| 2234 |   assert(found, "bad fieldID passed into jni_ToReflectedField" ); | 
| 2235 |   oop reflected = Reflection::new_field(&fd, CHECK_NULL); | 
| 2236 |   ret = JNIHandles::make_local(env, reflected); | 
| 2237 |   return ret; | 
| 2238 | JNI_END | 
| 2239 |  | 
| 2240 |  | 
| 2241 | // | 
| 2242 | // Accessing Static Fields | 
| 2243 | // | 
| 2244 | DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID | 
| 2245 |                     , HOTSPOT_JNI_GETSTATICFIELDID_RETURN((uintptr_t)_ret_ref)); | 
| 2246 |  | 
| 2247 | JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, | 
| 2248 |           const char *name, const char *sig)) | 
| 2249 |   JNIWrapper("GetStaticFieldID" ); | 
| 2250 |   HOTSPOT_JNI_GETSTATICFIELDID_ENTRY(env, clazz, (char *) name, (char *) sig); | 
| 2251 |   jfieldID ret = NULL; | 
| 2252 |   DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret); | 
| 2253 |  | 
| 2254 |   // The class should have been loaded (we have an instance of the class | 
| 2255 |   // passed in) so the field and signature should already be in the symbol | 
| 2256 |   // table.  If they're not there, the field doesn't exist. | 
| 2257 |   TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name)); | 
| 2258 |   TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig)); | 
| 2259 |   if (fieldname == NULL || signame == NULL) { | 
| 2260 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); | 
| 2261 |   } | 
| 2262 |   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); | 
| 2263 |   // Make sure class is initialized before handing id's out to static fields | 
| 2264 |   k->initialize(CHECK_NULL); | 
| 2265 |  | 
| 2266 |   fieldDescriptor fd; | 
| 2267 |   if (!k->is_instance_klass() || | 
| 2268 |       !InstanceKlass::cast(k)->find_field(fieldname, signame, true, &fd)) { | 
| 2269 |     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); | 
| 2270 |   } | 
| 2271 |  | 
| 2272 |   // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass* | 
| 2273 |   JNIid* id = fd.field_holder()->jni_id_for(fd.offset()); | 
| 2274 |   debug_only(id->set_is_static_field_id();) | 
| 2275 |  | 
| 2276 |   debug_only(id->verify(fd.field_holder())); | 
| 2277 |  | 
| 2278 |   ret = jfieldIDWorkaround::to_static_jfieldID(id); | 
| 2279 |   return ret; | 
| 2280 | JNI_END | 
| 2281 |  | 
| 2282 |  | 
| 2283 | JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)) | 
| 2284 |   JNIWrapper("GetStaticObjectField" ); | 
| 2285 |   HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID); | 
| 2286 | #if INCLUDE_JNI_CHECK | 
| 2287 |   DEBUG_ONLY(Klass* param_k = jniCheck::validate_class(thread, clazz);) | 
| 2288 | #endif // INCLUDE_JNI_CHECK | 
| 2289 |   JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); | 
| 2290 |   assert(id->is_static_field_id(), "invalid static field id" ); | 
| 2291 |   // Keep JVMTI addition small and only check enabled flag here. | 
| 2292 |   // jni_GetField_probe() assumes that is okay to create handles. | 
| 2293 |   if (JvmtiExport::should_post_field_access()) { | 
| 2294 |     JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); | 
| 2295 |   } | 
| 2296 |   jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset())); | 
| 2297 |   HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(ret); | 
| 2298 |   return ret; | 
| 2299 | JNI_END | 
| 2300 |  | 
| 2301 |  | 
| 2302 | #define DEFINE_GETSTATICFIELD(Return,Fieldname,Result \ | 
| 2303 |                               , EntryProbe, ReturnProbe) \ | 
| 2304 | \ | 
| 2305 |   DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return \ | 
| 2306 |                           , ReturnProbe);                                          \ | 
| 2307 | \ | 
| 2308 | JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \ | 
| 2309 |   JNIWrapper("GetStatic" XSTR(Result) "Field"); \ | 
| 2310 |   EntryProbe; \ | 
| 2311 |   Return ret = 0;\ | 
| 2312 |   DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \ | 
| 2313 |                      (const Return&)ret);\ | 
| 2314 |   JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ | 
| 2315 |   assert(id->is_static_field_id(), "invalid static field id"); \ | 
| 2316 |   /* Keep JVMTI addition small and only check enabled flag here. */ \ | 
| 2317 |   /* jni_GetField_probe() assumes that is okay to create handles. */ \ | 
| 2318 |   if (JvmtiExport::should_post_field_access()) { \ | 
| 2319 |     JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \ | 
| 2320 |   } \ | 
| 2321 |   ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \ | 
| 2322 |   return ret;\ | 
| 2323 | JNI_END | 
| 2324 |  | 
| 2325 | DEFINE_GETSTATICFIELD(jboolean, bool,   Boolean | 
| 2326 |                       , HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(_ret_ref)) | 
| 2327 | DEFINE_GETSTATICFIELD(jbyte,    byte,   Byte | 
| 2328 |                       , HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),    HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(_ret_ref)   ) | 
| 2329 | DEFINE_GETSTATICFIELD(jchar,    char,   Char | 
| 2330 |                       , HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),    HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(_ret_ref)   ) | 
| 2331 | DEFINE_GETSTATICFIELD(jshort,   short,  Short | 
| 2332 |                       , HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),   HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(_ret_ref)  ) | 
| 2333 | DEFINE_GETSTATICFIELD(jint,     int,    Int | 
| 2334 |                       , HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),     HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(_ret_ref)    ) | 
| 2335 | DEFINE_GETSTATICFIELD(jlong,    long,   Long | 
| 2336 |                       , HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),    HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(_ret_ref)   ) | 
| 2337 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 2338 | DEFINE_GETSTATICFIELD(jfloat,   float,  Float | 
| 2339 |                       , HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),   HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN()          ) | 
| 2340 | DEFINE_GETSTATICFIELD(jdouble,  double, Double | 
| 2341 |                       , HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),  HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN()         ) | 
| 2342 |  | 
| 2343 | JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)) | 
| 2344 |   JNIWrapper("SetStaticObjectField" ); | 
| 2345 |  HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value); | 
| 2346 |   JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); | 
| 2347 |   assert(id->is_static_field_id(), "invalid static field id" ); | 
| 2348 |   // Keep JVMTI addition small and only check enabled flag here. | 
| 2349 |   // jni_SetField_probe() assumes that is okay to create handles. | 
| 2350 |   if (JvmtiExport::should_post_field_modification()) { | 
| 2351 |     jvalue field_value; | 
| 2352 |     field_value.l = value; | 
| 2353 |     JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value); | 
| 2354 |   } | 
| 2355 |   id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value)); | 
| 2356 |   HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN(); | 
| 2357 | JNI_END | 
| 2358 |  | 
| 2359 |  | 
| 2360 |  | 
| 2361 | #define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType \ | 
| 2362 |                               , EntryProbe, ReturnProbe) \ | 
| 2363 | \ | 
| 2364 | JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \ | 
| 2365 |   JNIWrapper("SetStatic" XSTR(Result) "Field"); \ | 
| 2366 |   EntryProbe; \ | 
| 2367 | \ | 
| 2368 |   JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ | 
| 2369 |   assert(id->is_static_field_id(), "invalid static field id"); \ | 
| 2370 |   /* Keep JVMTI addition small and only check enabled flag here. */ \ | 
| 2371 |   /* jni_SetField_probe() assumes that is okay to create handles. */ \ | 
| 2372 |   if (JvmtiExport::should_post_field_modification()) { \ | 
| 2373 |     jvalue field_value; \ | 
| 2374 |     field_value.unionType = value; \ | 
| 2375 |     JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ | 
| 2376 |   } \ | 
| 2377 |   if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ | 
| 2378 |   id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ | 
| 2379 |   ReturnProbe;\ | 
| 2380 | JNI_END | 
| 2381 |  | 
| 2382 | DEFINE_SETSTATICFIELD(jboolean, bool,   Boolean, 'Z', z | 
| 2383 |                       , HOTSPOT_JNI_SETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t)fieldID, value), | 
| 2384 |                       HOTSPOT_JNI_SETSTATICBOOLEANFIELD_RETURN()) | 
| 2385 | DEFINE_SETSTATICFIELD(jbyte,    byte,   Byte,    'B', b | 
| 2386 |                       , HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), | 
| 2387 |                       HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN()) | 
| 2388 | DEFINE_SETSTATICFIELD(jchar,    char,   Char,    'C', c | 
| 2389 |                       , HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), | 
| 2390 |                       HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN()) | 
| 2391 | DEFINE_SETSTATICFIELD(jshort,   short,  Short,   'S', s | 
| 2392 |                       , HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), | 
| 2393 |                       HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN()) | 
| 2394 | DEFINE_SETSTATICFIELD(jint,     int,    Int,     'I', i | 
| 2395 |                       , HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), | 
| 2396 |                       HOTSPOT_JNI_SETSTATICINTFIELD_RETURN()) | 
| 2397 | DEFINE_SETSTATICFIELD(jlong,    long,   Long,    'J', j | 
| 2398 |                       , HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), | 
| 2399 |                       HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN()) | 
| 2400 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 2401 | DEFINE_SETSTATICFIELD(jfloat,   float,  Float,   'F', f | 
| 2402 |                       , HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), | 
| 2403 |                       HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN()) | 
| 2404 | DEFINE_SETSTATICFIELD(jdouble,  double, Double,  'D', d | 
| 2405 |                       , HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), | 
| 2406 |                       HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN()) | 
| 2407 |  | 
| 2408 | // | 
| 2409 | // String Operations | 
| 2410 | // | 
| 2411 |  | 
| 2412 | // Unicode Interface | 
| 2413 |  | 
| 2414 | DT_RETURN_MARK_DECL(NewString, jstring | 
| 2415 |                     , HOTSPOT_JNI_NEWSTRING_RETURN(_ret_ref)); | 
| 2416 |  | 
| 2417 | JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len)) | 
| 2418 |   JNIWrapper("NewString" ); | 
| 2419 |  HOTSPOT_JNI_NEWSTRING_ENTRY(env, (uint16_t *) unicodeChars, len); | 
| 2420 |   jstring ret = NULL; | 
| 2421 |   DT_RETURN_MARK(NewString, jstring, (const jstring&)ret); | 
| 2422 |   oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL); | 
| 2423 |   ret = (jstring) JNIHandles::make_local(env, string); | 
| 2424 |   return ret; | 
| 2425 | JNI_END | 
| 2426 |  | 
| 2427 |  | 
| 2428 | JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string)) | 
| 2429 |   JNIWrapper("GetStringLength" ); | 
| 2430 |   HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(env, string); | 
| 2431 |   jsize ret = 0; | 
| 2432 |   oop s = JNIHandles::resolve_non_null(string); | 
| 2433 |   ret = java_lang_String::length(s); | 
| 2434 |  HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(ret); | 
| 2435 |   return ret; | 
| 2436 | JNI_END | 
| 2437 |  | 
| 2438 |  | 
| 2439 | JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars( | 
| 2440 |   JNIEnv *env, jstring string, jboolean *isCopy)) | 
| 2441 |   JNIWrapper("GetStringChars" ); | 
| 2442 |  HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(env, string, (uintptr_t *) isCopy); | 
| 2443 |   jchar* buf = NULL; | 
| 2444 |   oop s = JNIHandles::resolve_non_null(string); | 
| 2445 |   typeArrayOop s_value = java_lang_String::value(s); | 
| 2446 |   if (s_value != NULL) { | 
| 2447 |     int s_len = java_lang_String::length(s, s_value); | 
| 2448 |     bool is_latin1 = java_lang_String::is_latin1(s); | 
| 2449 |     buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal);  // add one for zero termination | 
| 2450 |     /* JNI Specification states return NULL on OOM */ | 
| 2451 |     if (buf != NULL) { | 
| 2452 |       if (s_len > 0) { | 
| 2453 |         if (!is_latin1) { | 
| 2454 |           ArrayAccess<>::arraycopy_to_native(s_value, (size_t) typeArrayOopDesc::element_offset<jchar>(0), | 
| 2455 |                                              buf, s_len); | 
| 2456 |         } else { | 
| 2457 |           for (int i = 0; i < s_len; i++) { | 
| 2458 |             buf[i] = ((jchar) s_value->byte_at(i)) & 0xff; | 
| 2459 |           } | 
| 2460 |         } | 
| 2461 |       } | 
| 2462 |       buf[s_len] = 0; | 
| 2463 |       //%note jni_5 | 
| 2464 |       if (isCopy != NULL) { | 
| 2465 |         *isCopy = JNI_TRUE; | 
| 2466 |       } | 
| 2467 |     } | 
| 2468 |   } | 
| 2469 |   HOTSPOT_JNI_GETSTRINGCHARS_RETURN(buf); | 
| 2470 |   return buf; | 
| 2471 | JNI_END | 
| 2472 |  | 
| 2473 |  | 
| 2474 | JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)) | 
| 2475 |   JNIWrapper("ReleaseStringChars" ); | 
| 2476 |   HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY(env, str, (uint16_t *) chars); | 
| 2477 |   //%note jni_6 | 
| 2478 |   if (chars != NULL) { | 
| 2479 |     // Since String objects are supposed to be immutable, don't copy any | 
| 2480 |     // new data back.  A bad user will have to go after the char array. | 
| 2481 |     FreeHeap((void*) chars); | 
| 2482 |   } | 
| 2483 |   HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN(); | 
| 2484 | JNI_END | 
| 2485 |  | 
| 2486 |  | 
| 2487 | // UTF Interface | 
| 2488 |  | 
| 2489 | DT_RETURN_MARK_DECL(NewStringUTF, jstring | 
| 2490 |                     , HOTSPOT_JNI_NEWSTRINGUTF_RETURN(_ret_ref)); | 
| 2491 |  | 
| 2492 | JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes)) | 
| 2493 |   JNIWrapper("NewStringUTF" ); | 
| 2494 |   HOTSPOT_JNI_NEWSTRINGUTF_ENTRY(env, (char *) bytes); | 
| 2495 |   jstring ret; | 
| 2496 |   DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret); | 
| 2497 |  | 
| 2498 |   oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL); | 
| 2499 |   ret = (jstring) JNIHandles::make_local(env, result); | 
| 2500 |   return ret; | 
| 2501 | JNI_END | 
| 2502 |  | 
| 2503 |  | 
| 2504 | JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string)) | 
| 2505 |   JNIWrapper("GetStringUTFLength" ); | 
| 2506 |  HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(env, string); | 
| 2507 |   oop java_string = JNIHandles::resolve_non_null(string); | 
| 2508 |   jsize ret = java_lang_String::utf8_length(java_string); | 
| 2509 |   HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(ret); | 
| 2510 |   return ret; | 
| 2511 | JNI_END | 
| 2512 |  | 
| 2513 |  | 
| 2514 | JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)) | 
| 2515 |   JNIWrapper("GetStringUTFChars" ); | 
| 2516 |  HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(env, string, (uintptr_t *) isCopy); | 
| 2517 |   char* result = NULL; | 
| 2518 |   oop java_string = JNIHandles::resolve_non_null(string); | 
| 2519 |   typeArrayOop s_value = java_lang_String::value(java_string); | 
| 2520 |   if (s_value != NULL) { | 
| 2521 |     size_t length = java_lang_String::utf8_length(java_string, s_value); | 
| 2522 |     /* JNI Specification states return NULL on OOM */ | 
| 2523 |     result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL); | 
| 2524 |     if (result != NULL) { | 
| 2525 |       java_lang_String::as_utf8_string(java_string, s_value, result, (int) length + 1); | 
| 2526 |       if (isCopy != NULL) { | 
| 2527 |         *isCopy = JNI_TRUE; | 
| 2528 |       } | 
| 2529 |     } | 
| 2530 |   } | 
| 2531 |  HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN(result); | 
| 2532 |   return result; | 
| 2533 | JNI_END | 
| 2534 |  | 
| 2535 |  | 
| 2536 | JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars)) | 
| 2537 |   JNIWrapper("ReleaseStringUTFChars" ); | 
| 2538 |  HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY(env, str, (char *) chars); | 
| 2539 |   if (chars != NULL) { | 
| 2540 |     FreeHeap((char*) chars); | 
| 2541 |   } | 
| 2542 | HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN(); | 
| 2543 | JNI_END | 
| 2544 |  | 
| 2545 |  | 
| 2546 | JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array)) | 
| 2547 |   JNIWrapper("GetArrayLength" ); | 
| 2548 |  HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(env, array); | 
| 2549 |   arrayOop a = arrayOop(JNIHandles::resolve_non_null(array)); | 
| 2550 |   assert(a->is_array(), "must be array" ); | 
| 2551 |   jsize ret = a->length(); | 
| 2552 |  HOTSPOT_JNI_GETARRAYLENGTH_RETURN(ret); | 
| 2553 |   return ret; | 
| 2554 | JNI_END | 
| 2555 |  | 
| 2556 |  | 
| 2557 | // | 
| 2558 | // Object Array Operations | 
| 2559 | // | 
| 2560 |  | 
| 2561 | DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray | 
| 2562 |                     , HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(_ret_ref)); | 
| 2563 |  | 
| 2564 | JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)) | 
| 2565 |   JNIWrapper("NewObjectArray" ); | 
| 2566 |  HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(env, length, elementClass, initialElement); | 
| 2567 |   jobjectArray ret = NULL; | 
| 2568 |   DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret); | 
| 2569 |   Klass* ek = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass)); | 
| 2570 |   Klass* ak = ek->array_klass(CHECK_NULL); | 
| 2571 |   ObjArrayKlass::cast(ak)->initialize(CHECK_NULL); | 
| 2572 |   objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL); | 
| 2573 |   oop initial_value = JNIHandles::resolve(initialElement); | 
| 2574 |   if (initial_value != NULL) {  // array already initialized with NULL | 
| 2575 |     for (int index = 0; index < length; index++) { | 
| 2576 |       result->obj_at_put(index, initial_value); | 
| 2577 |     } | 
| 2578 |   } | 
| 2579 |   ret = (jobjectArray) JNIHandles::make_local(env, result); | 
| 2580 |   return ret; | 
| 2581 | JNI_END | 
| 2582 |  | 
| 2583 | DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject | 
| 2584 |                     , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref)); | 
| 2585 |  | 
| 2586 | JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)) | 
| 2587 |   JNIWrapper("GetObjectArrayElement" ); | 
| 2588 |  HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index); | 
| 2589 |   jobject ret = NULL; | 
| 2590 |   DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); | 
| 2591 |   objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); | 
| 2592 |   if (a->is_within_bounds(index)) { | 
| 2593 |     ret = JNIHandles::make_local(env, a->obj_at(index)); | 
| 2594 |     return ret; | 
| 2595 |   } else { | 
| 2596 |     ResourceMark rm(THREAD); | 
| 2597 |     stringStream ss; | 
| 2598 |     ss.print("Index %d out of bounds for length %d" , index, a->length()); | 
| 2599 |     THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); | 
| 2600 |   } | 
| 2601 | JNI_END | 
| 2602 |  | 
| 2603 | DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement | 
| 2604 |                          , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN()); | 
| 2605 |  | 
| 2606 | JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)) | 
| 2607 |   JNIWrapper("SetObjectArrayElement" ); | 
| 2608 |  HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value); | 
| 2609 |   DT_VOID_RETURN_MARK(SetObjectArrayElement); | 
| 2610 |  | 
| 2611 |   objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); | 
| 2612 |   oop v = JNIHandles::resolve(value); | 
| 2613 |   if (a->is_within_bounds(index)) { | 
| 2614 |     if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) { | 
| 2615 |       a->obj_at_put(index, v); | 
| 2616 |     } else { | 
| 2617 |       ResourceMark rm(THREAD); | 
| 2618 |       stringStream ss; | 
| 2619 |       Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass(); | 
| 2620 |       ss.print("type mismatch: can not store %s to %s[%d]" , | 
| 2621 |                v->klass()->external_name(), | 
| 2622 |                bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(), | 
| 2623 |                index); | 
| 2624 |       for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) { | 
| 2625 |         ss.print("[]" ); | 
| 2626 |       } | 
| 2627 |       THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string()); | 
| 2628 |     } | 
| 2629 |   } else { | 
| 2630 |     ResourceMark rm(THREAD); | 
| 2631 |     stringStream ss; | 
| 2632 |     ss.print("Index %d out of bounds for length %d" , index, a->length()); | 
| 2633 |     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); | 
| 2634 |   } | 
| 2635 | JNI_END | 
| 2636 |  | 
| 2637 |  | 
| 2638 |  | 
| 2639 | #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \ | 
| 2640 |                               ,EntryProbe,ReturnProbe)  \ | 
| 2641 | \ | 
| 2642 |   DT_RETURN_MARK_DECL(New##Result##Array, Return \ | 
| 2643 |                       , ReturnProbe); \ | 
| 2644 | \ | 
| 2645 | JNI_ENTRY(Return, \ | 
| 2646 |           jni_New##Result##Array(JNIEnv *env, jsize len)) \ | 
| 2647 |   JNIWrapper("New" XSTR(Result) "Array"); \ | 
| 2648 |   EntryProbe; \ | 
| 2649 |   Return ret = NULL;\ | 
| 2650 |   DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\ | 
| 2651 | \ | 
| 2652 |   oop obj= oopFactory::Allocator(len, CHECK_0); \ | 
| 2653 |   ret = (Return) JNIHandles::make_local(env, obj); \ | 
| 2654 |   return ret;\ | 
| 2655 | JNI_END | 
| 2656 |  | 
| 2657 | DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray,   Boolean, | 
| 2658 |                       HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY(env, len), | 
| 2659 |                       HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN(_ret_ref)) | 
| 2660 | DEFINE_NEWSCALARARRAY(jbyteArray,    new_byteArray,   Byte, | 
| 2661 |                       HOTSPOT_JNI_NEWBYTEARRAY_ENTRY(env, len), | 
| 2662 |                       HOTSPOT_JNI_NEWBYTEARRAY_RETURN(_ret_ref)) | 
| 2663 | DEFINE_NEWSCALARARRAY(jshortArray,   new_shortArray,  Short, | 
| 2664 |                       HOTSPOT_JNI_NEWSHORTARRAY_ENTRY(env, len), | 
| 2665 |                       HOTSPOT_JNI_NEWSHORTARRAY_RETURN(_ret_ref)) | 
| 2666 | DEFINE_NEWSCALARARRAY(jcharArray,    new_charArray,   Char, | 
| 2667 |                       HOTSPOT_JNI_NEWCHARARRAY_ENTRY(env, len), | 
| 2668 |                       HOTSPOT_JNI_NEWCHARARRAY_RETURN(_ret_ref)) | 
| 2669 | DEFINE_NEWSCALARARRAY(jintArray,     new_intArray,    Int, | 
| 2670 |                       HOTSPOT_JNI_NEWINTARRAY_ENTRY(env, len), | 
| 2671 |                       HOTSPOT_JNI_NEWINTARRAY_RETURN(_ret_ref)) | 
| 2672 | DEFINE_NEWSCALARARRAY(jlongArray,    new_longArray,   Long, | 
| 2673 |                       HOTSPOT_JNI_NEWLONGARRAY_ENTRY(env, len), | 
| 2674 |                       HOTSPOT_JNI_NEWLONGARRAY_RETURN(_ret_ref)) | 
| 2675 | DEFINE_NEWSCALARARRAY(jfloatArray,   new_floatArray,  Float, | 
| 2676 |                       HOTSPOT_JNI_NEWFLOATARRAY_ENTRY(env, len), | 
| 2677 |                       HOTSPOT_JNI_NEWFLOATARRAY_RETURN(_ret_ref)) | 
| 2678 | DEFINE_NEWSCALARARRAY(jdoubleArray,  new_doubleArray, Double, | 
| 2679 |                       HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(env, len), | 
| 2680 |                       HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(_ret_ref)) | 
| 2681 |  | 
| 2682 | // Return an address which will fault if the caller writes to it. | 
| 2683 |  | 
| 2684 | static char* get_bad_address() { | 
| 2685 |   static char* bad_address = NULL; | 
| 2686 |   if (bad_address == NULL) { | 
| 2687 |     size_t size = os::vm_allocation_granularity(); | 
| 2688 |     bad_address = os::reserve_memory(size); | 
| 2689 |     if (bad_address != NULL) { | 
| 2690 |       os::protect_memory(bad_address, size, os::MEM_PROT_READ, | 
| 2691 |                          /*is_committed*/false); | 
| 2692 |       MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal); | 
| 2693 |     } | 
| 2694 |   } | 
| 2695 |   return bad_address; | 
| 2696 | } | 
| 2697 |  | 
| 2698 |  | 
| 2699 |  | 
| 2700 | #define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag \ | 
| 2701 |                                       , EntryProbe, ReturnProbe) \ | 
| 2702 | \ | 
| 2703 | JNI_QUICK_ENTRY(ElementType*, \ | 
| 2704 |           jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \ | 
| 2705 |   JNIWrapper("Get" XSTR(Result) "ArrayElements"); \ | 
| 2706 |   EntryProbe; \ | 
| 2707 |   /* allocate an chunk of memory in c land */ \ | 
| 2708 |   typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | 
| 2709 |   ElementType* result; \ | 
| 2710 |   int len = a->length(); \ | 
| 2711 |   if (len == 0) { \ | 
| 2712 |     if (isCopy != NULL) { \ | 
| 2713 |       *isCopy = JNI_FALSE; \ | 
| 2714 |     } \ | 
| 2715 |     /* Empty array: legal but useless, can't return NULL. \ | 
| 2716 |      * Return a pointer to something useless. \ | 
| 2717 |      * Avoid asserts in typeArrayOop. */ \ | 
| 2718 |     result = (ElementType*)get_bad_address(); \ | 
| 2719 |   } else { \ | 
| 2720 |     /* JNI Specification states return NULL on OOM */                    \ | 
| 2721 |     result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \ | 
| 2722 |     if (result != NULL) {                                                \ | 
| 2723 |       /* copy the array to the c chunk */                                \ | 
| 2724 |       ArrayAccess<>::arraycopy_to_native(a, typeArrayOopDesc::element_offset<ElementType>(0), \ | 
| 2725 |                                          result, len);                   \ | 
| 2726 |       if (isCopy) {                                                      \ | 
| 2727 |         *isCopy = JNI_TRUE;                                              \ | 
| 2728 |       }                                                                  \ | 
| 2729 |     }                                                                    \ | 
| 2730 |   } \ | 
| 2731 |   ReturnProbe; \ | 
| 2732 |   return result; \ | 
| 2733 | JNI_END | 
| 2734 |  | 
| 2735 | DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool | 
| 2736 |                               , HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), | 
| 2737 |                               HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN((uintptr_t*)result)) | 
| 2738 | DEFINE_GETSCALARARRAYELEMENTS(T_BYTE,    jbyte,    Byte,    byte | 
| 2739 |                               , HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), | 
| 2740 |                               HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN((char*)result)) | 
| 2741 | DEFINE_GETSCALARARRAYELEMENTS(T_SHORT,   jshort,   Short,   short | 
| 2742 |                               , HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy), | 
| 2743 |                               HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN((uint16_t*)result)) | 
| 2744 | DEFINE_GETSCALARARRAYELEMENTS(T_CHAR,    jchar,    Char,    char | 
| 2745 |                               , HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy), | 
| 2746 |                               HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN(result)) | 
| 2747 | DEFINE_GETSCALARARRAYELEMENTS(T_INT,     jint,     Int,     int | 
| 2748 |                               , HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), | 
| 2749 |                               HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN((uint32_t*)result)) | 
| 2750 | DEFINE_GETSCALARARRAYELEMENTS(T_LONG,    jlong,    Long,    long | 
| 2751 |                               , HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), | 
| 2752 |                               HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN(((uintptr_t*)result))) | 
| 2753 | // Float and double probes don't return value because dtrace doesn't currently support it | 
| 2754 | DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT,   jfloat,   Float,   float | 
| 2755 |                               , HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), | 
| 2756 |                               HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN(result)) | 
| 2757 | DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE,  jdouble,  Double,  double | 
| 2758 |                               , HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), | 
| 2759 |                               HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(result)) | 
| 2760 |  | 
| 2761 |  | 
| 2762 | #define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag \ | 
| 2763 |                                           , EntryProbe, ReturnProbe);\ | 
| 2764 | \ | 
| 2765 | JNI_QUICK_ENTRY(void, \ | 
| 2766 |           jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \ | 
| 2767 |                                              ElementType *buf, jint mode)) \ | 
| 2768 |   JNIWrapper("Release" XSTR(Result) "ArrayElements"); \ | 
| 2769 |   EntryProbe; \ | 
| 2770 |   typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | 
| 2771 |   int len = a->length(); \ | 
| 2772 |   if (len != 0) {   /* Empty array:  nothing to free or copy. */  \ | 
| 2773 |     if ((mode == 0) || (mode == JNI_COMMIT)) { \ | 
| 2774 |       ArrayAccess<>::arraycopy_from_native(buf, a, typeArrayOopDesc::element_offset<ElementType>(0), len); \ | 
| 2775 |     } \ | 
| 2776 |     if ((mode == 0) || (mode == JNI_ABORT)) { \ | 
| 2777 |       FreeHeap(buf); \ | 
| 2778 |     } \ | 
| 2779 |   } \ | 
| 2780 |   ReturnProbe; \ | 
| 2781 | JNI_END | 
| 2782 |  | 
| 2783 | DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool | 
| 2784 |                                   , HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode), | 
| 2785 |                                   HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN()) | 
| 2786 | DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE,    jbyte,    Byte,    byte | 
| 2787 |                                   , HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY(env, array, (char *) buf, mode), | 
| 2788 |                                   HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN()) | 
| 2789 | DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT,   jshort,   Short,   short | 
| 2790 |                                   ,  HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode), | 
| 2791 |                                   HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN()) | 
| 2792 | DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR,    jchar,    Char,    char | 
| 2793 |                                   ,  HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode), | 
| 2794 |                                   HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN()) | 
| 2795 | DEFINE_RELEASESCALARARRAYELEMENTS(T_INT,     jint,     Int,     int | 
| 2796 |                                   , HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY(env, array, (uint32_t *) buf, mode), | 
| 2797 |                                   HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN()) | 
| 2798 | DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG,    jlong,    Long,    long | 
| 2799 |                                   , HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode), | 
| 2800 |                                   HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN()) | 
| 2801 | DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT,   jfloat,   Float,   float | 
| 2802 |                                   , HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY(env, array, (float *) buf, mode), | 
| 2803 |                                   HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN()) | 
| 2804 | DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE,  jdouble,  Double,  double | 
| 2805 |                                   , HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(env, array, (double *) buf, mode), | 
| 2806 |                                   HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN()) | 
| 2807 |  | 
| 2808 | static void check_bounds(jsize start, jsize copy_len, jsize array_len, TRAPS) { | 
| 2809 |   ResourceMark rm(THREAD); | 
| 2810 |   if (copy_len < 0) { | 
| 2811 |     stringStream ss; | 
| 2812 |     ss.print("Length %d is negative" , copy_len); | 
| 2813 |     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); | 
| 2814 |   } else if (start < 0 || (start > array_len - copy_len)) { | 
| 2815 |     stringStream ss; | 
| 2816 |     ss.print("Array region %d.."  INT64_FORMAT " out of bounds for length %d" , | 
| 2817 |              start, (int64_t)start+(int64_t)copy_len, array_len); | 
| 2818 |     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string()); | 
| 2819 |   } | 
| 2820 | } | 
| 2821 |  | 
| 2822 | #define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \ | 
| 2823 |                                     , EntryProbe, ReturnProbe); \ | 
| 2824 |   DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion \ | 
| 2825 |                            , ReturnProbe); \ | 
| 2826 | \ | 
| 2827 | JNI_ENTRY(void, \ | 
| 2828 | jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ | 
| 2829 |              jsize len, ElementType *buf)) \ | 
| 2830 |   JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \ | 
| 2831 |   EntryProbe; \ | 
| 2832 |   DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \ | 
| 2833 |   typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | 
| 2834 |   check_bounds(start, len, src->length(), CHECK); \ | 
| 2835 |   if (len > 0) {    \ | 
| 2836 |     ArrayAccess<>::arraycopy_to_native(src, typeArrayOopDesc::element_offset<ElementType>(start), buf, len); \ | 
| 2837 |   } \ | 
| 2838 | JNI_END | 
| 2839 |  | 
| 2840 | DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool | 
| 2841 |                             , HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf), | 
| 2842 |                             HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN()); | 
| 2843 | DEFINE_GETSCALARARRAYREGION(T_BYTE,    jbyte,   Byte,    byte | 
| 2844 |                             ,  HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf), | 
| 2845 |                             HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN()); | 
| 2846 | DEFINE_GETSCALARARRAYREGION(T_SHORT,   jshort,  Short,   short | 
| 2847 |                             , HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf), | 
| 2848 |                             HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN()); | 
| 2849 | DEFINE_GETSCALARARRAYREGION(T_CHAR,    jchar,   Char,    char | 
| 2850 |                             ,  HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t*) buf), | 
| 2851 |                             HOTSPOT_JNI_GETCHARARRAYREGION_RETURN()); | 
| 2852 | DEFINE_GETSCALARARRAYREGION(T_INT,     jint,    Int,     int | 
| 2853 |                             , HOTSPOT_JNI_GETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t*) buf), | 
| 2854 |                             HOTSPOT_JNI_GETINTARRAYREGION_RETURN()); | 
| 2855 | DEFINE_GETSCALARARRAYREGION(T_LONG,    jlong,   Long,    long | 
| 2856 |                             ,  HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf), | 
| 2857 |                             HOTSPOT_JNI_GETLONGARRAYREGION_RETURN()); | 
| 2858 | DEFINE_GETSCALARARRAYREGION(T_FLOAT,   jfloat,  Float,   float | 
| 2859 |                             , HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf), | 
| 2860 |                             HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN()); | 
| 2861 | DEFINE_GETSCALARARRAYREGION(T_DOUBLE,  jdouble, Double,  double | 
| 2862 |                             , HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf), | 
| 2863 |                             HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN()); | 
| 2864 |  | 
| 2865 |  | 
| 2866 | #define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \ | 
| 2867 |                                     , EntryProbe, ReturnProbe); \ | 
| 2868 |   DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion \ | 
| 2869 |                            ,ReturnProbe);           \ | 
| 2870 | \ | 
| 2871 | JNI_ENTRY(void, \ | 
| 2872 | jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ | 
| 2873 |              jsize len, const ElementType *buf)) \ | 
| 2874 |   JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \ | 
| 2875 |   EntryProbe; \ | 
| 2876 |   DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \ | 
| 2877 |   typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | 
| 2878 |   check_bounds(start, len, dst->length(), CHECK); \ | 
| 2879 |   if (len > 0) { \ | 
| 2880 |     ArrayAccess<>::arraycopy_from_native(buf, dst, typeArrayOopDesc::element_offset<ElementType>(start), len); \ | 
| 2881 |   } \ | 
| 2882 | JNI_END | 
| 2883 |  | 
| 2884 | DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool | 
| 2885 |                             , HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *)buf), | 
| 2886 |                             HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN()) | 
| 2887 | DEFINE_SETSCALARARRAYREGION(T_BYTE,    jbyte,    Byte,    byte | 
| 2888 |                             , HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf), | 
| 2889 |                             HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN()) | 
| 2890 | DEFINE_SETSCALARARRAYREGION(T_SHORT,   jshort,   Short,   short | 
| 2891 |                             , HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf), | 
| 2892 |                             HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN()) | 
| 2893 | DEFINE_SETSCALARARRAYREGION(T_CHAR,    jchar,    Char,    char | 
| 2894 |                             , HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf), | 
| 2895 |                             HOTSPOT_JNI_SETCHARARRAYREGION_RETURN()) | 
| 2896 | DEFINE_SETSCALARARRAYREGION(T_INT,     jint,     Int,     int | 
| 2897 |                             , HOTSPOT_JNI_SETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t *) buf), | 
| 2898 |                             HOTSPOT_JNI_SETINTARRAYREGION_RETURN()) | 
| 2899 | DEFINE_SETSCALARARRAYREGION(T_LONG,    jlong,    Long,    long | 
| 2900 |                             , HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf), | 
| 2901 |                             HOTSPOT_JNI_SETLONGARRAYREGION_RETURN()) | 
| 2902 | DEFINE_SETSCALARARRAYREGION(T_FLOAT,   jfloat,   Float,   float | 
| 2903 |                             , HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf), | 
| 2904 |                             HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN()) | 
| 2905 | DEFINE_SETSCALARARRAYREGION(T_DOUBLE,  jdouble,  Double,  double | 
| 2906 |                             , HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf), | 
| 2907 |                             HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN()) | 
| 2908 |  | 
| 2909 |  | 
| 2910 | // | 
| 2911 | // Interception of natives | 
| 2912 | // | 
| 2913 |  | 
| 2914 | // The RegisterNatives call being attempted tried to register with a method that | 
| 2915 | // is not native.  Ask JVM TI what prefixes have been specified.  Then check | 
| 2916 | // to see if the native method is now wrapped with the prefixes.  See the | 
| 2917 | // SetNativeMethodPrefix(es) functions in the JVM TI Spec for details. | 
| 2918 | static Method* find_prefixed_native(Klass* k, Symbol* name, Symbol* signature, TRAPS) { | 
| 2919 | #if INCLUDE_JVMTI | 
| 2920 |   ResourceMark rm(THREAD); | 
| 2921 |   Method* method; | 
| 2922 |   int name_len = name->utf8_length(); | 
| 2923 |   char* name_str = name->as_utf8(); | 
| 2924 |   int prefix_count; | 
| 2925 |   char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); | 
| 2926 |   for (int i = 0; i < prefix_count; i++) { | 
| 2927 |     char* prefix = prefixes[i]; | 
| 2928 |     int prefix_len = (int)strlen(prefix); | 
| 2929 |  | 
| 2930 |     // try adding this prefix to the method name and see if it matches another method name | 
| 2931 |     int trial_len = name_len + prefix_len; | 
| 2932 |     char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1); | 
| 2933 |     strcpy(trial_name_str, prefix); | 
| 2934 |     strcat(trial_name_str, name_str); | 
| 2935 |     TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len); | 
| 2936 |     if (trial_name == NULL) { | 
| 2937 |       continue; // no such symbol, so this prefix wasn't used, try the next prefix | 
| 2938 |     } | 
| 2939 |     method = k->lookup_method(trial_name, signature); | 
| 2940 |     if (method == NULL) { | 
| 2941 |       continue; // signature doesn't match, try the next prefix | 
| 2942 |     } | 
| 2943 |     if (method->is_native()) { | 
| 2944 |       method->set_is_prefixed_native(); | 
| 2945 |       return method; // wahoo, we found a prefixed version of the method, return it | 
| 2946 |     } | 
| 2947 |     // found as non-native, so prefix is good, add it, probably just need more prefixes | 
| 2948 |     name_len = trial_len; | 
| 2949 |     name_str = trial_name_str; | 
| 2950 |   } | 
| 2951 | #endif // INCLUDE_JVMTI | 
| 2952 |   return NULL; // not found | 
| 2953 | } | 
| 2954 |  | 
| 2955 | static bool register_native(Klass* k, Symbol* name, Symbol* signature, address entry, TRAPS) { | 
| 2956 |   Method* method = k->lookup_method(name, signature); | 
| 2957 |   if (method == NULL) { | 
| 2958 |     ResourceMark rm; | 
| 2959 |     stringStream st; | 
| 2960 |     st.print("Method '" ); | 
| 2961 |     Method::print_external_name(&st, k, name, signature); | 
| 2962 |     st.print("' name or signature does not match" ); | 
| 2963 |     THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); | 
| 2964 |   } | 
| 2965 |   if (!method->is_native()) { | 
| 2966 |     // trying to register to a non-native method, see if a JVM TI agent has added prefix(es) | 
| 2967 |     method = find_prefixed_native(k, name, signature, THREAD); | 
| 2968 |     if (method == NULL) { | 
| 2969 |       ResourceMark rm; | 
| 2970 |       stringStream st; | 
| 2971 |       st.print("Method '" ); | 
| 2972 |       Method::print_external_name(&st, k, name, signature); | 
| 2973 |       st.print("' is not declared as native" ); | 
| 2974 |       THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); | 
| 2975 |     } | 
| 2976 |   } | 
| 2977 |  | 
| 2978 |   if (entry != NULL) { | 
| 2979 |     method->set_native_function(entry, | 
| 2980 |       Method::native_bind_event_is_interesting); | 
| 2981 |   } else { | 
| 2982 |     method->clear_native_function(); | 
| 2983 |   } | 
| 2984 |   if (PrintJNIResolving) { | 
| 2985 |     ResourceMark rm(THREAD); | 
| 2986 |     tty->print_cr("[Registering JNI native method %s.%s]" , | 
| 2987 |       method->method_holder()->external_name(), | 
| 2988 |       method->name()->as_C_string()); | 
| 2989 |   } | 
| 2990 |   return true; | 
| 2991 | } | 
| 2992 |  | 
| 2993 | DT_RETURN_MARK_DECL(RegisterNatives, jint | 
| 2994 |                     , HOTSPOT_JNI_REGISTERNATIVES_RETURN(_ret_ref)); | 
| 2995 |  | 
| 2996 | JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz, | 
| 2997 |                                     const JNINativeMethod *methods, | 
| 2998 |                                     jint nMethods)) | 
| 2999 |   JNIWrapper("RegisterNatives" ); | 
| 3000 |   HOTSPOT_JNI_REGISTERNATIVES_ENTRY(env, clazz, (void *) methods, nMethods); | 
| 3001 |   jint ret = 0; | 
| 3002 |   DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret); | 
| 3003 |  | 
| 3004 |   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); | 
| 3005 |  | 
| 3006 |   for (int index = 0; index < nMethods; index++) { | 
| 3007 |     const char* meth_name = methods[index].name; | 
| 3008 |     const char* meth_sig = methods[index].signature; | 
| 3009 |     int meth_name_len = (int)strlen(meth_name); | 
| 3010 |  | 
| 3011 |     // The class should have been loaded (we have an instance of the class | 
| 3012 |     // passed in) so the method and signature should already be in the symbol | 
| 3013 |     // table.  If they're not there, the method doesn't exist. | 
| 3014 |     TempNewSymbol  name = SymbolTable::probe(meth_name, meth_name_len); | 
| 3015 |     TempNewSymbol  signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig)); | 
| 3016 |  | 
| 3017 |     if (name == NULL || signature == NULL) { | 
| 3018 |       ResourceMark rm; | 
| 3019 |       stringStream st; | 
| 3020 |       st.print("Method %s.%s%s not found" , k->external_name(), meth_name, meth_sig); | 
| 3021 |       // Must return negative value on failure | 
| 3022 |       THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1); | 
| 3023 |     } | 
| 3024 |  | 
| 3025 |     bool res = register_native(k, name, signature, | 
| 3026 |                                (address) methods[index].fnPtr, THREAD); | 
| 3027 |     if (!res) { | 
| 3028 |       ret = -1; | 
| 3029 |       break; | 
| 3030 |     } | 
| 3031 |   } | 
| 3032 |   return ret; | 
| 3033 | JNI_END | 
| 3034 |  | 
| 3035 |  | 
| 3036 | JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz)) | 
| 3037 |   JNIWrapper("UnregisterNatives" ); | 
| 3038 |  HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(env, clazz); | 
| 3039 |   Klass* k   = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); | 
| 3040 |   //%note jni_2 | 
| 3041 |   if (k->is_instance_klass()) { | 
| 3042 |     for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) { | 
| 3043 |       Method* m = InstanceKlass::cast(k)->methods()->at(index); | 
| 3044 |       if (m->is_native()) { | 
| 3045 |         m->clear_native_function(); | 
| 3046 |         m->set_signature_handler(NULL); | 
| 3047 |       } | 
| 3048 |     } | 
| 3049 |   } | 
| 3050 |  HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(0); | 
| 3051 |   return 0; | 
| 3052 | JNI_END | 
| 3053 |  | 
| 3054 | // | 
| 3055 | // Monitor functions | 
| 3056 | // | 
| 3057 |  | 
| 3058 | DT_RETURN_MARK_DECL(MonitorEnter, jint | 
| 3059 |                     , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref)); | 
| 3060 |  | 
| 3061 | JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj)) | 
| 3062 |  HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj); | 
| 3063 |   jint ret = JNI_ERR; | 
| 3064 |   DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret); | 
| 3065 |  | 
| 3066 |   // If the object is null, we can't do anything with it | 
| 3067 |   if (jobj == NULL) { | 
| 3068 |     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR); | 
| 3069 |   } | 
| 3070 |  | 
| 3071 |   Handle obj(thread, JNIHandles::resolve_non_null(jobj)); | 
| 3072 |   ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR)); | 
| 3073 |   ret = JNI_OK; | 
| 3074 |   return ret; | 
| 3075 | JNI_END | 
| 3076 |  | 
| 3077 | DT_RETURN_MARK_DECL(MonitorExit, jint | 
| 3078 |                     , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref)); | 
| 3079 |  | 
| 3080 | JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj)) | 
| 3081 |  HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj); | 
| 3082 |   jint ret = JNI_ERR; | 
| 3083 |   DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret); | 
| 3084 |  | 
| 3085 |   // Don't do anything with a null object | 
| 3086 |   if (jobj == NULL) { | 
| 3087 |     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR); | 
| 3088 |   } | 
| 3089 |  | 
| 3090 |   Handle obj(THREAD, JNIHandles::resolve_non_null(jobj)); | 
| 3091 |   ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR)); | 
| 3092 |  | 
| 3093 |   ret = JNI_OK; | 
| 3094 |   return ret; | 
| 3095 | JNI_END | 
| 3096 |  | 
| 3097 | // | 
| 3098 | // Extensions | 
| 3099 | // | 
| 3100 |  | 
| 3101 | DT_VOID_RETURN_MARK_DECL(GetStringRegion | 
| 3102 |                          , HOTSPOT_JNI_GETSTRINGREGION_RETURN()); | 
| 3103 |  | 
| 3104 | JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf)) | 
| 3105 |   JNIWrapper("GetStringRegion" ); | 
| 3106 |  HOTSPOT_JNI_GETSTRINGREGION_ENTRY(env, string, start, len, buf); | 
| 3107 |   DT_VOID_RETURN_MARK(GetStringRegion); | 
| 3108 |   oop s = JNIHandles::resolve_non_null(string); | 
| 3109 |   typeArrayOop s_value = java_lang_String::value(s); | 
| 3110 |   int s_len = java_lang_String::length(s, s_value); | 
| 3111 |   if (start < 0 || len < 0 || start > s_len - len) { | 
| 3112 |     THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); | 
| 3113 |   } else { | 
| 3114 |     if (len > 0) { | 
| 3115 |       bool is_latin1 = java_lang_String::is_latin1(s); | 
| 3116 |       if (!is_latin1) { | 
| 3117 |         ArrayAccess<>::arraycopy_to_native(s_value, typeArrayOopDesc::element_offset<jchar>(start), | 
| 3118 |                                            buf, len); | 
| 3119 |       } else { | 
| 3120 |         for (int i = 0; i < len; i++) { | 
| 3121 |           buf[i] = ((jchar) s_value->byte_at(i + start)) & 0xff; | 
| 3122 |         } | 
| 3123 |       } | 
| 3124 |     } | 
| 3125 |   } | 
| 3126 | JNI_END | 
| 3127 |  | 
| 3128 | DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion | 
| 3129 |                          , HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN()); | 
| 3130 |  | 
| 3131 | JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf)) | 
| 3132 |   JNIWrapper("GetStringUTFRegion" ); | 
| 3133 |  HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(env, string, start, len, buf); | 
| 3134 |   DT_VOID_RETURN_MARK(GetStringUTFRegion); | 
| 3135 |   oop s = JNIHandles::resolve_non_null(string); | 
| 3136 |   typeArrayOop s_value = java_lang_String::value(s); | 
| 3137 |   int s_len = java_lang_String::length(s, s_value); | 
| 3138 |   if (start < 0 || len < 0 || start > s_len - len) { | 
| 3139 |     THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); | 
| 3140 |   } else { | 
| 3141 |     //%note jni_7 | 
| 3142 |     if (len > 0) { | 
| 3143 |       // Assume the buffer is large enough as the JNI spec. does not require user error checking | 
| 3144 |       java_lang_String::as_utf8_string(s, s_value, start, len, buf, INT_MAX); | 
| 3145 |       // as_utf8_string null-terminates the result string | 
| 3146 |     } else { | 
| 3147 |       // JDK null-terminates the buffer even in len is zero | 
| 3148 |       if (buf != NULL) { | 
| 3149 |         buf[0] = 0; | 
| 3150 |       } | 
| 3151 |     } | 
| 3152 |   } | 
| 3153 | JNI_END | 
| 3154 |  | 
| 3155 | static oop lock_gc_or_pin_object(JavaThread* thread, jobject obj) { | 
| 3156 |   if (Universe::heap()->supports_object_pinning()) { | 
| 3157 |     const oop o = JNIHandles::resolve_non_null(obj); | 
| 3158 |     return Universe::heap()->pin_object(thread, o); | 
| 3159 |   } else { | 
| 3160 |     GCLocker::lock_critical(thread); | 
| 3161 |     return JNIHandles::resolve_non_null(obj); | 
| 3162 |   } | 
| 3163 | } | 
| 3164 |  | 
| 3165 | static void unlock_gc_or_unpin_object(JavaThread* thread, jobject obj) { | 
| 3166 |   if (Universe::heap()->supports_object_pinning()) { | 
| 3167 |     const oop o = JNIHandles::resolve_non_null(obj); | 
| 3168 |     return Universe::heap()->unpin_object(thread, o); | 
| 3169 |   } else { | 
| 3170 |     GCLocker::unlock_critical(thread); | 
| 3171 |   } | 
| 3172 | } | 
| 3173 |  | 
| 3174 | JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)) | 
| 3175 |   JNIWrapper("GetPrimitiveArrayCritical" ); | 
| 3176 |  HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(env, array, (uintptr_t *) isCopy); | 
| 3177 |   if (isCopy != NULL) { | 
| 3178 |     *isCopy = JNI_FALSE; | 
| 3179 |   } | 
| 3180 |   oop a = lock_gc_or_pin_object(thread, array); | 
| 3181 |   assert(a->is_array(), "just checking" ); | 
| 3182 |   BasicType type; | 
| 3183 |   if (a->is_objArray()) { | 
| 3184 |     type = T_OBJECT; | 
| 3185 |   } else { | 
| 3186 |     type = TypeArrayKlass::cast(a->klass())->element_type(); | 
| 3187 |   } | 
| 3188 |   void* ret = arrayOop(a)->base(type); | 
| 3189 |  HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN(ret); | 
| 3190 |   return ret; | 
| 3191 | JNI_END | 
| 3192 |  | 
| 3193 |  | 
| 3194 | JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)) | 
| 3195 |   JNIWrapper("ReleasePrimitiveArrayCritical" ); | 
| 3196 |   HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(env, array, carray, mode); | 
| 3197 |   unlock_gc_or_unpin_object(thread, array); | 
| 3198 | HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN(); | 
| 3199 | JNI_END | 
| 3200 |  | 
| 3201 |  | 
| 3202 | JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)) | 
| 3203 |   JNIWrapper("GetStringCritical" ); | 
| 3204 |   HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy); | 
| 3205 |   oop s = lock_gc_or_pin_object(thread, string); | 
| 3206 |   typeArrayOop s_value = java_lang_String::value(s); | 
| 3207 |   bool is_latin1 = java_lang_String::is_latin1(s); | 
| 3208 |   if (isCopy != NULL) { | 
| 3209 |     *isCopy = is_latin1 ? JNI_TRUE : JNI_FALSE; | 
| 3210 |   } | 
| 3211 |   jchar* ret; | 
| 3212 |   if (!is_latin1) { | 
| 3213 |     ret = (jchar*) s_value->base(T_CHAR); | 
| 3214 |   } else { | 
| 3215 |     // Inflate latin1 encoded string to UTF16 | 
| 3216 |     int s_len = java_lang_String::length(s, s_value); | 
| 3217 |     ret = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal);  // add one for zero termination | 
| 3218 |     /* JNI Specification states return NULL on OOM */ | 
| 3219 |     if (ret != NULL) { | 
| 3220 |       for (int i = 0; i < s_len; i++) { | 
| 3221 |         ret[i] = ((jchar) s_value->byte_at(i)) & 0xff; | 
| 3222 |       } | 
| 3223 |       ret[s_len] = 0; | 
| 3224 |     } | 
| 3225 |   } | 
| 3226 |  HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN((uint16_t *) ret); | 
| 3227 |   return ret; | 
| 3228 | JNI_END | 
| 3229 |  | 
| 3230 |  | 
| 3231 | JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars)) | 
| 3232 |   JNIWrapper("ReleaseStringCritical" ); | 
| 3233 |   HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars); | 
| 3234 |   // The str and chars arguments are ignored for UTF16 strings | 
| 3235 |   oop s = JNIHandles::resolve_non_null(str); | 
| 3236 |   bool is_latin1 = java_lang_String::is_latin1(s); | 
| 3237 |   if (is_latin1) { | 
| 3238 |     // For latin1 string, free jchar array allocated by earlier call to GetStringCritical. | 
| 3239 |     // This assumes that ReleaseStringCritical bookends GetStringCritical. | 
| 3240 |     FREE_C_HEAP_ARRAY(jchar, chars); | 
| 3241 |   } | 
| 3242 |   unlock_gc_or_unpin_object(thread, str); | 
| 3243 | HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN(); | 
| 3244 | JNI_END | 
| 3245 |  | 
| 3246 |  | 
| 3247 | JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref)) | 
| 3248 |   JNIWrapper("jni_NewWeakGlobalRef" ); | 
| 3249 |  HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref); | 
| 3250 |   Handle ref_handle(thread, JNIHandles::resolve(ref)); | 
| 3251 |   jweak ret = JNIHandles::make_weak_global(ref_handle); | 
| 3252 |  HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret); | 
| 3253 |   return ret; | 
| 3254 | JNI_END | 
| 3255 |  | 
| 3256 | // Must be JNI_ENTRY (with HandleMark) | 
| 3257 | JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref)) | 
| 3258 |   JNIWrapper("jni_DeleteWeakGlobalRef" ); | 
| 3259 |   HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref); | 
| 3260 |   JNIHandles::destroy_weak_global(ref); | 
| 3261 |   HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN(); | 
| 3262 | JNI_END | 
| 3263 |  | 
| 3264 |  | 
| 3265 | JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env)) | 
| 3266 |   JNIWrapper("jni_ExceptionCheck" ); | 
| 3267 |  HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env); | 
| 3268 |   jni_check_async_exceptions(thread); | 
| 3269 |   jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE; | 
| 3270 |  HOTSPOT_JNI_EXCEPTIONCHECK_RETURN(ret); | 
| 3271 |   return ret; | 
| 3272 | JNI_END | 
| 3273 |  | 
| 3274 |  | 
| 3275 | // Initialization state for three routines below relating to | 
| 3276 | // java.nio.DirectBuffers | 
| 3277 | static          int directBufferSupportInitializeStarted = 0; | 
| 3278 | static volatile int directBufferSupportInitializeEnded   = 0; | 
| 3279 | static volatile int directBufferSupportInitializeFailed  = 0; | 
| 3280 | static jclass    bufferClass                 = NULL; | 
| 3281 | static jclass    directBufferClass           = NULL; | 
| 3282 | static jclass    directByteBufferClass       = NULL; | 
| 3283 | static jmethodID directByteBufferConstructor = NULL; | 
| 3284 | static jfieldID  directBufferAddressField    = NULL; | 
| 3285 | static jfieldID  bufferCapacityField         = NULL; | 
| 3286 |  | 
| 3287 | static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) { | 
| 3288 |   Handle loader;            // null (bootstrap) loader | 
| 3289 |   Handle protection_domain; // null protection domain | 
| 3290 |  | 
| 3291 |   TempNewSymbol sym = SymbolTable::new_symbol(name); | 
| 3292 |   jclass result =  find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); | 
| 3293 |  | 
| 3294 |   if (log_is_enabled(Debug, class, resolve) && result != NULL) { | 
| 3295 |     trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); | 
| 3296 |   } | 
| 3297 |   return result; | 
| 3298 | } | 
| 3299 |  | 
| 3300 | // These lookups are done with the NULL (bootstrap) ClassLoader to | 
| 3301 | // circumvent any security checks that would be done by jni_FindClass. | 
| 3302 | JNI_ENTRY(bool, lookupDirectBufferClasses(JNIEnv* env)) | 
| 3303 | { | 
| 3304 |   if ((bufferClass           = lookupOne(env, "java/nio/Buffer" , thread))           == NULL) { return false; } | 
| 3305 |   if ((directBufferClass     = lookupOne(env, "sun/nio/ch/DirectBuffer" , thread))   == NULL) { return false; } | 
| 3306 |   if ((directByteBufferClass = lookupOne(env, "java/nio/DirectByteBuffer" , thread)) == NULL) { return false; } | 
| 3307 |   return true; | 
| 3308 | } | 
| 3309 | JNI_END | 
| 3310 |  | 
| 3311 |  | 
| 3312 | static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) { | 
| 3313 |   if (directBufferSupportInitializeFailed) { | 
| 3314 |     return false; | 
| 3315 |   } | 
| 3316 |  | 
| 3317 |   if (Atomic::cmpxchg(1, &directBufferSupportInitializeStarted, 0) == 0) { | 
| 3318 |     if (!lookupDirectBufferClasses(env)) { | 
| 3319 |       directBufferSupportInitializeFailed = 1; | 
| 3320 |       return false; | 
| 3321 |     } | 
| 3322 |  | 
| 3323 |     // Make global references for these | 
| 3324 |     bufferClass           = (jclass) env->NewGlobalRef(bufferClass); | 
| 3325 |     directBufferClass     = (jclass) env->NewGlobalRef(directBufferClass); | 
| 3326 |     directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass); | 
| 3327 |  | 
| 3328 |     // Get needed field and method IDs | 
| 3329 |     directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>" , "(JI)V" ); | 
| 3330 |     if (env->ExceptionCheck()) { | 
| 3331 |       env->ExceptionClear(); | 
| 3332 |       directBufferSupportInitializeFailed = 1; | 
| 3333 |       return false; | 
| 3334 |     } | 
| 3335 |     directBufferAddressField    = env->GetFieldID(bufferClass, "address" , "J" ); | 
| 3336 |     if (env->ExceptionCheck()) { | 
| 3337 |       env->ExceptionClear(); | 
| 3338 |       directBufferSupportInitializeFailed = 1; | 
| 3339 |       return false; | 
| 3340 |     } | 
| 3341 |     bufferCapacityField         = env->GetFieldID(bufferClass, "capacity" , "I" ); | 
| 3342 |     if (env->ExceptionCheck()) { | 
| 3343 |       env->ExceptionClear(); | 
| 3344 |       directBufferSupportInitializeFailed = 1; | 
| 3345 |       return false; | 
| 3346 |     } | 
| 3347 |  | 
| 3348 |     if ((directByteBufferConstructor == NULL) || | 
| 3349 |         (directBufferAddressField    == NULL) || | 
| 3350 |         (bufferCapacityField         == NULL)) { | 
| 3351 |       directBufferSupportInitializeFailed = 1; | 
| 3352 |       return false; | 
| 3353 |     } | 
| 3354 |  | 
| 3355 |     directBufferSupportInitializeEnded = 1; | 
| 3356 |   } else { | 
| 3357 |     while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) { | 
| 3358 |       os::naked_yield(); | 
| 3359 |     } | 
| 3360 |   } | 
| 3361 |  | 
| 3362 |   return !directBufferSupportInitializeFailed; | 
| 3363 | } | 
| 3364 |  | 
| 3365 | extern "C"  jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, jlong capacity) | 
| 3366 | { | 
| 3367 |   // thread_from_jni_environment() will block if VM is gone. | 
| 3368 |   JavaThread* thread = JavaThread::thread_from_jni_environment(env); | 
| 3369 |  | 
| 3370 |   JNIWrapper("jni_NewDirectByteBuffer" ); | 
| 3371 |  HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY(env, address, capacity); | 
| 3372 |  | 
| 3373 |   if (!directBufferSupportInitializeEnded) { | 
| 3374 |     if (!initializeDirectBufferSupport(env, thread)) { | 
| 3375 |       HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(NULL); | 
| 3376 |       return NULL; | 
| 3377 |     } | 
| 3378 |   } | 
| 3379 |  | 
| 3380 |   // Being paranoid about accidental sign extension on address | 
| 3381 |   jlong addr = (jlong) ((uintptr_t) address); | 
| 3382 |   // NOTE that package-private DirectByteBuffer constructor currently | 
| 3383 |   // takes int capacity | 
| 3384 |   jint  cap  = (jint)  capacity; | 
| 3385 |   jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap); | 
| 3386 |   HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(ret); | 
| 3387 |   return ret; | 
| 3388 | } | 
| 3389 |  | 
| 3390 | DT_RETURN_MARK_DECL(GetDirectBufferAddress, void* | 
| 3391 |                     , HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref)); | 
| 3392 |  | 
| 3393 | extern "C"  void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) | 
| 3394 | { | 
| 3395 |   // thread_from_jni_environment() will block if VM is gone. | 
| 3396 |   JavaThread* thread = JavaThread::thread_from_jni_environment(env); | 
| 3397 |  | 
| 3398 |   JNIWrapper("jni_GetDirectBufferAddress" ); | 
| 3399 |   HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY(env, buf); | 
| 3400 |   void* ret = NULL; | 
| 3401 |   DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret); | 
| 3402 |  | 
| 3403 |   if (!directBufferSupportInitializeEnded) { | 
| 3404 |     if (!initializeDirectBufferSupport(env, thread)) { | 
| 3405 |       return 0; | 
| 3406 |     } | 
| 3407 |   } | 
| 3408 |  | 
| 3409 |   if ((buf != NULL) && (!env->IsInstanceOf(buf, directBufferClass))) { | 
| 3410 |     return 0; | 
| 3411 |   } | 
| 3412 |  | 
| 3413 |   ret = (void*)(intptr_t)env->GetLongField(buf, directBufferAddressField); | 
| 3414 |   return ret; | 
| 3415 | } | 
| 3416 |  | 
| 3417 | DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong | 
| 3418 |                     , HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(_ret_ref)); | 
| 3419 |  | 
| 3420 | extern "C"  jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) | 
| 3421 | { | 
| 3422 |   // thread_from_jni_environment() will block if VM is gone. | 
| 3423 |   JavaThread* thread = JavaThread::thread_from_jni_environment(env); | 
| 3424 |  | 
| 3425 |   JNIWrapper("jni_GetDirectBufferCapacity" ); | 
| 3426 |   HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY(env, buf); | 
| 3427 |   jlong ret = -1; | 
| 3428 |   DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret); | 
| 3429 |  | 
| 3430 |   if (!directBufferSupportInitializeEnded) { | 
| 3431 |     if (!initializeDirectBufferSupport(env, thread)) { | 
| 3432 |       ret = 0; | 
| 3433 |       return ret; | 
| 3434 |     } | 
| 3435 |   } | 
| 3436 |  | 
| 3437 |   if (buf == NULL) { | 
| 3438 |     return -1; | 
| 3439 |   } | 
| 3440 |  | 
| 3441 |   if (!env->IsInstanceOf(buf, directBufferClass)) { | 
| 3442 |     return -1; | 
| 3443 |   } | 
| 3444 |  | 
| 3445 |   // NOTE that capacity is currently an int in the implementation | 
| 3446 |   ret = env->GetIntField(buf, bufferCapacityField); | 
| 3447 |   return ret; | 
| 3448 | } | 
| 3449 |  | 
| 3450 |  | 
| 3451 | JNI_LEAF(jint, jni_GetVersion(JNIEnv *env)) | 
| 3452 |   JNIWrapper("GetVersion" ); | 
| 3453 |   HOTSPOT_JNI_GETVERSION_ENTRY(env); | 
| 3454 |   HOTSPOT_JNI_GETVERSION_RETURN(CurrentVersion); | 
| 3455 |   return CurrentVersion; | 
| 3456 | JNI_END | 
| 3457 |  | 
| 3458 | extern struct JavaVM_ main_vm; | 
| 3459 |  | 
| 3460 | JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm)) | 
| 3461 |   JNIWrapper("jni_GetJavaVM" ); | 
| 3462 |   HOTSPOT_JNI_GETJAVAVM_ENTRY(env, (void **) vm); | 
| 3463 |   *vm  = (JavaVM *)(&main_vm); | 
| 3464 |   HOTSPOT_JNI_GETJAVAVM_RETURN(JNI_OK); | 
| 3465 |   return JNI_OK; | 
| 3466 | JNI_END | 
| 3467 |  | 
| 3468 |  | 
| 3469 | JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz)) | 
| 3470 |   JNIWrapper("GetModule" ); | 
| 3471 |   return Modules::get_module(clazz, THREAD); | 
| 3472 | JNI_END | 
| 3473 |  | 
| 3474 |  | 
| 3475 | // Structure containing all jni functions | 
| 3476 | struct JNINativeInterface_ jni_NativeInterface = { | 
| 3477 |     NULL, | 
| 3478 |     NULL, | 
| 3479 |     NULL, | 
| 3480 |  | 
| 3481 |     NULL, | 
| 3482 |  | 
| 3483 |     jni_GetVersion, | 
| 3484 |  | 
| 3485 |     jni_DefineClass, | 
| 3486 |     jni_FindClass, | 
| 3487 |  | 
| 3488 |     jni_FromReflectedMethod, | 
| 3489 |     jni_FromReflectedField, | 
| 3490 |  | 
| 3491 |     jni_ToReflectedMethod, | 
| 3492 |  | 
| 3493 |     jni_GetSuperclass, | 
| 3494 |     jni_IsAssignableFrom, | 
| 3495 |  | 
| 3496 |     jni_ToReflectedField, | 
| 3497 |  | 
| 3498 |     jni_Throw, | 
| 3499 |     jni_ThrowNew, | 
| 3500 |     jni_ExceptionOccurred, | 
| 3501 |     jni_ExceptionDescribe, | 
| 3502 |     jni_ExceptionClear, | 
| 3503 |     jni_FatalError, | 
| 3504 |  | 
| 3505 |     jni_PushLocalFrame, | 
| 3506 |     jni_PopLocalFrame, | 
| 3507 |  | 
| 3508 |     jni_NewGlobalRef, | 
| 3509 |     jni_DeleteGlobalRef, | 
| 3510 |     jni_DeleteLocalRef, | 
| 3511 |     jni_IsSameObject, | 
| 3512 |  | 
| 3513 |     jni_NewLocalRef, | 
| 3514 |     jni_EnsureLocalCapacity, | 
| 3515 |  | 
| 3516 |     jni_AllocObject, | 
| 3517 |     jni_NewObject, | 
| 3518 |     jni_NewObjectV, | 
| 3519 |     jni_NewObjectA, | 
| 3520 |  | 
| 3521 |     jni_GetObjectClass, | 
| 3522 |     jni_IsInstanceOf, | 
| 3523 |  | 
| 3524 |     jni_GetMethodID, | 
| 3525 |  | 
| 3526 |     jni_CallObjectMethod, | 
| 3527 |     jni_CallObjectMethodV, | 
| 3528 |     jni_CallObjectMethodA, | 
| 3529 |     jni_CallBooleanMethod, | 
| 3530 |     jni_CallBooleanMethodV, | 
| 3531 |     jni_CallBooleanMethodA, | 
| 3532 |     jni_CallByteMethod, | 
| 3533 |     jni_CallByteMethodV, | 
| 3534 |     jni_CallByteMethodA, | 
| 3535 |     jni_CallCharMethod, | 
| 3536 |     jni_CallCharMethodV, | 
| 3537 |     jni_CallCharMethodA, | 
| 3538 |     jni_CallShortMethod, | 
| 3539 |     jni_CallShortMethodV, | 
| 3540 |     jni_CallShortMethodA, | 
| 3541 |     jni_CallIntMethod, | 
| 3542 |     jni_CallIntMethodV, | 
| 3543 |     jni_CallIntMethodA, | 
| 3544 |     jni_CallLongMethod, | 
| 3545 |     jni_CallLongMethodV, | 
| 3546 |     jni_CallLongMethodA, | 
| 3547 |     jni_CallFloatMethod, | 
| 3548 |     jni_CallFloatMethodV, | 
| 3549 |     jni_CallFloatMethodA, | 
| 3550 |     jni_CallDoubleMethod, | 
| 3551 |     jni_CallDoubleMethodV, | 
| 3552 |     jni_CallDoubleMethodA, | 
| 3553 |     jni_CallVoidMethod, | 
| 3554 |     jni_CallVoidMethodV, | 
| 3555 |     jni_CallVoidMethodA, | 
| 3556 |  | 
| 3557 |     jni_CallNonvirtualObjectMethod, | 
| 3558 |     jni_CallNonvirtualObjectMethodV, | 
| 3559 |     jni_CallNonvirtualObjectMethodA, | 
| 3560 |     jni_CallNonvirtualBooleanMethod, | 
| 3561 |     jni_CallNonvirtualBooleanMethodV, | 
| 3562 |     jni_CallNonvirtualBooleanMethodA, | 
| 3563 |     jni_CallNonvirtualByteMethod, | 
| 3564 |     jni_CallNonvirtualByteMethodV, | 
| 3565 |     jni_CallNonvirtualByteMethodA, | 
| 3566 |     jni_CallNonvirtualCharMethod, | 
| 3567 |     jni_CallNonvirtualCharMethodV, | 
| 3568 |     jni_CallNonvirtualCharMethodA, | 
| 3569 |     jni_CallNonvirtualShortMethod, | 
| 3570 |     jni_CallNonvirtualShortMethodV, | 
| 3571 |     jni_CallNonvirtualShortMethodA, | 
| 3572 |     jni_CallNonvirtualIntMethod, | 
| 3573 |     jni_CallNonvirtualIntMethodV, | 
| 3574 |     jni_CallNonvirtualIntMethodA, | 
| 3575 |     jni_CallNonvirtualLongMethod, | 
| 3576 |     jni_CallNonvirtualLongMethodV, | 
| 3577 |     jni_CallNonvirtualLongMethodA, | 
| 3578 |     jni_CallNonvirtualFloatMethod, | 
| 3579 |     jni_CallNonvirtualFloatMethodV, | 
| 3580 |     jni_CallNonvirtualFloatMethodA, | 
| 3581 |     jni_CallNonvirtualDoubleMethod, | 
| 3582 |     jni_CallNonvirtualDoubleMethodV, | 
| 3583 |     jni_CallNonvirtualDoubleMethodA, | 
| 3584 |     jni_CallNonvirtualVoidMethod, | 
| 3585 |     jni_CallNonvirtualVoidMethodV, | 
| 3586 |     jni_CallNonvirtualVoidMethodA, | 
| 3587 |  | 
| 3588 |     jni_GetFieldID, | 
| 3589 |  | 
| 3590 |     jni_GetObjectField, | 
| 3591 |     jni_GetBooleanField, | 
| 3592 |     jni_GetByteField, | 
| 3593 |     jni_GetCharField, | 
| 3594 |     jni_GetShortField, | 
| 3595 |     jni_GetIntField, | 
| 3596 |     jni_GetLongField, | 
| 3597 |     jni_GetFloatField, | 
| 3598 |     jni_GetDoubleField, | 
| 3599 |  | 
| 3600 |     jni_SetObjectField, | 
| 3601 |     jni_SetBooleanField, | 
| 3602 |     jni_SetByteField, | 
| 3603 |     jni_SetCharField, | 
| 3604 |     jni_SetShortField, | 
| 3605 |     jni_SetIntField, | 
| 3606 |     jni_SetLongField, | 
| 3607 |     jni_SetFloatField, | 
| 3608 |     jni_SetDoubleField, | 
| 3609 |  | 
| 3610 |     jni_GetStaticMethodID, | 
| 3611 |  | 
| 3612 |     jni_CallStaticObjectMethod, | 
| 3613 |     jni_CallStaticObjectMethodV, | 
| 3614 |     jni_CallStaticObjectMethodA, | 
| 3615 |     jni_CallStaticBooleanMethod, | 
| 3616 |     jni_CallStaticBooleanMethodV, | 
| 3617 |     jni_CallStaticBooleanMethodA, | 
| 3618 |     jni_CallStaticByteMethod, | 
| 3619 |     jni_CallStaticByteMethodV, | 
| 3620 |     jni_CallStaticByteMethodA, | 
| 3621 |     jni_CallStaticCharMethod, | 
| 3622 |     jni_CallStaticCharMethodV, | 
| 3623 |     jni_CallStaticCharMethodA, | 
| 3624 |     jni_CallStaticShortMethod, | 
| 3625 |     jni_CallStaticShortMethodV, | 
| 3626 |     jni_CallStaticShortMethodA, | 
| 3627 |     jni_CallStaticIntMethod, | 
| 3628 |     jni_CallStaticIntMethodV, | 
| 3629 |     jni_CallStaticIntMethodA, | 
| 3630 |     jni_CallStaticLongMethod, | 
| 3631 |     jni_CallStaticLongMethodV, | 
| 3632 |     jni_CallStaticLongMethodA, | 
| 3633 |     jni_CallStaticFloatMethod, | 
| 3634 |     jni_CallStaticFloatMethodV, | 
| 3635 |     jni_CallStaticFloatMethodA, | 
| 3636 |     jni_CallStaticDoubleMethod, | 
| 3637 |     jni_CallStaticDoubleMethodV, | 
| 3638 |     jni_CallStaticDoubleMethodA, | 
| 3639 |     jni_CallStaticVoidMethod, | 
| 3640 |     jni_CallStaticVoidMethodV, | 
| 3641 |     jni_CallStaticVoidMethodA, | 
| 3642 |  | 
| 3643 |     jni_GetStaticFieldID, | 
| 3644 |  | 
| 3645 |     jni_GetStaticObjectField, | 
| 3646 |     jni_GetStaticBooleanField, | 
| 3647 |     jni_GetStaticByteField, | 
| 3648 |     jni_GetStaticCharField, | 
| 3649 |     jni_GetStaticShortField, | 
| 3650 |     jni_GetStaticIntField, | 
| 3651 |     jni_GetStaticLongField, | 
| 3652 |     jni_GetStaticFloatField, | 
| 3653 |     jni_GetStaticDoubleField, | 
| 3654 |  | 
| 3655 |     jni_SetStaticObjectField, | 
| 3656 |     jni_SetStaticBooleanField, | 
| 3657 |     jni_SetStaticByteField, | 
| 3658 |     jni_SetStaticCharField, | 
| 3659 |     jni_SetStaticShortField, | 
| 3660 |     jni_SetStaticIntField, | 
| 3661 |     jni_SetStaticLongField, | 
| 3662 |     jni_SetStaticFloatField, | 
| 3663 |     jni_SetStaticDoubleField, | 
| 3664 |  | 
| 3665 |     jni_NewString, | 
| 3666 |     jni_GetStringLength, | 
| 3667 |     jni_GetStringChars, | 
| 3668 |     jni_ReleaseStringChars, | 
| 3669 |  | 
| 3670 |     jni_NewStringUTF, | 
| 3671 |     jni_GetStringUTFLength, | 
| 3672 |     jni_GetStringUTFChars, | 
| 3673 |     jni_ReleaseStringUTFChars, | 
| 3674 |  | 
| 3675 |     jni_GetArrayLength, | 
| 3676 |  | 
| 3677 |     jni_NewObjectArray, | 
| 3678 |     jni_GetObjectArrayElement, | 
| 3679 |     jni_SetObjectArrayElement, | 
| 3680 |  | 
| 3681 |     jni_NewBooleanArray, | 
| 3682 |     jni_NewByteArray, | 
| 3683 |     jni_NewCharArray, | 
| 3684 |     jni_NewShortArray, | 
| 3685 |     jni_NewIntArray, | 
| 3686 |     jni_NewLongArray, | 
| 3687 |     jni_NewFloatArray, | 
| 3688 |     jni_NewDoubleArray, | 
| 3689 |  | 
| 3690 |     jni_GetBooleanArrayElements, | 
| 3691 |     jni_GetByteArrayElements, | 
| 3692 |     jni_GetCharArrayElements, | 
| 3693 |     jni_GetShortArrayElements, | 
| 3694 |     jni_GetIntArrayElements, | 
| 3695 |     jni_GetLongArrayElements, | 
| 3696 |     jni_GetFloatArrayElements, | 
| 3697 |     jni_GetDoubleArrayElements, | 
| 3698 |  | 
| 3699 |     jni_ReleaseBooleanArrayElements, | 
| 3700 |     jni_ReleaseByteArrayElements, | 
| 3701 |     jni_ReleaseCharArrayElements, | 
| 3702 |     jni_ReleaseShortArrayElements, | 
| 3703 |     jni_ReleaseIntArrayElements, | 
| 3704 |     jni_ReleaseLongArrayElements, | 
| 3705 |     jni_ReleaseFloatArrayElements, | 
| 3706 |     jni_ReleaseDoubleArrayElements, | 
| 3707 |  | 
| 3708 |     jni_GetBooleanArrayRegion, | 
| 3709 |     jni_GetByteArrayRegion, | 
| 3710 |     jni_GetCharArrayRegion, | 
| 3711 |     jni_GetShortArrayRegion, | 
| 3712 |     jni_GetIntArrayRegion, | 
| 3713 |     jni_GetLongArrayRegion, | 
| 3714 |     jni_GetFloatArrayRegion, | 
| 3715 |     jni_GetDoubleArrayRegion, | 
| 3716 |  | 
| 3717 |     jni_SetBooleanArrayRegion, | 
| 3718 |     jni_SetByteArrayRegion, | 
| 3719 |     jni_SetCharArrayRegion, | 
| 3720 |     jni_SetShortArrayRegion, | 
| 3721 |     jni_SetIntArrayRegion, | 
| 3722 |     jni_SetLongArrayRegion, | 
| 3723 |     jni_SetFloatArrayRegion, | 
| 3724 |     jni_SetDoubleArrayRegion, | 
| 3725 |  | 
| 3726 |     jni_RegisterNatives, | 
| 3727 |     jni_UnregisterNatives, | 
| 3728 |  | 
| 3729 |     jni_MonitorEnter, | 
| 3730 |     jni_MonitorExit, | 
| 3731 |  | 
| 3732 |     jni_GetJavaVM, | 
| 3733 |  | 
| 3734 |     jni_GetStringRegion, | 
| 3735 |     jni_GetStringUTFRegion, | 
| 3736 |  | 
| 3737 |     jni_GetPrimitiveArrayCritical, | 
| 3738 |     jni_ReleasePrimitiveArrayCritical, | 
| 3739 |  | 
| 3740 |     jni_GetStringCritical, | 
| 3741 |     jni_ReleaseStringCritical, | 
| 3742 |  | 
| 3743 |     jni_NewWeakGlobalRef, | 
| 3744 |     jni_DeleteWeakGlobalRef, | 
| 3745 |  | 
| 3746 |     jni_ExceptionCheck, | 
| 3747 |  | 
| 3748 |     jni_NewDirectByteBuffer, | 
| 3749 |     jni_GetDirectBufferAddress, | 
| 3750 |     jni_GetDirectBufferCapacity, | 
| 3751 |  | 
| 3752 |     // New 1_6 features | 
| 3753 |  | 
| 3754 |     jni_GetObjectRefType, | 
| 3755 |  | 
| 3756 |     // Module features | 
| 3757 |  | 
| 3758 |     jni_GetModule | 
| 3759 | }; | 
| 3760 |  | 
| 3761 |  | 
| 3762 | // For jvmti use to modify jni function table. | 
| 3763 | // Java threads in native contiues to run until it is transitioned | 
| 3764 | // to VM at safepoint. Before the transition or before it is blocked | 
| 3765 | // for safepoint it may access jni function table. VM could crash if | 
| 3766 | // any java thread access the jni function table in the middle of memcpy. | 
| 3767 | // To avoid this each function pointers are copied automically. | 
| 3768 | void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) { | 
| 3769 |   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint" ); | 
| 3770 |   intptr_t *a = (intptr_t *) jni_functions(); | 
| 3771 |   intptr_t *b = (intptr_t *) new_jni_NativeInterface; | 
| 3772 |   for (uint i=0; i <  sizeof(struct JNINativeInterface_)/sizeof(void *); i++) { | 
| 3773 |     Atomic::store(*b++, a++); | 
| 3774 |   } | 
| 3775 | } | 
| 3776 |  | 
| 3777 | void quicken_jni_functions() { | 
| 3778 |   // Replace Get<Primitive>Field with fast versions | 
| 3779 |   if (UseFastJNIAccessors && !JvmtiExport::can_post_field_access() | 
| 3780 |       && !VerifyJNIFields && !CountJNICalls && !CheckJNICalls) { | 
| 3781 |     address func; | 
| 3782 |     func = JNI_FastGetField::generate_fast_get_boolean_field(); | 
| 3783 |     if (func != (address)-1) { | 
| 3784 |       jni_NativeInterface.GetBooleanField = (GetBooleanField_t)func; | 
| 3785 |     } | 
| 3786 |     func = JNI_FastGetField::generate_fast_get_byte_field(); | 
| 3787 |     if (func != (address)-1) { | 
| 3788 |       jni_NativeInterface.GetByteField = (GetByteField_t)func; | 
| 3789 |     } | 
| 3790 |     func = JNI_FastGetField::generate_fast_get_char_field(); | 
| 3791 |     if (func != (address)-1) { | 
| 3792 |       jni_NativeInterface.GetCharField = (GetCharField_t)func; | 
| 3793 |     } | 
| 3794 |     func = JNI_FastGetField::generate_fast_get_short_field(); | 
| 3795 |     if (func != (address)-1) { | 
| 3796 |       jni_NativeInterface.GetShortField = (GetShortField_t)func; | 
| 3797 |     } | 
| 3798 |     func = JNI_FastGetField::generate_fast_get_int_field(); | 
| 3799 |     if (func != (address)-1) { | 
| 3800 |       jni_NativeInterface.GetIntField = (GetIntField_t)func; | 
| 3801 |     } | 
| 3802 |     func = JNI_FastGetField::generate_fast_get_long_field(); | 
| 3803 |     if (func != (address)-1) { | 
| 3804 |       jni_NativeInterface.GetLongField = (GetLongField_t)func; | 
| 3805 |     } | 
| 3806 |     func = JNI_FastGetField::generate_fast_get_float_field(); | 
| 3807 |     if (func != (address)-1) { | 
| 3808 |       jni_NativeInterface.GetFloatField = (GetFloatField_t)func; | 
| 3809 |     } | 
| 3810 |     func = JNI_FastGetField::generate_fast_get_double_field(); | 
| 3811 |     if (func != (address)-1) { | 
| 3812 |       jni_NativeInterface.GetDoubleField = (GetDoubleField_t)func; | 
| 3813 |     } | 
| 3814 |   } | 
| 3815 | } | 
| 3816 |  | 
| 3817 | // Returns the function structure | 
| 3818 | struct JNINativeInterface_* jni_functions() { | 
| 3819 | #if INCLUDE_JNI_CHECK | 
| 3820 |   if (CheckJNICalls) return jni_functions_check(); | 
| 3821 | #endif // INCLUDE_JNI_CHECK | 
| 3822 |   return &jni_NativeInterface; | 
| 3823 | } | 
| 3824 |  | 
| 3825 | // Returns the function structure | 
| 3826 | struct JNINativeInterface_* jni_functions_nocheck() { | 
| 3827 |   return &jni_NativeInterface; | 
| 3828 | } | 
| 3829 |  | 
| 3830 | static void post_thread_start_event(const JavaThread* jt) { | 
| 3831 |   assert(jt != NULL, "invariant" ); | 
| 3832 |   EventThreadStart event; | 
| 3833 |   if (event.should_commit()) { | 
| 3834 |     event.set_thread(JFR_THREAD_ID(jt)); | 
| 3835 |     event.commit(); | 
| 3836 |   } | 
| 3837 | } | 
| 3838 |  | 
| 3839 | // Invocation API | 
| 3840 |  | 
| 3841 |  | 
| 3842 | // Forward declaration | 
| 3843 | extern const struct JNIInvokeInterface_ jni_InvokeInterface; | 
| 3844 |  | 
| 3845 | // Global invocation API vars | 
| 3846 | volatile int vm_created = 0; | 
| 3847 | // Indicate whether it is safe to recreate VM | 
| 3848 | volatile int safe_to_recreate_vm = 1; | 
| 3849 | struct JavaVM_ main_vm = {&jni_InvokeInterface}; | 
| 3850 |  | 
| 3851 |  | 
| 3852 | #define JAVASTACKSIZE (400 * 1024)    /* Default size of a thread java stack */ | 
| 3853 | enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL }; | 
| 3854 |  | 
| 3855 | DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint | 
| 3856 |                     , HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(_ret_ref)); | 
| 3857 |  | 
| 3858 | _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { | 
| 3859 |   HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY(args_); | 
| 3860 |   JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_; | 
| 3861 |   jint ret = JNI_ERR; | 
| 3862 |   DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret); | 
| 3863 |  | 
| 3864 |   if (Threads::is_supported_jni_version(args->version)) { | 
| 3865 |     ret = JNI_OK; | 
| 3866 |   } | 
| 3867 |   // 1.1 style no longer supported in hotspot. | 
| 3868 |   // According the JNI spec, we should update args->version on return. | 
| 3869 |   // We also use the structure to communicate with launcher about default | 
| 3870 |   // stack size. | 
| 3871 |   if (args->version == JNI_VERSION_1_1) { | 
| 3872 |     args->version = JNI_VERSION_1_2; | 
| 3873 |     // javaStackSize is int in arguments structure | 
| 3874 |     assert(jlong(ThreadStackSize) * K < INT_MAX, "integer overflow" ); | 
| 3875 |     args->javaStackSize = (jint)(ThreadStackSize * K); | 
| 3876 |   } | 
| 3877 |   return ret; | 
| 3878 | } | 
| 3879 |  | 
| 3880 | DT_RETURN_MARK_DECL(CreateJavaVM, jint | 
| 3881 |                     , HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref)); | 
| 3882 |  | 
| 3883 | static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) { | 
| 3884 |   HOTSPOT_JNI_CREATEJAVAVM_ENTRY((void **) vm, penv, args); | 
| 3885 |  | 
| 3886 |   jint result = JNI_ERR; | 
| 3887 |   DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result); | 
| 3888 |  | 
| 3889 |   // We're about to use Atomic::xchg for synchronization.  Some Zero | 
| 3890 |   // platforms use the GCC builtin __sync_lock_test_and_set for this, | 
| 3891 |   // but __sync_lock_test_and_set is not guaranteed to do what we want | 
| 3892 |   // on all architectures.  So we check it works before relying on it. | 
| 3893 | #if defined(ZERO) && defined(ASSERT) | 
| 3894 |   { | 
| 3895 |     jint a = 0xcafebabe; | 
| 3896 |     jint b = Atomic::xchg((jint) 0xdeadbeef, &a); | 
| 3897 |     void *c = &a; | 
| 3898 |     void *d = Atomic::xchg(&b, &c); | 
| 3899 |     assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works" ); | 
| 3900 |     assert(c == &b && d == &a, "Atomic::xchg() works" ); | 
| 3901 |   } | 
| 3902 | #endif // ZERO && ASSERT | 
| 3903 |  | 
| 3904 |   // At the moment it's only possible to have one Java VM, | 
| 3905 |   // since some of the runtime state is in global variables. | 
| 3906 |  | 
| 3907 |   // We cannot use our mutex locks here, since they only work on | 
| 3908 |   // Threads. We do an atomic compare and exchange to ensure only | 
| 3909 |   // one thread can call this method at a time | 
| 3910 |  | 
| 3911 |   // We use Atomic::xchg rather than Atomic::add/dec since on some platforms | 
| 3912 |   // the add/dec implementations are dependent on whether we are running | 
| 3913 |   // on a multiprocessor Atomic::xchg does not have this problem. | 
| 3914 |   if (Atomic::xchg(1, &vm_created) == 1) { | 
| 3915 |     return JNI_EEXIST;   // already created, or create attempt in progress | 
| 3916 |   } | 
| 3917 |   if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) { | 
| 3918 |     return JNI_ERR;  // someone tried and failed and retry not allowed. | 
| 3919 |   } | 
| 3920 |  | 
| 3921 |   assert(vm_created == 1, "vm_created is true during the creation" ); | 
| 3922 |  | 
| 3923 |   /** | 
| 3924 |    * Certain errors during initialization are recoverable and do not | 
| 3925 |    * prevent this method from being called again at a later time | 
| 3926 |    * (perhaps with different arguments).  However, at a certain | 
| 3927 |    * point during initialization if an error occurs we cannot allow | 
| 3928 |    * this function to be called again (or it will crash).  In those | 
| 3929 |    * situations, the 'canTryAgain' flag is set to false, which atomically | 
| 3930 |    * sets safe_to_recreate_vm to 1, such that any new call to | 
| 3931 |    * JNI_CreateJavaVM will immediately fail using the above logic. | 
| 3932 |    */ | 
| 3933 |   bool can_try_again = true; | 
| 3934 |  | 
| 3935 |   result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again); | 
| 3936 |   if (result == JNI_OK) { | 
| 3937 |     JavaThread *thread = JavaThread::current(); | 
| 3938 |     assert(!thread->has_pending_exception(), "should have returned not OK" ); | 
| 3939 |     /* thread is thread_in_vm here */ | 
| 3940 |     *vm = (JavaVM *)(&main_vm); | 
| 3941 |     *(JNIEnv**)penv = thread->jni_environment(); | 
| 3942 |  | 
| 3943 | #if INCLUDE_JVMCI | 
| 3944 |     if (EnableJVMCI) { | 
| 3945 |       if (UseJVMCICompiler) { | 
| 3946 |         // JVMCI is initialized on a CompilerThread | 
| 3947 |         if (BootstrapJVMCI) { | 
| 3948 |           JavaThread* THREAD = thread; | 
| 3949 |           JVMCICompiler* compiler = JVMCICompiler::instance(true, CATCH); | 
| 3950 |           compiler->bootstrap(THREAD); | 
| 3951 |           if (HAS_PENDING_EXCEPTION) { | 
| 3952 |             HandleMark hm; | 
| 3953 |             vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); | 
| 3954 |           } | 
| 3955 |         } | 
| 3956 |       } | 
| 3957 |     } | 
| 3958 | #endif | 
| 3959 |  | 
| 3960 |     // Notify JVMTI | 
| 3961 |     if (JvmtiExport::should_post_thread_life()) { | 
| 3962 |        JvmtiExport::post_thread_start(thread); | 
| 3963 |     } | 
| 3964 |  | 
| 3965 |     post_thread_start_event(thread); | 
| 3966 |  | 
| 3967 | #ifndef PRODUCT | 
| 3968 |     if (ReplayCompiles) ciReplay::replay(thread); | 
| 3969 |  | 
| 3970 |     // Some platforms (like Win*) need a wrapper around these test | 
| 3971 |     // functions in order to properly handle error conditions. | 
| 3972 |     VMError::test_error_handler(); | 
| 3973 | #endif | 
| 3974 |  | 
| 3975 |     // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. | 
| 3976 |     ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_native); | 
| 3977 |   } else { | 
| 3978 |     // If create_vm exits because of a pending exception, exit with that | 
| 3979 |     // exception.  In the future when we figure out how to reclaim memory, | 
| 3980 |     // we may be able to exit with JNI_ERR and allow the calling application | 
| 3981 |     // to continue. | 
| 3982 |     if (Universe::is_fully_initialized()) { | 
| 3983 |       // otherwise no pending exception possible - VM will already have aborted | 
| 3984 |       JavaThread* THREAD = JavaThread::current(); | 
| 3985 |       if (HAS_PENDING_EXCEPTION) { | 
| 3986 |         HandleMark hm; | 
| 3987 |         vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); | 
| 3988 |       } | 
| 3989 |     } | 
| 3990 |  | 
| 3991 |     if (can_try_again) { | 
| 3992 |       // reset safe_to_recreate_vm to 1 so that retrial would be possible | 
| 3993 |       safe_to_recreate_vm = 1; | 
| 3994 |     } | 
| 3995 |  | 
| 3996 |     // Creation failed. We must reset vm_created | 
| 3997 |     *vm = 0; | 
| 3998 |     *(JNIEnv**)penv = 0; | 
| 3999 |     // reset vm_created last to avoid race condition. Use OrderAccess to | 
| 4000 |     // control both compiler and architectural-based reordering. | 
| 4001 |     OrderAccess::release_store(&vm_created, 0); | 
| 4002 |   } | 
| 4003 |  | 
| 4004 |   // Flush stdout and stderr before exit. | 
| 4005 |   fflush(stdout); | 
| 4006 |   fflush(stderr); | 
| 4007 |  | 
| 4008 |   return result; | 
| 4009 |  | 
| 4010 | } | 
| 4011 |  | 
| 4012 | _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { | 
| 4013 |   jint result = JNI_ERR; | 
| 4014 |   // On Windows, let CreateJavaVM run with SEH protection | 
| 4015 | #ifdef _WIN32 | 
| 4016 |   __try { | 
| 4017 | #endif | 
| 4018 |     result = JNI_CreateJavaVM_inner(vm, penv, args); | 
| 4019 | #ifdef _WIN32 | 
| 4020 |   } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) { | 
| 4021 |     // Nothing to do. | 
| 4022 |   } | 
| 4023 | #endif | 
| 4024 |   return result; | 
| 4025 | } | 
| 4026 |  | 
| 4027 | _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) { | 
| 4028 |   // See bug 4367188, the wrapper can sometimes cause VM crashes | 
| 4029 |   // JNIWrapper("GetCreatedJavaVMs"); | 
| 4030 |  | 
| 4031 |   HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY((void **) vm_buf, bufLen, (uintptr_t *) numVMs); | 
| 4032 |  | 
| 4033 |   if (vm_created == 1) { | 
| 4034 |     if (numVMs != NULL) *numVMs = 1; | 
| 4035 |     if (bufLen > 0)     *vm_buf = (JavaVM *)(&main_vm); | 
| 4036 |   } else { | 
| 4037 |     if (numVMs != NULL) *numVMs = 0; | 
| 4038 |   } | 
| 4039 |   HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN(JNI_OK); | 
| 4040 |   return JNI_OK; | 
| 4041 | } | 
| 4042 |  | 
| 4043 | extern "C"  { | 
| 4044 |  | 
| 4045 | DT_RETURN_MARK_DECL(DestroyJavaVM, jint | 
| 4046 |                     , HOTSPOT_JNI_DESTROYJAVAVM_RETURN(_ret_ref)); | 
| 4047 |  | 
| 4048 | static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) { | 
| 4049 |   HOTSPOT_JNI_DESTROYJAVAVM_ENTRY(vm); | 
| 4050 |   jint res = JNI_ERR; | 
| 4051 |   DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res); | 
| 4052 |  | 
| 4053 |   if (vm_created == 0) { | 
| 4054 |     res = JNI_ERR; | 
| 4055 |     return res; | 
| 4056 |   } | 
| 4057 |  | 
| 4058 |   JNIWrapper("DestroyJavaVM" ); | 
| 4059 |   JNIEnv *env; | 
| 4060 |   JavaVMAttachArgs destroyargs; | 
| 4061 |   destroyargs.version = CurrentVersion; | 
| 4062 |   destroyargs.name = (char *)"DestroyJavaVM" ; | 
| 4063 |   destroyargs.group = NULL; | 
| 4064 |   res = vm->AttachCurrentThread((void **)&env, (void *)&destroyargs); | 
| 4065 |   if (res != JNI_OK) { | 
| 4066 |     return res; | 
| 4067 |   } | 
| 4068 |  | 
| 4069 |   // Since this is not a JVM_ENTRY we have to set the thread state manually before entering. | 
| 4070 |   JavaThread* thread = JavaThread::current(); | 
| 4071 |   ThreadStateTransition::transition_from_native(thread, _thread_in_vm); | 
| 4072 |   if (Threads::destroy_vm()) { | 
| 4073 |     // Should not change thread state, VM is gone | 
| 4074 |     vm_created = 0; | 
| 4075 |     res = JNI_OK; | 
| 4076 |     return res; | 
| 4077 |   } else { | 
| 4078 |     ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_native); | 
| 4079 |     res = JNI_ERR; | 
| 4080 |     return res; | 
| 4081 |   } | 
| 4082 | } | 
| 4083 |  | 
| 4084 | jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { | 
| 4085 |   jint result = JNI_ERR; | 
| 4086 |   // On Windows, we need SEH protection | 
| 4087 | #ifdef _WIN32 | 
| 4088 |   __try { | 
| 4089 | #endif | 
| 4090 |     result = jni_DestroyJavaVM_inner(vm); | 
| 4091 | #ifdef _WIN32 | 
| 4092 |   } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) { | 
| 4093 |     // Nothing to do. | 
| 4094 |   } | 
| 4095 | #endif | 
| 4096 |   return result; | 
| 4097 | } | 
| 4098 |  | 
| 4099 | static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool daemon) { | 
| 4100 |   JavaVMAttachArgs *args = (JavaVMAttachArgs *) _args; | 
| 4101 |  | 
| 4102 |   // Check below commented out from JDK1.2fcs as well | 
| 4103 |   /* | 
| 4104 |   if (args && (args->version != JNI_VERSION_1_1 || args->version != JNI_VERSION_1_2)) { | 
| 4105 |     return JNI_EVERSION; | 
| 4106 |   } | 
| 4107 |   */ | 
| 4108 |  | 
| 4109 |   Thread* t = Thread::current_or_null(); | 
| 4110 |   if (t != NULL) { | 
| 4111 |     // If the thread has been attached this operation is a no-op | 
| 4112 |     *(JNIEnv**)penv = ((JavaThread*) t)->jni_environment(); | 
| 4113 |     return JNI_OK; | 
| 4114 |   } | 
| 4115 |  | 
| 4116 |   // Create a thread and mark it as attaching so it will be skipped by the | 
| 4117 |   // ThreadsListEnumerator - see CR 6404306 | 
| 4118 |   JavaThread* thread = new JavaThread(true); | 
| 4119 |  | 
| 4120 |   // Set correct safepoint info. The thread is going to call into Java when | 
| 4121 |   // initializing the Java level thread object. Hence, the correct state must | 
| 4122 |   // be set in order for the Safepoint code to deal with it correctly. | 
| 4123 |   thread->set_thread_state(_thread_in_vm); | 
| 4124 |   thread->record_stack_base_and_size(); | 
| 4125 |   thread->register_thread_stack_with_NMT(); | 
| 4126 |   thread->initialize_thread_current(); | 
| 4127 |  | 
| 4128 |   if (!os::create_attached_thread(thread)) { | 
| 4129 |     thread->smr_delete(); | 
| 4130 |     return JNI_ERR; | 
| 4131 |   } | 
| 4132 |   // Enable stack overflow checks | 
| 4133 |   thread->create_stack_guard_pages(); | 
| 4134 |  | 
| 4135 |   thread->initialize_tlab(); | 
| 4136 |  | 
| 4137 |   thread->cache_global_variables(); | 
| 4138 |  | 
| 4139 |   // Crucial that we do not have a safepoint check for this thread, since it has | 
| 4140 |   // not been added to the Thread list yet. | 
| 4141 |   { Threads_lock->lock_without_safepoint_check(); | 
| 4142 |     // This must be inside this lock in order to get FullGCALot to work properly, i.e., to | 
| 4143 |     // avoid this thread trying to do a GC before it is added to the thread-list | 
| 4144 |     thread->set_active_handles(JNIHandleBlock::allocate_block()); | 
| 4145 |     Threads::add(thread, daemon); | 
| 4146 |     Threads_lock->unlock(); | 
| 4147 |   } | 
| 4148 |   // Create thread group and name info from attach arguments | 
| 4149 |   oop group = NULL; | 
| 4150 |   char* thread_name = NULL; | 
| 4151 |   if (args != NULL && Threads::is_supported_jni_version(args->version)) { | 
| 4152 |     group = JNIHandles::resolve(args->group); | 
| 4153 |     thread_name = args->name; // may be NULL | 
| 4154 |   } | 
| 4155 |   if (group == NULL) group = Universe::main_thread_group(); | 
| 4156 |  | 
| 4157 |   // Create Java level thread object and attach it to this thread | 
| 4158 |   bool attach_failed = false; | 
| 4159 |   { | 
| 4160 |     EXCEPTION_MARK; | 
| 4161 |     HandleMark hm(THREAD); | 
| 4162 |     Handle thread_group(THREAD, group); | 
| 4163 |     thread->allocate_threadObj(thread_group, thread_name, daemon, THREAD); | 
| 4164 |     if (HAS_PENDING_EXCEPTION) { | 
| 4165 |       CLEAR_PENDING_EXCEPTION; | 
| 4166 |       // cleanup outside the handle mark. | 
| 4167 |       attach_failed = true; | 
| 4168 |     } | 
| 4169 |   } | 
| 4170 |  | 
| 4171 |   if (attach_failed) { | 
| 4172 |     // Added missing cleanup | 
| 4173 |     thread->cleanup_failed_attach_current_thread(daemon); | 
| 4174 |     return JNI_ERR; | 
| 4175 |   } | 
| 4176 |  | 
| 4177 |   // mark the thread as no longer attaching | 
| 4178 |   // this uses a fence to push the change through so we don't have | 
| 4179 |   // to regrab the threads_lock | 
| 4180 |   thread->set_done_attaching_via_jni(); | 
| 4181 |  | 
| 4182 |   // Set java thread status. | 
| 4183 |   java_lang_Thread::set_thread_status(thread->threadObj(), | 
| 4184 |               java_lang_Thread::RUNNABLE); | 
| 4185 |  | 
| 4186 |   // Notify the debugger | 
| 4187 |   if (JvmtiExport::should_post_thread_life()) { | 
| 4188 |     JvmtiExport::post_thread_start(thread); | 
| 4189 |   } | 
| 4190 |  | 
| 4191 |   post_thread_start_event(thread); | 
| 4192 |  | 
| 4193 |   *(JNIEnv**)penv = thread->jni_environment(); | 
| 4194 |  | 
| 4195 |   // Now leaving the VM, so change thread_state. This is normally automatically taken care | 
| 4196 |   // of in the JVM_ENTRY. But in this situation we have to do it manually. Notice, that by | 
| 4197 |   // using ThreadStateTransition::transition, we do a callback to the safepoint code if | 
| 4198 |   // needed. | 
| 4199 |  | 
| 4200 |   ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_native); | 
| 4201 |  | 
| 4202 |   // Perform any platform dependent FPU setup | 
| 4203 |   os::setup_fpu(); | 
| 4204 |  | 
| 4205 |   return JNI_OK; | 
| 4206 | } | 
| 4207 |  | 
| 4208 |  | 
| 4209 | jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) { | 
| 4210 |   HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(vm, penv, _args); | 
| 4211 |   if (vm_created == 0) { | 
| 4212 |   HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR); | 
| 4213 |     return JNI_ERR; | 
| 4214 |   } | 
| 4215 |  | 
| 4216 |   JNIWrapper("AttachCurrentThread" ); | 
| 4217 |   jint ret = attach_current_thread(vm, penv, _args, false); | 
| 4218 |   HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(ret); | 
| 4219 |   return ret; | 
| 4220 | } | 
| 4221 |  | 
| 4222 |  | 
| 4223 | jint JNICALL jni_DetachCurrentThread(JavaVM *vm)  { | 
| 4224 |   HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY(vm); | 
| 4225 |  | 
| 4226 |   JNIWrapper("DetachCurrentThread" ); | 
| 4227 |  | 
| 4228 |   // If the thread has already been detached the operation is a no-op | 
| 4229 |   if (Thread::current_or_null() == NULL) { | 
| 4230 |     HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK); | 
| 4231 |     return JNI_OK; | 
| 4232 |   } | 
| 4233 |  | 
| 4234 |   VM_Exit::block_if_vm_exited(); | 
| 4235 |  | 
| 4236 |   JavaThread* thread = JavaThread::current(); | 
| 4237 |   if (thread->has_last_Java_frame()) { | 
| 4238 |     HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR); | 
| 4239 |     // Can't detach a thread that's running java, that can't work. | 
| 4240 |     return JNI_ERR; | 
| 4241 |   } | 
| 4242 |  | 
| 4243 |   // Safepoint support. Have to do call-back to safepoint code, if in the | 
| 4244 |   // middle of a safepoint operation | 
| 4245 |   ThreadStateTransition::transition_from_native(thread, _thread_in_vm); | 
| 4246 |  | 
| 4247 |   // XXX: Note that JavaThread::exit() call below removes the guards on the | 
| 4248 |   // stack pages set up via enable_stack_{red,yellow}_zone() calls | 
| 4249 |   // above in jni_AttachCurrentThread. Unfortunately, while the setting | 
| 4250 |   // of the guards is visible in jni_AttachCurrentThread above, | 
| 4251 |   // the removal of the guards is buried below in JavaThread::exit() | 
| 4252 |   // here. The abstraction should be more symmetrically either exposed | 
| 4253 |   // or hidden (e.g. it could probably be hidden in the same | 
| 4254 |   // (platform-dependent) methods where we do alternate stack | 
| 4255 |   // maintenance work?) | 
| 4256 |   thread->exit(false, JavaThread::jni_detach); | 
| 4257 |   thread->smr_delete(); | 
| 4258 |  | 
| 4259 |   HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK); | 
| 4260 |   return JNI_OK; | 
| 4261 | } | 
| 4262 |  | 
| 4263 | DT_RETURN_MARK_DECL(GetEnv, jint | 
| 4264 |                     , HOTSPOT_JNI_GETENV_RETURN(_ret_ref)); | 
| 4265 |  | 
| 4266 | jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { | 
| 4267 |   HOTSPOT_JNI_GETENV_ENTRY(vm, penv, version); | 
| 4268 |   jint ret = JNI_ERR; | 
| 4269 |   DT_RETURN_MARK(GetEnv, jint, (const jint&)ret); | 
| 4270 |  | 
| 4271 |   if (vm_created == 0) { | 
| 4272 |     *penv = NULL; | 
| 4273 |     ret = JNI_EDETACHED; | 
| 4274 |     return ret; | 
| 4275 |   } | 
| 4276 |  | 
| 4277 |   if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) { | 
| 4278 |     return ret; | 
| 4279 |   } | 
| 4280 |  | 
| 4281 | #ifndef JVMPI_VERSION_1 | 
| 4282 | // need these in order to be polite about older agents | 
| 4283 | #define JVMPI_VERSION_1   ((jint)0x10000001) | 
| 4284 | #define JVMPI_VERSION_1_1 ((jint)0x10000002) | 
| 4285 | #define JVMPI_VERSION_1_2 ((jint)0x10000003) | 
| 4286 | #endif // !JVMPI_VERSION_1 | 
| 4287 |  | 
| 4288 |   Thread* thread = Thread::current_or_null(); | 
| 4289 |   if (thread != NULL && thread->is_Java_thread()) { | 
| 4290 |     if (Threads::is_supported_jni_version_including_1_1(version)) { | 
| 4291 |       *(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment(); | 
| 4292 |       ret = JNI_OK; | 
| 4293 |       return ret; | 
| 4294 |  | 
| 4295 |     } else if (version == JVMPI_VERSION_1 || | 
| 4296 |                version == JVMPI_VERSION_1_1 || | 
| 4297 |                version == JVMPI_VERSION_1_2) { | 
| 4298 |       tty->print_cr("ERROR: JVMPI, an experimental interface, is no longer supported." ); | 
| 4299 |       tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI)." ); | 
| 4300 |       ret = JNI_EVERSION; | 
| 4301 |       return ret; | 
| 4302 |     } else if (JvmtiExport::is_jvmdi_version(version)) { | 
| 4303 |       tty->print_cr("FATAL ERROR: JVMDI is no longer supported." ); | 
| 4304 |       tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI)." ); | 
| 4305 |       ret = JNI_EVERSION; | 
| 4306 |       return ret; | 
| 4307 |     } else { | 
| 4308 |       *penv = NULL; | 
| 4309 |       ret = JNI_EVERSION; | 
| 4310 |       return ret; | 
| 4311 |     } | 
| 4312 |   } else { | 
| 4313 |     *penv = NULL; | 
| 4314 |     ret = JNI_EDETACHED; | 
| 4315 |     return ret; | 
| 4316 |   } | 
| 4317 | } | 
| 4318 |  | 
| 4319 |  | 
| 4320 | jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) { | 
| 4321 |   HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(vm, penv, _args); | 
| 4322 |   if (vm_created == 0) { | 
| 4323 |   HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN((uint32_t) JNI_ERR); | 
| 4324 |     return JNI_ERR; | 
| 4325 |   } | 
| 4326 |  | 
| 4327 |   JNIWrapper("AttachCurrentThreadAsDaemon" ); | 
| 4328 |   jint ret = attach_current_thread(vm, penv, _args, true); | 
| 4329 |   HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(ret); | 
| 4330 |   return ret; | 
| 4331 | } | 
| 4332 |  | 
| 4333 |  | 
| 4334 | } // End extern "C" | 
| 4335 |  | 
| 4336 | const struct JNIInvokeInterface_ jni_InvokeInterface = { | 
| 4337 |     NULL, | 
| 4338 |     NULL, | 
| 4339 |     NULL, | 
| 4340 |  | 
| 4341 |     jni_DestroyJavaVM, | 
| 4342 |     jni_AttachCurrentThread, | 
| 4343 |     jni_DetachCurrentThread, | 
| 4344 |     jni_GetEnv, | 
| 4345 |     jni_AttachCurrentThreadAsDaemon | 
| 4346 | }; | 
| 4347 |  |