src/share/vm/prims/jni.cpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * Copyright (c) 2012 Red Hat, Inc.
aoqi@0 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 5 *
aoqi@0 6 * This code is free software; you can redistribute it and/or modify it
aoqi@0 7 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 8 * published by the Free Software Foundation.
aoqi@0 9 *
aoqi@0 10 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 13 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 14 * accompanied this code).
aoqi@0 15 *
aoqi@0 16 * You should have received a copy of the GNU General Public License version
aoqi@0 17 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 19 *
aoqi@0 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 21 * or visit www.oracle.com if you need additional information or have any
aoqi@0 22 * questions.
aoqi@0 23 *
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 #include "precompiled.hpp"
aoqi@0 27 #include "ci/ciReplay.hpp"
aoqi@0 28 #include "classfile/altHashing.hpp"
aoqi@0 29 #include "classfile/classLoader.hpp"
aoqi@0 30 #include "classfile/javaClasses.hpp"
aoqi@0 31 #include "classfile/symbolTable.hpp"
aoqi@0 32 #include "classfile/systemDictionary.hpp"
aoqi@0 33 #include "classfile/vmSymbols.hpp"
aoqi@0 34 #include "interpreter/linkResolver.hpp"
aoqi@0 35 #include "utilities/macros.hpp"
aoqi@0 36 #if INCLUDE_ALL_GCS
aoqi@0 37 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
aoqi@0 38 #endif // INCLUDE_ALL_GCS
aoqi@0 39 #include "memory/allocation.hpp"
aoqi@0 40 #include "memory/allocation.inline.hpp"
aoqi@0 41 #include "memory/gcLocker.inline.hpp"
aoqi@0 42 #include "memory/oopFactory.hpp"
aoqi@0 43 #include "memory/universe.inline.hpp"
aoqi@0 44 #include "oops/instanceKlass.hpp"
aoqi@0 45 #include "oops/instanceOop.hpp"
aoqi@0 46 #include "oops/markOop.hpp"
aoqi@0 47 #include "oops/method.hpp"
aoqi@0 48 #include "oops/objArrayKlass.hpp"
aoqi@0 49 #include "oops/objArrayOop.hpp"
aoqi@0 50 #include "oops/oop.inline.hpp"
aoqi@0 51 #include "oops/symbol.hpp"
aoqi@0 52 #include "oops/typeArrayKlass.hpp"
aoqi@0 53 #include "oops/typeArrayOop.hpp"
aoqi@0 54 #include "prims/jni.h"
aoqi@0 55 #include "prims/jniCheck.hpp"
aoqi@0 56 #include "prims/jniExport.hpp"
aoqi@0 57 #include "prims/jniFastGetField.hpp"
aoqi@0 58 #include "prims/jvm.h"
aoqi@0 59 #include "prims/jvm_misc.hpp"
aoqi@0 60 #include "prims/jvmtiExport.hpp"
aoqi@0 61 #include "prims/jvmtiThreadState.hpp"
aoqi@0 62 #include "runtime/compilationPolicy.hpp"
aoqi@0 63 #include "runtime/fieldDescriptor.hpp"
aoqi@0 64 #include "runtime/fprofiler.hpp"
aoqi@0 65 #include "runtime/handles.inline.hpp"
aoqi@0 66 #include "runtime/interfaceSupport.hpp"
aoqi@0 67 #include "runtime/java.hpp"
aoqi@0 68 #include "runtime/javaCalls.hpp"
aoqi@0 69 #include "runtime/jfieldIDWorkaround.hpp"
aoqi@0 70 #include "runtime/reflection.hpp"
aoqi@0 71 #include "runtime/sharedRuntime.hpp"
aoqi@0 72 #include "runtime/signature.hpp"
aoqi@0 73 #include "runtime/thread.inline.hpp"
aoqi@0 74 #include "runtime/vm_operations.hpp"
aoqi@0 75 #include "services/runtimeService.hpp"
aoqi@0 76 #include "trace/tracing.hpp"
aoqi@0 77 #include "utilities/defaultStream.hpp"
aoqi@0 78 #include "utilities/dtrace.hpp"
aoqi@0 79 #include "utilities/events.hpp"
aoqi@0 80 #include "utilities/histogram.hpp"
aoqi@0 81 #ifdef TARGET_OS_FAMILY_linux
aoqi@0 82 # include "os_linux.inline.hpp"
aoqi@0 83 #endif
aoqi@0 84 #ifdef TARGET_OS_FAMILY_solaris
aoqi@0 85 # include "os_solaris.inline.hpp"
aoqi@0 86 #endif
aoqi@0 87 #ifdef TARGET_OS_FAMILY_windows
aoqi@0 88 # include "os_windows.inline.hpp"
aoqi@0 89 #endif
aoqi@0 90 #ifdef TARGET_OS_FAMILY_bsd
aoqi@0 91 # include "os_bsd.inline.hpp"
aoqi@0 92 #endif
aoqi@0 93
aoqi@0 94 static jint CurrentVersion = JNI_VERSION_1_8;
aoqi@0 95
aoqi@0 96
aoqi@0 97 // The DT_RETURN_MARK macros create a scoped object to fire the dtrace
aoqi@0 98 // '-return' probe regardless of the return path is taken out of the function.
aoqi@0 99 // Methods that have multiple return paths use this to avoid having to
aoqi@0 100 // instrument each return path. Methods that use CHECK or THROW must use this
aoqi@0 101 // since those macros can cause an immedate uninstrumented return.
aoqi@0 102 //
aoqi@0 103 // In order to get the return value, a reference to the variable containing
aoqi@0 104 // the return value must be passed to the contructor of the object, and
aoqi@0 105 // the return value must be set before return (since the mark object has
aoqi@0 106 // a reference to it).
aoqi@0 107 //
aoqi@0 108 // Example:
aoqi@0 109 // DT_RETURN_MARK_DECL(SomeFunc, int);
aoqi@0 110 // JNI_ENTRY(int, SomeFunc, ...)
aoqi@0 111 // int return_value = 0;
aoqi@0 112 // DT_RETURN_MARK(SomeFunc, int, (const int&)return_value);
aoqi@0 113 // foo(CHECK_0)
aoqi@0 114 // return_value = 5;
aoqi@0 115 // return return_value;
aoqi@0 116 // JNI_END
aoqi@0 117 #ifndef USDT2
aoqi@0 118 #define DT_RETURN_MARK_DECL(name, type) \
aoqi@0 119 HS_DTRACE_PROBE_DECL1(hotspot_jni, name##__return, type); \
aoqi@0 120 DTRACE_ONLY( \
aoqi@0 121 class DTraceReturnProbeMark_##name { \
aoqi@0 122 public: \
aoqi@0 123 const type& _ret_ref; \
aoqi@0 124 DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \
aoqi@0 125 ~DTraceReturnProbeMark_##name() { \
aoqi@0 126 HS_DTRACE_PROBE1(hotspot_jni, name##__return, _ret_ref); \
aoqi@0 127 } \
aoqi@0 128 } \
aoqi@0 129 )
aoqi@0 130 // Void functions are simpler since there's no return value
aoqi@0 131 #define DT_VOID_RETURN_MARK_DECL(name) \
aoqi@0 132 HS_DTRACE_PROBE_DECL0(hotspot_jni, name##__return); \
aoqi@0 133 DTRACE_ONLY( \
aoqi@0 134 class DTraceReturnProbeMark_##name { \
aoqi@0 135 public: \
aoqi@0 136 ~DTraceReturnProbeMark_##name() { \
aoqi@0 137 HS_DTRACE_PROBE0(hotspot_jni, name##__return); \
aoqi@0 138 } \
aoqi@0 139 } \
aoqi@0 140 )
aoqi@0 141
aoqi@0 142 #else /* USDT2 */
aoqi@0 143
aoqi@0 144 #define DT_RETURN_MARK_DECL(name, type, probe) \
aoqi@0 145 DTRACE_ONLY( \
aoqi@0 146 class DTraceReturnProbeMark_##name { \
aoqi@0 147 public: \
aoqi@0 148 const type& _ret_ref; \
aoqi@0 149 DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \
aoqi@0 150 ~DTraceReturnProbeMark_##name() { \
aoqi@0 151 probe; \
aoqi@0 152 } \
aoqi@0 153 } \
aoqi@0 154 )
aoqi@0 155 // Void functions are simpler since there's no return value
aoqi@0 156 #define DT_VOID_RETURN_MARK_DECL(name, probe) \
aoqi@0 157 DTRACE_ONLY( \
aoqi@0 158 class DTraceReturnProbeMark_##name { \
aoqi@0 159 public: \
aoqi@0 160 ~DTraceReturnProbeMark_##name() { \
aoqi@0 161 probe; \
aoqi@0 162 } \
aoqi@0 163 } \
aoqi@0 164 )
aoqi@0 165 #endif /* USDT2 */
aoqi@0 166
aoqi@0 167 // Place these macros in the function to mark the return. Non-void
aoqi@0 168 // functions need the type and address of the return value.
aoqi@0 169 #define DT_RETURN_MARK(name, type, ref) \
aoqi@0 170 DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark(ref) )
aoqi@0 171 #define DT_VOID_RETURN_MARK(name) \
aoqi@0 172 DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark )
aoqi@0 173
aoqi@0 174
aoqi@0 175 // Use these to select distinct code for floating-point vs. non-floating point
aoqi@0 176 // situations. Used from within common macros where we need slightly
aoqi@0 177 // different behavior for Float/Double
aoqi@0 178 #define FP_SELECT_Boolean(intcode, fpcode) intcode
aoqi@0 179 #define FP_SELECT_Byte(intcode, fpcode) intcode
aoqi@0 180 #define FP_SELECT_Char(intcode, fpcode) intcode
aoqi@0 181 #define FP_SELECT_Short(intcode, fpcode) intcode
aoqi@0 182 #define FP_SELECT_Object(intcode, fpcode) intcode
aoqi@0 183 #define FP_SELECT_Int(intcode, fpcode) intcode
aoqi@0 184 #define FP_SELECT_Long(intcode, fpcode) intcode
aoqi@0 185 #define FP_SELECT_Float(intcode, fpcode) fpcode
aoqi@0 186 #define FP_SELECT_Double(intcode, fpcode) fpcode
aoqi@0 187 #define FP_SELECT(TypeName, intcode, fpcode) \
aoqi@0 188 FP_SELECT_##TypeName(intcode, fpcode)
aoqi@0 189
aoqi@0 190 #define COMMA ,
aoqi@0 191
aoqi@0 192 // Choose DT_RETURN_MARK macros based on the type: float/double -> void
aoqi@0 193 // (dtrace doesn't do FP yet)
aoqi@0 194 #ifndef USDT2
aoqi@0 195 #define DT_RETURN_MARK_DECL_FOR(TypeName, name, type) \
aoqi@0 196 FP_SELECT(TypeName, \
aoqi@0 197 DT_RETURN_MARK_DECL(name, type), DT_VOID_RETURN_MARK_DECL(name) )
aoqi@0 198 #else /* USDT2 */
aoqi@0 199 #define DT_RETURN_MARK_DECL_FOR(TypeName, name, type, probe) \
aoqi@0 200 FP_SELECT(TypeName, \
aoqi@0 201 DT_RETURN_MARK_DECL(name, type, probe), DT_VOID_RETURN_MARK_DECL(name, probe) )
aoqi@0 202 #endif /* USDT2 */
aoqi@0 203 #define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \
aoqi@0 204 FP_SELECT(TypeName, \
aoqi@0 205 DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) )
aoqi@0 206
aoqi@0 207
aoqi@0 208 // out-of-line helpers for class jfieldIDWorkaround:
aoqi@0 209
aoqi@0 210 bool jfieldIDWorkaround::is_valid_jfieldID(Klass* k, jfieldID id) {
aoqi@0 211 if (jfieldIDWorkaround::is_instance_jfieldID(k, id)) {
aoqi@0 212 uintptr_t as_uint = (uintptr_t) id;
aoqi@0 213 intptr_t offset = raw_instance_offset(id);
aoqi@0 214 if (is_checked_jfieldID(id)) {
aoqi@0 215 if (!klass_hash_ok(k, id)) {
aoqi@0 216 return false;
aoqi@0 217 }
aoqi@0 218 }
aoqi@0 219 return InstanceKlass::cast(k)->contains_field_offset(offset);
aoqi@0 220 } else {
aoqi@0 221 JNIid* result = (JNIid*) id;
aoqi@0 222 #ifdef ASSERT
aoqi@0 223 return result != NULL && result->is_static_field_id();
aoqi@0 224 #else
aoqi@0 225 return result != NULL;
aoqi@0 226 #endif
aoqi@0 227 }
aoqi@0 228 }
aoqi@0 229
aoqi@0 230
aoqi@0 231 intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, intptr_t offset) {
aoqi@0 232 if (offset <= small_offset_mask) {
aoqi@0 233 Klass* field_klass = k;
aoqi@0 234 Klass* super_klass = field_klass->super();
aoqi@0 235 // With compressed oops the most super class with nonstatic fields would
aoqi@0 236 // be the owner of fields embedded in the header.
aoqi@0 237 while (InstanceKlass::cast(super_klass)->has_nonstatic_fields() &&
aoqi@0 238 InstanceKlass::cast(super_klass)->contains_field_offset(offset)) {
aoqi@0 239 field_klass = super_klass; // super contains the field also
aoqi@0 240 super_klass = field_klass->super();
aoqi@0 241 }
aoqi@0 242 debug_only(No_Safepoint_Verifier nosafepoint;)
aoqi@0 243 uintptr_t klass_hash = field_klass->identity_hash();
aoqi@0 244 return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;
aoqi@0 245 } else {
aoqi@0 246 #if 0
aoqi@0 247 #ifndef PRODUCT
aoqi@0 248 {
aoqi@0 249 ResourceMark rm;
aoqi@0 250 warning("VerifyJNIFields: long offset %d in %s", offset, k->external_name());
aoqi@0 251 }
aoqi@0 252 #endif
aoqi@0 253 #endif
aoqi@0 254 return 0;
aoqi@0 255 }
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
aoqi@0 259 uintptr_t as_uint = (uintptr_t) id;
aoqi@0 260 intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;
aoqi@0 261 do {
aoqi@0 262 debug_only(No_Safepoint_Verifier nosafepoint;)
aoqi@0 263 // Could use a non-blocking query for identity_hash here...
aoqi@0 264 if ((k->identity_hash() & klass_mask) == klass_hash)
aoqi@0 265 return true;
aoqi@0 266 k = k->super();
aoqi@0 267 } while (k != NULL);
aoqi@0 268 return false;
aoqi@0 269 }
aoqi@0 270
aoqi@0 271 void jfieldIDWorkaround::verify_instance_jfieldID(Klass* k, jfieldID id) {
aoqi@0 272 guarantee(jfieldIDWorkaround::is_instance_jfieldID(k, id), "must be an instance field" );
aoqi@0 273 uintptr_t as_uint = (uintptr_t) id;
aoqi@0 274 intptr_t offset = raw_instance_offset(id);
aoqi@0 275 if (VerifyJNIFields) {
aoqi@0 276 if (is_checked_jfieldID(id)) {
aoqi@0 277 guarantee(klass_hash_ok(k, id),
aoqi@0 278 "Bug in native code: jfieldID class must match object");
aoqi@0 279 } else {
aoqi@0 280 #if 0
aoqi@0 281 #ifndef PRODUCT
aoqi@0 282 if (Verbose) {
aoqi@0 283 ResourceMark rm;
aoqi@0 284 warning("VerifyJNIFields: unverified offset %d for %s", offset, k->external_name());
aoqi@0 285 }
aoqi@0 286 #endif
aoqi@0 287 #endif
aoqi@0 288 }
aoqi@0 289 }
aoqi@0 290 guarantee(InstanceKlass::cast(k)->contains_field_offset(offset),
aoqi@0 291 "Bug in native code: jfieldID offset must address interior of object");
aoqi@0 292 }
aoqi@0 293
aoqi@0 294 // Pick a reasonable higher bound for local capacity requested
aoqi@0 295 // for EnsureLocalCapacity and PushLocalFrame. We don't want it too
aoqi@0 296 // high because a test (or very unusual application) may try to allocate
aoqi@0 297 // that many handles and run out of swap space. An implementation is
aoqi@0 298 // permitted to allocate more handles than the ensured capacity, so this
aoqi@0 299 // value is set high enough to prevent compatibility problems.
aoqi@0 300 const int MAX_REASONABLE_LOCAL_CAPACITY = 4*K;
aoqi@0 301
aoqi@0 302
aoqi@0 303 // Wrapper to trace JNI functions
aoqi@0 304
aoqi@0 305 #ifdef ASSERT
aoqi@0 306 Histogram* JNIHistogram;
aoqi@0 307 static volatile jint JNIHistogram_lock = 0;
aoqi@0 308
aoqi@0 309 class JNITraceWrapper : public StackObj {
aoqi@0 310 public:
aoqi@0 311 JNITraceWrapper(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) {
aoqi@0 312 if (TraceJNICalls) {
aoqi@0 313 va_list ap;
aoqi@0 314 va_start(ap, format);
aoqi@0 315 tty->print("JNI ");
aoqi@0 316 tty->vprint_cr(format, ap);
aoqi@0 317 va_end(ap);
aoqi@0 318 }
aoqi@0 319 }
aoqi@0 320 };
aoqi@0 321
aoqi@0 322 class JNIHistogramElement : public HistogramElement {
aoqi@0 323 public:
aoqi@0 324 JNIHistogramElement(const char* name);
aoqi@0 325 };
aoqi@0 326
aoqi@0 327 JNIHistogramElement::JNIHistogramElement(const char* elementName) {
aoqi@0 328 _name = elementName;
aoqi@0 329 uintx count = 0;
aoqi@0 330
aoqi@0 331 while (Atomic::cmpxchg(1, &JNIHistogram_lock, 0) != 0) {
aoqi@0 332 while (OrderAccess::load_acquire(&JNIHistogram_lock) != 0) {
aoqi@0 333 count +=1;
aoqi@0 334 if ( (WarnOnStalledSpinLock > 0)
aoqi@0 335 && (count % WarnOnStalledSpinLock == 0)) {
aoqi@0 336 warning("JNIHistogram_lock seems to be stalled");
aoqi@0 337 }
aoqi@0 338 }
aoqi@0 339 }
aoqi@0 340
aoqi@0 341
aoqi@0 342 if(JNIHistogram == NULL)
aoqi@0 343 JNIHistogram = new Histogram("JNI Call Counts",100);
aoqi@0 344
aoqi@0 345 JNIHistogram->add_element(this);
aoqi@0 346 Atomic::dec(&JNIHistogram_lock);
aoqi@0 347 }
aoqi@0 348
aoqi@0 349 #define JNICountWrapper(arg) \
aoqi@0 350 static JNIHistogramElement* e = new JNIHistogramElement(arg); \
aoqi@0 351 /* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \
aoqi@0 352 if (e != NULL) e->increment_count()
aoqi@0 353 #define JNIWrapper(arg) JNICountWrapper(arg); JNITraceWrapper(arg)
aoqi@0 354 #else
aoqi@0 355 #define JNIWrapper(arg)
aoqi@0 356 #endif
aoqi@0 357
aoqi@0 358
aoqi@0 359 // Implementation of JNI entries
aoqi@0 360
aoqi@0 361 #ifndef USDT2
aoqi@0 362 DT_RETURN_MARK_DECL(DefineClass, jclass);
aoqi@0 363 #else /* USDT2 */
aoqi@0 364 DT_RETURN_MARK_DECL(DefineClass, jclass
aoqi@0 365 , HOTSPOT_JNI_DEFINECLASS_RETURN(_ret_ref));
aoqi@0 366 #endif /* USDT2 */
aoqi@0 367
aoqi@0 368 JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef,
aoqi@0 369 const jbyte *buf, jsize bufLen))
aoqi@0 370 JNIWrapper("DefineClass");
aoqi@0 371
aoqi@0 372 #ifndef USDT2
aoqi@0 373 DTRACE_PROBE5(hotspot_jni, DefineClass__entry,
aoqi@0 374 env, name, loaderRef, buf, bufLen);
aoqi@0 375 #else /* USDT2 */
aoqi@0 376 HOTSPOT_JNI_DEFINECLASS_ENTRY(
aoqi@0 377 env, (char*) name, loaderRef, (char*) buf, bufLen);
aoqi@0 378 #endif /* USDT2 */
aoqi@0 379 jclass cls = NULL;
aoqi@0 380 DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls);
aoqi@0 381
aoqi@0 382 TempNewSymbol class_name = NULL;
aoqi@0 383 // Since exceptions can be thrown, class initialization can take place
aoqi@0 384 // if name is NULL no check for class name in .class stream has to be made.
aoqi@0 385 if (name != NULL) {
aoqi@0 386 const int str_len = (int)strlen(name);
aoqi@0 387 if (str_len > Symbol::max_length()) {
aoqi@0 388 // It's impossible to create this class; the name cannot fit
aoqi@0 389 // into the constant pool.
aoqi@0 390 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
aoqi@0 391 }
aoqi@0 392 class_name = SymbolTable::new_symbol(name, CHECK_NULL);
aoqi@0 393 }
aoqi@0 394 ResourceMark rm(THREAD);
aoqi@0 395 ClassFileStream st((u1*) buf, bufLen, NULL);
aoqi@0 396 Handle class_loader (THREAD, JNIHandles::resolve(loaderRef));
aoqi@0 397
aoqi@0 398 if (UsePerfData && !class_loader.is_null()) {
aoqi@0 399 // check whether the current caller thread holds the lock or not.
aoqi@0 400 // If not, increment the corresponding counter
aoqi@0 401 if (ObjectSynchronizer::
aoqi@0 402 query_lock_ownership((JavaThread*)THREAD, class_loader) !=
aoqi@0 403 ObjectSynchronizer::owner_self) {
aoqi@0 404 ClassLoader::sync_JNIDefineClassLockFreeCounter()->inc();
aoqi@0 405 }
aoqi@0 406 }
aoqi@0 407 Klass* k = SystemDictionary::resolve_from_stream(class_name, class_loader,
aoqi@0 408 Handle(), &st, true,
aoqi@0 409 CHECK_NULL);
aoqi@0 410
aoqi@0 411 if (TraceClassResolution && k != NULL) {
aoqi@0 412 trace_class_resolution(k);
aoqi@0 413 }
aoqi@0 414
aoqi@0 415 cls = (jclass)JNIHandles::make_local(
aoqi@0 416 env, k->java_mirror());
aoqi@0 417 return cls;
aoqi@0 418 JNI_END
aoqi@0 419
aoqi@0 420
aoqi@0 421
aoqi@0 422 static bool first_time_FindClass = true;
aoqi@0 423
aoqi@0 424 #ifndef USDT2
aoqi@0 425 DT_RETURN_MARK_DECL(FindClass, jclass);
aoqi@0 426 #else /* USDT2 */
aoqi@0 427 DT_RETURN_MARK_DECL(FindClass, jclass
aoqi@0 428 , HOTSPOT_JNI_FINDCLASS_RETURN(_ret_ref));
aoqi@0 429 #endif /* USDT2 */
aoqi@0 430
aoqi@0 431 JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name))
aoqi@0 432 JNIWrapper("FindClass");
aoqi@0 433 #ifndef USDT2
aoqi@0 434 DTRACE_PROBE2(hotspot_jni, FindClass__entry, env, name);
aoqi@0 435 #else /* USDT2 */
aoqi@0 436 HOTSPOT_JNI_FINDCLASS_ENTRY(
aoqi@0 437 env, (char *)name);
aoqi@0 438 #endif /* USDT2 */
aoqi@0 439
aoqi@0 440 jclass result = NULL;
aoqi@0 441 DT_RETURN_MARK(FindClass, jclass, (const jclass&)result);
aoqi@0 442
aoqi@0 443 // Remember if we are the first invocation of jni_FindClass
aoqi@0 444 bool first_time = first_time_FindClass;
aoqi@0 445 first_time_FindClass = false;
aoqi@0 446
aoqi@0 447 // Sanity check the name: it cannot be null or larger than the maximum size
aoqi@0 448 // name we can fit in the constant pool.
aoqi@0 449 if (name == NULL || (int)strlen(name) > Symbol::max_length()) {
aoqi@0 450 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
aoqi@0 451 }
aoqi@0 452
aoqi@0 453 //%note jni_3
aoqi@0 454 Handle loader;
aoqi@0 455 Handle protection_domain;
aoqi@0 456 // Find calling class
aoqi@0 457 instanceKlassHandle k (THREAD, thread->security_get_caller_class(0));
aoqi@0 458 if (k.not_null()) {
aoqi@0 459 loader = Handle(THREAD, k->class_loader());
aoqi@0 460 // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed
aoqi@0 461 // in the correct class context.
aoqi@0 462 if (loader.is_null() &&
aoqi@0 463 k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) {
aoqi@0 464 JavaValue result(T_OBJECT);
aoqi@0 465 JavaCalls::call_static(&result, k,
aoqi@0 466 vmSymbols::getFromClass_name(),
aoqi@0 467 vmSymbols::void_class_signature(),
aoqi@0 468 thread);
aoqi@0 469 if (HAS_PENDING_EXCEPTION) {
aoqi@0 470 Handle ex(thread, thread->pending_exception());
aoqi@0 471 CLEAR_PENDING_EXCEPTION;
aoqi@0 472 THROW_HANDLE_0(ex);
aoqi@0 473 }
aoqi@0 474 oop mirror = (oop) result.get_jobject();
aoqi@0 475 loader = Handle(THREAD,
aoqi@0 476 InstanceKlass::cast(java_lang_Class::as_Klass(mirror))->class_loader());
aoqi@0 477 protection_domain = Handle(THREAD,
aoqi@0 478 InstanceKlass::cast(java_lang_Class::as_Klass(mirror))->protection_domain());
aoqi@0 479 }
aoqi@0 480 } else {
aoqi@0 481 // We call ClassLoader.getSystemClassLoader to obtain the system class loader.
aoqi@0 482 loader = Handle(THREAD, SystemDictionary::java_system_loader());
aoqi@0 483 }
aoqi@0 484
aoqi@0 485 TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);
aoqi@0 486 result = find_class_from_class_loader(env, sym, true, loader,
aoqi@0 487 protection_domain, true, thread);
aoqi@0 488
aoqi@0 489 if (TraceClassResolution && result != NULL) {
aoqi@0 490 trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
aoqi@0 491 }
aoqi@0 492
aoqi@0 493 // If we were the first invocation of jni_FindClass, we enable compilation again
aoqi@0 494 // rather than just allowing invocation counter to overflow and decay.
aoqi@0 495 // Controlled by flag DelayCompilationDuringStartup.
aoqi@0 496 if (first_time && !CompileTheWorld)
aoqi@0 497 CompilationPolicy::completed_vm_startup();
aoqi@0 498
aoqi@0 499 return result;
aoqi@0 500 JNI_END
aoqi@0 501
aoqi@0 502 #ifndef USDT2
aoqi@0 503 DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID);
aoqi@0 504 #else /* USDT2 */
aoqi@0 505 DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID
aoqi@0 506 , HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN((uintptr_t)_ret_ref));
aoqi@0 507 #endif /* USDT2 */
aoqi@0 508
aoqi@0 509 JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method))
aoqi@0 510 JNIWrapper("FromReflectedMethod");
aoqi@0 511 #ifndef USDT2
aoqi@0 512 DTRACE_PROBE2(hotspot_jni, FromReflectedMethod__entry, env, method);
aoqi@0 513 #else /* USDT2 */
aoqi@0 514 HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY(
aoqi@0 515 env, method);
aoqi@0 516 #endif /* USDT2 */
aoqi@0 517 jmethodID ret = NULL;
aoqi@0 518 DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret);
aoqi@0 519
aoqi@0 520 // method is a handle to a java.lang.reflect.Method object
aoqi@0 521 oop reflected = JNIHandles::resolve_non_null(method);
aoqi@0 522 oop mirror = NULL;
aoqi@0 523 int slot = 0;
aoqi@0 524
aoqi@0 525 if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) {
aoqi@0 526 mirror = java_lang_reflect_Constructor::clazz(reflected);
aoqi@0 527 slot = java_lang_reflect_Constructor::slot(reflected);
aoqi@0 528 } else {
aoqi@0 529 assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type");
aoqi@0 530 mirror = java_lang_reflect_Method::clazz(reflected);
aoqi@0 531 slot = java_lang_reflect_Method::slot(reflected);
aoqi@0 532 }
aoqi@0 533 Klass* k = java_lang_Class::as_Klass(mirror);
aoqi@0 534
aoqi@0 535 KlassHandle k1(THREAD, k);
aoqi@0 536 // Make sure class is initialized before handing id's out to methods
aoqi@0 537 k1()->initialize(CHECK_NULL);
aoqi@0 538 Method* m = InstanceKlass::cast(k1())->method_with_idnum(slot);
aoqi@0 539 ret = m==NULL? NULL : m->jmethod_id(); // return NULL if reflected method deleted
aoqi@0 540 return ret;
aoqi@0 541 JNI_END
aoqi@0 542
aoqi@0 543 #ifndef USDT2
aoqi@0 544 DT_RETURN_MARK_DECL(FromReflectedField, jfieldID);
aoqi@0 545 #else /* USDT2 */
aoqi@0 546 DT_RETURN_MARK_DECL(FromReflectedField, jfieldID
aoqi@0 547 , HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN((uintptr_t)_ret_ref));
aoqi@0 548 #endif /* USDT2 */
aoqi@0 549
aoqi@0 550 JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field))
aoqi@0 551 JNIWrapper("FromReflectedField");
aoqi@0 552 #ifndef USDT2
aoqi@0 553 DTRACE_PROBE2(hotspot_jni, FromReflectedField__entry, env, field);
aoqi@0 554 #else /* USDT2 */
aoqi@0 555 HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY(
aoqi@0 556 env, field);
aoqi@0 557 #endif /* USDT2 */
aoqi@0 558 jfieldID ret = NULL;
aoqi@0 559 DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret);
aoqi@0 560
aoqi@0 561 // field is a handle to a java.lang.reflect.Field object
aoqi@0 562 oop reflected = JNIHandles::resolve_non_null(field);
aoqi@0 563 oop mirror = java_lang_reflect_Field::clazz(reflected);
aoqi@0 564 Klass* k = java_lang_Class::as_Klass(mirror);
aoqi@0 565 int slot = java_lang_reflect_Field::slot(reflected);
aoqi@0 566 int modifiers = java_lang_reflect_Field::modifiers(reflected);
aoqi@0 567
aoqi@0 568 KlassHandle k1(THREAD, k);
aoqi@0 569 // Make sure class is initialized before handing id's out to fields
aoqi@0 570 k1()->initialize(CHECK_NULL);
aoqi@0 571
aoqi@0 572 // First check if this is a static field
aoqi@0 573 if (modifiers & JVM_ACC_STATIC) {
aoqi@0 574 intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot );
aoqi@0 575 JNIid* id = InstanceKlass::cast(k1())->jni_id_for(offset);
aoqi@0 576 assert(id != NULL, "corrupt Field object");
aoqi@0 577 debug_only(id->set_is_static_field_id();)
aoqi@0 578 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
aoqi@0 579 ret = jfieldIDWorkaround::to_static_jfieldID(id);
aoqi@0 580 return ret;
aoqi@0 581 }
aoqi@0 582
aoqi@0 583 // The slot is the index of the field description in the field-array
aoqi@0 584 // The jfieldID is the offset of the field within the object
aoqi@0 585 // It may also have hash bits for k, if VerifyJNIFields is turned on.
aoqi@0 586 intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot );
aoqi@0 587 assert(InstanceKlass::cast(k1())->contains_field_offset(offset), "stay within object");
aoqi@0 588 ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset);
aoqi@0 589 return ret;
aoqi@0 590 JNI_END
aoqi@0 591
aoqi@0 592 #ifndef USDT2
aoqi@0 593 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject);
aoqi@0 594 #else /* USDT2 */
aoqi@0 595 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
aoqi@0 596 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
aoqi@0 597 #endif /* USDT2 */
aoqi@0 598
aoqi@0 599 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
aoqi@0 600 JNIWrapper("ToReflectedMethod");
aoqi@0 601 #ifndef USDT2
aoqi@0 602 DTRACE_PROBE4(hotspot_jni, ToReflectedMethod__entry, env, cls, method_id, isStatic);
aoqi@0 603 #else /* USDT2 */
aoqi@0 604 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(
aoqi@0 605 env, cls, (uintptr_t) method_id, isStatic);
aoqi@0 606 #endif /* USDT2 */
aoqi@0 607 jobject ret = NULL;
aoqi@0 608 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
aoqi@0 609
aoqi@0 610 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
aoqi@0 611 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
aoqi@0 612 oop reflection_method;
aoqi@0 613 if (m->is_initializer()) {
aoqi@0 614 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
aoqi@0 615 } else {
aoqi@0 616 reflection_method = Reflection::new_method(m, UseNewReflection, false, CHECK_NULL);
aoqi@0 617 }
aoqi@0 618 ret = JNIHandles::make_local(env, reflection_method);
aoqi@0 619 return ret;
aoqi@0 620 JNI_END
aoqi@0 621
aoqi@0 622 #ifndef USDT2
aoqi@0 623 DT_RETURN_MARK_DECL(GetSuperclass, jclass);
aoqi@0 624 #else /* USDT2 */
aoqi@0 625 DT_RETURN_MARK_DECL(GetSuperclass, jclass
aoqi@0 626 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
aoqi@0 627 #endif /* USDT2 */
aoqi@0 628
aoqi@0 629 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
aoqi@0 630 JNIWrapper("GetSuperclass");
aoqi@0 631 #ifndef USDT2
aoqi@0 632 DTRACE_PROBE2(hotspot_jni, GetSuperclass__entry, env, sub);
aoqi@0 633 #else /* USDT2 */
aoqi@0 634 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(
aoqi@0 635 env, sub);
aoqi@0 636 #endif /* USDT2 */
aoqi@0 637 jclass obj = NULL;
aoqi@0 638 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
aoqi@0 639
aoqi@0 640 oop mirror = JNIHandles::resolve_non_null(sub);
aoqi@0 641 // primitive classes return NULL
aoqi@0 642 if (java_lang_Class::is_primitive(mirror)) return NULL;
aoqi@0 643
aoqi@0 644 // Rules of Class.getSuperClass as implemented by KLass::java_super:
aoqi@0 645 // arrays return Object
aoqi@0 646 // interfaces return NULL
aoqi@0 647 // proper classes return Klass::super()
aoqi@0 648 Klass* k = java_lang_Class::as_Klass(mirror);
aoqi@0 649 if (k->is_interface()) return NULL;
aoqi@0 650
aoqi@0 651 // return mirror for superclass
aoqi@0 652 Klass* super = k->java_super();
aoqi@0 653 // super2 is the value computed by the compiler's getSuperClass intrinsic:
aoqi@0 654 debug_only(Klass* super2 = ( k->oop_is_array()
aoqi@0 655 ? SystemDictionary::Object_klass()
aoqi@0 656 : k->super() ) );
aoqi@0 657 assert(super == super2,
aoqi@0 658 "java_super computation depends on interface, array, other super");
aoqi@0 659 obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(super->java_mirror());
aoqi@0 660 return obj;
aoqi@0 661 JNI_END
aoqi@0 662
aoqi@0 663 JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))
aoqi@0 664 JNIWrapper("IsSubclassOf");
aoqi@0 665 #ifndef USDT2
aoqi@0 666 DTRACE_PROBE3(hotspot_jni, IsAssignableFrom__entry, env, sub, super);
aoqi@0 667 #else /* USDT2 */
aoqi@0 668 HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(
aoqi@0 669 env, sub, super);
aoqi@0 670 #endif /* USDT2 */
aoqi@0 671 oop sub_mirror = JNIHandles::resolve_non_null(sub);
aoqi@0 672 oop super_mirror = JNIHandles::resolve_non_null(super);
aoqi@0 673 if (java_lang_Class::is_primitive(sub_mirror) ||
aoqi@0 674 java_lang_Class::is_primitive(super_mirror)) {
aoqi@0 675 jboolean ret = (sub_mirror == super_mirror);
aoqi@0 676 #ifndef USDT2
aoqi@0 677 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret);
aoqi@0 678 #else /* USDT2 */
aoqi@0 679 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(
aoqi@0 680 ret);
aoqi@0 681 #endif /* USDT2 */
aoqi@0 682 return ret;
aoqi@0 683 }
aoqi@0 684 Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
aoqi@0 685 Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
aoqi@0 686 assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
aoqi@0 687 jboolean ret = sub_klass->is_subtype_of(super_klass) ?
aoqi@0 688 JNI_TRUE : JNI_FALSE;
aoqi@0 689 #ifndef USDT2
aoqi@0 690 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret);
aoqi@0 691 #else /* USDT2 */
aoqi@0 692 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(
aoqi@0 693 ret);
aoqi@0 694 #endif /* USDT2 */
aoqi@0 695 return ret;
aoqi@0 696 JNI_END
aoqi@0 697
aoqi@0 698 #ifndef USDT2
aoqi@0 699 DT_RETURN_MARK_DECL(Throw, jint);
aoqi@0 700 #else /* USDT2 */
aoqi@0 701 DT_RETURN_MARK_DECL(Throw, jint
aoqi@0 702 , HOTSPOT_JNI_THROW_RETURN(_ret_ref));
aoqi@0 703 #endif /* USDT2 */
aoqi@0 704
aoqi@0 705 JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
aoqi@0 706 JNIWrapper("Throw");
aoqi@0 707 #ifndef USDT2
aoqi@0 708 DTRACE_PROBE2(hotspot_jni, Throw__entry, env, obj);
aoqi@0 709 #else /* USDT2 */
aoqi@0 710 HOTSPOT_JNI_THROW_ENTRY(
aoqi@0 711 env, obj);
aoqi@0 712 #endif /* USDT2 */
aoqi@0 713 jint ret = JNI_OK;
aoqi@0 714 DT_RETURN_MARK(Throw, jint, (const jint&)ret);
aoqi@0 715
aoqi@0 716 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
aoqi@0 717 ShouldNotReachHere();
aoqi@0 718 JNI_END
aoqi@0 719
aoqi@0 720 #ifndef USDT2
aoqi@0 721 DT_RETURN_MARK_DECL(ThrowNew, jint);
aoqi@0 722 #else /* USDT2 */
aoqi@0 723 DT_RETURN_MARK_DECL(ThrowNew, jint
aoqi@0 724 , HOTSPOT_JNI_THROWNEW_RETURN(_ret_ref));
aoqi@0 725 #endif /* USDT2 */
aoqi@0 726
aoqi@0 727 JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message))
aoqi@0 728 JNIWrapper("ThrowNew");
aoqi@0 729 #ifndef USDT2
aoqi@0 730 DTRACE_PROBE3(hotspot_jni, ThrowNew__entry, env, clazz, message);
aoqi@0 731 #else /* USDT2 */
aoqi@0 732 HOTSPOT_JNI_THROWNEW_ENTRY(
aoqi@0 733 env, clazz, (char *) message);
aoqi@0 734 #endif /* USDT2 */
aoqi@0 735 jint ret = JNI_OK;
aoqi@0 736 DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret);
aoqi@0 737
aoqi@0 738 InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
aoqi@0 739 Symbol* name = k->name();
aoqi@0 740 Handle class_loader (THREAD, k->class_loader());
aoqi@0 741 Handle protection_domain (THREAD, k->protection_domain());
aoqi@0 742 THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);
aoqi@0 743 ShouldNotReachHere();
aoqi@0 744 JNI_END
aoqi@0 745
aoqi@0 746
aoqi@0 747 // JNI functions only transform a pending async exception to a synchronous
aoqi@0 748 // exception in ExceptionOccurred and ExceptionCheck calls, since
aoqi@0 749 // delivering an async exception in other places won't change the native
aoqi@0 750 // code's control flow and would be harmful when native code further calls
aoqi@0 751 // JNI functions with a pending exception. Async exception is also checked
aoqi@0 752 // during the call, so ExceptionOccurred/ExceptionCheck won't return
aoqi@0 753 // false but deliver the async exception at the very end during
aoqi@0 754 // state transition.
aoqi@0 755
aoqi@0 756 static void jni_check_async_exceptions(JavaThread *thread) {
aoqi@0 757 assert(thread == Thread::current(), "must be itself");
aoqi@0 758 thread->check_and_handle_async_exceptions();
aoqi@0 759 }
aoqi@0 760
aoqi@0 761 JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env))
aoqi@0 762 JNIWrapper("ExceptionOccurred");
aoqi@0 763 #ifndef USDT2
aoqi@0 764 DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__entry, env);
aoqi@0 765 #else /* USDT2 */
aoqi@0 766 HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY(
aoqi@0 767 env);
aoqi@0 768 #endif /* USDT2 */
aoqi@0 769 jni_check_async_exceptions(thread);
aoqi@0 770 oop exception = thread->pending_exception();
aoqi@0 771 jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception);
aoqi@0 772 #ifndef USDT2
aoqi@0 773 DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__return, ret);
aoqi@0 774 #else /* USDT2 */
aoqi@0 775 HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(
aoqi@0 776 ret);
aoqi@0 777 #endif /* USDT2 */
aoqi@0 778 return ret;
aoqi@0 779 JNI_END
aoqi@0 780
aoqi@0 781
aoqi@0 782 JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env))
aoqi@0 783 JNIWrapper("ExceptionDescribe");
aoqi@0 784 #ifndef USDT2
aoqi@0 785 DTRACE_PROBE1(hotspot_jni, ExceptionDescribe__entry, env);
aoqi@0 786 #else /* USDT2 */
aoqi@0 787 HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY(
aoqi@0 788 env);
aoqi@0 789 #endif /* USDT2 */
aoqi@0 790 if (thread->has_pending_exception()) {
aoqi@0 791 Handle ex(thread, thread->pending_exception());
aoqi@0 792 thread->clear_pending_exception();
aoqi@0 793 if (ex->is_a(SystemDictionary::ThreadDeath_klass())) {
aoqi@0 794 // Don't print anything if we are being killed.
aoqi@0 795 } else {
aoqi@0 796 jio_fprintf(defaultStream::error_stream(), "Exception ");
aoqi@0 797 if (thread != NULL && thread->threadObj() != NULL) {
aoqi@0 798 ResourceMark rm(THREAD);
aoqi@0 799 jio_fprintf(defaultStream::error_stream(),
aoqi@0 800 "in thread \"%s\" ", thread->get_thread_name());
aoqi@0 801 }
aoqi@0 802 if (ex->is_a(SystemDictionary::Throwable_klass())) {
aoqi@0 803 JavaValue result(T_VOID);
aoqi@0 804 JavaCalls::call_virtual(&result,
aoqi@0 805 ex,
aoqi@0 806 KlassHandle(THREAD,
aoqi@0 807 SystemDictionary::Throwable_klass()),
aoqi@0 808 vmSymbols::printStackTrace_name(),
aoqi@0 809 vmSymbols::void_method_signature(),
aoqi@0 810 THREAD);
aoqi@0 811 // If an exception is thrown in the call it gets thrown away. Not much
aoqi@0 812 // we can do with it. The native code that calls this, does not check
aoqi@0 813 // for the exception - hence, it might still be in the thread when DestroyVM gets
aoqi@0 814 // called, potentially causing a few asserts to trigger - since no pending exception
aoqi@0 815 // is expected.
aoqi@0 816 CLEAR_PENDING_EXCEPTION;
aoqi@0 817 } else {
aoqi@0 818 ResourceMark rm(THREAD);
aoqi@0 819 jio_fprintf(defaultStream::error_stream(),
aoqi@0 820 ". Uncaught exception of type %s.",
aoqi@0 821 ex->klass()->external_name());
aoqi@0 822 }
aoqi@0 823 }
aoqi@0 824 }
aoqi@0 825 #ifndef USDT2
aoqi@0 826 DTRACE_PROBE(hotspot_jni, ExceptionDescribe__return);
aoqi@0 827 #else /* USDT2 */
aoqi@0 828 HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN(
aoqi@0 829 );
aoqi@0 830 #endif /* USDT2 */
aoqi@0 831 JNI_END
aoqi@0 832
aoqi@0 833
aoqi@0 834 JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env))
aoqi@0 835 JNIWrapper("ExceptionClear");
aoqi@0 836 #ifndef USDT2
aoqi@0 837 DTRACE_PROBE1(hotspot_jni, ExceptionClear__entry, env);
aoqi@0 838 #else /* USDT2 */
aoqi@0 839 HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY(
aoqi@0 840 env);
aoqi@0 841 #endif /* USDT2 */
aoqi@0 842
aoqi@0 843 // The jni code might be using this API to clear java thrown exception.
aoqi@0 844 // So just mark jvmti thread exception state as exception caught.
aoqi@0 845 JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state();
aoqi@0 846 if (state != NULL && state->is_exception_detected()) {
aoqi@0 847 state->set_exception_caught();
aoqi@0 848 }
aoqi@0 849 thread->clear_pending_exception();
aoqi@0 850 #ifndef USDT2
aoqi@0 851 DTRACE_PROBE(hotspot_jni, ExceptionClear__return);
aoqi@0 852 #else /* USDT2 */
aoqi@0 853 HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN(
aoqi@0 854 );
aoqi@0 855 #endif /* USDT2 */
aoqi@0 856 JNI_END
aoqi@0 857
aoqi@0 858
aoqi@0 859 JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg))
aoqi@0 860 JNIWrapper("FatalError");
aoqi@0 861 #ifndef USDT2
aoqi@0 862 DTRACE_PROBE2(hotspot_jni, FatalError__entry, env, msg);
aoqi@0 863 #else /* USDT2 */
aoqi@0 864 HOTSPOT_JNI_FATALERROR_ENTRY(
aoqi@0 865 env, (char *) msg);
aoqi@0 866 #endif /* USDT2 */
aoqi@0 867 tty->print_cr("FATAL ERROR in native method: %s", msg);
aoqi@0 868 thread->print_stack();
aoqi@0 869 os::abort(); // Dump core and abort
aoqi@0 870 JNI_END
aoqi@0 871
aoqi@0 872
aoqi@0 873 JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity))
aoqi@0 874 JNIWrapper("PushLocalFrame");
aoqi@0 875 #ifndef USDT2
aoqi@0 876 DTRACE_PROBE2(hotspot_jni, PushLocalFrame__entry, env, capacity);
aoqi@0 877 #else /* USDT2 */
aoqi@0 878 HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY(
aoqi@0 879 env, capacity);
aoqi@0 880 #endif /* USDT2 */
aoqi@0 881 //%note jni_11
aoqi@0 882 if (capacity < 0 || capacity > MAX_REASONABLE_LOCAL_CAPACITY) {
aoqi@0 883 #ifndef USDT2
aoqi@0 884 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR);
aoqi@0 885 #else /* USDT2 */
aoqi@0 886 HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(
aoqi@0 887 (uint32_t)JNI_ERR);
aoqi@0 888 #endif /* USDT2 */
aoqi@0 889 return JNI_ERR;
aoqi@0 890 }
aoqi@0 891 JNIHandleBlock* old_handles = thread->active_handles();
aoqi@0 892 JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
aoqi@0 893 assert(new_handles != NULL, "should not be NULL");
aoqi@0 894 new_handles->set_pop_frame_link(old_handles);
aoqi@0 895 thread->set_active_handles(new_handles);
aoqi@0 896 jint ret = JNI_OK;
aoqi@0 897 #ifndef USDT2
aoqi@0 898 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, ret);
aoqi@0 899 #else /* USDT2 */
aoqi@0 900 HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(
aoqi@0 901 ret);
aoqi@0 902 #endif /* USDT2 */
aoqi@0 903 return ret;
aoqi@0 904 JNI_END
aoqi@0 905
aoqi@0 906
aoqi@0 907 JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result))
aoqi@0 908 JNIWrapper("PopLocalFrame");
aoqi@0 909 #ifndef USDT2
aoqi@0 910 DTRACE_PROBE2(hotspot_jni, PopLocalFrame__entry, env, result);
aoqi@0 911 #else /* USDT2 */
aoqi@0 912 HOTSPOT_JNI_POPLOCALFRAME_ENTRY(
aoqi@0 913 env, result);
aoqi@0 914 #endif /* USDT2 */
aoqi@0 915 //%note jni_11
aoqi@0 916 Handle result_handle(thread, JNIHandles::resolve(result));
aoqi@0 917 JNIHandleBlock* old_handles = thread->active_handles();
aoqi@0 918 JNIHandleBlock* new_handles = old_handles->pop_frame_link();
aoqi@0 919 if (new_handles != NULL) {
aoqi@0 920 // As a sanity check we only release the handle blocks if the pop_frame_link is not NULL.
aoqi@0 921 // This way code will still work if PopLocalFrame is called without a corresponding
aoqi@0 922 // PushLocalFrame call. Note that we set the pop_frame_link to NULL explicitly, otherwise
aoqi@0 923 // the release_block call will release the blocks.
aoqi@0 924 thread->set_active_handles(new_handles);
aoqi@0 925 old_handles->set_pop_frame_link(NULL); // clear link we won't release new_handles below
aoqi@0 926 JNIHandleBlock::release_block(old_handles, thread); // may block
aoqi@0 927 result = JNIHandles::make_local(thread, result_handle());
aoqi@0 928 }
aoqi@0 929 #ifndef USDT2
aoqi@0 930 DTRACE_PROBE1(hotspot_jni, PopLocalFrame__return, result);
aoqi@0 931 #else /* USDT2 */
aoqi@0 932 HOTSPOT_JNI_POPLOCALFRAME_RETURN(
aoqi@0 933 result);
aoqi@0 934 #endif /* USDT2 */
aoqi@0 935 return result;
aoqi@0 936 JNI_END
aoqi@0 937
aoqi@0 938
aoqi@0 939 JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref))
aoqi@0 940 JNIWrapper("NewGlobalRef");
aoqi@0 941 #ifndef USDT2
aoqi@0 942 DTRACE_PROBE2(hotspot_jni, NewGlobalRef__entry, env, ref);
aoqi@0 943 #else /* USDT2 */
aoqi@0 944 HOTSPOT_JNI_NEWGLOBALREF_ENTRY(
aoqi@0 945 env, ref);
aoqi@0 946 #endif /* USDT2 */
aoqi@0 947 Handle ref_handle(thread, JNIHandles::resolve(ref));
aoqi@0 948 jobject ret = JNIHandles::make_global(ref_handle);
aoqi@0 949 #ifndef USDT2
aoqi@0 950 DTRACE_PROBE1(hotspot_jni, NewGlobalRef__return, ret);
aoqi@0 951 #else /* USDT2 */
aoqi@0 952 HOTSPOT_JNI_NEWGLOBALREF_RETURN(
aoqi@0 953 ret);
aoqi@0 954 #endif /* USDT2 */
aoqi@0 955 return ret;
aoqi@0 956 JNI_END
aoqi@0 957
aoqi@0 958 // Must be JNI_ENTRY (with HandleMark)
aoqi@0 959 JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref))
aoqi@0 960 JNIWrapper("DeleteGlobalRef");
aoqi@0 961 #ifndef USDT2
aoqi@0 962 DTRACE_PROBE2(hotspot_jni, DeleteGlobalRef__entry, env, ref);
aoqi@0 963 #else /* USDT2 */
aoqi@0 964 HOTSPOT_JNI_DELETEGLOBALREF_ENTRY(
aoqi@0 965 env, ref);
aoqi@0 966 #endif /* USDT2 */
aoqi@0 967 JNIHandles::destroy_global(ref);
aoqi@0 968 #ifndef USDT2
aoqi@0 969 DTRACE_PROBE(hotspot_jni, DeleteGlobalRef__return);
aoqi@0 970 #else /* USDT2 */
aoqi@0 971 HOTSPOT_JNI_DELETEGLOBALREF_RETURN(
aoqi@0 972 );
aoqi@0 973 #endif /* USDT2 */
aoqi@0 974 JNI_END
aoqi@0 975
aoqi@0 976 JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj))
aoqi@0 977 JNIWrapper("DeleteLocalRef");
aoqi@0 978 #ifndef USDT2
aoqi@0 979 DTRACE_PROBE2(hotspot_jni, DeleteLocalRef__entry, env, obj);
aoqi@0 980 #else /* USDT2 */
aoqi@0 981 HOTSPOT_JNI_DELETELOCALREF_ENTRY(
aoqi@0 982 env, obj);
aoqi@0 983 #endif /* USDT2 */
aoqi@0 984 JNIHandles::destroy_local(obj);
aoqi@0 985 #ifndef USDT2
aoqi@0 986 DTRACE_PROBE(hotspot_jni, DeleteLocalRef__return);
aoqi@0 987 #else /* USDT2 */
aoqi@0 988 HOTSPOT_JNI_DELETELOCALREF_RETURN(
aoqi@0 989 );
aoqi@0 990 #endif /* USDT2 */
aoqi@0 991 JNI_END
aoqi@0 992
aoqi@0 993 JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2))
aoqi@0 994 JNIWrapper("IsSameObject");
aoqi@0 995 #ifndef USDT2
aoqi@0 996 DTRACE_PROBE3(hotspot_jni, IsSameObject__entry, env, r1, r2);
aoqi@0 997 #else /* USDT2 */
aoqi@0 998 HOTSPOT_JNI_ISSAMEOBJECT_ENTRY(
aoqi@0 999 env, r1, r2);
aoqi@0 1000 #endif /* USDT2 */
aoqi@0 1001 oop a = JNIHandles::resolve(r1);
aoqi@0 1002 oop b = JNIHandles::resolve(r2);
aoqi@0 1003 jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE;
aoqi@0 1004 #ifndef USDT2
aoqi@0 1005 DTRACE_PROBE1(hotspot_jni, IsSameObject__return, ret);
aoqi@0 1006 #else /* USDT2 */
aoqi@0 1007 HOTSPOT_JNI_ISSAMEOBJECT_RETURN(
aoqi@0 1008 ret);
aoqi@0 1009 #endif /* USDT2 */
aoqi@0 1010 return ret;
aoqi@0 1011 JNI_END
aoqi@0 1012
aoqi@0 1013
aoqi@0 1014 JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref))
aoqi@0 1015 JNIWrapper("NewLocalRef");
aoqi@0 1016 #ifndef USDT2
aoqi@0 1017 DTRACE_PROBE2(hotspot_jni, NewLocalRef__entry, env, ref);
aoqi@0 1018 #else /* USDT2 */
aoqi@0 1019 HOTSPOT_JNI_NEWLOCALREF_ENTRY(
aoqi@0 1020 env, ref);
aoqi@0 1021 #endif /* USDT2 */
aoqi@0 1022 jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref));
aoqi@0 1023 #ifndef USDT2
aoqi@0 1024 DTRACE_PROBE1(hotspot_jni, NewLocalRef__return, ret);
aoqi@0 1025 #else /* USDT2 */
aoqi@0 1026 HOTSPOT_JNI_NEWLOCALREF_RETURN(
aoqi@0 1027 ret);
aoqi@0 1028 #endif /* USDT2 */
aoqi@0 1029 return ret;
aoqi@0 1030 JNI_END
aoqi@0 1031
aoqi@0 1032 JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity))
aoqi@0 1033 JNIWrapper("EnsureLocalCapacity");
aoqi@0 1034 #ifndef USDT2
aoqi@0 1035 DTRACE_PROBE2(hotspot_jni, EnsureLocalCapacity__entry, env, capacity);
aoqi@0 1036 #else /* USDT2 */
aoqi@0 1037 HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY(
aoqi@0 1038 env, capacity);
aoqi@0 1039 #endif /* USDT2 */
aoqi@0 1040 jint ret;
aoqi@0 1041 if (capacity >= 0 && capacity <= MAX_REASONABLE_LOCAL_CAPACITY) {
aoqi@0 1042 ret = JNI_OK;
aoqi@0 1043 } else {
aoqi@0 1044 ret = JNI_ERR;
aoqi@0 1045 }
aoqi@0 1046 #ifndef USDT2
aoqi@0 1047 DTRACE_PROBE1(hotspot_jni, EnsureLocalCapacity__return, ret);
aoqi@0 1048 #else /* USDT2 */
aoqi@0 1049 HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN(
aoqi@0 1050 ret);
aoqi@0 1051 #endif /* USDT2 */
aoqi@0 1052 return ret;
aoqi@0 1053 JNI_END
aoqi@0 1054
aoqi@0 1055 // Return the Handle Type
aoqi@0 1056 JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj))
aoqi@0 1057 JNIWrapper("GetObjectRefType");
aoqi@0 1058 #ifndef USDT2
aoqi@0 1059 DTRACE_PROBE2(hotspot_jni, GetObjectRefType__entry, env, obj);
aoqi@0 1060 #else /* USDT2 */
aoqi@0 1061 HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY(
aoqi@0 1062 env, obj);
aoqi@0 1063 #endif /* USDT2 */
aoqi@0 1064 jobjectRefType ret;
aoqi@0 1065 if (JNIHandles::is_local_handle(thread, obj) ||
aoqi@0 1066 JNIHandles::is_frame_handle(thread, obj))
aoqi@0 1067 ret = JNILocalRefType;
aoqi@0 1068 else if (JNIHandles::is_global_handle(obj))
aoqi@0 1069 ret = JNIGlobalRefType;
aoqi@0 1070 else if (JNIHandles::is_weak_global_handle(obj))
aoqi@0 1071 ret = JNIWeakGlobalRefType;
aoqi@0 1072 else
aoqi@0 1073 ret = JNIInvalidRefType;
aoqi@0 1074 #ifndef USDT2
aoqi@0 1075 DTRACE_PROBE1(hotspot_jni, GetObjectRefType__return, ret);
aoqi@0 1076 #else /* USDT2 */
aoqi@0 1077 HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN(
aoqi@0 1078 (void *) ret);
aoqi@0 1079 #endif /* USDT2 */
aoqi@0 1080 return ret;
aoqi@0 1081 JNI_END
aoqi@0 1082
aoqi@0 1083
aoqi@0 1084 class JNI_ArgumentPusher : public SignatureIterator {
aoqi@0 1085 protected:
aoqi@0 1086 JavaCallArguments* _arguments;
aoqi@0 1087
aoqi@0 1088 virtual void get_bool () = 0;
aoqi@0 1089 virtual void get_char () = 0;
aoqi@0 1090 virtual void get_short () = 0;
aoqi@0 1091 virtual void get_byte () = 0;
aoqi@0 1092 virtual void get_int () = 0;
aoqi@0 1093 virtual void get_long () = 0;
aoqi@0 1094 virtual void get_float () = 0;
aoqi@0 1095 virtual void get_double () = 0;
aoqi@0 1096 virtual void get_object () = 0;
aoqi@0 1097
aoqi@0 1098 JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) {
aoqi@0 1099 this->_return_type = T_ILLEGAL;
aoqi@0 1100 _arguments = NULL;
aoqi@0 1101 }
aoqi@0 1102
aoqi@0 1103 public:
aoqi@0 1104 virtual void iterate( uint64_t fingerprint ) = 0;
aoqi@0 1105
aoqi@0 1106 void set_java_argument_object(JavaCallArguments *arguments) { _arguments = arguments; }
aoqi@0 1107
aoqi@0 1108 inline void do_bool() { if (!is_return_type()) get_bool(); }
aoqi@0 1109 inline void do_char() { if (!is_return_type()) get_char(); }
aoqi@0 1110 inline void do_short() { if (!is_return_type()) get_short(); }
aoqi@0 1111 inline void do_byte() { if (!is_return_type()) get_byte(); }
aoqi@0 1112 inline void do_int() { if (!is_return_type()) get_int(); }
aoqi@0 1113 inline void do_long() { if (!is_return_type()) get_long(); }
aoqi@0 1114 inline void do_float() { if (!is_return_type()) get_float(); }
aoqi@0 1115 inline void do_double() { if (!is_return_type()) get_double(); }
aoqi@0 1116 inline void do_object(int begin, int end) { if (!is_return_type()) get_object(); }
aoqi@0 1117 inline void do_array(int begin, int end) { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array
aoqi@0 1118 inline void do_void() { }
aoqi@0 1119
aoqi@0 1120 JavaCallArguments* arguments() { return _arguments; }
aoqi@0 1121 void push_receiver(Handle h) { _arguments->push_oop(h); }
aoqi@0 1122 };
aoqi@0 1123
aoqi@0 1124
aoqi@0 1125 class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
aoqi@0 1126 protected:
aoqi@0 1127 va_list _ap;
aoqi@0 1128
aoqi@0 1129 inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg
aoqi@0 1130 inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg
aoqi@0 1131 inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg
aoqi@0 1132 inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg
aoqi@0 1133 inline void get_int() { _arguments->push_int(va_arg(_ap, jint)); }
aoqi@0 1134
aoqi@0 1135 // each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
aoqi@0 1136
aoqi@0 1137 inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); }
aoqi@0 1138 inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg
aoqi@0 1139 inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); }
aoqi@0 1140 inline void get_object() { jobject l = va_arg(_ap, jobject);
aoqi@0 1141 _arguments->push_oop(Handle((oop *)l, false)); }
aoqi@0 1142
aoqi@0 1143 inline void set_ap(va_list rap) {
aoqi@0 1144 #ifdef va_copy
aoqi@0 1145 va_copy(_ap, rap);
aoqi@0 1146 #elif defined (__va_copy)
aoqi@0 1147 __va_copy(_ap, rap);
aoqi@0 1148 #else
aoqi@0 1149 _ap = rap;
aoqi@0 1150 #endif
aoqi@0 1151 }
aoqi@0 1152
aoqi@0 1153 public:
aoqi@0 1154 JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap)
aoqi@0 1155 : JNI_ArgumentPusher(signature) {
aoqi@0 1156 set_ap(rap);
aoqi@0 1157 }
aoqi@0 1158 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
aoqi@0 1159 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {
aoqi@0 1160 set_ap(rap);
aoqi@0 1161 }
aoqi@0 1162
aoqi@0 1163 // Optimized path if we have the bitvector form of signature
aoqi@0 1164 void iterate( uint64_t fingerprint ) {
aoqi@0 1165 if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate();// Must be too many arguments
aoqi@0 1166 else {
aoqi@0 1167 _return_type = (BasicType)((fingerprint >> static_feature_size) &
aoqi@0 1168 result_feature_mask);
aoqi@0 1169
aoqi@0 1170 assert(fingerprint, "Fingerprint should not be 0");
aoqi@0 1171 fingerprint = fingerprint >> (static_feature_size + result_feature_size);
aoqi@0 1172 while ( 1 ) {
aoqi@0 1173 switch ( fingerprint & parameter_feature_mask ) {
aoqi@0 1174 case bool_parm:
aoqi@0 1175 case char_parm:
aoqi@0 1176 case short_parm:
aoqi@0 1177 case byte_parm:
aoqi@0 1178 case int_parm:
aoqi@0 1179 get_int();
aoqi@0 1180 break;
aoqi@0 1181 case obj_parm:
aoqi@0 1182 get_object();
aoqi@0 1183 break;
aoqi@0 1184 case long_parm:
aoqi@0 1185 get_long();
aoqi@0 1186 break;
aoqi@0 1187 case float_parm:
aoqi@0 1188 get_float();
aoqi@0 1189 break;
aoqi@0 1190 case double_parm:
aoqi@0 1191 get_double();
aoqi@0 1192 break;
aoqi@0 1193 case done_parm:
aoqi@0 1194 return;
aoqi@0 1195 break;
aoqi@0 1196 default:
aoqi@0 1197 ShouldNotReachHere();
aoqi@0 1198 break;
aoqi@0 1199 }
aoqi@0 1200 fingerprint >>= parameter_feature_size;
aoqi@0 1201 }
aoqi@0 1202 }
aoqi@0 1203 }
aoqi@0 1204 };
aoqi@0 1205
aoqi@0 1206
aoqi@0 1207 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
aoqi@0 1208 protected:
aoqi@0 1209 const jvalue *_ap;
aoqi@0 1210
aoqi@0 1211 inline void get_bool() { _arguments->push_int((jint)(_ap++)->z); }
aoqi@0 1212 inline void get_char() { _arguments->push_int((jint)(_ap++)->c); }
aoqi@0 1213 inline void get_short() { _arguments->push_int((jint)(_ap++)->s); }
aoqi@0 1214 inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); }
aoqi@0 1215 inline void get_int() { _arguments->push_int((jint)(_ap++)->i); }
aoqi@0 1216
aoqi@0 1217 inline void get_long() { _arguments->push_long((_ap++)->j); }
aoqi@0 1218 inline void get_float() { _arguments->push_float((_ap++)->f); }
aoqi@0 1219 inline void get_double() { _arguments->push_double((_ap++)->d);}
aoqi@0 1220 inline void get_object() { _arguments->push_oop(Handle((oop *)(_ap++)->l, false)); }
aoqi@0 1221
aoqi@0 1222 inline void set_ap(const jvalue *rap) { _ap = rap; }
aoqi@0 1223
aoqi@0 1224 public:
aoqi@0 1225 JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap)
aoqi@0 1226 : JNI_ArgumentPusher(signature) {
aoqi@0 1227 set_ap(rap);
aoqi@0 1228 }
aoqi@0 1229 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
aoqi@0 1230 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {
aoqi@0 1231 set_ap(rap);
aoqi@0 1232 }
aoqi@0 1233
aoqi@0 1234 // Optimized path if we have the bitvector form of signature
aoqi@0 1235 void iterate( uint64_t fingerprint ) {
aoqi@0 1236 if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate(); // Must be too many arguments
aoqi@0 1237 else {
aoqi@0 1238 _return_type = (BasicType)((fingerprint >> static_feature_size) &
aoqi@0 1239 result_feature_mask);
aoqi@0 1240 assert(fingerprint, "Fingerprint should not be 0");
aoqi@0 1241 fingerprint = fingerprint >> (static_feature_size + result_feature_size);
aoqi@0 1242 while ( 1 ) {
aoqi@0 1243 switch ( fingerprint & parameter_feature_mask ) {
aoqi@0 1244 case bool_parm:
aoqi@0 1245 get_bool();
aoqi@0 1246 break;
aoqi@0 1247 case char_parm:
aoqi@0 1248 get_char();
aoqi@0 1249 break;
aoqi@0 1250 case short_parm:
aoqi@0 1251 get_short();
aoqi@0 1252 break;
aoqi@0 1253 case byte_parm:
aoqi@0 1254 get_byte();
aoqi@0 1255 break;
aoqi@0 1256 case int_parm:
aoqi@0 1257 get_int();
aoqi@0 1258 break;
aoqi@0 1259 case obj_parm:
aoqi@0 1260 get_object();
aoqi@0 1261 break;
aoqi@0 1262 case long_parm:
aoqi@0 1263 get_long();
aoqi@0 1264 break;
aoqi@0 1265 case float_parm:
aoqi@0 1266 get_float();
aoqi@0 1267 break;
aoqi@0 1268 case double_parm:
aoqi@0 1269 get_double();
aoqi@0 1270 break;
aoqi@0 1271 case done_parm:
aoqi@0 1272 return;
aoqi@0 1273 break;
aoqi@0 1274 default:
aoqi@0 1275 ShouldNotReachHere();
aoqi@0 1276 break;
aoqi@0 1277 }
aoqi@0 1278 fingerprint >>= parameter_feature_size;
aoqi@0 1279 }
aoqi@0 1280 }
aoqi@0 1281 }
aoqi@0 1282 };
aoqi@0 1283
aoqi@0 1284
aoqi@0 1285 enum JNICallType {
aoqi@0 1286 JNI_STATIC,
aoqi@0 1287 JNI_VIRTUAL,
aoqi@0 1288 JNI_NONVIRTUAL
aoqi@0 1289 };
aoqi@0 1290
aoqi@0 1291
aoqi@0 1292
aoqi@0 1293 static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
aoqi@0 1294 methodHandle method(THREAD, Method::resolve_jmethod_id(method_id));
aoqi@0 1295
aoqi@0 1296 // Create object to hold arguments for the JavaCall, and associate it with
aoqi@0 1297 // the jni parser
aoqi@0 1298 ResourceMark rm(THREAD);
aoqi@0 1299 int number_of_parameters = method->size_of_parameters();
aoqi@0 1300 JavaCallArguments java_args(number_of_parameters);
aoqi@0 1301 args->set_java_argument_object(&java_args);
aoqi@0 1302
aoqi@0 1303 assert(method->is_static(), "method should be static");
aoqi@0 1304
aoqi@0 1305 // Fill out JavaCallArguments object
aoqi@0 1306 args->iterate( Fingerprinter(method).fingerprint() );
aoqi@0 1307 // Initialize result type
aoqi@0 1308 result->set_type(args->get_ret_type());
aoqi@0 1309
aoqi@0 1310 // Invoke the method. Result is returned as oop.
aoqi@0 1311 JavaCalls::call(result, method, &java_args, CHECK);
aoqi@0 1312
aoqi@0 1313 // Convert result
aoqi@0 1314 if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
aoqi@0 1315 result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));
aoqi@0 1316 }
aoqi@0 1317 }
aoqi@0 1318
aoqi@0 1319
aoqi@0 1320 static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
aoqi@0 1321 oop recv = JNIHandles::resolve(receiver);
aoqi@0 1322 if (recv == NULL) {
aoqi@0 1323 THROW(vmSymbols::java_lang_NullPointerException());
aoqi@0 1324 }
aoqi@0 1325 Handle h_recv(THREAD, recv);
aoqi@0 1326
aoqi@0 1327 int number_of_parameters;
aoqi@0 1328 Method* selected_method;
aoqi@0 1329 {
aoqi@0 1330 Method* m = Method::resolve_jmethod_id(method_id);
aoqi@0 1331 number_of_parameters = m->size_of_parameters();
aoqi@0 1332 Klass* holder = m->method_holder();
aoqi@0 1333 if (!(holder)->is_interface()) {
aoqi@0 1334 // non-interface call -- for that little speed boost, don't handlize
aoqi@0 1335 debug_only(No_Safepoint_Verifier nosafepoint;)
aoqi@0 1336 if (call_type == JNI_VIRTUAL) {
aoqi@0 1337 // jni_GetMethodID makes sure class is linked and initialized
aoqi@0 1338 // so m should have a valid vtable index.
aoqi@0 1339 assert(!m->has_itable_index(), "");
aoqi@0 1340 int vtbl_index = m->vtable_index();
aoqi@0 1341 if (vtbl_index != Method::nonvirtual_vtable_index) {
aoqi@0 1342 Klass* k = h_recv->klass();
aoqi@0 1343 // k might be an arrayKlassOop but all vtables start at
aoqi@0 1344 // the same place. The cast is to avoid virtual call and assertion.
aoqi@0 1345 InstanceKlass *ik = (InstanceKlass*)k;
aoqi@0 1346 selected_method = ik->method_at_vtable(vtbl_index);
aoqi@0 1347 } else {
aoqi@0 1348 // final method
aoqi@0 1349 selected_method = m;
aoqi@0 1350 }
aoqi@0 1351 } else {
aoqi@0 1352 // JNI_NONVIRTUAL call
aoqi@0 1353 selected_method = m;
aoqi@0 1354 }
aoqi@0 1355 } else {
aoqi@0 1356 // interface call
aoqi@0 1357 KlassHandle h_holder(THREAD, holder);
aoqi@0 1358
aoqi@0 1359 if (call_type == JNI_VIRTUAL) {
aoqi@0 1360 int itbl_index = m->itable_index();
aoqi@0 1361 Klass* k = h_recv->klass();
aoqi@0 1362 selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
aoqi@0 1363 } else {
aoqi@0 1364 selected_method = m;
aoqi@0 1365 }
aoqi@0 1366 }
aoqi@0 1367 }
aoqi@0 1368
aoqi@0 1369 methodHandle method(THREAD, selected_method);
aoqi@0 1370
aoqi@0 1371 // Create object to hold arguments for the JavaCall, and associate it with
aoqi@0 1372 // the jni parser
aoqi@0 1373 ResourceMark rm(THREAD);
aoqi@0 1374 JavaCallArguments java_args(number_of_parameters);
aoqi@0 1375 args->set_java_argument_object(&java_args);
aoqi@0 1376
aoqi@0 1377 // handle arguments
aoqi@0 1378 assert(!method->is_static(), "method should not be static");
aoqi@0 1379 args->push_receiver(h_recv); // Push jobject handle
aoqi@0 1380
aoqi@0 1381 // Fill out JavaCallArguments object
aoqi@0 1382 args->iterate( Fingerprinter(method).fingerprint() );
aoqi@0 1383 // Initialize result type
aoqi@0 1384 result->set_type(args->get_ret_type());
aoqi@0 1385
aoqi@0 1386 // Invoke the method. Result is returned as oop.
aoqi@0 1387 JavaCalls::call(result, method, &java_args, CHECK);
aoqi@0 1388
aoqi@0 1389 // Convert result
aoqi@0 1390 if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
aoqi@0 1391 result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));
aoqi@0 1392 }
aoqi@0 1393 }
aoqi@0 1394
aoqi@0 1395
aoqi@0 1396 static instanceOop alloc_object(jclass clazz, TRAPS) {
aoqi@0 1397 KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
aoqi@0 1398 k()->check_valid_for_instantiation(false, CHECK_NULL);
aoqi@0 1399 InstanceKlass::cast(k())->initialize(CHECK_NULL);
aoqi@0 1400 instanceOop ih = InstanceKlass::cast(k())->allocate_instance(THREAD);
aoqi@0 1401 return ih;
aoqi@0 1402 }
aoqi@0 1403
aoqi@0 1404 #ifndef USDT2
aoqi@0 1405 DT_RETURN_MARK_DECL(AllocObject, jobject);
aoqi@0 1406 #else /* USDT2 */
aoqi@0 1407 DT_RETURN_MARK_DECL(AllocObject, jobject
aoqi@0 1408 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
aoqi@0 1409 #endif /* USDT2 */
aoqi@0 1410
aoqi@0 1411 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
aoqi@0 1412 JNIWrapper("AllocObject");
aoqi@0 1413
aoqi@0 1414 #ifndef USDT2
aoqi@0 1415 DTRACE_PROBE2(hotspot_jni, AllocObject__entry, env, clazz);
aoqi@0 1416 #else /* USDT2 */
aoqi@0 1417 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(
aoqi@0 1418 env, clazz);
aoqi@0 1419 #endif /* USDT2 */
aoqi@0 1420 jobject ret = NULL;
aoqi@0 1421 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
aoqi@0 1422
aoqi@0 1423 instanceOop i = alloc_object(clazz, CHECK_NULL);
aoqi@0 1424 ret = JNIHandles::make_local(env, i);
aoqi@0 1425 return ret;
aoqi@0 1426 JNI_END
aoqi@0 1427
aoqi@0 1428 #ifndef USDT2
aoqi@0 1429 DT_RETURN_MARK_DECL(NewObjectA, jobject);
aoqi@0 1430 #else /* USDT2 */
aoqi@0 1431 DT_RETURN_MARK_DECL(NewObjectA, jobject
aoqi@0 1432 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
aoqi@0 1433 #endif /* USDT2 */
aoqi@0 1434
aoqi@0 1435 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
aoqi@0 1436 JNIWrapper("NewObjectA");
aoqi@0 1437 #ifndef USDT2
aoqi@0 1438 DTRACE_PROBE3(hotspot_jni, NewObjectA__entry, env, clazz, methodID);
aoqi@0 1439 #else /* USDT2 */
aoqi@0 1440 HOTSPOT_JNI_NEWOBJECTA_ENTRY(
aoqi@0 1441 env, clazz, (uintptr_t) methodID);
aoqi@0 1442 #endif /* USDT2 */
aoqi@0 1443 jobject obj = NULL;
aoqi@0 1444 DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj);
aoqi@0 1445
aoqi@0 1446 instanceOop i = alloc_object(clazz, CHECK_NULL);
aoqi@0 1447 obj = JNIHandles::make_local(env, i);
aoqi@0 1448 JavaValue jvalue(T_VOID);
aoqi@0 1449 JNI_ArgumentPusherArray ap(methodID, args);
aoqi@0 1450 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
aoqi@0 1451 return obj;
aoqi@0 1452 JNI_END
aoqi@0 1453
aoqi@0 1454 #ifndef USDT2
aoqi@0 1455 DT_RETURN_MARK_DECL(NewObjectV, jobject);
aoqi@0 1456 #else /* USDT2 */
aoqi@0 1457 DT_RETURN_MARK_DECL(NewObjectV, jobject
aoqi@0 1458 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
aoqi@0 1459 #endif /* USDT2 */
aoqi@0 1460
aoqi@0 1461 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
aoqi@0 1462 JNIWrapper("NewObjectV");
aoqi@0 1463 #ifndef USDT2
aoqi@0 1464 DTRACE_PROBE3(hotspot_jni, NewObjectV__entry, env, clazz, methodID);
aoqi@0 1465 #else /* USDT2 */
aoqi@0 1466 HOTSPOT_JNI_NEWOBJECTV_ENTRY(
aoqi@0 1467 env, clazz, (uintptr_t) methodID);
aoqi@0 1468 #endif /* USDT2 */
aoqi@0 1469 jobject obj = NULL;
aoqi@0 1470 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
aoqi@0 1471
aoqi@0 1472 instanceOop i = alloc_object(clazz, CHECK_NULL);
aoqi@0 1473 obj = JNIHandles::make_local(env, i);
aoqi@0 1474 JavaValue jvalue(T_VOID);
aoqi@0 1475 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 1476 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
aoqi@0 1477 return obj;
aoqi@0 1478 JNI_END
aoqi@0 1479
aoqi@0 1480 #ifndef USDT2
aoqi@0 1481 DT_RETURN_MARK_DECL(NewObject, jobject);
aoqi@0 1482 #else /* USDT2 */
aoqi@0 1483 DT_RETURN_MARK_DECL(NewObject, jobject
aoqi@0 1484 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
aoqi@0 1485 #endif /* USDT2 */
aoqi@0 1486
aoqi@0 1487 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
aoqi@0 1488 JNIWrapper("NewObject");
aoqi@0 1489 #ifndef USDT2
aoqi@0 1490 DTRACE_PROBE3(hotspot_jni, NewObject__entry, env, clazz, methodID);
aoqi@0 1491 #else /* USDT2 */
aoqi@0 1492 HOTSPOT_JNI_NEWOBJECT_ENTRY(
aoqi@0 1493 env, clazz, (uintptr_t) methodID);
aoqi@0 1494 #endif /* USDT2 */
aoqi@0 1495 jobject obj = NULL;
aoqi@0 1496 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
aoqi@0 1497
aoqi@0 1498 instanceOop i = alloc_object(clazz, CHECK_NULL);
aoqi@0 1499 obj = JNIHandles::make_local(env, i);
aoqi@0 1500 va_list args;
aoqi@0 1501 va_start(args, methodID);
aoqi@0 1502 JavaValue jvalue(T_VOID);
aoqi@0 1503 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 1504 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
aoqi@0 1505 va_end(args);
aoqi@0 1506 return obj;
aoqi@0 1507 JNI_END
aoqi@0 1508
aoqi@0 1509
aoqi@0 1510 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
aoqi@0 1511 JNIWrapper("GetObjectClass");
aoqi@0 1512 #ifndef USDT2
aoqi@0 1513 DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj);
aoqi@0 1514 #else /* USDT2 */
aoqi@0 1515 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(
aoqi@0 1516 env, obj);
aoqi@0 1517 #endif /* USDT2 */
aoqi@0 1518 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
aoqi@0 1519 jclass ret =
aoqi@0 1520 (jclass) JNIHandles::make_local(env, k->java_mirror());
aoqi@0 1521 #ifndef USDT2
aoqi@0 1522 DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret);
aoqi@0 1523 #else /* USDT2 */
aoqi@0 1524 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(
aoqi@0 1525 ret);
aoqi@0 1526 #endif /* USDT2 */
aoqi@0 1527 return ret;
aoqi@0 1528 JNI_END
aoqi@0 1529
aoqi@0 1530 JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
aoqi@0 1531 JNIWrapper("IsInstanceOf");
aoqi@0 1532 #ifndef USDT2
aoqi@0 1533 DTRACE_PROBE3(hotspot_jni, IsInstanceOf__entry, env, obj, clazz);
aoqi@0 1534 #else /* USDT2 */
aoqi@0 1535 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(
aoqi@0 1536 env, obj, clazz);
aoqi@0 1537 #endif /* USDT2 */
aoqi@0 1538 jboolean ret = JNI_TRUE;
aoqi@0 1539 if (obj != NULL) {
aoqi@0 1540 ret = JNI_FALSE;
aoqi@0 1541 Klass* k = java_lang_Class::as_Klass(
aoqi@0 1542 JNIHandles::resolve_non_null(clazz));
aoqi@0 1543 if (k != NULL) {
aoqi@0 1544 ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE;
aoqi@0 1545 }
aoqi@0 1546 }
aoqi@0 1547 #ifndef USDT2
aoqi@0 1548 DTRACE_PROBE1(hotspot_jni, IsInstanceOf__return, ret);
aoqi@0 1549 #else /* USDT2 */
aoqi@0 1550 HOTSPOT_JNI_ISINSTANCEOF_RETURN(
aoqi@0 1551 ret);
aoqi@0 1552 #endif /* USDT2 */
aoqi@0 1553 return ret;
aoqi@0 1554 JNI_END
aoqi@0 1555
aoqi@0 1556
aoqi@0 1557 static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str,
aoqi@0 1558 const char *sig, bool is_static, TRAPS) {
aoqi@0 1559 // %%%% This code should probably just call into a method in the LinkResolver
aoqi@0 1560 //
aoqi@0 1561 // The class should have been loaded (we have an instance of the class
aoqi@0 1562 // passed in) so the method and signature should already be in the symbol
aoqi@0 1563 // table. If they're not there, the method doesn't exist.
aoqi@0 1564 const char *name_to_probe = (name_str == NULL)
aoqi@0 1565 ? vmSymbols::object_initializer_name()->as_C_string()
aoqi@0 1566 : name_str;
aoqi@0 1567 TempNewSymbol name = SymbolTable::probe(name_to_probe, (int)strlen(name_to_probe));
aoqi@0 1568 TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig));
aoqi@0 1569
aoqi@0 1570 if (name == NULL || signature == NULL) {
aoqi@0 1571 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
aoqi@0 1572 }
aoqi@0 1573
aoqi@0 1574 // Throw a NoSuchMethodError exception if we have an instance of a
aoqi@0 1575 // primitive java.lang.Class
aoqi@0 1576 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) {
aoqi@0 1577 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
aoqi@0 1578 }
aoqi@0 1579
aoqi@0 1580 KlassHandle klass(THREAD,
aoqi@0 1581 java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
aoqi@0 1582
aoqi@0 1583 // Make sure class is linked and initialized before handing id's out to
aoqi@0 1584 // Method*s.
aoqi@0 1585 klass()->initialize(CHECK_NULL);
aoqi@0 1586
aoqi@0 1587 Method* m;
aoqi@0 1588 if (name == vmSymbols::object_initializer_name() ||
aoqi@0 1589 name == vmSymbols::class_initializer_name()) {
aoqi@0 1590 // Never search superclasses for constructors
aoqi@0 1591 if (klass->oop_is_instance()) {
aoqi@0 1592 m = InstanceKlass::cast(klass())->find_method(name, signature);
aoqi@0 1593 } else {
aoqi@0 1594 m = NULL;
aoqi@0 1595 }
aoqi@0 1596 } else {
aoqi@0 1597 m = klass->lookup_method(name, signature);
aoqi@0 1598 if (m == NULL && klass->oop_is_instance()) {
aoqi@0 1599 m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature);
aoqi@0 1600 }
aoqi@0 1601 }
aoqi@0 1602 if (m == NULL || (m->is_static() != is_static)) {
aoqi@0 1603 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
aoqi@0 1604 }
aoqi@0 1605 return m->jmethod_id();
aoqi@0 1606 }
aoqi@0 1607
aoqi@0 1608
aoqi@0 1609 JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz,
aoqi@0 1610 const char *name, const char *sig))
aoqi@0 1611 JNIWrapper("GetMethodID");
aoqi@0 1612 #ifndef USDT2
aoqi@0 1613 DTRACE_PROBE4(hotspot_jni, GetMethodID__entry, env, clazz, name, sig);
aoqi@0 1614 #else /* USDT2 */
aoqi@0 1615 HOTSPOT_JNI_GETMETHODID_ENTRY(
aoqi@0 1616 env, clazz, (char *) name, (char *) sig);
aoqi@0 1617 #endif /* USDT2 */
aoqi@0 1618 jmethodID ret = get_method_id(env, clazz, name, sig, false, thread);
aoqi@0 1619 #ifndef USDT2
aoqi@0 1620 DTRACE_PROBE1(hotspot_jni, GetMethodID__return, ret);
aoqi@0 1621 #else /* USDT2 */
aoqi@0 1622 HOTSPOT_JNI_GETMETHODID_RETURN(
aoqi@0 1623 (uintptr_t) ret);
aoqi@0 1624 #endif /* USDT2 */
aoqi@0 1625 return ret;
aoqi@0 1626 JNI_END
aoqi@0 1627
aoqi@0 1628
aoqi@0 1629 JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz,
aoqi@0 1630 const char *name, const char *sig))
aoqi@0 1631 JNIWrapper("GetStaticMethodID");
aoqi@0 1632 #ifndef USDT2
aoqi@0 1633 DTRACE_PROBE4(hotspot_jni, GetStaticMethodID__entry, env, clazz, name, sig);
aoqi@0 1634 #else /* USDT2 */
aoqi@0 1635 HOTSPOT_JNI_GETSTATICMETHODID_ENTRY(
aoqi@0 1636 env, (char *) clazz, (char *) name, (char *)sig);
aoqi@0 1637 #endif /* USDT2 */
aoqi@0 1638 jmethodID ret = get_method_id(env, clazz, name, sig, true, thread);
aoqi@0 1639 #ifndef USDT2
aoqi@0 1640 DTRACE_PROBE1(hotspot_jni, GetStaticMethodID__return, ret);
aoqi@0 1641 #else /* USDT2 */
aoqi@0 1642 HOTSPOT_JNI_GETSTATICMETHODID_RETURN(
aoqi@0 1643 (uintptr_t) ret);
aoqi@0 1644 #endif /* USDT2 */
aoqi@0 1645 return ret;
aoqi@0 1646 JNI_END
aoqi@0 1647
aoqi@0 1648
aoqi@0 1649
aoqi@0 1650 //
aoqi@0 1651 // Calling Methods
aoqi@0 1652 //
aoqi@0 1653
aoqi@0 1654 #ifndef USDT2
aoqi@0 1655 #define DEFINE_CALLMETHOD(ResultType, Result, Tag) \
aoqi@0 1656 \
aoqi@0 1657 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType);\
aoqi@0 1658 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType);\
aoqi@0 1659 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType);\
aoqi@0 1660 \
aoqi@0 1661 JNI_ENTRY(ResultType, \
aoqi@0 1662 jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \
aoqi@0 1663 JNIWrapper("Call" XSTR(Result) "Method"); \
aoqi@0 1664 \
aoqi@0 1665 DTRACE_PROBE3(hotspot_jni, Call##Result##Method__entry, env, obj, methodID); \
aoqi@0 1666 ResultType ret = 0;\
aoqi@0 1667 DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \
aoqi@0 1668 (const ResultType&)ret);\
aoqi@0 1669 \
aoqi@0 1670 va_list args; \
aoqi@0 1671 va_start(args, methodID); \
aoqi@0 1672 JavaValue jvalue(Tag); \
aoqi@0 1673 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 1674 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1675 va_end(args); \
aoqi@0 1676 ret = jvalue.get_##ResultType(); \
aoqi@0 1677 return ret;\
aoqi@0 1678 JNI_END \
aoqi@0 1679 \
aoqi@0 1680 \
aoqi@0 1681 JNI_ENTRY(ResultType, \
aoqi@0 1682 jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \
aoqi@0 1683 JNIWrapper("Call" XSTR(Result) "MethodV"); \
aoqi@0 1684 \
aoqi@0 1685 DTRACE_PROBE3(hotspot_jni, Call##Result##MethodV__entry, env, obj, methodID); \
aoqi@0 1686 ResultType ret = 0;\
aoqi@0 1687 DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \
aoqi@0 1688 (const ResultType&)ret);\
aoqi@0 1689 \
aoqi@0 1690 JavaValue jvalue(Tag); \
aoqi@0 1691 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 1692 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1693 ret = jvalue.get_##ResultType(); \
aoqi@0 1694 return ret;\
aoqi@0 1695 JNI_END \
aoqi@0 1696 \
aoqi@0 1697 \
aoqi@0 1698 JNI_ENTRY(ResultType, \
aoqi@0 1699 jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \
aoqi@0 1700 JNIWrapper("Call" XSTR(Result) "MethodA"); \
aoqi@0 1701 DTRACE_PROBE3(hotspot_jni, Call##Result##MethodA__entry, env, obj, methodID); \
aoqi@0 1702 ResultType ret = 0;\
aoqi@0 1703 DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \
aoqi@0 1704 (const ResultType&)ret);\
aoqi@0 1705 \
aoqi@0 1706 JavaValue jvalue(Tag); \
aoqi@0 1707 JNI_ArgumentPusherArray ap(methodID, args); \
aoqi@0 1708 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1709 ret = jvalue.get_##ResultType(); \
aoqi@0 1710 return ret;\
aoqi@0 1711 JNI_END
aoqi@0 1712
aoqi@0 1713 // the runtime type of subword integral basic types is integer
aoqi@0 1714 DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN)
aoqi@0 1715 DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE)
aoqi@0 1716 DEFINE_CALLMETHOD(jchar, Char, T_CHAR)
aoqi@0 1717 DEFINE_CALLMETHOD(jshort, Short, T_SHORT)
aoqi@0 1718
aoqi@0 1719 DEFINE_CALLMETHOD(jobject, Object, T_OBJECT)
aoqi@0 1720 DEFINE_CALLMETHOD(jint, Int, T_INT)
aoqi@0 1721 DEFINE_CALLMETHOD(jlong, Long, T_LONG)
aoqi@0 1722 DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT)
aoqi@0 1723 DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE)
aoqi@0 1724
aoqi@0 1725 DT_VOID_RETURN_MARK_DECL(CallVoidMethod);
aoqi@0 1726 DT_VOID_RETURN_MARK_DECL(CallVoidMethodV);
aoqi@0 1727 DT_VOID_RETURN_MARK_DECL(CallVoidMethodA);
aoqi@0 1728
aoqi@0 1729 #else /* USDT2 */
aoqi@0 1730
aoqi@0 1731 #define DEFINE_CALLMETHOD(ResultType, Result, Tag \
aoqi@0 1732 , EntryProbe, ReturnProbe) \
aoqi@0 1733 \
aoqi@0 1734 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType \
aoqi@0 1735 , ReturnProbe); \
aoqi@0 1736 \
aoqi@0 1737 JNI_ENTRY(ResultType, \
aoqi@0 1738 jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \
aoqi@0 1739 JNIWrapper("Call" XSTR(Result) "Method"); \
aoqi@0 1740 \
aoqi@0 1741 EntryProbe; \
aoqi@0 1742 ResultType ret = 0;\
aoqi@0 1743 DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \
aoqi@0 1744 (const ResultType&)ret);\
aoqi@0 1745 \
aoqi@0 1746 va_list args; \
aoqi@0 1747 va_start(args, methodID); \
aoqi@0 1748 JavaValue jvalue(Tag); \
aoqi@0 1749 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 1750 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1751 va_end(args); \
aoqi@0 1752 ret = jvalue.get_##ResultType(); \
aoqi@0 1753 return ret;\
aoqi@0 1754 JNI_END
aoqi@0 1755
aoqi@0 1756 // the runtime type of subword integral basic types is integer
aoqi@0 1757 DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN
aoqi@0 1758 , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1759 HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref))
aoqi@0 1760 DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE
aoqi@0 1761 , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1762 HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref))
aoqi@0 1763 DEFINE_CALLMETHOD(jchar, Char, T_CHAR
aoqi@0 1764 , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1765 HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref))
aoqi@0 1766 DEFINE_CALLMETHOD(jshort, Short, T_SHORT
aoqi@0 1767 , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1768 HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref))
aoqi@0 1769
aoqi@0 1770 DEFINE_CALLMETHOD(jobject, Object, T_OBJECT
aoqi@0 1771 , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1772 HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref))
aoqi@0 1773 DEFINE_CALLMETHOD(jint, Int, T_INT,
aoqi@0 1774 HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1775 HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref))
aoqi@0 1776 DEFINE_CALLMETHOD(jlong, Long, T_LONG
aoqi@0 1777 , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1778 HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref))
aoqi@0 1779 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 1780 DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT
aoqi@0 1781 , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1782 HOTSPOT_JNI_CALLFLOATMETHOD_RETURN())
aoqi@0 1783 DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE
aoqi@0 1784 , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1785 HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN())
aoqi@0 1786
aoqi@0 1787 #define DEFINE_CALLMETHODV(ResultType, Result, Tag \
aoqi@0 1788 , EntryProbe, ReturnProbe) \
aoqi@0 1789 \
aoqi@0 1790 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType \
aoqi@0 1791 , ReturnProbe); \
aoqi@0 1792 \
aoqi@0 1793 JNI_ENTRY(ResultType, \
aoqi@0 1794 jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \
aoqi@0 1795 JNIWrapper("Call" XSTR(Result) "MethodV"); \
aoqi@0 1796 \
aoqi@0 1797 EntryProbe;\
aoqi@0 1798 ResultType ret = 0;\
aoqi@0 1799 DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \
aoqi@0 1800 (const ResultType&)ret);\
aoqi@0 1801 \
aoqi@0 1802 JavaValue jvalue(Tag); \
aoqi@0 1803 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 1804 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1805 ret = jvalue.get_##ResultType(); \
aoqi@0 1806 return ret;\
aoqi@0 1807 JNI_END
aoqi@0 1808
aoqi@0 1809 // the runtime type of subword integral basic types is integer
aoqi@0 1810 DEFINE_CALLMETHODV(jboolean, Boolean, T_BOOLEAN
aoqi@0 1811 , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1812 HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref))
aoqi@0 1813 DEFINE_CALLMETHODV(jbyte, Byte, T_BYTE
aoqi@0 1814 , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1815 HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref))
aoqi@0 1816 DEFINE_CALLMETHODV(jchar, Char, T_CHAR
aoqi@0 1817 , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1818 HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref))
aoqi@0 1819 DEFINE_CALLMETHODV(jshort, Short, T_SHORT
aoqi@0 1820 , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1821 HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref))
aoqi@0 1822
aoqi@0 1823 DEFINE_CALLMETHODV(jobject, Object, T_OBJECT
aoqi@0 1824 , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1825 HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref))
aoqi@0 1826 DEFINE_CALLMETHODV(jint, Int, T_INT,
aoqi@0 1827 HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1828 HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref))
aoqi@0 1829 DEFINE_CALLMETHODV(jlong, Long, T_LONG
aoqi@0 1830 , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1831 HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref))
aoqi@0 1832 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 1833 DEFINE_CALLMETHODV(jfloat, Float, T_FLOAT
aoqi@0 1834 , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1835 HOTSPOT_JNI_CALLFLOATMETHOD_RETURN())
aoqi@0 1836 DEFINE_CALLMETHODV(jdouble, Double, T_DOUBLE
aoqi@0 1837 , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1838 HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN())
aoqi@0 1839
aoqi@0 1840 #define DEFINE_CALLMETHODA(ResultType, Result, Tag \
aoqi@0 1841 , EntryProbe, ReturnProbe) \
aoqi@0 1842 \
aoqi@0 1843 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType \
aoqi@0 1844 , ReturnProbe); \
aoqi@0 1845 \
aoqi@0 1846 JNI_ENTRY(ResultType, \
aoqi@0 1847 jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \
aoqi@0 1848 JNIWrapper("Call" XSTR(Result) "MethodA"); \
aoqi@0 1849 EntryProbe; \
aoqi@0 1850 ResultType ret = 0;\
aoqi@0 1851 DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \
aoqi@0 1852 (const ResultType&)ret);\
aoqi@0 1853 \
aoqi@0 1854 JavaValue jvalue(Tag); \
aoqi@0 1855 JNI_ArgumentPusherArray ap(methodID, args); \
aoqi@0 1856 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1857 ret = jvalue.get_##ResultType(); \
aoqi@0 1858 return ret;\
aoqi@0 1859 JNI_END
aoqi@0 1860
aoqi@0 1861 // the runtime type of subword integral basic types is integer
aoqi@0 1862 DEFINE_CALLMETHODA(jboolean, Boolean, T_BOOLEAN
aoqi@0 1863 , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1864 HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref))
aoqi@0 1865 DEFINE_CALLMETHODA(jbyte, Byte, T_BYTE
aoqi@0 1866 , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1867 HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref))
aoqi@0 1868 DEFINE_CALLMETHODA(jchar, Char, T_CHAR
aoqi@0 1869 , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1870 HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref))
aoqi@0 1871 DEFINE_CALLMETHODA(jshort, Short, T_SHORT
aoqi@0 1872 , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1873 HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref))
aoqi@0 1874
aoqi@0 1875 DEFINE_CALLMETHODA(jobject, Object, T_OBJECT
aoqi@0 1876 , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1877 HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref))
aoqi@0 1878 DEFINE_CALLMETHODA(jint, Int, T_INT,
aoqi@0 1879 HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1880 HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref))
aoqi@0 1881 DEFINE_CALLMETHODA(jlong, Long, T_LONG
aoqi@0 1882 , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1883 HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref))
aoqi@0 1884 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 1885 DEFINE_CALLMETHODA(jfloat, Float, T_FLOAT
aoqi@0 1886 , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1887 HOTSPOT_JNI_CALLFLOATMETHOD_RETURN())
aoqi@0 1888 DEFINE_CALLMETHODA(jdouble, Double, T_DOUBLE
aoqi@0 1889 , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
aoqi@0 1890 HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN())
aoqi@0 1891
aoqi@0 1892 DT_VOID_RETURN_MARK_DECL(CallVoidMethod, HOTSPOT_JNI_CALLVOIDMETHOD_RETURN());
aoqi@0 1893 DT_VOID_RETURN_MARK_DECL(CallVoidMethodV, HOTSPOT_JNI_CALLVOIDMETHODV_RETURN());
aoqi@0 1894 DT_VOID_RETURN_MARK_DECL(CallVoidMethodA, HOTSPOT_JNI_CALLVOIDMETHODA_RETURN());
aoqi@0 1895
aoqi@0 1896 #endif /* USDT2 */
aoqi@0 1897
aoqi@0 1898 JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...))
aoqi@0 1899 JNIWrapper("CallVoidMethod");
aoqi@0 1900 #ifndef USDT2
aoqi@0 1901 DTRACE_PROBE3(hotspot_jni, CallVoidMethod__entry, env, obj, methodID);
aoqi@0 1902 #else /* USDT2 */
aoqi@0 1903 HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY(
aoqi@0 1904 env, obj, (uintptr_t) methodID);
aoqi@0 1905 #endif /* USDT2 */
aoqi@0 1906 DT_VOID_RETURN_MARK(CallVoidMethod);
aoqi@0 1907
aoqi@0 1908 va_list args;
aoqi@0 1909 va_start(args, methodID);
aoqi@0 1910 JavaValue jvalue(T_VOID);
aoqi@0 1911 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 1912 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
aoqi@0 1913 va_end(args);
aoqi@0 1914 JNI_END
aoqi@0 1915
aoqi@0 1916
aoqi@0 1917 JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args))
aoqi@0 1918 JNIWrapper("CallVoidMethodV");
aoqi@0 1919 #ifndef USDT2
aoqi@0 1920 DTRACE_PROBE3(hotspot_jni, CallVoidMethodV__entry, env, obj, methodID);
aoqi@0 1921 #else /* USDT2 */
aoqi@0 1922 HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY(
aoqi@0 1923 env, obj, (uintptr_t) methodID);
aoqi@0 1924 #endif /* USDT2 */
aoqi@0 1925 DT_VOID_RETURN_MARK(CallVoidMethodV);
aoqi@0 1926
aoqi@0 1927 JavaValue jvalue(T_VOID);
aoqi@0 1928 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 1929 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
aoqi@0 1930 JNI_END
aoqi@0 1931
aoqi@0 1932
aoqi@0 1933 JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args))
aoqi@0 1934 JNIWrapper("CallVoidMethodA");
aoqi@0 1935 #ifndef USDT2
aoqi@0 1936 DTRACE_PROBE3(hotspot_jni, CallVoidMethodA__entry, env, obj, methodID);
aoqi@0 1937 #else /* USDT2 */
aoqi@0 1938 HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY(
aoqi@0 1939 env, obj, (uintptr_t) methodID);
aoqi@0 1940 #endif /* USDT2 */
aoqi@0 1941 DT_VOID_RETURN_MARK(CallVoidMethodA);
aoqi@0 1942
aoqi@0 1943 JavaValue jvalue(T_VOID);
aoqi@0 1944 JNI_ArgumentPusherArray ap(methodID, args);
aoqi@0 1945 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
aoqi@0 1946 JNI_END
aoqi@0 1947
aoqi@0 1948
aoqi@0 1949 #ifndef USDT2
aoqi@0 1950 #define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag) \
aoqi@0 1951 \
aoqi@0 1952 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType);\
aoqi@0 1953 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType);\
aoqi@0 1954 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType);\
aoqi@0 1955 \
aoqi@0 1956 JNI_ENTRY(ResultType, \
aoqi@0 1957 jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \
aoqi@0 1958 JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \
aoqi@0 1959 \
aoqi@0 1960 DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##Method__entry, env, obj, cls, methodID);\
aoqi@0 1961 ResultType ret;\
aoqi@0 1962 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \
aoqi@0 1963 (const ResultType&)ret);\
aoqi@0 1964 \
aoqi@0 1965 va_list args; \
aoqi@0 1966 va_start(args, methodID); \
aoqi@0 1967 JavaValue jvalue(Tag); \
aoqi@0 1968 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 1969 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1970 va_end(args); \
aoqi@0 1971 ret = jvalue.get_##ResultType(); \
aoqi@0 1972 return ret;\
aoqi@0 1973 JNI_END \
aoqi@0 1974 \
aoqi@0 1975 JNI_ENTRY(ResultType, \
aoqi@0 1976 jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \
aoqi@0 1977 JNIWrapper("CallNonvitual" XSTR(Result) "#MethodV"); \
aoqi@0 1978 DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodV__entry, env, obj, cls, methodID);\
aoqi@0 1979 ResultType ret;\
aoqi@0 1980 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \
aoqi@0 1981 (const ResultType&)ret);\
aoqi@0 1982 \
aoqi@0 1983 JavaValue jvalue(Tag); \
aoqi@0 1984 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 1985 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 1986 ret = jvalue.get_##ResultType(); \
aoqi@0 1987 return ret;\
aoqi@0 1988 JNI_END \
aoqi@0 1989 \
aoqi@0 1990 JNI_ENTRY(ResultType, \
aoqi@0 1991 jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \
aoqi@0 1992 JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \
aoqi@0 1993 DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodA__entry, env, obj, cls, methodID);\
aoqi@0 1994 ResultType ret;\
aoqi@0 1995 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \
aoqi@0 1996 (const ResultType&)ret);\
aoqi@0 1997 \
aoqi@0 1998 JavaValue jvalue(Tag); \
aoqi@0 1999 JNI_ArgumentPusherArray ap(methodID, args); \
aoqi@0 2000 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 2001 ret = jvalue.get_##ResultType(); \
aoqi@0 2002 return ret;\
aoqi@0 2003 JNI_END
aoqi@0 2004
aoqi@0 2005 // the runtime type of subword integral basic types is integer
aoqi@0 2006 DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN)
aoqi@0 2007 DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE)
aoqi@0 2008 DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR)
aoqi@0 2009 DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT)
aoqi@0 2010
aoqi@0 2011 DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT)
aoqi@0 2012 DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT)
aoqi@0 2013 DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG)
aoqi@0 2014 DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT)
aoqi@0 2015 DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE)
aoqi@0 2016
aoqi@0 2017
aoqi@0 2018 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod);
aoqi@0 2019 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV);
aoqi@0 2020 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA);
aoqi@0 2021
aoqi@0 2022 #else /* USDT2 */
aoqi@0 2023
aoqi@0 2024 #define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag \
aoqi@0 2025 , EntryProbe, ReturnProbe) \
aoqi@0 2026 \
aoqi@0 2027 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType \
aoqi@0 2028 , ReturnProbe);\
aoqi@0 2029 \
aoqi@0 2030 JNI_ENTRY(ResultType, \
aoqi@0 2031 jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \
aoqi@0 2032 JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \
aoqi@0 2033 \
aoqi@0 2034 EntryProbe;\
aoqi@0 2035 ResultType ret;\
aoqi@0 2036 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \
aoqi@0 2037 (const ResultType&)ret);\
aoqi@0 2038 \
aoqi@0 2039 va_list args; \
aoqi@0 2040 va_start(args, methodID); \
aoqi@0 2041 JavaValue jvalue(Tag); \
aoqi@0 2042 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 2043 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 2044 va_end(args); \
aoqi@0 2045 ret = jvalue.get_##ResultType(); \
aoqi@0 2046 return ret;\
aoqi@0 2047 JNI_END
aoqi@0 2048
aoqi@0 2049 // the runtime type of subword integral basic types is integer
aoqi@0 2050 DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN
aoqi@0 2051 , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2052 HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN(_ret_ref))
aoqi@0 2053 DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE
aoqi@0 2054 , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2055 HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN(_ret_ref))
aoqi@0 2056 DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR
aoqi@0 2057 , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2058 HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN(_ret_ref))
aoqi@0 2059 DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT
aoqi@0 2060 , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2061 HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN(_ret_ref))
aoqi@0 2062
aoqi@0 2063 DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT
aoqi@0 2064 , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2065 HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN(_ret_ref))
aoqi@0 2066 DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT
aoqi@0 2067 , HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2068 HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN(_ret_ref))
aoqi@0 2069 DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG
aoqi@0 2070 , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2071 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2072 HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN(_ret_ref))
aoqi@0 2073 DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT
aoqi@0 2074 , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2075 HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN())
aoqi@0 2076 DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE
aoqi@0 2077 , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2078 HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN())
aoqi@0 2079
aoqi@0 2080 #define DEFINE_CALLNONVIRTUALMETHODV(ResultType, Result, Tag \
aoqi@0 2081 , EntryProbe, ReturnProbe) \
aoqi@0 2082 \
aoqi@0 2083 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType \
aoqi@0 2084 , ReturnProbe);\
aoqi@0 2085 \
aoqi@0 2086 JNI_ENTRY(ResultType, \
aoqi@0 2087 jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \
aoqi@0 2088 JNIWrapper("CallNonvitual" XSTR(Result) "MethodV"); \
aoqi@0 2089 \
aoqi@0 2090 EntryProbe;\
aoqi@0 2091 ResultType ret;\
aoqi@0 2092 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \
aoqi@0 2093 (const ResultType&)ret);\
aoqi@0 2094 \
aoqi@0 2095 JavaValue jvalue(Tag); \
aoqi@0 2096 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 2097 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 2098 ret = jvalue.get_##ResultType(); \
aoqi@0 2099 return ret;\
aoqi@0 2100 JNI_END
aoqi@0 2101
aoqi@0 2102 // the runtime type of subword integral basic types is integer
aoqi@0 2103 DEFINE_CALLNONVIRTUALMETHODV(jboolean, Boolean, T_BOOLEAN
aoqi@0 2104 , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2105 HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN(_ret_ref))
aoqi@0 2106 DEFINE_CALLNONVIRTUALMETHODV(jbyte, Byte, T_BYTE
aoqi@0 2107 , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2108 HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN(_ret_ref))
aoqi@0 2109 DEFINE_CALLNONVIRTUALMETHODV(jchar, Char, T_CHAR
aoqi@0 2110 , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2111 HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN(_ret_ref))
aoqi@0 2112 DEFINE_CALLNONVIRTUALMETHODV(jshort, Short, T_SHORT
aoqi@0 2113 , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2114 HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN(_ret_ref))
aoqi@0 2115
aoqi@0 2116 DEFINE_CALLNONVIRTUALMETHODV(jobject, Object, T_OBJECT
aoqi@0 2117 , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2118 HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN(_ret_ref))
aoqi@0 2119 DEFINE_CALLNONVIRTUALMETHODV(jint, Int, T_INT
aoqi@0 2120 , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2121 HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN(_ret_ref))
aoqi@0 2122 DEFINE_CALLNONVIRTUALMETHODV(jlong, Long, T_LONG
aoqi@0 2123 , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2124 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2125 HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN(_ret_ref))
aoqi@0 2126 DEFINE_CALLNONVIRTUALMETHODV(jfloat, Float, T_FLOAT
aoqi@0 2127 , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2128 HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN())
aoqi@0 2129 DEFINE_CALLNONVIRTUALMETHODV(jdouble, Double, T_DOUBLE
aoqi@0 2130 , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2131 HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN())
aoqi@0 2132
aoqi@0 2133 #define DEFINE_CALLNONVIRTUALMETHODA(ResultType, Result, Tag \
aoqi@0 2134 , EntryProbe, ReturnProbe) \
aoqi@0 2135 \
aoqi@0 2136 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType \
aoqi@0 2137 , ReturnProbe);\
aoqi@0 2138 \
aoqi@0 2139 JNI_ENTRY(ResultType, \
aoqi@0 2140 jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \
aoqi@0 2141 JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \
aoqi@0 2142 \
aoqi@0 2143 EntryProbe;\
aoqi@0 2144 ResultType ret;\
aoqi@0 2145 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \
aoqi@0 2146 (const ResultType&)ret);\
aoqi@0 2147 \
aoqi@0 2148 JavaValue jvalue(Tag); \
aoqi@0 2149 JNI_ArgumentPusherArray ap(methodID, args); \
aoqi@0 2150 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
aoqi@0 2151 ret = jvalue.get_##ResultType(); \
aoqi@0 2152 return ret;\
aoqi@0 2153 JNI_END
aoqi@0 2154
aoqi@0 2155 // the runtime type of subword integral basic types is integer
aoqi@0 2156 DEFINE_CALLNONVIRTUALMETHODA(jboolean, Boolean, T_BOOLEAN
aoqi@0 2157 , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2158 HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN(_ret_ref))
aoqi@0 2159 DEFINE_CALLNONVIRTUALMETHODA(jbyte, Byte, T_BYTE
aoqi@0 2160 , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2161 HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN(_ret_ref))
aoqi@0 2162 DEFINE_CALLNONVIRTUALMETHODA(jchar, Char, T_CHAR
aoqi@0 2163 , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2164 HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN(_ret_ref))
aoqi@0 2165 DEFINE_CALLNONVIRTUALMETHODA(jshort, Short, T_SHORT
aoqi@0 2166 , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2167 HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN(_ret_ref))
aoqi@0 2168
aoqi@0 2169 DEFINE_CALLNONVIRTUALMETHODA(jobject, Object, T_OBJECT
aoqi@0 2170 , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2171 HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN(_ret_ref))
aoqi@0 2172 DEFINE_CALLNONVIRTUALMETHODA(jint, Int, T_INT
aoqi@0 2173 , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2174 HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN(_ret_ref))
aoqi@0 2175 DEFINE_CALLNONVIRTUALMETHODA(jlong, Long, T_LONG
aoqi@0 2176 , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2177 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2178 HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN(_ret_ref))
aoqi@0 2179 DEFINE_CALLNONVIRTUALMETHODA(jfloat, Float, T_FLOAT
aoqi@0 2180 , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2181 HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN())
aoqi@0 2182 DEFINE_CALLNONVIRTUALMETHODA(jdouble, Double, T_DOUBLE
aoqi@0 2183 , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
aoqi@0 2184 HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN())
aoqi@0 2185
aoqi@0 2186 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod
aoqi@0 2187 , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN());
aoqi@0 2188 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV
aoqi@0 2189 , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN());
aoqi@0 2190 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA
aoqi@0 2191 , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN());
aoqi@0 2192 #endif /* USDT2 */
aoqi@0 2193
aoqi@0 2194 JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...))
aoqi@0 2195 JNIWrapper("CallNonvirtualVoidMethod");
aoqi@0 2196
aoqi@0 2197 #ifndef USDT2
aoqi@0 2198 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethod__entry,
aoqi@0 2199 env, obj, cls, methodID);
aoqi@0 2200 #else /* USDT2 */
aoqi@0 2201 HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY(
aoqi@0 2202 env, obj, cls, (uintptr_t) methodID);
aoqi@0 2203 #endif /* USDT2 */
aoqi@0 2204 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod);
aoqi@0 2205
aoqi@0 2206 va_list args;
aoqi@0 2207 va_start(args, methodID);
aoqi@0 2208 JavaValue jvalue(T_VOID);
aoqi@0 2209 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 2210 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
aoqi@0 2211 va_end(args);
aoqi@0 2212 JNI_END
aoqi@0 2213
aoqi@0 2214
aoqi@0 2215 JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args))
aoqi@0 2216 JNIWrapper("CallNonvirtualVoidMethodV");
aoqi@0 2217
aoqi@0 2218 #ifndef USDT2
aoqi@0 2219 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodV__entry,
aoqi@0 2220 env, obj, cls, methodID);
aoqi@0 2221 #else /* USDT2 */
aoqi@0 2222 HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY(
aoqi@0 2223 env, obj, cls, (uintptr_t) methodID);
aoqi@0 2224 #endif /* USDT2 */
aoqi@0 2225 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV);
aoqi@0 2226
aoqi@0 2227 JavaValue jvalue(T_VOID);
aoqi@0 2228 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 2229 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
aoqi@0 2230 JNI_END
aoqi@0 2231
aoqi@0 2232
aoqi@0 2233 JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args))
aoqi@0 2234 JNIWrapper("CallNonvirtualVoidMethodA");
aoqi@0 2235 #ifndef USDT2
aoqi@0 2236 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodA__entry,
aoqi@0 2237 env, obj, cls, methodID);
aoqi@0 2238 #else /* USDT2 */
aoqi@0 2239 HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY(
aoqi@0 2240 env, obj, cls, (uintptr_t) methodID);
aoqi@0 2241 #endif /* USDT2 */
aoqi@0 2242 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA);
aoqi@0 2243 JavaValue jvalue(T_VOID);
aoqi@0 2244 JNI_ArgumentPusherArray ap(methodID, args);
aoqi@0 2245 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
aoqi@0 2246 JNI_END
aoqi@0 2247
aoqi@0 2248
aoqi@0 2249 #ifndef USDT2
aoqi@0 2250 #define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag) \
aoqi@0 2251 \
aoqi@0 2252 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType);\
aoqi@0 2253 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType);\
aoqi@0 2254 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType);\
aoqi@0 2255 \
aoqi@0 2256 JNI_ENTRY(ResultType, \
aoqi@0 2257 jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \
aoqi@0 2258 JNIWrapper("CallStatic" XSTR(Result) "Method"); \
aoqi@0 2259 \
aoqi@0 2260 DTRACE_PROBE3(hotspot_jni, CallStatic##Result##Method__entry, env, cls, methodID);\
aoqi@0 2261 ResultType ret = 0;\
aoqi@0 2262 DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \
aoqi@0 2263 (const ResultType&)ret);\
aoqi@0 2264 \
aoqi@0 2265 va_list args; \
aoqi@0 2266 va_start(args, methodID); \
aoqi@0 2267 JavaValue jvalue(Tag); \
aoqi@0 2268 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 2269 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
aoqi@0 2270 va_end(args); \
aoqi@0 2271 ret = jvalue.get_##ResultType(); \
aoqi@0 2272 return ret;\
aoqi@0 2273 JNI_END \
aoqi@0 2274 \
aoqi@0 2275 JNI_ENTRY(ResultType, \
aoqi@0 2276 jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \
aoqi@0 2277 JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \
aoqi@0 2278 DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodV__entry, env, cls, methodID);\
aoqi@0 2279 ResultType ret = 0;\
aoqi@0 2280 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \
aoqi@0 2281 (const ResultType&)ret);\
aoqi@0 2282 \
aoqi@0 2283 JavaValue jvalue(Tag); \
aoqi@0 2284 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 2285 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
aoqi@0 2286 ret = jvalue.get_##ResultType(); \
aoqi@0 2287 return ret;\
aoqi@0 2288 JNI_END \
aoqi@0 2289 \
aoqi@0 2290 JNI_ENTRY(ResultType, \
aoqi@0 2291 jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \
aoqi@0 2292 JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \
aoqi@0 2293 DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodA__entry, env, cls, methodID);\
aoqi@0 2294 ResultType ret = 0;\
aoqi@0 2295 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \
aoqi@0 2296 (const ResultType&)ret);\
aoqi@0 2297 \
aoqi@0 2298 JavaValue jvalue(Tag); \
aoqi@0 2299 JNI_ArgumentPusherArray ap(methodID, args); \
aoqi@0 2300 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
aoqi@0 2301 ret = jvalue.get_##ResultType(); \
aoqi@0 2302 return ret;\
aoqi@0 2303 JNI_END
aoqi@0 2304
aoqi@0 2305 // the runtime type of subword integral basic types is integer
aoqi@0 2306 DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN)
aoqi@0 2307 DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE)
aoqi@0 2308 DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR)
aoqi@0 2309 DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT)
aoqi@0 2310
aoqi@0 2311 DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT)
aoqi@0 2312 DEFINE_CALLSTATICMETHOD(jint, Int, T_INT)
aoqi@0 2313 DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG)
aoqi@0 2314 DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT)
aoqi@0 2315 DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE)
aoqi@0 2316
aoqi@0 2317
aoqi@0 2318 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod);
aoqi@0 2319 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV);
aoqi@0 2320 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA);
aoqi@0 2321
aoqi@0 2322 #else /* USDT2 */
aoqi@0 2323
aoqi@0 2324 #define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag \
aoqi@0 2325 , EntryProbe, ResultProbe) \
aoqi@0 2326 \
aoqi@0 2327 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType \
aoqi@0 2328 , ResultProbe); \
aoqi@0 2329 \
aoqi@0 2330 JNI_ENTRY(ResultType, \
aoqi@0 2331 jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \
aoqi@0 2332 JNIWrapper("CallStatic" XSTR(Result) "Method"); \
aoqi@0 2333 \
aoqi@0 2334 EntryProbe; \
aoqi@0 2335 ResultType ret = 0;\
aoqi@0 2336 DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \
aoqi@0 2337 (const ResultType&)ret);\
aoqi@0 2338 \
aoqi@0 2339 va_list args; \
aoqi@0 2340 va_start(args, methodID); \
aoqi@0 2341 JavaValue jvalue(Tag); \
aoqi@0 2342 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 2343 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
aoqi@0 2344 va_end(args); \
aoqi@0 2345 ret = jvalue.get_##ResultType(); \
aoqi@0 2346 return ret;\
aoqi@0 2347 JNI_END
aoqi@0 2348
aoqi@0 2349 // the runtime type of subword integral basic types is integer
aoqi@0 2350 DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN
aoqi@0 2351 , HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2352 HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN(_ret_ref));
aoqi@0 2353 DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE
aoqi@0 2354 , HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2355 HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN(_ret_ref));
aoqi@0 2356 DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR
aoqi@0 2357 , HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2358 HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN(_ret_ref));
aoqi@0 2359 DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT
aoqi@0 2360 , HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2361 HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN(_ret_ref));
aoqi@0 2362
aoqi@0 2363 DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT
aoqi@0 2364 , HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2365 HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN(_ret_ref));
aoqi@0 2366 DEFINE_CALLSTATICMETHOD(jint, Int, T_INT
aoqi@0 2367 , HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2368 HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN(_ret_ref));
aoqi@0 2369 DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG
aoqi@0 2370 , HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2371 HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN(_ret_ref));
aoqi@0 2372 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2373 DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT
aoqi@0 2374 , HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2375 HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN());
aoqi@0 2376 DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE
aoqi@0 2377 , HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2378 HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN());
aoqi@0 2379
aoqi@0 2380 #define DEFINE_CALLSTATICMETHODV(ResultType, Result, Tag \
aoqi@0 2381 , EntryProbe, ResultProbe) \
aoqi@0 2382 \
aoqi@0 2383 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType \
aoqi@0 2384 , ResultProbe); \
aoqi@0 2385 \
aoqi@0 2386 JNI_ENTRY(ResultType, \
aoqi@0 2387 jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \
aoqi@0 2388 JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \
aoqi@0 2389 \
aoqi@0 2390 EntryProbe; \
aoqi@0 2391 ResultType ret = 0;\
aoqi@0 2392 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \
aoqi@0 2393 (const ResultType&)ret);\
aoqi@0 2394 \
aoqi@0 2395 JavaValue jvalue(Tag); \
aoqi@0 2396 JNI_ArgumentPusherVaArg ap(methodID, args); \
aoqi@0 2397 /* Make sure class is initialized before trying to invoke its method */ \
aoqi@0 2398 KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls))); \
aoqi@0 2399 k()->initialize(CHECK_0); \
aoqi@0 2400 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
aoqi@0 2401 va_end(args); \
aoqi@0 2402 ret = jvalue.get_##ResultType(); \
aoqi@0 2403 return ret;\
aoqi@0 2404 JNI_END
aoqi@0 2405
aoqi@0 2406 // the runtime type of subword integral basic types is integer
aoqi@0 2407 DEFINE_CALLSTATICMETHODV(jboolean, Boolean, T_BOOLEAN
aoqi@0 2408 , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2409 HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN(_ret_ref));
aoqi@0 2410 DEFINE_CALLSTATICMETHODV(jbyte, Byte, T_BYTE
aoqi@0 2411 , HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2412 HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN(_ret_ref));
aoqi@0 2413 DEFINE_CALLSTATICMETHODV(jchar, Char, T_CHAR
aoqi@0 2414 , HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2415 HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN(_ret_ref));
aoqi@0 2416 DEFINE_CALLSTATICMETHODV(jshort, Short, T_SHORT
aoqi@0 2417 , HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2418 HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN(_ret_ref));
aoqi@0 2419
aoqi@0 2420 DEFINE_CALLSTATICMETHODV(jobject, Object, T_OBJECT
aoqi@0 2421 , HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2422 HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN(_ret_ref));
aoqi@0 2423 DEFINE_CALLSTATICMETHODV(jint, Int, T_INT
aoqi@0 2424 , HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2425 HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN(_ret_ref));
aoqi@0 2426 DEFINE_CALLSTATICMETHODV(jlong, Long, T_LONG
aoqi@0 2427 , HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2428 HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN(_ret_ref));
aoqi@0 2429 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2430 DEFINE_CALLSTATICMETHODV(jfloat, Float, T_FLOAT
aoqi@0 2431 , HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2432 HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN());
aoqi@0 2433 DEFINE_CALLSTATICMETHODV(jdouble, Double, T_DOUBLE
aoqi@0 2434 , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2435 HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN());
aoqi@0 2436
aoqi@0 2437 #define DEFINE_CALLSTATICMETHODA(ResultType, Result, Tag \
aoqi@0 2438 , EntryProbe, ResultProbe) \
aoqi@0 2439 \
aoqi@0 2440 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType \
aoqi@0 2441 , ResultProbe); \
aoqi@0 2442 \
aoqi@0 2443 JNI_ENTRY(ResultType, \
aoqi@0 2444 jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \
aoqi@0 2445 JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \
aoqi@0 2446 \
aoqi@0 2447 EntryProbe; \
aoqi@0 2448 ResultType ret = 0;\
aoqi@0 2449 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \
aoqi@0 2450 (const ResultType&)ret);\
aoqi@0 2451 \
aoqi@0 2452 JavaValue jvalue(Tag); \
aoqi@0 2453 JNI_ArgumentPusherArray ap(methodID, args); \
aoqi@0 2454 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
aoqi@0 2455 ret = jvalue.get_##ResultType(); \
aoqi@0 2456 return ret;\
aoqi@0 2457 JNI_END
aoqi@0 2458
aoqi@0 2459 // the runtime type of subword integral basic types is integer
aoqi@0 2460 DEFINE_CALLSTATICMETHODA(jboolean, Boolean, T_BOOLEAN
aoqi@0 2461 , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2462 HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN(_ret_ref));
aoqi@0 2463 DEFINE_CALLSTATICMETHODA(jbyte, Byte, T_BYTE
aoqi@0 2464 , HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2465 HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN(_ret_ref));
aoqi@0 2466 DEFINE_CALLSTATICMETHODA(jchar, Char, T_CHAR
aoqi@0 2467 , HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2468 HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN(_ret_ref));
aoqi@0 2469 DEFINE_CALLSTATICMETHODA(jshort, Short, T_SHORT
aoqi@0 2470 , HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2471 HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN(_ret_ref));
aoqi@0 2472
aoqi@0 2473 DEFINE_CALLSTATICMETHODA(jobject, Object, T_OBJECT
aoqi@0 2474 , HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2475 HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN(_ret_ref));
aoqi@0 2476 DEFINE_CALLSTATICMETHODA(jint, Int, T_INT
aoqi@0 2477 , HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2478 HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN(_ret_ref));
aoqi@0 2479 DEFINE_CALLSTATICMETHODA(jlong, Long, T_LONG
aoqi@0 2480 , HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2481 HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN(_ret_ref));
aoqi@0 2482 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2483 DEFINE_CALLSTATICMETHODA(jfloat, Float, T_FLOAT
aoqi@0 2484 , HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2485 HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN());
aoqi@0 2486 DEFINE_CALLSTATICMETHODA(jdouble, Double, T_DOUBLE
aoqi@0 2487 , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
aoqi@0 2488 HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN());
aoqi@0 2489
aoqi@0 2490 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod
aoqi@0 2491 , HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN());
aoqi@0 2492 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV
aoqi@0 2493 , HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN());
aoqi@0 2494 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA
aoqi@0 2495 , HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN());
aoqi@0 2496 #endif /* USDT2 */
aoqi@0 2497
aoqi@0 2498 JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...))
aoqi@0 2499 JNIWrapper("CallStaticVoidMethod");
aoqi@0 2500 #ifndef USDT2
aoqi@0 2501 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethod__entry, env, cls, methodID);
aoqi@0 2502 #else /* USDT2 */
aoqi@0 2503 HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY(
aoqi@0 2504 env, cls, (uintptr_t) methodID);
aoqi@0 2505 #endif /* USDT2 */
aoqi@0 2506 DT_VOID_RETURN_MARK(CallStaticVoidMethod);
aoqi@0 2507
aoqi@0 2508 va_list args;
aoqi@0 2509 va_start(args, methodID);
aoqi@0 2510 JavaValue jvalue(T_VOID);
aoqi@0 2511 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 2512 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
aoqi@0 2513 va_end(args);
aoqi@0 2514 JNI_END
aoqi@0 2515
aoqi@0 2516
aoqi@0 2517 JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args))
aoqi@0 2518 JNIWrapper("CallStaticVoidMethodV");
aoqi@0 2519 #ifndef USDT2
aoqi@0 2520 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodV__entry, env, cls, methodID);
aoqi@0 2521 #else /* USDT2 */
aoqi@0 2522 HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY(
aoqi@0 2523 env, cls, (uintptr_t) methodID);
aoqi@0 2524 #endif /* USDT2 */
aoqi@0 2525 DT_VOID_RETURN_MARK(CallStaticVoidMethodV);
aoqi@0 2526
aoqi@0 2527 JavaValue jvalue(T_VOID);
aoqi@0 2528 JNI_ArgumentPusherVaArg ap(methodID, args);
aoqi@0 2529 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
aoqi@0 2530 JNI_END
aoqi@0 2531
aoqi@0 2532
aoqi@0 2533 JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args))
aoqi@0 2534 JNIWrapper("CallStaticVoidMethodA");
aoqi@0 2535 #ifndef USDT2
aoqi@0 2536 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodA__entry, env, cls, methodID);
aoqi@0 2537 #else /* USDT2 */
aoqi@0 2538 HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY(
aoqi@0 2539 env, cls, (uintptr_t) methodID);
aoqi@0 2540 #endif /* USDT2 */
aoqi@0 2541 DT_VOID_RETURN_MARK(CallStaticVoidMethodA);
aoqi@0 2542
aoqi@0 2543 JavaValue jvalue(T_VOID);
aoqi@0 2544 JNI_ArgumentPusherArray ap(methodID, args);
aoqi@0 2545 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
aoqi@0 2546 JNI_END
aoqi@0 2547
aoqi@0 2548
aoqi@0 2549 //
aoqi@0 2550 // Accessing Fields
aoqi@0 2551 //
aoqi@0 2552
aoqi@0 2553
aoqi@0 2554 #ifndef USDT2
aoqi@0 2555 DT_RETURN_MARK_DECL(GetFieldID, jfieldID);
aoqi@0 2556 #else /* USDT2 */
aoqi@0 2557 DT_RETURN_MARK_DECL(GetFieldID, jfieldID
aoqi@0 2558 , HOTSPOT_JNI_GETFIELDID_RETURN((uintptr_t)_ret_ref));
aoqi@0 2559 #endif /* USDT2 */
aoqi@0 2560
aoqi@0 2561 JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz,
aoqi@0 2562 const char *name, const char *sig))
aoqi@0 2563 JNIWrapper("GetFieldID");
aoqi@0 2564 #ifndef USDT2
aoqi@0 2565 DTRACE_PROBE4(hotspot_jni, GetFieldID__entry, env, clazz, name, sig);
aoqi@0 2566 #else /* USDT2 */
aoqi@0 2567 HOTSPOT_JNI_GETFIELDID_ENTRY(
aoqi@0 2568 env, clazz, (char *) name, (char *) sig);
aoqi@0 2569 #endif /* USDT2 */
aoqi@0 2570 jfieldID ret = 0;
aoqi@0 2571 DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret);
aoqi@0 2572
aoqi@0 2573 // The class should have been loaded (we have an instance of the class
aoqi@0 2574 // passed in) so the field and signature should already be in the symbol
aoqi@0 2575 // table. If they're not there, the field doesn't exist.
aoqi@0 2576 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
aoqi@0 2577 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
aoqi@0 2578 if (fieldname == NULL || signame == NULL) {
aoqi@0 2579 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
aoqi@0 2580 }
aoqi@0 2581 KlassHandle k(THREAD,
aoqi@0 2582 java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
aoqi@0 2583 // Make sure class is initialized before handing id's out to fields
aoqi@0 2584 k()->initialize(CHECK_NULL);
aoqi@0 2585
aoqi@0 2586 fieldDescriptor fd;
aoqi@0 2587 if (!k()->oop_is_instance() ||
aoqi@0 2588 !InstanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) {
aoqi@0 2589 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
aoqi@0 2590 }
aoqi@0 2591
aoqi@0 2592 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
aoqi@0 2593 // It may also have hash bits for k, if VerifyJNIFields is turned on.
aoqi@0 2594 ret = jfieldIDWorkaround::to_instance_jfieldID(k(), fd.offset());
aoqi@0 2595 return ret;
aoqi@0 2596 JNI_END
aoqi@0 2597
aoqi@0 2598
aoqi@0 2599 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
aoqi@0 2600 JNIWrapper("GetObjectField");
aoqi@0 2601 #ifndef USDT2
aoqi@0 2602 DTRACE_PROBE3(hotspot_jni, GetObjectField__entry, env, obj, fieldID);
aoqi@0 2603 #else /* USDT2 */
aoqi@0 2604 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(
aoqi@0 2605 env, obj, (uintptr_t) fieldID);
aoqi@0 2606 #endif /* USDT2 */
aoqi@0 2607 oop o = JNIHandles::resolve_non_null(obj);
aoqi@0 2608 Klass* k = o->klass();
aoqi@0 2609 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
aoqi@0 2610 // Keep JVMTI addition small and only check enabled flag here.
aoqi@0 2611 // jni_GetField_probe() assumes that is okay to create handles.
aoqi@0 2612 if (JvmtiExport::should_post_field_access()) {
aoqi@0 2613 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
aoqi@0 2614 }
aoqi@0 2615 jobject ret = JNIHandles::make_local(env, o->obj_field(offset));
aoqi@0 2616 #if INCLUDE_ALL_GCS
aoqi@0 2617 // If G1 is enabled and we are accessing the value of the referent
aoqi@0 2618 // field in a reference object then we need to register a non-null
aoqi@0 2619 // referent with the SATB barrier.
aoqi@0 2620 if (UseG1GC) {
aoqi@0 2621 bool needs_barrier = false;
aoqi@0 2622
aoqi@0 2623 if (ret != NULL &&
aoqi@0 2624 offset == java_lang_ref_Reference::referent_offset &&
aoqi@0 2625 InstanceKlass::cast(k)->reference_type() != REF_NONE) {
aoqi@0 2626 assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity");
aoqi@0 2627 needs_barrier = true;
aoqi@0 2628 }
aoqi@0 2629
aoqi@0 2630 if (needs_barrier) {
aoqi@0 2631 oop referent = JNIHandles::resolve(ret);
aoqi@0 2632 G1SATBCardTableModRefBS::enqueue(referent);
aoqi@0 2633 }
aoqi@0 2634 }
aoqi@0 2635 #endif // INCLUDE_ALL_GCS
aoqi@0 2636 #ifndef USDT2
aoqi@0 2637 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret);
aoqi@0 2638 #else /* USDT2 */
aoqi@0 2639 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(
aoqi@0 2640 ret);
aoqi@0 2641 #endif /* USDT2 */
aoqi@0 2642 return ret;
aoqi@0 2643 JNI_END
aoqi@0 2644
aoqi@0 2645
aoqi@0 2646 #ifndef USDT2
aoqi@0 2647 #define DEFINE_GETFIELD(Return,Fieldname,Result) \
aoqi@0 2648 \
aoqi@0 2649 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return);\
aoqi@0 2650 \
aoqi@0 2651 JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
aoqi@0 2652 JNIWrapper("Get" XSTR(Result) "Field"); \
aoqi@0 2653 \
aoqi@0 2654 DTRACE_PROBE3(hotspot_jni, Get##Result##Field__entry, env, obj, fieldID);\
aoqi@0 2655 Return ret = 0;\
aoqi@0 2656 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
aoqi@0 2657 \
aoqi@0 2658 oop o = JNIHandles::resolve_non_null(obj); \
aoqi@0 2659 Klass* k = o->klass(); \
aoqi@0 2660 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
aoqi@0 2661 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 2662 /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \
aoqi@0 2663 /* and creates a ResetNoHandleMark. */ \
aoqi@0 2664 if (JvmtiExport::should_post_field_access()) { \
aoqi@0 2665 o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \
aoqi@0 2666 } \
aoqi@0 2667 ret = o->Fieldname##_field(offset); \
aoqi@0 2668 return ret; \
aoqi@0 2669 JNI_END
aoqi@0 2670
aoqi@0 2671 DEFINE_GETFIELD(jboolean, bool, Boolean)
aoqi@0 2672 DEFINE_GETFIELD(jbyte, byte, Byte)
aoqi@0 2673 DEFINE_GETFIELD(jchar, char, Char)
aoqi@0 2674 DEFINE_GETFIELD(jshort, short, Short)
aoqi@0 2675 DEFINE_GETFIELD(jint, int, Int)
aoqi@0 2676 DEFINE_GETFIELD(jlong, long, Long)
aoqi@0 2677 DEFINE_GETFIELD(jfloat, float, Float)
aoqi@0 2678 DEFINE_GETFIELD(jdouble, double, Double)
aoqi@0 2679
aoqi@0 2680 #else /* USDT2 */
aoqi@0 2681
aoqi@0 2682 #define DEFINE_GETFIELD(Return,Fieldname,Result \
aoqi@0 2683 , EntryProbe, ReturnProbe) \
aoqi@0 2684 \
aoqi@0 2685 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
aoqi@0 2686 , ReturnProbe); \
aoqi@0 2687 \
aoqi@0 2688 JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
aoqi@0 2689 JNIWrapper("Get" XSTR(Result) "Field"); \
aoqi@0 2690 \
aoqi@0 2691 EntryProbe; \
aoqi@0 2692 Return ret = 0;\
aoqi@0 2693 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
aoqi@0 2694 \
aoqi@0 2695 oop o = JNIHandles::resolve_non_null(obj); \
aoqi@0 2696 Klass* k = o->klass(); \
aoqi@0 2697 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
aoqi@0 2698 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 2699 /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \
aoqi@0 2700 /* and creates a ResetNoHandleMark. */ \
aoqi@0 2701 if (JvmtiExport::should_post_field_access()) { \
aoqi@0 2702 o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \
aoqi@0 2703 } \
aoqi@0 2704 ret = o->Fieldname##_field(offset); \
aoqi@0 2705 return ret; \
aoqi@0 2706 JNI_END
aoqi@0 2707
aoqi@0 2708 DEFINE_GETFIELD(jboolean, bool, Boolean
aoqi@0 2709 , HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2710 HOTSPOT_JNI_GETBOOLEANFIELD_RETURN(_ret_ref))
aoqi@0 2711 DEFINE_GETFIELD(jbyte, byte, Byte
aoqi@0 2712 , HOTSPOT_JNI_GETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2713 HOTSPOT_JNI_GETBYTEFIELD_RETURN(_ret_ref))
aoqi@0 2714 DEFINE_GETFIELD(jchar, char, Char
aoqi@0 2715 , HOTSPOT_JNI_GETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2716 HOTSPOT_JNI_GETCHARFIELD_RETURN(_ret_ref))
aoqi@0 2717 DEFINE_GETFIELD(jshort, short, Short
aoqi@0 2718 , HOTSPOT_JNI_GETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2719 HOTSPOT_JNI_GETSHORTFIELD_RETURN(_ret_ref))
aoqi@0 2720 DEFINE_GETFIELD(jint, int, Int
aoqi@0 2721 , HOTSPOT_JNI_GETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2722 HOTSPOT_JNI_GETINTFIELD_RETURN(_ret_ref))
aoqi@0 2723 DEFINE_GETFIELD(jlong, long, Long
aoqi@0 2724 , HOTSPOT_JNI_GETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2725 HOTSPOT_JNI_GETLONGFIELD_RETURN(_ret_ref))
aoqi@0 2726 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2727 DEFINE_GETFIELD(jfloat, float, Float
aoqi@0 2728 , HOTSPOT_JNI_GETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2729 HOTSPOT_JNI_GETFLOATFIELD_RETURN())
aoqi@0 2730 DEFINE_GETFIELD(jdouble, double, Double
aoqi@0 2731 , HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2732 HOTSPOT_JNI_GETDOUBLEFIELD_RETURN())
aoqi@0 2733 #endif /* USDT2 */
aoqi@0 2734
aoqi@0 2735 address jni_GetBooleanField_addr() {
aoqi@0 2736 return (address)jni_GetBooleanField;
aoqi@0 2737 }
aoqi@0 2738 address jni_GetByteField_addr() {
aoqi@0 2739 return (address)jni_GetByteField;
aoqi@0 2740 }
aoqi@0 2741 address jni_GetCharField_addr() {
aoqi@0 2742 return (address)jni_GetCharField;
aoqi@0 2743 }
aoqi@0 2744 address jni_GetShortField_addr() {
aoqi@0 2745 return (address)jni_GetShortField;
aoqi@0 2746 }
aoqi@0 2747 address jni_GetIntField_addr() {
aoqi@0 2748 return (address)jni_GetIntField;
aoqi@0 2749 }
aoqi@0 2750 address jni_GetLongField_addr() {
aoqi@0 2751 return (address)jni_GetLongField;
aoqi@0 2752 }
aoqi@0 2753 address jni_GetFloatField_addr() {
aoqi@0 2754 return (address)jni_GetFloatField;
aoqi@0 2755 }
aoqi@0 2756 address jni_GetDoubleField_addr() {
aoqi@0 2757 return (address)jni_GetDoubleField;
aoqi@0 2758 }
aoqi@0 2759
aoqi@0 2760 JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
aoqi@0 2761 JNIWrapper("SetObjectField");
aoqi@0 2762 #ifndef USDT2
aoqi@0 2763 DTRACE_PROBE4(hotspot_jni, SetObjectField__entry, env, obj, fieldID, value);
aoqi@0 2764 #else /* USDT2 */
aoqi@0 2765 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(
aoqi@0 2766 env, obj, (uintptr_t) fieldID, value);
aoqi@0 2767 #endif /* USDT2 */
aoqi@0 2768 oop o = JNIHandles::resolve_non_null(obj);
aoqi@0 2769 Klass* k = o->klass();
aoqi@0 2770 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
aoqi@0 2771 // Keep JVMTI addition small and only check enabled flag here.
aoqi@0 2772 // jni_SetField_probe_nh() assumes that is not okay to create handles
aoqi@0 2773 // and creates a ResetNoHandleMark.
aoqi@0 2774 if (JvmtiExport::should_post_field_modification()) {
aoqi@0 2775 jvalue field_value;
aoqi@0 2776 field_value.l = value;
aoqi@0 2777 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value);
aoqi@0 2778 }
aoqi@0 2779 o->obj_field_put(offset, JNIHandles::resolve(value));
aoqi@0 2780 #ifndef USDT2
aoqi@0 2781 DTRACE_PROBE(hotspot_jni, SetObjectField__return);
aoqi@0 2782 #else /* USDT2 */
aoqi@0 2783 HOTSPOT_JNI_SETOBJECTFIELD_RETURN(
aoqi@0 2784 );
aoqi@0 2785 #endif /* USDT2 */
aoqi@0 2786 JNI_END
aoqi@0 2787
aoqi@0 2788 #ifndef USDT2
aoqi@0 2789 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType) \
aoqi@0 2790 \
aoqi@0 2791 JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
aoqi@0 2792 JNIWrapper("Set" XSTR(Result) "Field"); \
aoqi@0 2793 \
aoqi@0 2794 FP_SELECT_##Result( \
aoqi@0 2795 DTRACE_PROBE4(hotspot_jni, Set##Result##Field__entry, env, obj, fieldID, value), \
aoqi@0 2796 DTRACE_PROBE3(hotspot_jni, Set##Result##Field__entry, env, obj, fieldID)); \
aoqi@0 2797 \
aoqi@0 2798 oop o = JNIHandles::resolve_non_null(obj); \
aoqi@0 2799 Klass* k = o->klass(); \
aoqi@0 2800 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
aoqi@0 2801 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 2802 /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \
aoqi@0 2803 /* and creates a ResetNoHandleMark. */ \
aoqi@0 2804 if (JvmtiExport::should_post_field_modification()) { \
aoqi@0 2805 jvalue field_value; \
aoqi@0 2806 field_value.unionType = value; \
aoqi@0 2807 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
aoqi@0 2808 } \
aoqi@0 2809 o->Fieldname##_field_put(offset, value); \
aoqi@0 2810 DTRACE_PROBE(hotspot_jni, Set##Result##Field__return);\
aoqi@0 2811 JNI_END
aoqi@0 2812
aoqi@0 2813 DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z)
aoqi@0 2814 DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b)
aoqi@0 2815 DEFINE_SETFIELD(jchar, char, Char, 'C', c)
aoqi@0 2816 DEFINE_SETFIELD(jshort, short, Short, 'S', s)
aoqi@0 2817 DEFINE_SETFIELD(jint, int, Int, 'I', i)
aoqi@0 2818 DEFINE_SETFIELD(jlong, long, Long, 'J', j)
aoqi@0 2819 DEFINE_SETFIELD(jfloat, float, Float, 'F', f)
aoqi@0 2820 DEFINE_SETFIELD(jdouble, double, Double, 'D', d)
aoqi@0 2821
aoqi@0 2822 #else /* USDT2 */
aoqi@0 2823
aoqi@0 2824 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
aoqi@0 2825 , EntryProbe, ReturnProbe) \
aoqi@0 2826 \
aoqi@0 2827 JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
aoqi@0 2828 JNIWrapper("Set" XSTR(Result) "Field"); \
aoqi@0 2829 \
aoqi@0 2830 EntryProbe; \
aoqi@0 2831 \
aoqi@0 2832 oop o = JNIHandles::resolve_non_null(obj); \
aoqi@0 2833 Klass* k = o->klass(); \
aoqi@0 2834 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
aoqi@0 2835 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 2836 /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \
aoqi@0 2837 /* and creates a ResetNoHandleMark. */ \
aoqi@0 2838 if (JvmtiExport::should_post_field_modification()) { \
aoqi@0 2839 jvalue field_value; \
aoqi@0 2840 field_value.unionType = value; \
aoqi@0 2841 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
aoqi@0 2842 } \
aoqi@0 2843 o->Fieldname##_field_put(offset, value); \
aoqi@0 2844 ReturnProbe; \
aoqi@0 2845 JNI_END
aoqi@0 2846
aoqi@0 2847 DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z
aoqi@0 2848 , HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
aoqi@0 2849 HOTSPOT_JNI_SETBOOLEANFIELD_RETURN())
aoqi@0 2850 DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b
aoqi@0 2851 , HOTSPOT_JNI_SETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
aoqi@0 2852 HOTSPOT_JNI_SETBYTEFIELD_RETURN())
aoqi@0 2853 DEFINE_SETFIELD(jchar, char, Char, 'C', c
aoqi@0 2854 , HOTSPOT_JNI_SETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
aoqi@0 2855 HOTSPOT_JNI_SETCHARFIELD_RETURN())
aoqi@0 2856 DEFINE_SETFIELD(jshort, short, Short, 'S', s
aoqi@0 2857 , HOTSPOT_JNI_SETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
aoqi@0 2858 HOTSPOT_JNI_SETSHORTFIELD_RETURN())
aoqi@0 2859 DEFINE_SETFIELD(jint, int, Int, 'I', i
aoqi@0 2860 , HOTSPOT_JNI_SETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
aoqi@0 2861 HOTSPOT_JNI_SETINTFIELD_RETURN())
aoqi@0 2862 DEFINE_SETFIELD(jlong, long, Long, 'J', j
aoqi@0 2863 , HOTSPOT_JNI_SETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
aoqi@0 2864 HOTSPOT_JNI_SETLONGFIELD_RETURN())
aoqi@0 2865 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 2866 DEFINE_SETFIELD(jfloat, float, Float, 'F', f
aoqi@0 2867 , HOTSPOT_JNI_SETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2868 HOTSPOT_JNI_SETFLOATFIELD_RETURN())
aoqi@0 2869 DEFINE_SETFIELD(jdouble, double, Double, 'D', d
aoqi@0 2870 , HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
aoqi@0 2871 HOTSPOT_JNI_SETDOUBLEFIELD_RETURN())
aoqi@0 2872 #endif /* USDT2 */
aoqi@0 2873
aoqi@0 2874 #ifndef USDT2
aoqi@0 2875 DT_RETURN_MARK_DECL(ToReflectedField, jobject);
aoqi@0 2876 #else /* USDT2 */
aoqi@0 2877 DT_RETURN_MARK_DECL(ToReflectedField, jobject
aoqi@0 2878 , HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(_ret_ref));
aoqi@0 2879 #endif /* USDT2 */
aoqi@0 2880
aoqi@0 2881 JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic))
aoqi@0 2882 JNIWrapper("ToReflectedField");
aoqi@0 2883 #ifndef USDT2
aoqi@0 2884 DTRACE_PROBE4(hotspot_jni, ToReflectedField__entry,
aoqi@0 2885 env, cls, fieldID, isStatic);
aoqi@0 2886 #else /* USDT2 */
aoqi@0 2887 HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY(
aoqi@0 2888 env, cls, (uintptr_t) fieldID, isStatic);
aoqi@0 2889 #endif /* USDT2 */
aoqi@0 2890 jobject ret = NULL;
aoqi@0 2891 DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret);
aoqi@0 2892
aoqi@0 2893 fieldDescriptor fd;
aoqi@0 2894 bool found = false;
aoqi@0 2895 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
aoqi@0 2896
aoqi@0 2897 assert(jfieldIDWorkaround::is_static_jfieldID(fieldID) == (isStatic != 0), "invalid fieldID");
aoqi@0 2898
aoqi@0 2899 if (isStatic) {
aoqi@0 2900 // Static field. The fieldID a JNIid specifying the field holder and the offset within the Klass*.
aoqi@0 2901 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);
aoqi@0 2902 assert(id->is_static_field_id(), "invalid static field id");
aoqi@0 2903 found = id->find_local_field(&fd);
aoqi@0 2904 } else {
aoqi@0 2905 // Non-static field. The fieldID is really the offset of the field within the instanceOop.
aoqi@0 2906 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
aoqi@0 2907 found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, &fd);
aoqi@0 2908 }
aoqi@0 2909 assert(found, "bad fieldID passed into jni_ToReflectedField");
aoqi@0 2910 oop reflected = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);
aoqi@0 2911 ret = JNIHandles::make_local(env, reflected);
aoqi@0 2912 return ret;
aoqi@0 2913 JNI_END
aoqi@0 2914
aoqi@0 2915
aoqi@0 2916 //
aoqi@0 2917 // Accessing Static Fields
aoqi@0 2918 //
aoqi@0 2919 #ifndef USDT2
aoqi@0 2920 DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID);
aoqi@0 2921 #else /* USDT2 */
aoqi@0 2922 DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID
aoqi@0 2923 , HOTSPOT_JNI_GETSTATICFIELDID_RETURN((uintptr_t)_ret_ref));
aoqi@0 2924 #endif /* USDT2 */
aoqi@0 2925
aoqi@0 2926 JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz,
aoqi@0 2927 const char *name, const char *sig))
aoqi@0 2928 JNIWrapper("GetStaticFieldID");
aoqi@0 2929 #ifndef USDT2
aoqi@0 2930 DTRACE_PROBE4(hotspot_jni, GetStaticFieldID__entry, env, clazz, name, sig);
aoqi@0 2931 #else /* USDT2 */
aoqi@0 2932 HOTSPOT_JNI_GETSTATICFIELDID_ENTRY(
aoqi@0 2933 env, clazz, (char *) name, (char *) sig);
aoqi@0 2934 #endif /* USDT2 */
aoqi@0 2935 jfieldID ret = NULL;
aoqi@0 2936 DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret);
aoqi@0 2937
aoqi@0 2938 // The class should have been loaded (we have an instance of the class
aoqi@0 2939 // passed in) so the field and signature should already be in the symbol
aoqi@0 2940 // table. If they're not there, the field doesn't exist.
aoqi@0 2941 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
aoqi@0 2942 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
aoqi@0 2943 if (fieldname == NULL || signame == NULL) {
aoqi@0 2944 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
aoqi@0 2945 }
aoqi@0 2946 KlassHandle k(THREAD,
aoqi@0 2947 java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
aoqi@0 2948 // Make sure class is initialized before handing id's out to static fields
aoqi@0 2949 k()->initialize(CHECK_NULL);
aoqi@0 2950
aoqi@0 2951 fieldDescriptor fd;
aoqi@0 2952 if (!k()->oop_is_instance() ||
aoqi@0 2953 !InstanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) {
aoqi@0 2954 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
aoqi@0 2955 }
aoqi@0 2956
aoqi@0 2957 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
aoqi@0 2958 JNIid* id = fd.field_holder()->jni_id_for(fd.offset());
aoqi@0 2959 debug_only(id->set_is_static_field_id();)
aoqi@0 2960
aoqi@0 2961 debug_only(id->verify(fd.field_holder()));
aoqi@0 2962
aoqi@0 2963 ret = jfieldIDWorkaround::to_static_jfieldID(id);
aoqi@0 2964 return ret;
aoqi@0 2965 JNI_END
aoqi@0 2966
aoqi@0 2967
aoqi@0 2968 JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID))
aoqi@0 2969 JNIWrapper("GetStaticObjectField");
aoqi@0 2970 #ifndef USDT2
aoqi@0 2971 DTRACE_PROBE3(hotspot_jni, GetStaticObjectField__entry, env, clazz, fieldID);
aoqi@0 2972 #else /* USDT2 */
aoqi@0 2973 HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY(
aoqi@0 2974 env, clazz, (uintptr_t) fieldID);
aoqi@0 2975 #endif /* USDT2 */
aoqi@0 2976 #if INCLUDE_JNI_CHECK
aoqi@0 2977 DEBUG_ONLY(Klass* param_k = jniCheck::validate_class(thread, clazz);)
aoqi@0 2978 #endif // INCLUDE_JNI_CHECK
aoqi@0 2979 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);
aoqi@0 2980 assert(id->is_static_field_id(), "invalid static field id");
aoqi@0 2981 // Keep JVMTI addition small and only check enabled flag here.
aoqi@0 2982 // jni_GetField_probe() assumes that is okay to create handles.
aoqi@0 2983 if (JvmtiExport::should_post_field_access()) {
aoqi@0 2984 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true);
aoqi@0 2985 }
aoqi@0 2986 jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset()));
aoqi@0 2987 #ifndef USDT2
aoqi@0 2988 DTRACE_PROBE1(hotspot_jni, GetStaticObjectField__return, ret);
aoqi@0 2989 #else /* USDT2 */
aoqi@0 2990 HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(
aoqi@0 2991 ret);
aoqi@0 2992 #endif /* USDT2 */
aoqi@0 2993 return ret;
aoqi@0 2994 JNI_END
aoqi@0 2995
aoqi@0 2996 #ifndef USDT2
aoqi@0 2997 #define DEFINE_GETSTATICFIELD(Return,Fieldname,Result) \
aoqi@0 2998 \
aoqi@0 2999 DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return);\
aoqi@0 3000 \
aoqi@0 3001 JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \
aoqi@0 3002 JNIWrapper("GetStatic" XSTR(Result) "Field"); \
aoqi@0 3003 DTRACE_PROBE3(hotspot_jni, GetStatic##Result##Field__entry, env, clazz, fieldID);\
aoqi@0 3004 Return ret = 0;\
aoqi@0 3005 DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \
aoqi@0 3006 (const Return&)ret);\
aoqi@0 3007 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \
aoqi@0 3008 assert(id->is_static_field_id(), "invalid static field id"); \
aoqi@0 3009 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 3010 /* jni_GetField_probe() assumes that is okay to create handles. */ \
aoqi@0 3011 if (JvmtiExport::should_post_field_access()) { \
aoqi@0 3012 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \
aoqi@0 3013 } \
aoqi@0 3014 ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \
aoqi@0 3015 return ret;\
aoqi@0 3016 JNI_END
aoqi@0 3017
aoqi@0 3018 DEFINE_GETSTATICFIELD(jboolean, bool, Boolean)
aoqi@0 3019 DEFINE_GETSTATICFIELD(jbyte, byte, Byte)
aoqi@0 3020 DEFINE_GETSTATICFIELD(jchar, char, Char)
aoqi@0 3021 DEFINE_GETSTATICFIELD(jshort, short, Short)
aoqi@0 3022 DEFINE_GETSTATICFIELD(jint, int, Int)
aoqi@0 3023 DEFINE_GETSTATICFIELD(jlong, long, Long)
aoqi@0 3024 DEFINE_GETSTATICFIELD(jfloat, float, Float)
aoqi@0 3025 DEFINE_GETSTATICFIELD(jdouble, double, Double)
aoqi@0 3026
aoqi@0 3027 #else /* USDT2 */
aoqi@0 3028
aoqi@0 3029 #define DEFINE_GETSTATICFIELD(Return,Fieldname,Result \
aoqi@0 3030 , EntryProbe, ReturnProbe) \
aoqi@0 3031 \
aoqi@0 3032 DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return \
aoqi@0 3033 , ReturnProbe); \
aoqi@0 3034 \
aoqi@0 3035 JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \
aoqi@0 3036 JNIWrapper("GetStatic" XSTR(Result) "Field"); \
aoqi@0 3037 EntryProbe; \
aoqi@0 3038 Return ret = 0;\
aoqi@0 3039 DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \
aoqi@0 3040 (const Return&)ret);\
aoqi@0 3041 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \
aoqi@0 3042 assert(id->is_static_field_id(), "invalid static field id"); \
aoqi@0 3043 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 3044 /* jni_GetField_probe() assumes that is okay to create handles. */ \
aoqi@0 3045 if (JvmtiExport::should_post_field_access()) { \
aoqi@0 3046 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \
aoqi@0 3047 } \
aoqi@0 3048 ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \
aoqi@0 3049 return ret;\
aoqi@0 3050 JNI_END
aoqi@0 3051
aoqi@0 3052 DEFINE_GETSTATICFIELD(jboolean, bool, Boolean
aoqi@0 3053 , HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(_ret_ref))
aoqi@0 3054 DEFINE_GETSTATICFIELD(jbyte, byte, Byte
aoqi@0 3055 , HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(_ret_ref) )
aoqi@0 3056 DEFINE_GETSTATICFIELD(jchar, char, Char
aoqi@0 3057 , HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(_ret_ref) )
aoqi@0 3058 DEFINE_GETSTATICFIELD(jshort, short, Short
aoqi@0 3059 , HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(_ret_ref) )
aoqi@0 3060 DEFINE_GETSTATICFIELD(jint, int, Int
aoqi@0 3061 , HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(_ret_ref) )
aoqi@0 3062 DEFINE_GETSTATICFIELD(jlong, long, Long
aoqi@0 3063 , HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(_ret_ref) )
aoqi@0 3064 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 3065 DEFINE_GETSTATICFIELD(jfloat, float, Float
aoqi@0 3066 , HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() )
aoqi@0 3067 DEFINE_GETSTATICFIELD(jdouble, double, Double
aoqi@0 3068 , HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() )
aoqi@0 3069 #endif /* USDT2 */
aoqi@0 3070
aoqi@0 3071 JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value))
aoqi@0 3072 JNIWrapper("SetStaticObjectField");
aoqi@0 3073 #ifndef USDT2
aoqi@0 3074 DTRACE_PROBE4(hotspot_jni, SetStaticObjectField__entry, env, clazz, fieldID, value);
aoqi@0 3075 #else /* USDT2 */
aoqi@0 3076 HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY(
aoqi@0 3077 env, clazz, (uintptr_t) fieldID, value);
aoqi@0 3078 #endif /* USDT2 */
aoqi@0 3079 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);
aoqi@0 3080 assert(id->is_static_field_id(), "invalid static field id");
aoqi@0 3081 // Keep JVMTI addition small and only check enabled flag here.
aoqi@0 3082 // jni_SetField_probe() assumes that is okay to create handles.
aoqi@0 3083 if (JvmtiExport::should_post_field_modification()) {
aoqi@0 3084 jvalue field_value;
aoqi@0 3085 field_value.l = value;
aoqi@0 3086 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value);
aoqi@0 3087 }
aoqi@0 3088 id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value));
aoqi@0 3089 #ifndef USDT2
aoqi@0 3090 DTRACE_PROBE(hotspot_jni, SetStaticObjectField__return);
aoqi@0 3091 #else /* USDT2 */
aoqi@0 3092 HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN(
aoqi@0 3093 );
aoqi@0 3094 #endif /* USDT2 */
aoqi@0 3095 JNI_END
aoqi@0 3096
aoqi@0 3097
aoqi@0 3098 #ifndef USDT2
aoqi@0 3099 #define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType) \
aoqi@0 3100 \
aoqi@0 3101 JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \
aoqi@0 3102 JNIWrapper("SetStatic" XSTR(Result) "Field"); \
aoqi@0 3103 FP_SELECT_##Result( \
aoqi@0 3104 DTRACE_PROBE4(hotspot_jni, SetStatic##Result##Field__entry, env, clazz, fieldID, value), \
aoqi@0 3105 DTRACE_PROBE3(hotspot_jni, SetStatic##Result##Field__entry, env, clazz, fieldID)); \
aoqi@0 3106 \
aoqi@0 3107 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \
aoqi@0 3108 assert(id->is_static_field_id(), "invalid static field id"); \
aoqi@0 3109 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 3110 /* jni_SetField_probe() assumes that is okay to create handles. */ \
aoqi@0 3111 if (JvmtiExport::should_post_field_modification()) { \
aoqi@0 3112 jvalue field_value; \
aoqi@0 3113 field_value.unionType = value; \
aoqi@0 3114 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
aoqi@0 3115 } \
aoqi@0 3116 id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \
aoqi@0 3117 DTRACE_PROBE(hotspot_jni, SetStatic##Result##Field__return);\
aoqi@0 3118 JNI_END
aoqi@0 3119
aoqi@0 3120 DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z)
aoqi@0 3121 DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b)
aoqi@0 3122 DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c)
aoqi@0 3123 DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s)
aoqi@0 3124 DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i)
aoqi@0 3125 DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j)
aoqi@0 3126 DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f)
aoqi@0 3127 DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d)
aoqi@0 3128
aoqi@0 3129 #else /* USDT2 */
aoqi@0 3130
aoqi@0 3131 #define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType \
aoqi@0 3132 , EntryProbe, ReturnProbe) \
aoqi@0 3133 \
aoqi@0 3134 JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \
aoqi@0 3135 JNIWrapper("SetStatic" XSTR(Result) "Field"); \
aoqi@0 3136 EntryProbe; \
aoqi@0 3137 \
aoqi@0 3138 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \
aoqi@0 3139 assert(id->is_static_field_id(), "invalid static field id"); \
aoqi@0 3140 /* Keep JVMTI addition small and only check enabled flag here. */ \
aoqi@0 3141 /* jni_SetField_probe() assumes that is okay to create handles. */ \
aoqi@0 3142 if (JvmtiExport::should_post_field_modification()) { \
aoqi@0 3143 jvalue field_value; \
aoqi@0 3144 field_value.unionType = value; \
aoqi@0 3145 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
aoqi@0 3146 } \
aoqi@0 3147 id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \
aoqi@0 3148 ReturnProbe;\
aoqi@0 3149 JNI_END
aoqi@0 3150
aoqi@0 3151 DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z
aoqi@0 3152 , HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t)fieldID, value),
aoqi@0 3153 HOTSPOT_JNI_SETBOOLEANFIELD_RETURN())
aoqi@0 3154 DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b
aoqi@0 3155 , HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
aoqi@0 3156 HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN())
aoqi@0 3157 DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c
aoqi@0 3158 , HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
aoqi@0 3159 HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN())
aoqi@0 3160 DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s
aoqi@0 3161 , HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
aoqi@0 3162 HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN())
aoqi@0 3163 DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i
aoqi@0 3164 , HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
aoqi@0 3165 HOTSPOT_JNI_SETSTATICINTFIELD_RETURN())
aoqi@0 3166 DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j
aoqi@0 3167 , HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
aoqi@0 3168 HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN())
aoqi@0 3169 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 3170 DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f
aoqi@0 3171 , HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),
aoqi@0 3172 HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN())
aoqi@0 3173 DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d
aoqi@0 3174 , HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),
aoqi@0 3175 HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN())
aoqi@0 3176 #endif /* USDT2 */
aoqi@0 3177
aoqi@0 3178 //
aoqi@0 3179 // String Operations
aoqi@0 3180 //
aoqi@0 3181
aoqi@0 3182 // Unicode Interface
aoqi@0 3183
aoqi@0 3184 #ifndef USDT2
aoqi@0 3185 DT_RETURN_MARK_DECL(NewString, jstring);
aoqi@0 3186 #else /* USDT2 */
aoqi@0 3187 DT_RETURN_MARK_DECL(NewString, jstring
aoqi@0 3188 , HOTSPOT_JNI_NEWSTRING_RETURN(_ret_ref));
aoqi@0 3189 #endif /* USDT2 */
aoqi@0 3190
aoqi@0 3191 JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len))
aoqi@0 3192 JNIWrapper("NewString");
aoqi@0 3193 #ifndef USDT2
aoqi@0 3194 DTRACE_PROBE3(hotspot_jni, NewString__entry, env, unicodeChars, len);
aoqi@0 3195 #else /* USDT2 */
aoqi@0 3196 HOTSPOT_JNI_NEWSTRING_ENTRY(
aoqi@0 3197 env, (uint16_t *) unicodeChars, len);
aoqi@0 3198 #endif /* USDT2 */
aoqi@0 3199 jstring ret = NULL;
aoqi@0 3200 DT_RETURN_MARK(NewString, jstring, (const jstring&)ret);
aoqi@0 3201 oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL);
aoqi@0 3202 ret = (jstring) JNIHandles::make_local(env, string);
aoqi@0 3203 return ret;
aoqi@0 3204 JNI_END
aoqi@0 3205
aoqi@0 3206
aoqi@0 3207 JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string))
aoqi@0 3208 JNIWrapper("GetStringLength");
aoqi@0 3209 #ifndef USDT2
aoqi@0 3210 DTRACE_PROBE2(hotspot_jni, GetStringLength__entry, env, string);
aoqi@0 3211 #else /* USDT2 */
aoqi@0 3212 HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(
aoqi@0 3213 env, string);
aoqi@0 3214 #endif /* USDT2 */
aoqi@0 3215 jsize ret = 0;
aoqi@0 3216 oop s = JNIHandles::resolve_non_null(string);
aoqi@0 3217 if (java_lang_String::value(s) != NULL) {
aoqi@0 3218 ret = java_lang_String::length(s);
aoqi@0 3219 }
aoqi@0 3220 #ifndef USDT2
aoqi@0 3221 DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret);
aoqi@0 3222 #else /* USDT2 */
aoqi@0 3223 HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(
aoqi@0 3224 ret);
aoqi@0 3225 #endif /* USDT2 */
aoqi@0 3226 return ret;
aoqi@0 3227 JNI_END
aoqi@0 3228
aoqi@0 3229
aoqi@0 3230 JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
aoqi@0 3231 JNIEnv *env, jstring string, jboolean *isCopy))
aoqi@0 3232 JNIWrapper("GetStringChars");
aoqi@0 3233 #ifndef USDT2
aoqi@0 3234 DTRACE_PROBE3(hotspot_jni, GetStringChars__entry, env, string, isCopy);
aoqi@0 3235 #else /* USDT2 */
aoqi@0 3236 HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(
aoqi@0 3237 env, string, (uintptr_t *) isCopy);
aoqi@0 3238 #endif /* USDT2 */
aoqi@0 3239 jchar* buf = NULL;
aoqi@0 3240 oop s = JNIHandles::resolve_non_null(string);
aoqi@0 3241 typeArrayOop s_value = java_lang_String::value(s);
aoqi@0 3242 if (s_value != NULL) {
aoqi@0 3243 int s_len = java_lang_String::length(s);
aoqi@0 3244 int s_offset = java_lang_String::offset(s);
aoqi@0 3245 buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
aoqi@0 3246 /* JNI Specification states return NULL on OOM */
aoqi@0 3247 if (buf != NULL) {
aoqi@0 3248 if (s_len > 0) {
aoqi@0 3249 memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
aoqi@0 3250 }
aoqi@0 3251 buf[s_len] = 0;
aoqi@0 3252 //%note jni_5
aoqi@0 3253 if (isCopy != NULL) {
aoqi@0 3254 *isCopy = JNI_TRUE;
aoqi@0 3255 }
aoqi@0 3256 }
aoqi@0 3257 }
aoqi@0 3258 #ifndef USDT2
aoqi@0 3259 DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf);
aoqi@0 3260 #else /* USDT2 */
aoqi@0 3261 HOTSPOT_JNI_GETSTRINGCHARS_RETURN(
aoqi@0 3262 buf);
aoqi@0 3263 #endif /* USDT2 */
aoqi@0 3264 return buf;
aoqi@0 3265 JNI_END
aoqi@0 3266
aoqi@0 3267
aoqi@0 3268 JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars))
aoqi@0 3269 JNIWrapper("ReleaseStringChars");
aoqi@0 3270 #ifndef USDT2
aoqi@0 3271 DTRACE_PROBE3(hotspot_jni, ReleaseStringChars__entry, env, str, chars);
aoqi@0 3272 #else /* USDT2 */
aoqi@0 3273 HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY(
aoqi@0 3274 env, str, (uint16_t *) chars);
aoqi@0 3275 #endif /* USDT2 */
aoqi@0 3276 //%note jni_6
aoqi@0 3277 if (chars != NULL) {
aoqi@0 3278 // Since String objects are supposed to be immutable, don't copy any
aoqi@0 3279 // new data back. A bad user will have to go after the char array.
aoqi@0 3280 FreeHeap((void*) chars);
aoqi@0 3281 }
aoqi@0 3282 #ifndef USDT2
aoqi@0 3283 DTRACE_PROBE(hotspot_jni, ReleaseStringChars__return);
aoqi@0 3284 #else /* USDT2 */
aoqi@0 3285 HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN(
aoqi@0 3286 );
aoqi@0 3287 #endif /* USDT2 */
aoqi@0 3288 JNI_END
aoqi@0 3289
aoqi@0 3290
aoqi@0 3291 // UTF Interface
aoqi@0 3292
aoqi@0 3293 #ifndef USDT2
aoqi@0 3294 DT_RETURN_MARK_DECL(NewStringUTF, jstring);
aoqi@0 3295 #else /* USDT2 */
aoqi@0 3296 DT_RETURN_MARK_DECL(NewStringUTF, jstring
aoqi@0 3297 , HOTSPOT_JNI_NEWSTRINGUTF_RETURN(_ret_ref));
aoqi@0 3298 #endif /* USDT2 */
aoqi@0 3299
aoqi@0 3300 JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes))
aoqi@0 3301 JNIWrapper("NewStringUTF");
aoqi@0 3302 #ifndef USDT2
aoqi@0 3303 DTRACE_PROBE2(hotspot_jni, NewStringUTF__entry, env, bytes);
aoqi@0 3304 #else /* USDT2 */
aoqi@0 3305 HOTSPOT_JNI_NEWSTRINGUTF_ENTRY(
aoqi@0 3306 env, (char *) bytes);
aoqi@0 3307 #endif /* USDT2 */
aoqi@0 3308 jstring ret;
aoqi@0 3309 DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret);
aoqi@0 3310
aoqi@0 3311 oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL);
aoqi@0 3312 ret = (jstring) JNIHandles::make_local(env, result);
aoqi@0 3313 return ret;
aoqi@0 3314 JNI_END
aoqi@0 3315
aoqi@0 3316
aoqi@0 3317 JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string))
aoqi@0 3318 JNIWrapper("GetStringUTFLength");
aoqi@0 3319 #ifndef USDT2
aoqi@0 3320 DTRACE_PROBE2(hotspot_jni, GetStringUTFLength__entry, env, string);
aoqi@0 3321 #else /* USDT2 */
aoqi@0 3322 HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(
aoqi@0 3323 env, string);
aoqi@0 3324 #endif /* USDT2 */
aoqi@0 3325 jsize ret = 0;
aoqi@0 3326 oop java_string = JNIHandles::resolve_non_null(string);
aoqi@0 3327 if (java_lang_String::value(java_string) != NULL) {
aoqi@0 3328 ret = java_lang_String::utf8_length(java_string);
aoqi@0 3329 }
aoqi@0 3330 #ifndef USDT2
aoqi@0 3331 DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret);
aoqi@0 3332 #else /* USDT2 */
aoqi@0 3333 HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(
aoqi@0 3334 ret);
aoqi@0 3335 #endif /* USDT2 */
aoqi@0 3336 return ret;
aoqi@0 3337 JNI_END
aoqi@0 3338
aoqi@0 3339
aoqi@0 3340 JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy))
aoqi@0 3341 JNIWrapper("GetStringUTFChars");
aoqi@0 3342 #ifndef USDT2
aoqi@0 3343 DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy);
aoqi@0 3344 #else /* USDT2 */
aoqi@0 3345 HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(
aoqi@0 3346 env, string, (uintptr_t *) isCopy);
aoqi@0 3347 #endif /* USDT2 */
aoqi@0 3348 char* result = NULL;
aoqi@0 3349 oop java_string = JNIHandles::resolve_non_null(string);
aoqi@0 3350 if (java_lang_String::value(java_string) != NULL) {
aoqi@0 3351 size_t length = java_lang_String::utf8_length(java_string);
aoqi@0 3352 /* JNI Specification states return NULL on OOM */
aoqi@0 3353 result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
aoqi@0 3354 if (result != NULL) {
aoqi@0 3355 java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
aoqi@0 3356 if (isCopy != NULL) {
aoqi@0 3357 *isCopy = JNI_TRUE;
aoqi@0 3358 }
aoqi@0 3359 }
aoqi@0 3360 }
aoqi@0 3361 #ifndef USDT2
aoqi@0 3362 DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
aoqi@0 3363 #else /* USDT2 */
aoqi@0 3364 HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN(
aoqi@0 3365 result);
aoqi@0 3366 #endif /* USDT2 */
aoqi@0 3367 return result;
aoqi@0 3368 JNI_END
aoqi@0 3369
aoqi@0 3370
aoqi@0 3371 JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars))
aoqi@0 3372 JNIWrapper("ReleaseStringUTFChars");
aoqi@0 3373 #ifndef USDT2
aoqi@0 3374 DTRACE_PROBE3(hotspot_jni, ReleaseStringUTFChars__entry, env, str, chars);
aoqi@0 3375 #else /* USDT2 */
aoqi@0 3376 HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY(
aoqi@0 3377 env, str, (char *) chars);
aoqi@0 3378 #endif /* USDT2 */
aoqi@0 3379 if (chars != NULL) {
aoqi@0 3380 FreeHeap((char*) chars);
aoqi@0 3381 }
aoqi@0 3382 #ifndef USDT2
aoqi@0 3383 DTRACE_PROBE(hotspot_jni, ReleaseStringUTFChars__return);
aoqi@0 3384 #else /* USDT2 */
aoqi@0 3385 HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN(
aoqi@0 3386 );
aoqi@0 3387 #endif /* USDT2 */
aoqi@0 3388 JNI_END
aoqi@0 3389
aoqi@0 3390
aoqi@0 3391 JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array))
aoqi@0 3392 JNIWrapper("GetArrayLength");
aoqi@0 3393 #ifndef USDT2
aoqi@0 3394 DTRACE_PROBE2(hotspot_jni, GetArrayLength__entry, env, array);
aoqi@0 3395 #else /* USDT2 */
aoqi@0 3396 HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(
aoqi@0 3397 env, array);
aoqi@0 3398 #endif /* USDT2 */
aoqi@0 3399 arrayOop a = arrayOop(JNIHandles::resolve_non_null(array));
aoqi@0 3400 assert(a->is_array(), "must be array");
aoqi@0 3401 jsize ret = a->length();
aoqi@0 3402 #ifndef USDT2
aoqi@0 3403 DTRACE_PROBE1(hotspot_jni, GetArrayLength__return, ret);
aoqi@0 3404 #else /* USDT2 */
aoqi@0 3405 HOTSPOT_JNI_GETARRAYLENGTH_RETURN(
aoqi@0 3406 ret);
aoqi@0 3407 #endif /* USDT2 */
aoqi@0 3408 return ret;
aoqi@0 3409 JNI_END
aoqi@0 3410
aoqi@0 3411
aoqi@0 3412 //
aoqi@0 3413 // Object Array Operations
aoqi@0 3414 //
aoqi@0 3415
aoqi@0 3416 #ifndef USDT2
aoqi@0 3417 DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray);
aoqi@0 3418 #else /* USDT2 */
aoqi@0 3419 DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray
aoqi@0 3420 , HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(_ret_ref));
aoqi@0 3421 #endif /* USDT2 */
aoqi@0 3422
aoqi@0 3423 JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement))
aoqi@0 3424 JNIWrapper("NewObjectArray");
aoqi@0 3425 #ifndef USDT2
aoqi@0 3426 DTRACE_PROBE4(hotspot_jni, NewObjectArray__entry, env, length, elementClass, initialElement);
aoqi@0 3427 #else /* USDT2 */
aoqi@0 3428 HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(
aoqi@0 3429 env, length, elementClass, initialElement);
aoqi@0 3430 #endif /* USDT2 */
aoqi@0 3431 jobjectArray ret = NULL;
aoqi@0 3432 DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret);
aoqi@0 3433 KlassHandle ek(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass)));
aoqi@0 3434 Klass* ako = ek()->array_klass(CHECK_NULL);
aoqi@0 3435 KlassHandle ak = KlassHandle(THREAD, ako);
aoqi@0 3436 ObjArrayKlass::cast(ak())->initialize(CHECK_NULL);
aoqi@0 3437 objArrayOop result = ObjArrayKlass::cast(ak())->allocate(length, CHECK_NULL);
aoqi@0 3438 oop initial_value = JNIHandles::resolve(initialElement);
aoqi@0 3439 if (initial_value != NULL) { // array already initialized with NULL
aoqi@0 3440 for (int index = 0; index < length; index++) {
aoqi@0 3441 result->obj_at_put(index, initial_value);
aoqi@0 3442 }
aoqi@0 3443 }
aoqi@0 3444 ret = (jobjectArray) JNIHandles::make_local(env, result);
aoqi@0 3445 return ret;
aoqi@0 3446 JNI_END
aoqi@0 3447
aoqi@0 3448 #ifndef USDT2
aoqi@0 3449 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject);
aoqi@0 3450 #else /* USDT2 */
aoqi@0 3451 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
aoqi@0 3452 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
aoqi@0 3453 #endif /* USDT2 */
aoqi@0 3454
aoqi@0 3455 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
aoqi@0 3456 JNIWrapper("GetObjectArrayElement");
aoqi@0 3457 #ifndef USDT2
aoqi@0 3458 DTRACE_PROBE3(hotspot_jni, GetObjectArrayElement__entry, env, array, index);
aoqi@0 3459 #else /* USDT2 */
aoqi@0 3460 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(
aoqi@0 3461 env, array, index);
aoqi@0 3462 #endif /* USDT2 */
aoqi@0 3463 jobject ret = NULL;
aoqi@0 3464 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
aoqi@0 3465 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
aoqi@0 3466 if (a->is_within_bounds(index)) {
aoqi@0 3467 ret = JNIHandles::make_local(env, a->obj_at(index));
aoqi@0 3468 return ret;
aoqi@0 3469 } else {
aoqi@0 3470 char buf[jintAsStringSize];
aoqi@0 3471 sprintf(buf, "%d", index);
aoqi@0 3472 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), buf);
aoqi@0 3473 }
aoqi@0 3474 JNI_END
aoqi@0 3475
aoqi@0 3476 #ifndef USDT2
aoqi@0 3477 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement);
aoqi@0 3478 #else /* USDT2 */
aoqi@0 3479 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
aoqi@0 3480 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
aoqi@0 3481 #endif /* USDT2 */
aoqi@0 3482
aoqi@0 3483 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
aoqi@0 3484 JNIWrapper("SetObjectArrayElement");
aoqi@0 3485 #ifndef USDT2
aoqi@0 3486 DTRACE_PROBE4(hotspot_jni, SetObjectArrayElement__entry, env, array, index, value);
aoqi@0 3487 #else /* USDT2 */
aoqi@0 3488 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(
aoqi@0 3489 env, array, index, value);
aoqi@0 3490 #endif /* USDT2 */
aoqi@0 3491 DT_VOID_RETURN_MARK(SetObjectArrayElement);
aoqi@0 3492
aoqi@0 3493 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
aoqi@0 3494 oop v = JNIHandles::resolve(value);
aoqi@0 3495 if (a->is_within_bounds(index)) {
aoqi@0 3496 if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
aoqi@0 3497 a->obj_at_put(index, v);
aoqi@0 3498 } else {
aoqi@0 3499 THROW(vmSymbols::java_lang_ArrayStoreException());
aoqi@0 3500 }
aoqi@0 3501 } else {
aoqi@0 3502 char buf[jintAsStringSize];
aoqi@0 3503 sprintf(buf, "%d", index);
aoqi@0 3504 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), buf);
aoqi@0 3505 }
aoqi@0 3506 JNI_END
aoqi@0 3507
aoqi@0 3508
aoqi@0 3509 #ifndef USDT2
aoqi@0 3510 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \
aoqi@0 3511 \
aoqi@0 3512 DT_RETURN_MARK_DECL(New##Result##Array, Return); \
aoqi@0 3513 \
aoqi@0 3514 JNI_ENTRY(Return, \
aoqi@0 3515 jni_New##Result##Array(JNIEnv *env, jsize len)) \
aoqi@0 3516 JNIWrapper("New" XSTR(Result) "Array"); \
aoqi@0 3517 DTRACE_PROBE2(hotspot_jni, New##Result##Array__entry, env, len);\
aoqi@0 3518 Return ret = NULL;\
aoqi@0 3519 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
aoqi@0 3520 \
aoqi@0 3521 oop obj= oopFactory::Allocator(len, CHECK_0); \
aoqi@0 3522 ret = (Return) JNIHandles::make_local(env, obj); \
aoqi@0 3523 return ret;\
aoqi@0 3524 JNI_END
aoqi@0 3525
aoqi@0 3526 DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean)
aoqi@0 3527 DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte)
aoqi@0 3528 DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short)
aoqi@0 3529 DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char)
aoqi@0 3530 DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int)
aoqi@0 3531 DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long)
aoqi@0 3532 DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float)
aoqi@0 3533 DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double)
aoqi@0 3534
aoqi@0 3535 #else /* USDT2 */
aoqi@0 3536
aoqi@0 3537 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
aoqi@0 3538 ,EntryProbe,ReturnProbe) \
aoqi@0 3539 \
aoqi@0 3540 DT_RETURN_MARK_DECL(New##Result##Array, Return \
aoqi@0 3541 , ReturnProbe); \
aoqi@0 3542 \
aoqi@0 3543 JNI_ENTRY(Return, \
aoqi@0 3544 jni_New##Result##Array(JNIEnv *env, jsize len)) \
aoqi@0 3545 JNIWrapper("New" XSTR(Result) "Array"); \
aoqi@0 3546 EntryProbe; \
aoqi@0 3547 Return ret = NULL;\
aoqi@0 3548 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
aoqi@0 3549 \
aoqi@0 3550 oop obj= oopFactory::Allocator(len, CHECK_0); \
aoqi@0 3551 ret = (Return) JNIHandles::make_local(env, obj); \
aoqi@0 3552 return ret;\
aoqi@0 3553 JNI_END
aoqi@0 3554
aoqi@0 3555 DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean,
aoqi@0 3556 HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY(env, len),
aoqi@0 3557 HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN(_ret_ref))
aoqi@0 3558 DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte,
aoqi@0 3559 HOTSPOT_JNI_NEWBYTEARRAY_ENTRY(env, len),
aoqi@0 3560 HOTSPOT_JNI_NEWBYTEARRAY_RETURN(_ret_ref))
aoqi@0 3561 DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short,
aoqi@0 3562 HOTSPOT_JNI_NEWSHORTARRAY_ENTRY(env, len),
aoqi@0 3563 HOTSPOT_JNI_NEWSHORTARRAY_RETURN(_ret_ref))
aoqi@0 3564 DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char,
aoqi@0 3565 HOTSPOT_JNI_NEWCHARARRAY_ENTRY(env, len),
aoqi@0 3566 HOTSPOT_JNI_NEWCHARARRAY_RETURN(_ret_ref))
aoqi@0 3567 DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int,
aoqi@0 3568 HOTSPOT_JNI_NEWINTARRAY_ENTRY(env, len),
aoqi@0 3569 HOTSPOT_JNI_NEWINTARRAY_RETURN(_ret_ref))
aoqi@0 3570 DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long,
aoqi@0 3571 HOTSPOT_JNI_NEWLONGARRAY_ENTRY(env, len),
aoqi@0 3572 HOTSPOT_JNI_NEWLONGARRAY_RETURN(_ret_ref))
aoqi@0 3573 DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float,
aoqi@0 3574 HOTSPOT_JNI_NEWFLOATARRAY_ENTRY(env, len),
aoqi@0 3575 HOTSPOT_JNI_NEWFLOATARRAY_RETURN(_ret_ref))
aoqi@0 3576 DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double,
aoqi@0 3577 HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(env, len),
aoqi@0 3578 HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(_ret_ref))
aoqi@0 3579 #endif /* USDT2 */
aoqi@0 3580
aoqi@0 3581 // Return an address which will fault if the caller writes to it.
aoqi@0 3582
aoqi@0 3583 static char* get_bad_address() {
aoqi@0 3584 static char* bad_address = NULL;
aoqi@0 3585 if (bad_address == NULL) {
aoqi@0 3586 size_t size = os::vm_allocation_granularity();
aoqi@0 3587 bad_address = os::reserve_memory(size);
aoqi@0 3588 if (bad_address != NULL) {
aoqi@0 3589 os::protect_memory(bad_address, size, os::MEM_PROT_READ,
aoqi@0 3590 /*is_committed*/false);
aoqi@0 3591 }
aoqi@0 3592 }
aoqi@0 3593 return bad_address;
aoqi@0 3594 }
aoqi@0 3595
aoqi@0 3596
aoqi@0 3597 #ifndef USDT2
aoqi@0 3598 #define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag) \
aoqi@0 3599 \
aoqi@0 3600 JNI_QUICK_ENTRY(ElementType*, \
aoqi@0 3601 jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \
aoqi@0 3602 JNIWrapper("Get" XSTR(Result) "ArrayElements"); \
aoqi@0 3603 DTRACE_PROBE3(hotspot_jni, Get##Result##ArrayElements__entry, env, array, isCopy);\
aoqi@0 3604 /* allocate an chunk of memory in c land */ \
aoqi@0 3605 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3606 ElementType* result; \
aoqi@0 3607 int len = a->length(); \
aoqi@0 3608 if (len == 0) { \
aoqi@0 3609 /* Empty array: legal but useless, can't return NULL. \
aoqi@0 3610 * Return a pointer to something useless. \
aoqi@0 3611 * Avoid asserts in typeArrayOop. */ \
aoqi@0 3612 result = (ElementType*)get_bad_address(); \
aoqi@0 3613 } else { \
aoqi@0 3614 /* JNI Specification states return NULL on OOM */ \
aoqi@0 3615 result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \
aoqi@0 3616 if (result != NULL) { \
aoqi@0 3617 /* copy the array to the c chunk */ \
aoqi@0 3618 memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
aoqi@0 3619 if (isCopy) { \
aoqi@0 3620 *isCopy = JNI_TRUE; \
aoqi@0 3621 } \
aoqi@0 3622 } \
aoqi@0 3623 } \
aoqi@0 3624 DTRACE_PROBE1(hotspot_jni, Get##Result##ArrayElements__return, result);\
aoqi@0 3625 return result; \
aoqi@0 3626 JNI_END
aoqi@0 3627
aoqi@0 3628 DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool)
aoqi@0 3629 DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte)
aoqi@0 3630 DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short)
aoqi@0 3631 DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char)
aoqi@0 3632 DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int)
aoqi@0 3633 DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long)
aoqi@0 3634 DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float)
aoqi@0 3635 DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double)
aoqi@0 3636
aoqi@0 3637 #else /* USDT2 */
aoqi@0 3638
aoqi@0 3639 #define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag \
aoqi@0 3640 , EntryProbe, ReturnProbe) \
aoqi@0 3641 \
aoqi@0 3642 JNI_QUICK_ENTRY(ElementType*, \
aoqi@0 3643 jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \
aoqi@0 3644 JNIWrapper("Get" XSTR(Result) "ArrayElements"); \
aoqi@0 3645 EntryProbe; \
aoqi@0 3646 /* allocate an chunk of memory in c land */ \
aoqi@0 3647 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3648 ElementType* result; \
aoqi@0 3649 int len = a->length(); \
aoqi@0 3650 if (len == 0) { \
aoqi@0 3651 /* Empty array: legal but useless, can't return NULL. \
aoqi@0 3652 * Return a pointer to something useless. \
aoqi@0 3653 * Avoid asserts in typeArrayOop. */ \
aoqi@0 3654 result = (ElementType*)get_bad_address(); \
aoqi@0 3655 } else { \
aoqi@0 3656 /* JNI Specification states return NULL on OOM */ \
aoqi@0 3657 result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \
aoqi@0 3658 if (result != NULL) { \
aoqi@0 3659 /* copy the array to the c chunk */ \
aoqi@0 3660 memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
aoqi@0 3661 if (isCopy) { \
aoqi@0 3662 *isCopy = JNI_TRUE; \
aoqi@0 3663 } \
aoqi@0 3664 } \
aoqi@0 3665 } \
aoqi@0 3666 ReturnProbe; \
aoqi@0 3667 return result; \
aoqi@0 3668 JNI_END
aoqi@0 3669
aoqi@0 3670 DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool
aoqi@0 3671 , HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
aoqi@0 3672 HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN((uintptr_t*)result))
aoqi@0 3673 DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte
aoqi@0 3674 , HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
aoqi@0 3675 HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN((char*)result))
aoqi@0 3676 DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short
aoqi@0 3677 , HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy),
aoqi@0 3678 HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN((uint16_t*)result))
aoqi@0 3679 DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char
aoqi@0 3680 , HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy),
aoqi@0 3681 HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN(result))
aoqi@0 3682 DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int
aoqi@0 3683 , HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
aoqi@0 3684 HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN((uint32_t*)result))
aoqi@0 3685 DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long
aoqi@0 3686 , HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
aoqi@0 3687 HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN(((uintptr_t*)result)))
aoqi@0 3688 // Float and double probes don't return value because dtrace doesn't currently support it
aoqi@0 3689 DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float
aoqi@0 3690 , HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
aoqi@0 3691 HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN(result))
aoqi@0 3692 DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double
aoqi@0 3693 , HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
aoqi@0 3694 HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(result))
aoqi@0 3695 #endif /* USDT2 */
aoqi@0 3696
aoqi@0 3697 #ifndef USDT2
aoqi@0 3698 #define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag) \
aoqi@0 3699 \
aoqi@0 3700 JNI_QUICK_ENTRY(void, \
aoqi@0 3701 jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \
aoqi@0 3702 ElementType *buf, jint mode)) \
aoqi@0 3703 JNIWrapper("Release" XSTR(Result) "ArrayElements"); \
aoqi@0 3704 DTRACE_PROBE4(hotspot_jni, Release##Result##ArrayElements__entry, env, array, buf, mode);\
aoqi@0 3705 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3706 int len = a->length(); \
aoqi@0 3707 if (len != 0) { /* Empty array: nothing to free or copy. */ \
aoqi@0 3708 if ((mode == 0) || (mode == JNI_COMMIT)) { \
aoqi@0 3709 memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \
aoqi@0 3710 } \
aoqi@0 3711 if ((mode == 0) || (mode == JNI_ABORT)) { \
aoqi@0 3712 FreeHeap(buf); \
aoqi@0 3713 } \
aoqi@0 3714 } \
aoqi@0 3715 DTRACE_PROBE(hotspot_jni, Release##Result##ArrayElements__return);\
aoqi@0 3716 JNI_END
aoqi@0 3717
aoqi@0 3718 DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool)
aoqi@0 3719 DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte)
aoqi@0 3720 DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short)
aoqi@0 3721 DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char)
aoqi@0 3722 DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int)
aoqi@0 3723 DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long)
aoqi@0 3724 DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float)
aoqi@0 3725 DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double)
aoqi@0 3726
aoqi@0 3727 #else /* USDT2 */
aoqi@0 3728
aoqi@0 3729 #define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag \
aoqi@0 3730 , EntryProbe, ReturnProbe);\
aoqi@0 3731 \
aoqi@0 3732 JNI_QUICK_ENTRY(void, \
aoqi@0 3733 jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \
aoqi@0 3734 ElementType *buf, jint mode)) \
aoqi@0 3735 JNIWrapper("Release" XSTR(Result) "ArrayElements"); \
aoqi@0 3736 EntryProbe; \
aoqi@0 3737 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3738 int len = a->length(); \
aoqi@0 3739 if (len != 0) { /* Empty array: nothing to free or copy. */ \
aoqi@0 3740 if ((mode == 0) || (mode == JNI_COMMIT)) { \
aoqi@0 3741 memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \
aoqi@0 3742 } \
aoqi@0 3743 if ((mode == 0) || (mode == JNI_ABORT)) { \
aoqi@0 3744 FreeHeap(buf); \
aoqi@0 3745 } \
aoqi@0 3746 } \
aoqi@0 3747 ReturnProbe; \
aoqi@0 3748 JNI_END
aoqi@0 3749
aoqi@0 3750 DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool
aoqi@0 3751 , HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode),
aoqi@0 3752 HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN())
aoqi@0 3753 DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte
aoqi@0 3754 , HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY(env, array, (char *) buf, mode),
aoqi@0 3755 HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN())
aoqi@0 3756 DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short
aoqi@0 3757 , HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode),
aoqi@0 3758 HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN())
aoqi@0 3759 DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char
aoqi@0 3760 , HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode),
aoqi@0 3761 HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN())
aoqi@0 3762 DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int
aoqi@0 3763 , HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY(env, array, (uint32_t *) buf, mode),
aoqi@0 3764 HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN())
aoqi@0 3765 DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long
aoqi@0 3766 , HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode),
aoqi@0 3767 HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN())
aoqi@0 3768 DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float
aoqi@0 3769 , HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY(env, array, (float *) buf, mode),
aoqi@0 3770 HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN())
aoqi@0 3771 DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double
aoqi@0 3772 , HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(env, array, (double *) buf, mode),
aoqi@0 3773 HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN())
aoqi@0 3774 #endif /* USDT2 */
aoqi@0 3775
aoqi@0 3776 #ifndef USDT2
aoqi@0 3777 #define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \
aoqi@0 3778 DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion);\
aoqi@0 3779 \
aoqi@0 3780 JNI_ENTRY(void, \
aoqi@0 3781 jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \
aoqi@0 3782 jsize len, ElementType *buf)) \
aoqi@0 3783 JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \
aoqi@0 3784 DTRACE_PROBE5(hotspot_jni, Get##Result##ArrayRegion__entry, env, array, start, len, buf);\
aoqi@0 3785 DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \
aoqi@0 3786 typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3787 if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \
aoqi@0 3788 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
aoqi@0 3789 } else { \
aoqi@0 3790 if (len > 0) { \
aoqi@0 3791 int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \
aoqi@0 3792 memcpy((u_char*) buf, \
aoqi@0 3793 (u_char*) src->Tag##_at_addr(start), \
aoqi@0 3794 len << sc); \
aoqi@0 3795 } \
aoqi@0 3796 } \
aoqi@0 3797 JNI_END
aoqi@0 3798
aoqi@0 3799 DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool)
aoqi@0 3800 DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte)
aoqi@0 3801 DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short)
aoqi@0 3802 DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char)
aoqi@0 3803 DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int)
aoqi@0 3804 DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long)
aoqi@0 3805 DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float)
aoqi@0 3806 DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double)
aoqi@0 3807
aoqi@0 3808 #else /* USDT2 */
aoqi@0 3809
aoqi@0 3810 #define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \
aoqi@0 3811 , EntryProbe, ReturnProbe); \
aoqi@0 3812 DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion \
aoqi@0 3813 , ReturnProbe); \
aoqi@0 3814 \
aoqi@0 3815 JNI_ENTRY(void, \
aoqi@0 3816 jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \
aoqi@0 3817 jsize len, ElementType *buf)) \
aoqi@0 3818 JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \
aoqi@0 3819 EntryProbe; \
aoqi@0 3820 DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \
aoqi@0 3821 typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3822 if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \
aoqi@0 3823 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
aoqi@0 3824 } else { \
aoqi@0 3825 if (len > 0) { \
aoqi@0 3826 int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \
aoqi@0 3827 memcpy((u_char*) buf, \
aoqi@0 3828 (u_char*) src->Tag##_at_addr(start), \
aoqi@0 3829 len << sc); \
aoqi@0 3830 } \
aoqi@0 3831 } \
aoqi@0 3832 JNI_END
aoqi@0 3833
aoqi@0 3834 DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool
aoqi@0 3835 , HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),
aoqi@0 3836 HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN());
aoqi@0 3837 DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte
aoqi@0 3838 , HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf),
aoqi@0 3839 HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN());
aoqi@0 3840 DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short
aoqi@0 3841 , HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),
aoqi@0 3842 HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN());
aoqi@0 3843 DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char
aoqi@0 3844 , HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t*) buf),
aoqi@0 3845 HOTSPOT_JNI_GETCHARARRAYREGION_RETURN());
aoqi@0 3846 DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int
aoqi@0 3847 , HOTSPOT_JNI_GETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t*) buf),
aoqi@0 3848 HOTSPOT_JNI_GETINTARRAYREGION_RETURN());
aoqi@0 3849 DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long
aoqi@0 3850 , HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),
aoqi@0 3851 HOTSPOT_JNI_GETLONGARRAYREGION_RETURN());
aoqi@0 3852 DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float
aoqi@0 3853 , HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf),
aoqi@0 3854 HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN());
aoqi@0 3855 DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double
aoqi@0 3856 , HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf),
aoqi@0 3857 HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN());
aoqi@0 3858 #endif /* USDT2 */
aoqi@0 3859
aoqi@0 3860 #ifndef USDT2
aoqi@0 3861 #define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \
aoqi@0 3862 DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion);\
aoqi@0 3863 \
aoqi@0 3864 JNI_ENTRY(void, \
aoqi@0 3865 jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \
aoqi@0 3866 jsize len, const ElementType *buf)) \
aoqi@0 3867 JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \
aoqi@0 3868 DTRACE_PROBE5(hotspot_jni, Set##Result##ArrayRegion__entry, env, array, start, len, buf);\
aoqi@0 3869 DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \
aoqi@0 3870 typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3871 if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \
aoqi@0 3872 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
aoqi@0 3873 } else { \
aoqi@0 3874 if (len > 0) { \
aoqi@0 3875 int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \
aoqi@0 3876 memcpy((u_char*) dst->Tag##_at_addr(start), \
aoqi@0 3877 (u_char*) buf, \
aoqi@0 3878 len << sc); \
aoqi@0 3879 } \
aoqi@0 3880 } \
aoqi@0 3881 JNI_END
aoqi@0 3882
aoqi@0 3883 DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool)
aoqi@0 3884 DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte)
aoqi@0 3885 DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short)
aoqi@0 3886 DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char)
aoqi@0 3887 DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int)
aoqi@0 3888 DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long)
aoqi@0 3889 DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float)
aoqi@0 3890 DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double)
aoqi@0 3891
aoqi@0 3892 #else /* USDT2 */
aoqi@0 3893
aoqi@0 3894 #define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \
aoqi@0 3895 , EntryProbe, ReturnProbe); \
aoqi@0 3896 DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion \
aoqi@0 3897 ,ReturnProbe); \
aoqi@0 3898 \
aoqi@0 3899 JNI_ENTRY(void, \
aoqi@0 3900 jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \
aoqi@0 3901 jsize len, const ElementType *buf)) \
aoqi@0 3902 JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \
aoqi@0 3903 EntryProbe; \
aoqi@0 3904 DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \
aoqi@0 3905 typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \
aoqi@0 3906 if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \
aoqi@0 3907 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
aoqi@0 3908 } else { \
aoqi@0 3909 if (len > 0) { \
aoqi@0 3910 int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \
aoqi@0 3911 memcpy((u_char*) dst->Tag##_at_addr(start), \
aoqi@0 3912 (u_char*) buf, \
aoqi@0 3913 len << sc); \
aoqi@0 3914 } \
aoqi@0 3915 } \
aoqi@0 3916 JNI_END
aoqi@0 3917
aoqi@0 3918 DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool
aoqi@0 3919 , HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *)buf),
aoqi@0 3920 HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN())
aoqi@0 3921 DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte
aoqi@0 3922 , HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf),
aoqi@0 3923 HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN())
aoqi@0 3924 DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short
aoqi@0 3925 , HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),
aoqi@0 3926 HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN())
aoqi@0 3927 DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char
aoqi@0 3928 , HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),
aoqi@0 3929 HOTSPOT_JNI_SETCHARARRAYREGION_RETURN())
aoqi@0 3930 DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int
aoqi@0 3931 , HOTSPOT_JNI_SETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t *) buf),
aoqi@0 3932 HOTSPOT_JNI_SETINTARRAYREGION_RETURN())
aoqi@0 3933 DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long
aoqi@0 3934 , HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),
aoqi@0 3935 HOTSPOT_JNI_SETLONGARRAYREGION_RETURN())
aoqi@0 3936 DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float
aoqi@0 3937 , HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf),
aoqi@0 3938 HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN())
aoqi@0 3939 DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double
aoqi@0 3940 , HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf),
aoqi@0 3941 HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN())
aoqi@0 3942 #endif /* USDT2 */
aoqi@0 3943
aoqi@0 3944
aoqi@0 3945 //
aoqi@0 3946 // Interception of natives
aoqi@0 3947 //
aoqi@0 3948
aoqi@0 3949 // The RegisterNatives call being attempted tried to register with a method that
aoqi@0 3950 // is not native. Ask JVM TI what prefixes have been specified. Then check
aoqi@0 3951 // to see if the native method is now wrapped with the prefixes. See the
aoqi@0 3952 // SetNativeMethodPrefix(es) functions in the JVM TI Spec for details.
aoqi@0 3953 static Method* find_prefixed_native(KlassHandle k,
aoqi@0 3954 Symbol* name, Symbol* signature, TRAPS) {
aoqi@0 3955 #if INCLUDE_JVMTI
aoqi@0 3956 ResourceMark rm(THREAD);
aoqi@0 3957 Method* method;
aoqi@0 3958 int name_len = name->utf8_length();
aoqi@0 3959 char* name_str = name->as_utf8();
aoqi@0 3960 int prefix_count;
aoqi@0 3961 char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
aoqi@0 3962 for (int i = 0; i < prefix_count; i++) {
aoqi@0 3963 char* prefix = prefixes[i];
aoqi@0 3964 int prefix_len = (int)strlen(prefix);
aoqi@0 3965
aoqi@0 3966 // try adding this prefix to the method name and see if it matches another method name
aoqi@0 3967 int trial_len = name_len + prefix_len;
aoqi@0 3968 char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1);
aoqi@0 3969 strcpy(trial_name_str, prefix);
aoqi@0 3970 strcat(trial_name_str, name_str);
aoqi@0 3971 TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len);
aoqi@0 3972 if (trial_name == NULL) {
aoqi@0 3973 continue; // no such symbol, so this prefix wasn't used, try the next prefix
aoqi@0 3974 }
aoqi@0 3975 method = k()->lookup_method(trial_name, signature);
aoqi@0 3976 if (method == NULL) {
aoqi@0 3977 continue; // signature doesn't match, try the next prefix
aoqi@0 3978 }
aoqi@0 3979 if (method->is_native()) {
aoqi@0 3980 method->set_is_prefixed_native();
aoqi@0 3981 return method; // wahoo, we found a prefixed version of the method, return it
aoqi@0 3982 }
aoqi@0 3983 // found as non-native, so prefix is good, add it, probably just need more prefixes
aoqi@0 3984 name_len = trial_len;
aoqi@0 3985 name_str = trial_name_str;
aoqi@0 3986 }
aoqi@0 3987 #endif // INCLUDE_JVMTI
aoqi@0 3988 return NULL; // not found
aoqi@0 3989 }
aoqi@0 3990
aoqi@0 3991 static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) {
aoqi@0 3992 Method* method = k()->lookup_method(name, signature);
aoqi@0 3993 if (method == NULL) {
aoqi@0 3994 ResourceMark rm;
aoqi@0 3995 stringStream st;
aoqi@0 3996 st.print("Method %s name or signature does not match",
aoqi@0 3997 Method::name_and_sig_as_C_string(k(), name, signature));
aoqi@0 3998 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
aoqi@0 3999 }
aoqi@0 4000 if (!method->is_native()) {
aoqi@0 4001 // trying to register to a non-native method, see if a JVM TI agent has added prefix(es)
aoqi@0 4002 method = find_prefixed_native(k, name, signature, THREAD);
aoqi@0 4003 if (method == NULL) {
aoqi@0 4004 ResourceMark rm;
aoqi@0 4005 stringStream st;
aoqi@0 4006 st.print("Method %s is not declared as native",
aoqi@0 4007 Method::name_and_sig_as_C_string(k(), name, signature));
aoqi@0 4008 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
aoqi@0 4009 }
aoqi@0 4010 }
aoqi@0 4011
aoqi@0 4012 if (entry != NULL) {
aoqi@0 4013 method->set_native_function(entry,
aoqi@0 4014 Method::native_bind_event_is_interesting);
aoqi@0 4015 } else {
aoqi@0 4016 method->clear_native_function();
aoqi@0 4017 }
aoqi@0 4018 if (PrintJNIResolving) {
aoqi@0 4019 ResourceMark rm(THREAD);
aoqi@0 4020 tty->print_cr("[Registering JNI native method %s.%s]",
aoqi@0 4021 method->method_holder()->external_name(),
aoqi@0 4022 method->name()->as_C_string());
aoqi@0 4023 }
aoqi@0 4024 return true;
aoqi@0 4025 }
aoqi@0 4026
aoqi@0 4027 #ifndef USDT2
aoqi@0 4028 DT_RETURN_MARK_DECL(RegisterNatives, jint);
aoqi@0 4029 #else /* USDT2 */
aoqi@0 4030 DT_RETURN_MARK_DECL(RegisterNatives, jint
aoqi@0 4031 , HOTSPOT_JNI_REGISTERNATIVES_RETURN(_ret_ref));
aoqi@0 4032 #endif /* USDT2 */
aoqi@0 4033
aoqi@0 4034 JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,
aoqi@0 4035 const JNINativeMethod *methods,
aoqi@0 4036 jint nMethods))
aoqi@0 4037 JNIWrapper("RegisterNatives");
aoqi@0 4038 #ifndef USDT2
aoqi@0 4039 DTRACE_PROBE4(hotspot_jni, RegisterNatives__entry, env, clazz, methods, nMethods);
aoqi@0 4040 #else /* USDT2 */
aoqi@0 4041 HOTSPOT_JNI_REGISTERNATIVES_ENTRY(
aoqi@0 4042 env, clazz, (void *) methods, nMethods);
aoqi@0 4043 #endif /* USDT2 */
aoqi@0 4044 jint ret = 0;
aoqi@0 4045 DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret);
aoqi@0 4046
aoqi@0 4047 KlassHandle h_k(thread, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
aoqi@0 4048
aoqi@0 4049 for (int index = 0; index < nMethods; index++) {
aoqi@0 4050 const char* meth_name = methods[index].name;
aoqi@0 4051 const char* meth_sig = methods[index].signature;
aoqi@0 4052 int meth_name_len = (int)strlen(meth_name);
aoqi@0 4053
aoqi@0 4054 // The class should have been loaded (we have an instance of the class
aoqi@0 4055 // passed in) so the method and signature should already be in the symbol
aoqi@0 4056 // table. If they're not there, the method doesn't exist.
aoqi@0 4057 TempNewSymbol name = SymbolTable::probe(meth_name, meth_name_len);
aoqi@0 4058 TempNewSymbol signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));
aoqi@0 4059
aoqi@0 4060 if (name == NULL || signature == NULL) {
aoqi@0 4061 ResourceMark rm;
aoqi@0 4062 stringStream st;
aoqi@0 4063 st.print("Method %s.%s%s not found", h_k()->external_name(), meth_name, meth_sig);
aoqi@0 4064 // Must return negative value on failure
aoqi@0 4065 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1);
aoqi@0 4066 }
aoqi@0 4067
aoqi@0 4068 bool res = register_native(h_k, name, signature,
aoqi@0 4069 (address) methods[index].fnPtr, THREAD);
aoqi@0 4070 if (!res) {
aoqi@0 4071 ret = -1;
aoqi@0 4072 break;
aoqi@0 4073 }
aoqi@0 4074 }
aoqi@0 4075 return ret;
aoqi@0 4076 JNI_END
aoqi@0 4077
aoqi@0 4078
aoqi@0 4079 JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz))
aoqi@0 4080 JNIWrapper("UnregisterNatives");
aoqi@0 4081 #ifndef USDT2
aoqi@0 4082 DTRACE_PROBE2(hotspot_jni, UnregisterNatives__entry, env, clazz);
aoqi@0 4083 #else /* USDT2 */
aoqi@0 4084 HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(
aoqi@0 4085 env, clazz);
aoqi@0 4086 #endif /* USDT2 */
aoqi@0 4087 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
aoqi@0 4088 //%note jni_2
aoqi@0 4089 if (k->oop_is_instance()) {
aoqi@0 4090 for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) {
aoqi@0 4091 Method* m = InstanceKlass::cast(k)->methods()->at(index);
aoqi@0 4092 if (m->is_native()) {
aoqi@0 4093 m->clear_native_function();
aoqi@0 4094 m->set_signature_handler(NULL);
aoqi@0 4095 }
aoqi@0 4096 }
aoqi@0 4097 }
aoqi@0 4098 #ifndef USDT2
aoqi@0 4099 DTRACE_PROBE1(hotspot_jni, UnregisterNatives__return, 0);
aoqi@0 4100 #else /* USDT2 */
aoqi@0 4101 HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(
aoqi@0 4102 0);
aoqi@0 4103 #endif /* USDT2 */
aoqi@0 4104 return 0;
aoqi@0 4105 JNI_END
aoqi@0 4106
aoqi@0 4107 //
aoqi@0 4108 // Monitor functions
aoqi@0 4109 //
aoqi@0 4110
aoqi@0 4111 #ifndef USDT2
aoqi@0 4112 DT_RETURN_MARK_DECL(MonitorEnter, jint);
aoqi@0 4113 #else /* USDT2 */
aoqi@0 4114 DT_RETURN_MARK_DECL(MonitorEnter, jint
aoqi@0 4115 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
aoqi@0 4116 #endif /* USDT2 */
aoqi@0 4117
aoqi@0 4118 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
aoqi@0 4119 #ifndef USDT2
aoqi@0 4120 DTRACE_PROBE2(hotspot_jni, MonitorEnter__entry, env, jobj);
aoqi@0 4121 #else /* USDT2 */
aoqi@0 4122 HOTSPOT_JNI_MONITORENTER_ENTRY(
aoqi@0 4123 env, jobj);
aoqi@0 4124 #endif /* USDT2 */
aoqi@0 4125 jint ret = JNI_ERR;
aoqi@0 4126 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
aoqi@0 4127
aoqi@0 4128 // If the object is null, we can't do anything with it
aoqi@0 4129 if (jobj == NULL) {
aoqi@0 4130 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
aoqi@0 4131 }
aoqi@0 4132
aoqi@0 4133 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
aoqi@0 4134 ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
aoqi@0 4135 ret = JNI_OK;
aoqi@0 4136 return ret;
aoqi@0 4137 JNI_END
aoqi@0 4138
aoqi@0 4139 #ifndef USDT2
aoqi@0 4140 DT_RETURN_MARK_DECL(MonitorExit, jint);
aoqi@0 4141 #else /* USDT2 */
aoqi@0 4142 DT_RETURN_MARK_DECL(MonitorExit, jint
aoqi@0 4143 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
aoqi@0 4144 #endif /* USDT2 */
aoqi@0 4145
aoqi@0 4146 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
aoqi@0 4147 #ifndef USDT2
aoqi@0 4148 DTRACE_PROBE2(hotspot_jni, MonitorExit__entry, env, jobj);
aoqi@0 4149 #else /* USDT2 */
aoqi@0 4150 HOTSPOT_JNI_MONITOREXIT_ENTRY(
aoqi@0 4151 env, jobj);
aoqi@0 4152 #endif /* USDT2 */
aoqi@0 4153 jint ret = JNI_ERR;
aoqi@0 4154 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
aoqi@0 4155
aoqi@0 4156 // Don't do anything with a null object
aoqi@0 4157 if (jobj == NULL) {
aoqi@0 4158 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
aoqi@0 4159 }
aoqi@0 4160
aoqi@0 4161 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
aoqi@0 4162 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
aoqi@0 4163
aoqi@0 4164 ret = JNI_OK;
aoqi@0 4165 return ret;
aoqi@0 4166 JNI_END
aoqi@0 4167
aoqi@0 4168 //
aoqi@0 4169 // Extensions
aoqi@0 4170 //
aoqi@0 4171
aoqi@0 4172 #ifndef USDT2
aoqi@0 4173 DT_VOID_RETURN_MARK_DECL(GetStringRegion);
aoqi@0 4174 #else /* USDT2 */
aoqi@0 4175 DT_VOID_RETURN_MARK_DECL(GetStringRegion
aoqi@0 4176 , HOTSPOT_JNI_GETSTRINGREGION_RETURN());
aoqi@0 4177 #endif /* USDT2 */
aoqi@0 4178
aoqi@0 4179 JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf))
aoqi@0 4180 JNIWrapper("GetStringRegion");
aoqi@0 4181 #ifndef USDT2
aoqi@0 4182 DTRACE_PROBE5(hotspot_jni, GetStringRegion__entry, env, string, start, len, buf);
aoqi@0 4183 #else /* USDT2 */
aoqi@0 4184 HOTSPOT_JNI_GETSTRINGREGION_ENTRY(
aoqi@0 4185 env, string, start, len, buf);
aoqi@0 4186 #endif /* USDT2 */
aoqi@0 4187 DT_VOID_RETURN_MARK(GetStringRegion);
aoqi@0 4188 oop s = JNIHandles::resolve_non_null(string);
aoqi@0 4189 int s_len = java_lang_String::length(s);
aoqi@0 4190 if (start < 0 || len < 0 || start + len > s_len) {
aoqi@0 4191 THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
aoqi@0 4192 } else {
aoqi@0 4193 if (len > 0) {
aoqi@0 4194 int s_offset = java_lang_String::offset(s);
aoqi@0 4195 typeArrayOop s_value = java_lang_String::value(s);
aoqi@0 4196 memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len);
aoqi@0 4197 }
aoqi@0 4198 }
aoqi@0 4199 JNI_END
aoqi@0 4200
aoqi@0 4201 #ifndef USDT2
aoqi@0 4202 DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion);
aoqi@0 4203 #else /* USDT2 */
aoqi@0 4204 DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion
aoqi@0 4205 , HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN());
aoqi@0 4206 #endif /* USDT2 */
aoqi@0 4207
aoqi@0 4208 JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf))
aoqi@0 4209 JNIWrapper("GetStringUTFRegion");
aoqi@0 4210 #ifndef USDT2
aoqi@0 4211 DTRACE_PROBE5(hotspot_jni, GetStringUTFRegion__entry, env, string, start, len, buf);
aoqi@0 4212 #else /* USDT2 */
aoqi@0 4213 HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(
aoqi@0 4214 env, string, start, len, buf);
aoqi@0 4215 #endif /* USDT2 */
aoqi@0 4216 DT_VOID_RETURN_MARK(GetStringUTFRegion);
aoqi@0 4217 oop s = JNIHandles::resolve_non_null(string);
aoqi@0 4218 int s_len = java_lang_String::length(s);
aoqi@0 4219 if (start < 0 || len < 0 || start + len > s_len) {
aoqi@0 4220 THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
aoqi@0 4221 } else {
aoqi@0 4222 //%note jni_7
aoqi@0 4223 if (len > 0) {
aoqi@0 4224 ResourceMark rm(THREAD);
aoqi@0 4225 char *utf_region = java_lang_String::as_utf8_string(s, start, len);
aoqi@0 4226 int utf_len = (int)strlen(utf_region);
aoqi@0 4227 memcpy(buf, utf_region, utf_len);
aoqi@0 4228 buf[utf_len] = 0;
aoqi@0 4229 } else {
aoqi@0 4230 // JDK null-terminates the buffer even in len is zero
aoqi@0 4231 if (buf != NULL) {
aoqi@0 4232 buf[0] = 0;
aoqi@0 4233 }
aoqi@0 4234 }
aoqi@0 4235 }
aoqi@0 4236 JNI_END
aoqi@0 4237
aoqi@0 4238
aoqi@0 4239 JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy))
aoqi@0 4240 JNIWrapper("GetPrimitiveArrayCritical");
aoqi@0 4241 #ifndef USDT2
aoqi@0 4242 DTRACE_PROBE3(hotspot_jni, GetPrimitiveArrayCritical__entry, env, array, isCopy);
aoqi@0 4243 #else /* USDT2 */
aoqi@0 4244 HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(
aoqi@0 4245 env, array, (uintptr_t *) isCopy);
aoqi@0 4246 #endif /* USDT2 */
aoqi@0 4247 GC_locker::lock_critical(thread);
aoqi@0 4248 if (isCopy != NULL) {
aoqi@0 4249 *isCopy = JNI_FALSE;
aoqi@0 4250 }
aoqi@0 4251 oop a = JNIHandles::resolve_non_null(array);
aoqi@0 4252 assert(a->is_array(), "just checking");
aoqi@0 4253 BasicType type;
aoqi@0 4254 if (a->is_objArray()) {
aoqi@0 4255 type = T_OBJECT;
aoqi@0 4256 } else {
aoqi@0 4257 type = TypeArrayKlass::cast(a->klass())->element_type();
aoqi@0 4258 }
aoqi@0 4259 void* ret = arrayOop(a)->base(type);
aoqi@0 4260 #ifndef USDT2
aoqi@0 4261 DTRACE_PROBE1(hotspot_jni, GetPrimitiveArrayCritical__return, ret);
aoqi@0 4262 #else /* USDT2 */
aoqi@0 4263 HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN(
aoqi@0 4264 ret);
aoqi@0 4265 #endif /* USDT2 */
aoqi@0 4266 return ret;
aoqi@0 4267 JNI_END
aoqi@0 4268
aoqi@0 4269
aoqi@0 4270 JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode))
aoqi@0 4271 JNIWrapper("ReleasePrimitiveArrayCritical");
aoqi@0 4272 #ifndef USDT2
aoqi@0 4273 DTRACE_PROBE4(hotspot_jni, ReleasePrimitiveArrayCritical__entry, env, array, carray, mode);
aoqi@0 4274 #else /* USDT2 */
aoqi@0 4275 HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(
aoqi@0 4276 env, array, carray, mode);
aoqi@0 4277 #endif /* USDT2 */
aoqi@0 4278 // The array, carray and mode arguments are ignored
aoqi@0 4279 GC_locker::unlock_critical(thread);
aoqi@0 4280 #ifndef USDT2
aoqi@0 4281 DTRACE_PROBE(hotspot_jni, ReleasePrimitiveArrayCritical__return);
aoqi@0 4282 #else /* USDT2 */
aoqi@0 4283 HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN(
aoqi@0 4284 );
aoqi@0 4285 #endif /* USDT2 */
aoqi@0 4286 JNI_END
aoqi@0 4287
aoqi@0 4288
aoqi@0 4289 JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy))
aoqi@0 4290 JNIWrapper("GetStringCritical");
aoqi@0 4291 #ifndef USDT2
aoqi@0 4292 DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy);
aoqi@0 4293 #else /* USDT2 */
aoqi@0 4294 HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(
aoqi@0 4295 env, string, (uintptr_t *) isCopy);
aoqi@0 4296 #endif /* USDT2 */
aoqi@0 4297 GC_locker::lock_critical(thread);
aoqi@0 4298 if (isCopy != NULL) {
aoqi@0 4299 *isCopy = JNI_FALSE;
aoqi@0 4300 }
aoqi@0 4301 oop s = JNIHandles::resolve_non_null(string);
aoqi@0 4302 int s_len = java_lang_String::length(s);
aoqi@0 4303 typeArrayOop s_value = java_lang_String::value(s);
aoqi@0 4304 int s_offset = java_lang_String::offset(s);
aoqi@0 4305 const jchar* ret;
aoqi@0 4306 if (s_len > 0) {
aoqi@0 4307 ret = s_value->char_at_addr(s_offset);
aoqi@0 4308 } else {
aoqi@0 4309 ret = (jchar*) s_value->base(T_CHAR);
aoqi@0 4310 }
aoqi@0 4311 #ifndef USDT2
aoqi@0 4312 DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret);
aoqi@0 4313 #else /* USDT2 */
aoqi@0 4314 HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN(
aoqi@0 4315 (uint16_t *) ret);
aoqi@0 4316 #endif /* USDT2 */
aoqi@0 4317 return ret;
aoqi@0 4318 JNI_END
aoqi@0 4319
aoqi@0 4320
aoqi@0 4321 JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars))
aoqi@0 4322 JNIWrapper("ReleaseStringCritical");
aoqi@0 4323 #ifndef USDT2
aoqi@0 4324 DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars);
aoqi@0 4325 #else /* USDT2 */
aoqi@0 4326 HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(
aoqi@0 4327 env, str, (uint16_t *) chars);
aoqi@0 4328 #endif /* USDT2 */
aoqi@0 4329 // The str and chars arguments are ignored
aoqi@0 4330 GC_locker::unlock_critical(thread);
aoqi@0 4331 #ifndef USDT2
aoqi@0 4332 DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return);
aoqi@0 4333 #else /* USDT2 */
aoqi@0 4334 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN(
aoqi@0 4335 );
aoqi@0 4336 #endif /* USDT2 */
aoqi@0 4337 JNI_END
aoqi@0 4338
aoqi@0 4339
aoqi@0 4340 JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
aoqi@0 4341 JNIWrapper("jni_NewWeakGlobalRef");
aoqi@0 4342 #ifndef USDT2
aoqi@0 4343 DTRACE_PROBE2(hotspot_jni, NewWeakGlobalRef__entry, env, ref);
aoqi@0 4344 #else /* USDT2 */
aoqi@0 4345 HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(
aoqi@0 4346 env, ref);
aoqi@0 4347 #endif /* USDT2 */
aoqi@0 4348 Handle ref_handle(thread, JNIHandles::resolve(ref));
aoqi@0 4349 jweak ret = JNIHandles::make_weak_global(ref_handle);
aoqi@0 4350 #ifndef USDT2
aoqi@0 4351 DTRACE_PROBE1(hotspot_jni, NewWeakGlobalRef__return, ret);
aoqi@0 4352 #else /* USDT2 */
aoqi@0 4353 HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(
aoqi@0 4354 ret);
aoqi@0 4355 #endif /* USDT2 */
aoqi@0 4356 return ret;
aoqi@0 4357 JNI_END
aoqi@0 4358
aoqi@0 4359 // Must be JNI_ENTRY (with HandleMark)
aoqi@0 4360 JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
aoqi@0 4361 JNIWrapper("jni_DeleteWeakGlobalRef");
aoqi@0 4362 #ifndef USDT2
aoqi@0 4363 DTRACE_PROBE2(hotspot_jni, DeleteWeakGlobalRef__entry, env, ref);
aoqi@0 4364 #else /* USDT2 */
aoqi@0 4365 HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(
aoqi@0 4366 env, ref);
aoqi@0 4367 #endif /* USDT2 */
aoqi@0 4368 JNIHandles::destroy_weak_global(ref);
aoqi@0 4369 #ifndef USDT2
aoqi@0 4370 DTRACE_PROBE(hotspot_jni, DeleteWeakGlobalRef__return);
aoqi@0 4371 #else /* USDT2 */
aoqi@0 4372 HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN(
aoqi@0 4373 );
aoqi@0 4374 #endif /* USDT2 */
aoqi@0 4375 JNI_END
aoqi@0 4376
aoqi@0 4377
aoqi@0 4378 JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env))
aoqi@0 4379 JNIWrapper("jni_ExceptionCheck");
aoqi@0 4380 #ifndef USDT2
aoqi@0 4381 DTRACE_PROBE1(hotspot_jni, ExceptionCheck__entry, env);
aoqi@0 4382 #else /* USDT2 */
aoqi@0 4383 HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(
aoqi@0 4384 env);
aoqi@0 4385 #endif /* USDT2 */
aoqi@0 4386 jni_check_async_exceptions(thread);
aoqi@0 4387 jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;
aoqi@0 4388 #ifndef USDT2
aoqi@0 4389 DTRACE_PROBE1(hotspot_jni, ExceptionCheck__return, ret);
aoqi@0 4390 #else /* USDT2 */
aoqi@0 4391 HOTSPOT_JNI_EXCEPTIONCHECK_RETURN(
aoqi@0 4392 ret);
aoqi@0 4393 #endif /* USDT2 */
aoqi@0 4394 return ret;
aoqi@0 4395 JNI_END
aoqi@0 4396
aoqi@0 4397
aoqi@0 4398 // Initialization state for three routines below relating to
aoqi@0 4399 // java.nio.DirectBuffers
aoqi@0 4400 static jint directBufferSupportInitializeStarted = 0;
aoqi@0 4401 static volatile jint directBufferSupportInitializeEnded = 0;
aoqi@0 4402 static volatile jint directBufferSupportInitializeFailed = 0;
aoqi@0 4403 static jclass bufferClass = NULL;
aoqi@0 4404 static jclass directBufferClass = NULL;
aoqi@0 4405 static jclass directByteBufferClass = NULL;
aoqi@0 4406 static jmethodID directByteBufferConstructor = NULL;
aoqi@0 4407 static jfieldID directBufferAddressField = NULL;
aoqi@0 4408 static jfieldID bufferCapacityField = NULL;
aoqi@0 4409
aoqi@0 4410 static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) {
aoqi@0 4411 Handle loader; // null (bootstrap) loader
aoqi@0 4412 Handle protection_domain; // null protection domain
aoqi@0 4413
aoqi@0 4414 TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);
aoqi@0 4415 jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
aoqi@0 4416
aoqi@0 4417 if (TraceClassResolution && result != NULL) {
aoqi@0 4418 trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
aoqi@0 4419 }
aoqi@0 4420 return result;
aoqi@0 4421 }
aoqi@0 4422
aoqi@0 4423 // These lookups are done with the NULL (bootstrap) ClassLoader to
aoqi@0 4424 // circumvent any security checks that would be done by jni_FindClass.
aoqi@0 4425 JNI_ENTRY(bool, lookupDirectBufferClasses(JNIEnv* env))
aoqi@0 4426 {
aoqi@0 4427 if ((bufferClass = lookupOne(env, "java/nio/Buffer", thread)) == NULL) { return false; }
aoqi@0 4428 if ((directBufferClass = lookupOne(env, "sun/nio/ch/DirectBuffer", thread)) == NULL) { return false; }
aoqi@0 4429 if ((directByteBufferClass = lookupOne(env, "java/nio/DirectByteBuffer", thread)) == NULL) { return false; }
aoqi@0 4430 return true;
aoqi@0 4431 }
aoqi@0 4432 JNI_END
aoqi@0 4433
aoqi@0 4434
aoqi@0 4435 static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) {
aoqi@0 4436 if (directBufferSupportInitializeFailed) {
aoqi@0 4437 return false;
aoqi@0 4438 }
aoqi@0 4439
aoqi@0 4440 if (Atomic::cmpxchg(1, &directBufferSupportInitializeStarted, 0) == 0) {
aoqi@0 4441 if (!lookupDirectBufferClasses(env)) {
aoqi@0 4442 directBufferSupportInitializeFailed = 1;
aoqi@0 4443 return false;
aoqi@0 4444 }
aoqi@0 4445
aoqi@0 4446 // Make global references for these
aoqi@0 4447 bufferClass = (jclass) env->NewGlobalRef(bufferClass);
aoqi@0 4448 directBufferClass = (jclass) env->NewGlobalRef(directBufferClass);
aoqi@0 4449 directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass);
aoqi@0 4450
aoqi@0 4451 // Get needed field and method IDs
aoqi@0 4452 directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>", "(JI)V");
aoqi@0 4453 if (env->ExceptionCheck()) {
aoqi@0 4454 env->ExceptionClear();
aoqi@0 4455 directBufferSupportInitializeFailed = 1;
aoqi@0 4456 return false;
aoqi@0 4457 }
aoqi@0 4458 directBufferAddressField = env->GetFieldID(bufferClass, "address", "J");
aoqi@0 4459 if (env->ExceptionCheck()) {
aoqi@0 4460 env->ExceptionClear();
aoqi@0 4461 directBufferSupportInitializeFailed = 1;
aoqi@0 4462 return false;
aoqi@0 4463 }
aoqi@0 4464 bufferCapacityField = env->GetFieldID(bufferClass, "capacity", "I");
aoqi@0 4465 if (env->ExceptionCheck()) {
aoqi@0 4466 env->ExceptionClear();
aoqi@0 4467 directBufferSupportInitializeFailed = 1;
aoqi@0 4468 return false;
aoqi@0 4469 }
aoqi@0 4470
aoqi@0 4471 if ((directByteBufferConstructor == NULL) ||
aoqi@0 4472 (directBufferAddressField == NULL) ||
aoqi@0 4473 (bufferCapacityField == NULL)) {
aoqi@0 4474 directBufferSupportInitializeFailed = 1;
aoqi@0 4475 return false;
aoqi@0 4476 }
aoqi@0 4477
aoqi@0 4478 directBufferSupportInitializeEnded = 1;
aoqi@0 4479 } else {
aoqi@0 4480 while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) {
aoqi@0 4481 // Set state as yield_all can call os:sleep. On Solaris, yield_all calls
aoqi@0 4482 // os::sleep which requires the VM state transition. On other platforms, it
aoqi@0 4483 // is not necessary. The following call to change the VM state is purposely
aoqi@0 4484 // put inside the loop to avoid potential deadlock when multiple threads
aoqi@0 4485 // try to call this method. See 6791815 for more details.
aoqi@0 4486 ThreadInVMfromNative tivn(thread);
aoqi@0 4487 os::yield_all();
aoqi@0 4488 }
aoqi@0 4489 }
aoqi@0 4490
aoqi@0 4491 return !directBufferSupportInitializeFailed;
aoqi@0 4492 }
aoqi@0 4493
aoqi@0 4494 extern "C" jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, jlong capacity)
aoqi@0 4495 {
aoqi@0 4496 // thread_from_jni_environment() will block if VM is gone.
aoqi@0 4497 JavaThread* thread = JavaThread::thread_from_jni_environment(env);
aoqi@0 4498
aoqi@0 4499 JNIWrapper("jni_NewDirectByteBuffer");
aoqi@0 4500 #ifndef USDT2
aoqi@0 4501 DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity);
aoqi@0 4502 #else /* USDT2 */
aoqi@0 4503 HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY(
aoqi@0 4504 env, address, capacity);
aoqi@0 4505 #endif /* USDT2 */
aoqi@0 4506
aoqi@0 4507 if (!directBufferSupportInitializeEnded) {
aoqi@0 4508 if (!initializeDirectBufferSupport(env, thread)) {
aoqi@0 4509 #ifndef USDT2
aoqi@0 4510 DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL);
aoqi@0 4511 #else /* USDT2 */
aoqi@0 4512 HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(
aoqi@0 4513 NULL);
aoqi@0 4514 #endif /* USDT2 */
aoqi@0 4515 return NULL;
aoqi@0 4516 }
aoqi@0 4517 }
aoqi@0 4518
aoqi@0 4519 // Being paranoid about accidental sign extension on address
aoqi@0 4520 jlong addr = (jlong) ((uintptr_t) address);
aoqi@0 4521 // NOTE that package-private DirectByteBuffer constructor currently
aoqi@0 4522 // takes int capacity
aoqi@0 4523 jint cap = (jint) capacity;
aoqi@0 4524 jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap);
aoqi@0 4525 #ifndef USDT2
aoqi@0 4526 DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, ret);
aoqi@0 4527 #else /* USDT2 */
aoqi@0 4528 HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(
aoqi@0 4529 ret);
aoqi@0 4530 #endif /* USDT2 */
aoqi@0 4531 return ret;
aoqi@0 4532 }
aoqi@0 4533
aoqi@0 4534 #ifndef USDT2
aoqi@0 4535 DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*);
aoqi@0 4536 #else /* USDT2 */
aoqi@0 4537 DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*
aoqi@0 4538 , HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref));
aoqi@0 4539 #endif /* USDT2 */
aoqi@0 4540
aoqi@0 4541 extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
aoqi@0 4542 {
aoqi@0 4543 // thread_from_jni_environment() will block if VM is gone.
aoqi@0 4544 JavaThread* thread = JavaThread::thread_from_jni_environment(env);
aoqi@0 4545
aoqi@0 4546 JNIWrapper("jni_GetDirectBufferAddress");
aoqi@0 4547 #ifndef USDT2
aoqi@0 4548 DTRACE_PROBE2(hotspot_jni, GetDirectBufferAddress__entry, env, buf);
aoqi@0 4549 #else /* USDT2 */
aoqi@0 4550 HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY(
aoqi@0 4551 env, buf);
aoqi@0 4552 #endif /* USDT2 */
aoqi@0 4553 void* ret = NULL;
aoqi@0 4554 DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret);
aoqi@0 4555
aoqi@0 4556 if (!directBufferSupportInitializeEnded) {
aoqi@0 4557 if (!initializeDirectBufferSupport(env, thread)) {
aoqi@0 4558 return 0;
aoqi@0 4559 }
aoqi@0 4560 }
aoqi@0 4561
aoqi@0 4562 if ((buf != NULL) && (!env->IsInstanceOf(buf, directBufferClass))) {
aoqi@0 4563 return 0;
aoqi@0 4564 }
aoqi@0 4565
aoqi@0 4566 ret = (void*)(intptr_t)env->GetLongField(buf, directBufferAddressField);
aoqi@0 4567 return ret;
aoqi@0 4568 }
aoqi@0 4569
aoqi@0 4570 #ifndef USDT2
aoqi@0 4571 DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong);
aoqi@0 4572 #else /* USDT2 */
aoqi@0 4573 DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong
aoqi@0 4574 , HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(_ret_ref));
aoqi@0 4575 #endif /* USDT2 */
aoqi@0 4576
aoqi@0 4577 extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf)
aoqi@0 4578 {
aoqi@0 4579 // thread_from_jni_environment() will block if VM is gone.
aoqi@0 4580 JavaThread* thread = JavaThread::thread_from_jni_environment(env);
aoqi@0 4581
aoqi@0 4582 JNIWrapper("jni_GetDirectBufferCapacity");
aoqi@0 4583 #ifndef USDT2
aoqi@0 4584 DTRACE_PROBE2(hotspot_jni, GetDirectBufferCapacity__entry, env, buf);
aoqi@0 4585 #else /* USDT2 */
aoqi@0 4586 HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY(
aoqi@0 4587 env, buf);
aoqi@0 4588 #endif /* USDT2 */
aoqi@0 4589 jlong ret = -1;
aoqi@0 4590 DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret);
aoqi@0 4591
aoqi@0 4592 if (!directBufferSupportInitializeEnded) {
aoqi@0 4593 if (!initializeDirectBufferSupport(env, thread)) {
aoqi@0 4594 ret = 0;
aoqi@0 4595 return ret;
aoqi@0 4596 }
aoqi@0 4597 }
aoqi@0 4598
aoqi@0 4599 if (buf == NULL) {
aoqi@0 4600 return -1;
aoqi@0 4601 }
aoqi@0 4602
aoqi@0 4603 if (!env->IsInstanceOf(buf, directBufferClass)) {
aoqi@0 4604 return -1;
aoqi@0 4605 }
aoqi@0 4606
aoqi@0 4607 // NOTE that capacity is currently an int in the implementation
aoqi@0 4608 ret = env->GetIntField(buf, bufferCapacityField);
aoqi@0 4609 return ret;
aoqi@0 4610 }
aoqi@0 4611
aoqi@0 4612
aoqi@0 4613 JNI_LEAF(jint, jni_GetVersion(JNIEnv *env))
aoqi@0 4614 JNIWrapper("GetVersion");
aoqi@0 4615 #ifndef USDT2
aoqi@0 4616 DTRACE_PROBE1(hotspot_jni, GetVersion__entry, env);
aoqi@0 4617 #else /* USDT2 */
aoqi@0 4618 HOTSPOT_JNI_GETVERSION_ENTRY(
aoqi@0 4619 env);
aoqi@0 4620 #endif /* USDT2 */
aoqi@0 4621 #ifndef USDT2
aoqi@0 4622 DTRACE_PROBE1(hotspot_jni, GetVersion__return, CurrentVersion);
aoqi@0 4623 #else /* USDT2 */
aoqi@0 4624 HOTSPOT_JNI_GETVERSION_RETURN(
aoqi@0 4625 CurrentVersion);
aoqi@0 4626 #endif /* USDT2 */
aoqi@0 4627 return CurrentVersion;
aoqi@0 4628 JNI_END
aoqi@0 4629
aoqi@0 4630 extern struct JavaVM_ main_vm;
aoqi@0 4631
aoqi@0 4632 JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm))
aoqi@0 4633 JNIWrapper("jni_GetJavaVM");
aoqi@0 4634 #ifndef USDT2
aoqi@0 4635 DTRACE_PROBE2(hotspot_jni, GetJavaVM__entry, env, vm);
aoqi@0 4636 #else /* USDT2 */
aoqi@0 4637 HOTSPOT_JNI_GETJAVAVM_ENTRY(
aoqi@0 4638 env, (void **) vm);
aoqi@0 4639 #endif /* USDT2 */
aoqi@0 4640 *vm = (JavaVM *)(&main_vm);
aoqi@0 4641 #ifndef USDT2
aoqi@0 4642 DTRACE_PROBE1(hotspot_jni, GetJavaVM__return, JNI_OK);
aoqi@0 4643 #else /* USDT2 */
aoqi@0 4644 HOTSPOT_JNI_GETJAVAVM_RETURN(
aoqi@0 4645 JNI_OK);
aoqi@0 4646 #endif /* USDT2 */
aoqi@0 4647 return JNI_OK;
aoqi@0 4648 JNI_END
aoqi@0 4649
aoqi@0 4650 // Structure containing all jni functions
aoqi@0 4651 struct JNINativeInterface_ jni_NativeInterface = {
aoqi@0 4652 NULL,
aoqi@0 4653 NULL,
aoqi@0 4654 NULL,
aoqi@0 4655
aoqi@0 4656 NULL,
aoqi@0 4657
aoqi@0 4658 jni_GetVersion,
aoqi@0 4659
aoqi@0 4660 jni_DefineClass,
aoqi@0 4661 jni_FindClass,
aoqi@0 4662
aoqi@0 4663 jni_FromReflectedMethod,
aoqi@0 4664 jni_FromReflectedField,
aoqi@0 4665
aoqi@0 4666 jni_ToReflectedMethod,
aoqi@0 4667
aoqi@0 4668 jni_GetSuperclass,
aoqi@0 4669 jni_IsAssignableFrom,
aoqi@0 4670
aoqi@0 4671 jni_ToReflectedField,
aoqi@0 4672
aoqi@0 4673 jni_Throw,
aoqi@0 4674 jni_ThrowNew,
aoqi@0 4675 jni_ExceptionOccurred,
aoqi@0 4676 jni_ExceptionDescribe,
aoqi@0 4677 jni_ExceptionClear,
aoqi@0 4678 jni_FatalError,
aoqi@0 4679
aoqi@0 4680 jni_PushLocalFrame,
aoqi@0 4681 jni_PopLocalFrame,
aoqi@0 4682
aoqi@0 4683 jni_NewGlobalRef,
aoqi@0 4684 jni_DeleteGlobalRef,
aoqi@0 4685 jni_DeleteLocalRef,
aoqi@0 4686 jni_IsSameObject,
aoqi@0 4687
aoqi@0 4688 jni_NewLocalRef,
aoqi@0 4689 jni_EnsureLocalCapacity,
aoqi@0 4690
aoqi@0 4691 jni_AllocObject,
aoqi@0 4692 jni_NewObject,
aoqi@0 4693 jni_NewObjectV,
aoqi@0 4694 jni_NewObjectA,
aoqi@0 4695
aoqi@0 4696 jni_GetObjectClass,
aoqi@0 4697 jni_IsInstanceOf,
aoqi@0 4698
aoqi@0 4699 jni_GetMethodID,
aoqi@0 4700
aoqi@0 4701 jni_CallObjectMethod,
aoqi@0 4702 jni_CallObjectMethodV,
aoqi@0 4703 jni_CallObjectMethodA,
aoqi@0 4704 jni_CallBooleanMethod,
aoqi@0 4705 jni_CallBooleanMethodV,
aoqi@0 4706 jni_CallBooleanMethodA,
aoqi@0 4707 jni_CallByteMethod,
aoqi@0 4708 jni_CallByteMethodV,
aoqi@0 4709 jni_CallByteMethodA,
aoqi@0 4710 jni_CallCharMethod,
aoqi@0 4711 jni_CallCharMethodV,
aoqi@0 4712 jni_CallCharMethodA,
aoqi@0 4713 jni_CallShortMethod,
aoqi@0 4714 jni_CallShortMethodV,
aoqi@0 4715 jni_CallShortMethodA,
aoqi@0 4716 jni_CallIntMethod,
aoqi@0 4717 jni_CallIntMethodV,
aoqi@0 4718 jni_CallIntMethodA,
aoqi@0 4719 jni_CallLongMethod,
aoqi@0 4720 jni_CallLongMethodV,
aoqi@0 4721 jni_CallLongMethodA,
aoqi@0 4722 jni_CallFloatMethod,
aoqi@0 4723 jni_CallFloatMethodV,
aoqi@0 4724 jni_CallFloatMethodA,
aoqi@0 4725 jni_CallDoubleMethod,
aoqi@0 4726 jni_CallDoubleMethodV,
aoqi@0 4727 jni_CallDoubleMethodA,
aoqi@0 4728 jni_CallVoidMethod,
aoqi@0 4729 jni_CallVoidMethodV,
aoqi@0 4730 jni_CallVoidMethodA,
aoqi@0 4731
aoqi@0 4732 jni_CallNonvirtualObjectMethod,
aoqi@0 4733 jni_CallNonvirtualObjectMethodV,
aoqi@0 4734 jni_CallNonvirtualObjectMethodA,
aoqi@0 4735 jni_CallNonvirtualBooleanMethod,
aoqi@0 4736 jni_CallNonvirtualBooleanMethodV,
aoqi@0 4737 jni_CallNonvirtualBooleanMethodA,
aoqi@0 4738 jni_CallNonvirtualByteMethod,
aoqi@0 4739 jni_CallNonvirtualByteMethodV,
aoqi@0 4740 jni_CallNonvirtualByteMethodA,
aoqi@0 4741 jni_CallNonvirtualCharMethod,
aoqi@0 4742 jni_CallNonvirtualCharMethodV,
aoqi@0 4743 jni_CallNonvirtualCharMethodA,
aoqi@0 4744 jni_CallNonvirtualShortMethod,
aoqi@0 4745 jni_CallNonvirtualShortMethodV,
aoqi@0 4746 jni_CallNonvirtualShortMethodA,
aoqi@0 4747 jni_CallNonvirtualIntMethod,
aoqi@0 4748 jni_CallNonvirtualIntMethodV,
aoqi@0 4749 jni_CallNonvirtualIntMethodA,
aoqi@0 4750 jni_CallNonvirtualLongMethod,
aoqi@0 4751 jni_CallNonvirtualLongMethodV,
aoqi@0 4752 jni_CallNonvirtualLongMethodA,
aoqi@0 4753 jni_CallNonvirtualFloatMethod,
aoqi@0 4754 jni_CallNonvirtualFloatMethodV,
aoqi@0 4755 jni_CallNonvirtualFloatMethodA,
aoqi@0 4756 jni_CallNonvirtualDoubleMethod,
aoqi@0 4757 jni_CallNonvirtualDoubleMethodV,
aoqi@0 4758 jni_CallNonvirtualDoubleMethodA,
aoqi@0 4759 jni_CallNonvirtualVoidMethod,
aoqi@0 4760 jni_CallNonvirtualVoidMethodV,
aoqi@0 4761 jni_CallNonvirtualVoidMethodA,
aoqi@0 4762
aoqi@0 4763 jni_GetFieldID,
aoqi@0 4764
aoqi@0 4765 jni_GetObjectField,
aoqi@0 4766 jni_GetBooleanField,
aoqi@0 4767 jni_GetByteField,
aoqi@0 4768 jni_GetCharField,
aoqi@0 4769 jni_GetShortField,
aoqi@0 4770 jni_GetIntField,
aoqi@0 4771 jni_GetLongField,
aoqi@0 4772 jni_GetFloatField,
aoqi@0 4773 jni_GetDoubleField,
aoqi@0 4774
aoqi@0 4775 jni_SetObjectField,
aoqi@0 4776 jni_SetBooleanField,
aoqi@0 4777 jni_SetByteField,
aoqi@0 4778 jni_SetCharField,
aoqi@0 4779 jni_SetShortField,
aoqi@0 4780 jni_SetIntField,
aoqi@0 4781 jni_SetLongField,
aoqi@0 4782 jni_SetFloatField,
aoqi@0 4783 jni_SetDoubleField,
aoqi@0 4784
aoqi@0 4785 jni_GetStaticMethodID,
aoqi@0 4786
aoqi@0 4787 jni_CallStaticObjectMethod,
aoqi@0 4788 jni_CallStaticObjectMethodV,
aoqi@0 4789 jni_CallStaticObjectMethodA,
aoqi@0 4790 jni_CallStaticBooleanMethod,
aoqi@0 4791 jni_CallStaticBooleanMethodV,
aoqi@0 4792 jni_CallStaticBooleanMethodA,
aoqi@0 4793 jni_CallStaticByteMethod,
aoqi@0 4794 jni_CallStaticByteMethodV,
aoqi@0 4795 jni_CallStaticByteMethodA,
aoqi@0 4796 jni_CallStaticCharMethod,
aoqi@0 4797 jni_CallStaticCharMethodV,
aoqi@0 4798 jni_CallStaticCharMethodA,
aoqi@0 4799 jni_CallStaticShortMethod,
aoqi@0 4800 jni_CallStaticShortMethodV,
aoqi@0 4801 jni_CallStaticShortMethodA,
aoqi@0 4802 jni_CallStaticIntMethod,
aoqi@0 4803 jni_CallStaticIntMethodV,
aoqi@0 4804 jni_CallStaticIntMethodA,
aoqi@0 4805 jni_CallStaticLongMethod,
aoqi@0 4806 jni_CallStaticLongMethodV,
aoqi@0 4807 jni_CallStaticLongMethodA,
aoqi@0 4808 jni_CallStaticFloatMethod,
aoqi@0 4809 jni_CallStaticFloatMethodV,
aoqi@0 4810 jni_CallStaticFloatMethodA,
aoqi@0 4811 jni_CallStaticDoubleMethod,
aoqi@0 4812 jni_CallStaticDoubleMethodV,
aoqi@0 4813 jni_CallStaticDoubleMethodA,
aoqi@0 4814 jni_CallStaticVoidMethod,
aoqi@0 4815 jni_CallStaticVoidMethodV,
aoqi@0 4816 jni_CallStaticVoidMethodA,
aoqi@0 4817
aoqi@0 4818 jni_GetStaticFieldID,
aoqi@0 4819
aoqi@0 4820 jni_GetStaticObjectField,
aoqi@0 4821 jni_GetStaticBooleanField,
aoqi@0 4822 jni_GetStaticByteField,
aoqi@0 4823 jni_GetStaticCharField,
aoqi@0 4824 jni_GetStaticShortField,
aoqi@0 4825 jni_GetStaticIntField,
aoqi@0 4826 jni_GetStaticLongField,
aoqi@0 4827 jni_GetStaticFloatField,
aoqi@0 4828 jni_GetStaticDoubleField,
aoqi@0 4829
aoqi@0 4830 jni_SetStaticObjectField,
aoqi@0 4831 jni_SetStaticBooleanField,
aoqi@0 4832 jni_SetStaticByteField,
aoqi@0 4833 jni_SetStaticCharField,
aoqi@0 4834 jni_SetStaticShortField,
aoqi@0 4835 jni_SetStaticIntField,
aoqi@0 4836 jni_SetStaticLongField,
aoqi@0 4837 jni_SetStaticFloatField,
aoqi@0 4838 jni_SetStaticDoubleField,
aoqi@0 4839
aoqi@0 4840 jni_NewString,
aoqi@0 4841 jni_GetStringLength,
aoqi@0 4842 jni_GetStringChars,
aoqi@0 4843 jni_ReleaseStringChars,
aoqi@0 4844
aoqi@0 4845 jni_NewStringUTF,
aoqi@0 4846 jni_GetStringUTFLength,
aoqi@0 4847 jni_GetStringUTFChars,
aoqi@0 4848 jni_ReleaseStringUTFChars,
aoqi@0 4849
aoqi@0 4850 jni_GetArrayLength,
aoqi@0 4851
aoqi@0 4852 jni_NewObjectArray,
aoqi@0 4853 jni_GetObjectArrayElement,
aoqi@0 4854 jni_SetObjectArrayElement,
aoqi@0 4855
aoqi@0 4856 jni_NewBooleanArray,
aoqi@0 4857 jni_NewByteArray,
aoqi@0 4858 jni_NewCharArray,
aoqi@0 4859 jni_NewShortArray,
aoqi@0 4860 jni_NewIntArray,
aoqi@0 4861 jni_NewLongArray,
aoqi@0 4862 jni_NewFloatArray,
aoqi@0 4863 jni_NewDoubleArray,
aoqi@0 4864
aoqi@0 4865 jni_GetBooleanArrayElements,
aoqi@0 4866 jni_GetByteArrayElements,
aoqi@0 4867 jni_GetCharArrayElements,
aoqi@0 4868 jni_GetShortArrayElements,
aoqi@0 4869 jni_GetIntArrayElements,
aoqi@0 4870 jni_GetLongArrayElements,
aoqi@0 4871 jni_GetFloatArrayElements,
aoqi@0 4872 jni_GetDoubleArrayElements,
aoqi@0 4873
aoqi@0 4874 jni_ReleaseBooleanArrayElements,
aoqi@0 4875 jni_ReleaseByteArrayElements,
aoqi@0 4876 jni_ReleaseCharArrayElements,
aoqi@0 4877 jni_ReleaseShortArrayElements,
aoqi@0 4878 jni_ReleaseIntArrayElements,
aoqi@0 4879 jni_ReleaseLongArrayElements,
aoqi@0 4880 jni_ReleaseFloatArrayElements,
aoqi@0 4881 jni_ReleaseDoubleArrayElements,
aoqi@0 4882
aoqi@0 4883 jni_GetBooleanArrayRegion,
aoqi@0 4884 jni_GetByteArrayRegion,
aoqi@0 4885 jni_GetCharArrayRegion,
aoqi@0 4886 jni_GetShortArrayRegion,
aoqi@0 4887 jni_GetIntArrayRegion,
aoqi@0 4888 jni_GetLongArrayRegion,
aoqi@0 4889 jni_GetFloatArrayRegion,
aoqi@0 4890 jni_GetDoubleArrayRegion,
aoqi@0 4891
aoqi@0 4892 jni_SetBooleanArrayRegion,
aoqi@0 4893 jni_SetByteArrayRegion,
aoqi@0 4894 jni_SetCharArrayRegion,
aoqi@0 4895 jni_SetShortArrayRegion,
aoqi@0 4896 jni_SetIntArrayRegion,
aoqi@0 4897 jni_SetLongArrayRegion,
aoqi@0 4898 jni_SetFloatArrayRegion,
aoqi@0 4899 jni_SetDoubleArrayRegion,
aoqi@0 4900
aoqi@0 4901 jni_RegisterNatives,
aoqi@0 4902 jni_UnregisterNatives,
aoqi@0 4903
aoqi@0 4904 jni_MonitorEnter,
aoqi@0 4905 jni_MonitorExit,
aoqi@0 4906
aoqi@0 4907 jni_GetJavaVM,
aoqi@0 4908
aoqi@0 4909 jni_GetStringRegion,
aoqi@0 4910 jni_GetStringUTFRegion,
aoqi@0 4911
aoqi@0 4912 jni_GetPrimitiveArrayCritical,
aoqi@0 4913 jni_ReleasePrimitiveArrayCritical,
aoqi@0 4914
aoqi@0 4915 jni_GetStringCritical,
aoqi@0 4916 jni_ReleaseStringCritical,
aoqi@0 4917
aoqi@0 4918 jni_NewWeakGlobalRef,
aoqi@0 4919 jni_DeleteWeakGlobalRef,
aoqi@0 4920
aoqi@0 4921 jni_ExceptionCheck,
aoqi@0 4922
aoqi@0 4923 jni_NewDirectByteBuffer,
aoqi@0 4924 jni_GetDirectBufferAddress,
aoqi@0 4925 jni_GetDirectBufferCapacity,
aoqi@0 4926
aoqi@0 4927 // New 1_6 features
aoqi@0 4928
aoqi@0 4929 jni_GetObjectRefType
aoqi@0 4930 };
aoqi@0 4931
aoqi@0 4932
aoqi@0 4933 // For jvmti use to modify jni function table.
aoqi@0 4934 // Java threads in native contiues to run until it is transitioned
aoqi@0 4935 // to VM at safepoint. Before the transition or before it is blocked
aoqi@0 4936 // for safepoint it may access jni function table. VM could crash if
aoqi@0 4937 // any java thread access the jni function table in the middle of memcpy.
aoqi@0 4938 // To avoid this each function pointers are copied automically.
aoqi@0 4939 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
aoqi@0 4940 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
aoqi@0 4941 intptr_t *a = (intptr_t *) jni_functions();
aoqi@0 4942 intptr_t *b = (intptr_t *) new_jni_NativeInterface;
aoqi@0 4943 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
aoqi@0 4944 Atomic::store_ptr(*b++, a++);
aoqi@0 4945 }
aoqi@0 4946 }
aoqi@0 4947
aoqi@0 4948 void quicken_jni_functions() {
aoqi@0 4949 // Replace Get<Primitive>Field with fast versions
aoqi@0 4950 if (UseFastJNIAccessors && !JvmtiExport::can_post_field_access()
aoqi@0 4951 && !VerifyJNIFields && !TraceJNICalls && !CountJNICalls && !CheckJNICalls
aoqi@0 4952 #if defined(_WINDOWS) && defined(IA32) && defined(COMPILER2)
aoqi@0 4953 // windows x86 currently needs SEH wrapper and the gain of the fast
aoqi@0 4954 // versions currently isn't certain for server vm on uniprocessor.
aoqi@0 4955 && os::is_MP()
aoqi@0 4956 #endif
aoqi@0 4957 ) {
aoqi@0 4958 address func;
aoqi@0 4959 func = JNI_FastGetField::generate_fast_get_boolean_field();
aoqi@0 4960 if (func != (address)-1) {
aoqi@0 4961 jni_NativeInterface.GetBooleanField = (GetBooleanField_t)func;
aoqi@0 4962 }
aoqi@0 4963 func = JNI_FastGetField::generate_fast_get_byte_field();
aoqi@0 4964 if (func != (address)-1) {
aoqi@0 4965 jni_NativeInterface.GetByteField = (GetByteField_t)func;
aoqi@0 4966 }
aoqi@0 4967 func = JNI_FastGetField::generate_fast_get_char_field();
aoqi@0 4968 if (func != (address)-1) {
aoqi@0 4969 jni_NativeInterface.GetCharField = (GetCharField_t)func;
aoqi@0 4970 }
aoqi@0 4971 func = JNI_FastGetField::generate_fast_get_short_field();
aoqi@0 4972 if (func != (address)-1) {
aoqi@0 4973 jni_NativeInterface.GetShortField = (GetShortField_t)func;
aoqi@0 4974 }
aoqi@0 4975 func = JNI_FastGetField::generate_fast_get_int_field();
aoqi@0 4976 if (func != (address)-1) {
aoqi@0 4977 jni_NativeInterface.GetIntField = (GetIntField_t)func;
aoqi@0 4978 }
aoqi@0 4979 func = JNI_FastGetField::generate_fast_get_long_field();
aoqi@0 4980 if (func != (address)-1) {
aoqi@0 4981 jni_NativeInterface.GetLongField = (GetLongField_t)func;
aoqi@0 4982 }
aoqi@0 4983 func = JNI_FastGetField::generate_fast_get_float_field();
aoqi@0 4984 if (func != (address)-1) {
aoqi@0 4985 jni_NativeInterface.GetFloatField = (GetFloatField_t)func;
aoqi@0 4986 }
aoqi@0 4987 func = JNI_FastGetField::generate_fast_get_double_field();
aoqi@0 4988 if (func != (address)-1) {
aoqi@0 4989 jni_NativeInterface.GetDoubleField = (GetDoubleField_t)func;
aoqi@0 4990 }
aoqi@0 4991 }
aoqi@0 4992 }
aoqi@0 4993
aoqi@0 4994 // Returns the function structure
aoqi@0 4995 struct JNINativeInterface_* jni_functions() {
aoqi@0 4996 #if INCLUDE_JNI_CHECK
aoqi@0 4997 if (CheckJNICalls) return jni_functions_check();
aoqi@0 4998 #endif // INCLUDE_JNI_CHECK
aoqi@0 4999 return &jni_NativeInterface;
aoqi@0 5000 }
aoqi@0 5001
aoqi@0 5002 // Returns the function structure
aoqi@0 5003 struct JNINativeInterface_* jni_functions_nocheck() {
aoqi@0 5004 return &jni_NativeInterface;
aoqi@0 5005 }
aoqi@0 5006
aoqi@0 5007
aoqi@0 5008 // Invocation API
aoqi@0 5009
aoqi@0 5010
aoqi@0 5011 // Forward declaration
aoqi@0 5012 extern const struct JNIInvokeInterface_ jni_InvokeInterface;
aoqi@0 5013
aoqi@0 5014 // Global invocation API vars
aoqi@0 5015 volatile jint vm_created = 0;
aoqi@0 5016 // Indicate whether it is safe to recreate VM
aoqi@0 5017 volatile jint safe_to_recreate_vm = 1;
aoqi@0 5018 struct JavaVM_ main_vm = {&jni_InvokeInterface};
aoqi@0 5019
aoqi@0 5020
aoqi@0 5021 #define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */
aoqi@0 5022 enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };
aoqi@0 5023
aoqi@0 5024 #ifndef USDT2
aoqi@0 5025 HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*);
aoqi@0 5026 DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint);
aoqi@0 5027 #else /* USDT2 */
aoqi@0 5028 DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint
aoqi@0 5029 , HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(_ret_ref));
aoqi@0 5030 #endif /* USDT2 */
aoqi@0 5031
aoqi@0 5032 _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
aoqi@0 5033 #ifndef USDT2
aoqi@0 5034 HS_DTRACE_PROBE1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, args_);
aoqi@0 5035 #else /* USDT2 */
aoqi@0 5036 HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY(
aoqi@0 5037 args_);
aoqi@0 5038 #endif /* USDT2 */
aoqi@0 5039 JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_;
aoqi@0 5040 jint ret = JNI_ERR;
aoqi@0 5041 DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret);
aoqi@0 5042
aoqi@0 5043 if (Threads::is_supported_jni_version(args->version)) {
aoqi@0 5044 ret = JNI_OK;
aoqi@0 5045 }
aoqi@0 5046 // 1.1 style no longer supported in hotspot.
aoqi@0 5047 // According the JNI spec, we should update args->version on return.
aoqi@0 5048 // We also use the structure to communicate with launcher about default
aoqi@0 5049 // stack size.
aoqi@0 5050 if (args->version == JNI_VERSION_1_1) {
aoqi@0 5051 args->version = JNI_VERSION_1_2;
aoqi@0 5052 // javaStackSize is int in arguments structure
aoqi@0 5053 assert(jlong(ThreadStackSize) * K < INT_MAX, "integer overflow");
aoqi@0 5054 args->javaStackSize = (jint)(ThreadStackSize * K);
aoqi@0 5055 }
aoqi@0 5056 return ret;
aoqi@0 5057 }
aoqi@0 5058
aoqi@0 5059 #ifndef PRODUCT
aoqi@0 5060
aoqi@0 5061 #include "gc_implementation/shared/gcTimer.hpp"
aoqi@0 5062 #include "gc_interface/collectedHeap.hpp"
aoqi@0 5063 #if INCLUDE_ALL_GCS
aoqi@0 5064 #include "gc_implementation/g1/heapRegionRemSet.hpp"
aoqi@0 5065 #endif
aoqi@0 5066 #include "utilities/quickSort.hpp"
aoqi@0 5067 #include "utilities/ostream.hpp"
aoqi@0 5068 #if INCLUDE_VM_STRUCTS
aoqi@0 5069 #include "runtime/vmStructs.hpp"
aoqi@0 5070 #endif
aoqi@0 5071
aoqi@0 5072 #define run_unit_test(unit_test_function_call) \
aoqi@0 5073 tty->print_cr("Running test: " #unit_test_function_call); \
aoqi@0 5074 unit_test_function_call
aoqi@0 5075
aoqi@0 5076 // Forward declaration
aoqi@0 5077 void TestReservedSpace_test();
aoqi@0 5078 void TestReserveMemorySpecial_test();
aoqi@0 5079 void TestVirtualSpace_test();
aoqi@0 5080 void TestMetaspaceAux_test();
aoqi@0 5081 void TestMetachunk_test();
aoqi@0 5082 void TestVirtualSpaceNode_test();
aoqi@0 5083 void TestNewSize_test();
aoqi@0 5084 #if INCLUDE_ALL_GCS
aoqi@0 5085 void TestOldFreeSpaceCalculation_test();
aoqi@0 5086 void TestG1BiasedArray_test();
aoqi@0 5087 void TestCodeCacheRemSet_test();
aoqi@0 5088 #endif
aoqi@0 5089
aoqi@0 5090 void execute_internal_vm_tests() {
aoqi@0 5091 if (ExecuteInternalVMTests) {
aoqi@0 5092 tty->print_cr("Running internal VM tests");
aoqi@0 5093 run_unit_test(TestReservedSpace_test());
aoqi@0 5094 run_unit_test(TestReserveMemorySpecial_test());
aoqi@0 5095 run_unit_test(TestVirtualSpace_test());
aoqi@0 5096 run_unit_test(TestMetaspaceAux_test());
aoqi@0 5097 run_unit_test(TestMetachunk_test());
aoqi@0 5098 run_unit_test(TestVirtualSpaceNode_test());
aoqi@0 5099 run_unit_test(GlobalDefinitions::test_globals());
aoqi@0 5100 run_unit_test(GCTimerAllTest::all());
aoqi@0 5101 run_unit_test(arrayOopDesc::test_max_array_length());
aoqi@0 5102 run_unit_test(CollectedHeap::test_is_in());
aoqi@0 5103 run_unit_test(QuickSort::test_quick_sort());
aoqi@0 5104 run_unit_test(AltHashing::test_alt_hash());
aoqi@0 5105 run_unit_test(test_loggc_filename());
aoqi@0 5106 run_unit_test(TestNewSize_test());
aoqi@0 5107 #if INCLUDE_VM_STRUCTS
aoqi@0 5108 run_unit_test(VMStructs::test());
aoqi@0 5109 #endif
aoqi@0 5110 #if INCLUDE_ALL_GCS
aoqi@0 5111 run_unit_test(TestOldFreeSpaceCalculation_test());
aoqi@0 5112 run_unit_test(TestG1BiasedArray_test());
aoqi@0 5113 run_unit_test(HeapRegionRemSet::test_prt());
aoqi@0 5114 run_unit_test(TestCodeCacheRemSet_test());
aoqi@0 5115 #endif
aoqi@0 5116 tty->print_cr("All internal VM tests passed");
aoqi@0 5117 }
aoqi@0 5118 }
aoqi@0 5119
aoqi@0 5120 #undef run_unit_test
aoqi@0 5121
aoqi@0 5122 #endif
aoqi@0 5123
aoqi@0 5124 #ifndef USDT2
aoqi@0 5125 HS_DTRACE_PROBE_DECL3(hotspot_jni, CreateJavaVM__entry, vm, penv, args);
aoqi@0 5126 DT_RETURN_MARK_DECL(CreateJavaVM, jint);
aoqi@0 5127 #else /* USDT2 */
aoqi@0 5128 DT_RETURN_MARK_DECL(CreateJavaVM, jint
aoqi@0 5129 , HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref));
aoqi@0 5130 #endif /* USDT2 */
aoqi@0 5131
aoqi@0 5132 _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {
aoqi@0 5133 #ifndef USDT2
aoqi@0 5134 HS_DTRACE_PROBE3(hotspot_jni, CreateJavaVM__entry, vm, penv, args);
aoqi@0 5135 #else /* USDT2 */
aoqi@0 5136 HOTSPOT_JNI_CREATEJAVAVM_ENTRY(
aoqi@0 5137 (void **) vm, penv, args);
aoqi@0 5138 #endif /* USDT2 */
aoqi@0 5139
aoqi@0 5140 jint result = JNI_ERR;
aoqi@0 5141 DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result);
aoqi@0 5142
aoqi@0 5143 // We're about to use Atomic::xchg for synchronization. Some Zero
aoqi@0 5144 // platforms use the GCC builtin __sync_lock_test_and_set for this,
aoqi@0 5145 // but __sync_lock_test_and_set is not guaranteed to do what we want
aoqi@0 5146 // on all architectures. So we check it works before relying on it.
aoqi@0 5147 #if defined(ZERO) && defined(ASSERT)
aoqi@0 5148 {
aoqi@0 5149 jint a = 0xcafebabe;
aoqi@0 5150 jint b = Atomic::xchg(0xdeadbeef, &a);
aoqi@0 5151 void *c = &a;
aoqi@0 5152 void *d = Atomic::xchg_ptr(&b, &c);
aoqi@0 5153 assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works");
aoqi@0 5154 assert(c == &b && d == &a, "Atomic::xchg_ptr() works");
aoqi@0 5155 }
aoqi@0 5156 #endif // ZERO && ASSERT
aoqi@0 5157
aoqi@0 5158 // At the moment it's only possible to have one Java VM,
aoqi@0 5159 // since some of the runtime state is in global variables.
aoqi@0 5160
aoqi@0 5161 // We cannot use our mutex locks here, since they only work on
aoqi@0 5162 // Threads. We do an atomic compare and exchange to ensure only
aoqi@0 5163 // one thread can call this method at a time
aoqi@0 5164
aoqi@0 5165 // We use Atomic::xchg rather than Atomic::add/dec since on some platforms
aoqi@0 5166 // the add/dec implementations are dependent on whether we are running
aoqi@0 5167 // on a multiprocessor, and at this stage of initialization the os::is_MP
aoqi@0 5168 // function used to determine this will always return false. Atomic::xchg
aoqi@0 5169 // does not have this problem.
aoqi@0 5170 if (Atomic::xchg(1, &vm_created) == 1) {
aoqi@0 5171 return JNI_EEXIST; // already created, or create attempt in progress
aoqi@0 5172 }
aoqi@0 5173 if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) {
aoqi@0 5174 return JNI_ERR; // someone tried and failed and retry not allowed.
aoqi@0 5175 }
aoqi@0 5176
aoqi@0 5177 assert(vm_created == 1, "vm_created is true during the creation");
aoqi@0 5178
aoqi@0 5179 /**
aoqi@0 5180 * Certain errors during initialization are recoverable and do not
aoqi@0 5181 * prevent this method from being called again at a later time
aoqi@0 5182 * (perhaps with different arguments). However, at a certain
aoqi@0 5183 * point during initialization if an error occurs we cannot allow
aoqi@0 5184 * this function to be called again (or it will crash). In those
aoqi@0 5185 * situations, the 'canTryAgain' flag is set to false, which atomically
aoqi@0 5186 * sets safe_to_recreate_vm to 1, such that any new call to
aoqi@0 5187 * JNI_CreateJavaVM will immediately fail using the above logic.
aoqi@0 5188 */
aoqi@0 5189 bool can_try_again = true;
aoqi@0 5190
aoqi@0 5191 result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again);
aoqi@0 5192 if (result == JNI_OK) {
aoqi@0 5193 JavaThread *thread = JavaThread::current();
aoqi@0 5194 /* thread is thread_in_vm here */
aoqi@0 5195 *vm = (JavaVM *)(&main_vm);
aoqi@0 5196 *(JNIEnv**)penv = thread->jni_environment();
aoqi@0 5197
aoqi@0 5198 // Tracks the time application was running before GC
aoqi@0 5199 RuntimeService::record_application_start();
aoqi@0 5200
aoqi@0 5201 // Notify JVMTI
aoqi@0 5202 if (JvmtiExport::should_post_thread_life()) {
aoqi@0 5203 JvmtiExport::post_thread_start(thread);
aoqi@0 5204 }
aoqi@0 5205
aoqi@0 5206 EventThreadStart event;
aoqi@0 5207 if (event.should_commit()) {
aoqi@0 5208 event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj()));
aoqi@0 5209 event.commit();
aoqi@0 5210 }
aoqi@0 5211
aoqi@0 5212 #ifndef PRODUCT
aoqi@0 5213 #ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
aoqi@0 5214 #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
aoqi@0 5215 #endif
aoqi@0 5216
aoqi@0 5217 // Check if we should compile all classes on bootclasspath
aoqi@0 5218 if (CompileTheWorld) ClassLoader::compile_the_world();
aoqi@0 5219 if (ReplayCompiles) ciReplay::replay(thread);
aoqi@0 5220
aoqi@0 5221 // Some platforms (like Win*) need a wrapper around these test
aoqi@0 5222 // functions in order to properly handle error conditions.
aoqi@0 5223 CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(test_error_handler);
aoqi@0 5224 CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(execute_internal_vm_tests);
aoqi@0 5225 #endif
aoqi@0 5226
aoqi@0 5227 // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
aoqi@0 5228 ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);
aoqi@0 5229 } else {
aoqi@0 5230 if (can_try_again) {
aoqi@0 5231 // reset safe_to_recreate_vm to 1 so that retrial would be possible
aoqi@0 5232 safe_to_recreate_vm = 1;
aoqi@0 5233 }
aoqi@0 5234
aoqi@0 5235 // Creation failed. We must reset vm_created
aoqi@0 5236 *vm = 0;
aoqi@0 5237 *(JNIEnv**)penv = 0;
aoqi@0 5238 // reset vm_created last to avoid race condition. Use OrderAccess to
aoqi@0 5239 // control both compiler and architectural-based reordering.
aoqi@0 5240 OrderAccess::release_store(&vm_created, 0);
aoqi@0 5241 }
aoqi@0 5242
aoqi@0 5243 return result;
aoqi@0 5244 }
aoqi@0 5245
aoqi@0 5246 #ifndef USDT2
aoqi@0 5247 HS_DTRACE_PROBE_DECL3(hotspot_jni, GetCreatedJavaVMs__entry, \
aoqi@0 5248 JavaVM**, jsize, jsize*);
aoqi@0 5249 HS_DTRACE_PROBE_DECL1(hotspot_jni, GetCreatedJavaVMs__return, jint);
aoqi@0 5250 #endif /* !USDT2 */
aoqi@0 5251
aoqi@0 5252 _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) {
aoqi@0 5253 // See bug 4367188, the wrapper can sometimes cause VM crashes
aoqi@0 5254 // JNIWrapper("GetCreatedJavaVMs");
aoqi@0 5255 #ifndef USDT2
aoqi@0 5256 HS_DTRACE_PROBE3(hotspot_jni, GetCreatedJavaVMs__entry, \
aoqi@0 5257 vm_buf, bufLen, numVMs);
aoqi@0 5258 #else /* USDT2 */
aoqi@0 5259 HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY(
aoqi@0 5260 (void **) vm_buf, bufLen, (uintptr_t *) numVMs);
aoqi@0 5261 #endif /* USDT2 */
aoqi@0 5262 if (vm_created) {
aoqi@0 5263 if (numVMs != NULL) *numVMs = 1;
aoqi@0 5264 if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm);
aoqi@0 5265 } else {
aoqi@0 5266 if (numVMs != NULL) *numVMs = 0;
aoqi@0 5267 }
aoqi@0 5268 #ifndef USDT2
aoqi@0 5269 HS_DTRACE_PROBE1(hotspot_jni, GetCreatedJavaVMs__return, JNI_OK);
aoqi@0 5270 #else /* USDT2 */
aoqi@0 5271 HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN(
aoqi@0 5272 JNI_OK);
aoqi@0 5273 #endif /* USDT2 */
aoqi@0 5274 return JNI_OK;
aoqi@0 5275 }
aoqi@0 5276
aoqi@0 5277 extern "C" {
aoqi@0 5278
aoqi@0 5279 #ifndef USDT2
aoqi@0 5280 DT_RETURN_MARK_DECL(DestroyJavaVM, jint);
aoqi@0 5281 #else /* USDT2 */
aoqi@0 5282 DT_RETURN_MARK_DECL(DestroyJavaVM, jint
aoqi@0 5283 , HOTSPOT_JNI_DESTROYJAVAVM_RETURN(_ret_ref));
aoqi@0 5284 #endif /* USDT2 */
aoqi@0 5285
aoqi@0 5286 jint JNICALL jni_DestroyJavaVM(JavaVM *vm) {
aoqi@0 5287 #ifndef USDT2
aoqi@0 5288 DTRACE_PROBE1(hotspot_jni, DestroyJavaVM__entry, vm);
aoqi@0 5289 #else /* USDT2 */
aoqi@0 5290 HOTSPOT_JNI_DESTROYJAVAVM_ENTRY(
aoqi@0 5291 vm);
aoqi@0 5292 #endif /* USDT2 */
aoqi@0 5293 jint res = JNI_ERR;
aoqi@0 5294 DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res);
aoqi@0 5295
aoqi@0 5296 if (!vm_created) {
aoqi@0 5297 res = JNI_ERR;
aoqi@0 5298 return res;
aoqi@0 5299 }
aoqi@0 5300
aoqi@0 5301 JNIWrapper("DestroyJavaVM");
aoqi@0 5302 JNIEnv *env;
aoqi@0 5303 JavaVMAttachArgs destroyargs;
aoqi@0 5304 destroyargs.version = CurrentVersion;
aoqi@0 5305 destroyargs.name = (char *)"DestroyJavaVM";
aoqi@0 5306 destroyargs.group = NULL;
aoqi@0 5307 res = vm->AttachCurrentThread((void **)&env, (void *)&destroyargs);
aoqi@0 5308 if (res != JNI_OK) {
aoqi@0 5309 return res;
aoqi@0 5310 }
aoqi@0 5311
aoqi@0 5312 // Since this is not a JVM_ENTRY we have to set the thread state manually before entering.
aoqi@0 5313 JavaThread* thread = JavaThread::current();
aoqi@0 5314 ThreadStateTransition::transition_from_native(thread, _thread_in_vm);
aoqi@0 5315 if (Threads::destroy_vm()) {
aoqi@0 5316 // Should not change thread state, VM is gone
aoqi@0 5317 vm_created = false;
aoqi@0 5318 res = JNI_OK;
aoqi@0 5319 return res;
aoqi@0 5320 } else {
aoqi@0 5321 ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);
aoqi@0 5322 res = JNI_ERR;
aoqi@0 5323 return res;
aoqi@0 5324 }
aoqi@0 5325 }
aoqi@0 5326
aoqi@0 5327
aoqi@0 5328 static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool daemon) {
aoqi@0 5329 JavaVMAttachArgs *args = (JavaVMAttachArgs *) _args;
aoqi@0 5330
aoqi@0 5331 // Check below commented out from JDK1.2fcs as well
aoqi@0 5332 /*
aoqi@0 5333 if (args && (args->version != JNI_VERSION_1_1 || args->version != JNI_VERSION_1_2)) {
aoqi@0 5334 return JNI_EVERSION;
aoqi@0 5335 }
aoqi@0 5336 */
aoqi@0 5337
aoqi@0 5338 Thread* t = ThreadLocalStorage::get_thread_slow();
aoqi@0 5339 if (t != NULL) {
aoqi@0 5340 // If the thread has been attached this operation is a no-op
aoqi@0 5341 *(JNIEnv**)penv = ((JavaThread*) t)->jni_environment();
aoqi@0 5342 return JNI_OK;
aoqi@0 5343 }
aoqi@0 5344
aoqi@0 5345 // Create a thread and mark it as attaching so it will be skipped by the
aoqi@0 5346 // ThreadsListEnumerator - see CR 6404306
aoqi@0 5347 JavaThread* thread = new JavaThread(true);
aoqi@0 5348
aoqi@0 5349 // Set correct safepoint info. The thread is going to call into Java when
aoqi@0 5350 // initializing the Java level thread object. Hence, the correct state must
aoqi@0 5351 // be set in order for the Safepoint code to deal with it correctly.
aoqi@0 5352 thread->set_thread_state(_thread_in_vm);
aoqi@0 5353 // Must do this before initialize_thread_local_storage
aoqi@0 5354 thread->record_stack_base_and_size();
aoqi@0 5355
aoqi@0 5356 thread->initialize_thread_local_storage();
aoqi@0 5357
aoqi@0 5358 if (!os::create_attached_thread(thread)) {
aoqi@0 5359 delete thread;
aoqi@0 5360 return JNI_ERR;
aoqi@0 5361 }
aoqi@0 5362 // Enable stack overflow checks
aoqi@0 5363 thread->create_stack_guard_pages();
aoqi@0 5364
aoqi@0 5365 thread->initialize_tlab();
aoqi@0 5366
aoqi@0 5367 thread->cache_global_variables();
aoqi@0 5368
aoqi@0 5369 // Crucial that we do not have a safepoint check for this thread, since it has
aoqi@0 5370 // not been added to the Thread list yet.
aoqi@0 5371 { Threads_lock->lock_without_safepoint_check();
aoqi@0 5372 // This must be inside this lock in order to get FullGCALot to work properly, i.e., to
aoqi@0 5373 // avoid this thread trying to do a GC before it is added to the thread-list
aoqi@0 5374 thread->set_active_handles(JNIHandleBlock::allocate_block());
aoqi@0 5375 Threads::add(thread, daemon);
aoqi@0 5376 Threads_lock->unlock();
aoqi@0 5377 }
aoqi@0 5378 // Create thread group and name info from attach arguments
aoqi@0 5379 oop group = NULL;
aoqi@0 5380 char* thread_name = NULL;
aoqi@0 5381 if (args != NULL && Threads::is_supported_jni_version(args->version)) {
aoqi@0 5382 group = JNIHandles::resolve(args->group);
aoqi@0 5383 thread_name = args->name; // may be NULL
aoqi@0 5384 }
aoqi@0 5385 if (group == NULL) group = Universe::main_thread_group();
aoqi@0 5386
aoqi@0 5387 // Create Java level thread object and attach it to this thread
aoqi@0 5388 bool attach_failed = false;
aoqi@0 5389 {
aoqi@0 5390 EXCEPTION_MARK;
aoqi@0 5391 HandleMark hm(THREAD);
aoqi@0 5392 Handle thread_group(THREAD, group);
aoqi@0 5393 thread->allocate_threadObj(thread_group, thread_name, daemon, THREAD);
aoqi@0 5394 if (HAS_PENDING_EXCEPTION) {
aoqi@0 5395 CLEAR_PENDING_EXCEPTION;
aoqi@0 5396 // cleanup outside the handle mark.
aoqi@0 5397 attach_failed = true;
aoqi@0 5398 }
aoqi@0 5399 }
aoqi@0 5400
aoqi@0 5401 if (attach_failed) {
aoqi@0 5402 // Added missing cleanup
aoqi@0 5403 thread->cleanup_failed_attach_current_thread();
aoqi@0 5404 return JNI_ERR;
aoqi@0 5405 }
aoqi@0 5406
aoqi@0 5407 // mark the thread as no longer attaching
aoqi@0 5408 // this uses a fence to push the change through so we don't have
aoqi@0 5409 // to regrab the threads_lock
aoqi@0 5410 thread->set_done_attaching_via_jni();
aoqi@0 5411
aoqi@0 5412 // Set java thread status.
aoqi@0 5413 java_lang_Thread::set_thread_status(thread->threadObj(),
aoqi@0 5414 java_lang_Thread::RUNNABLE);
aoqi@0 5415
aoqi@0 5416 // Notify the debugger
aoqi@0 5417 if (JvmtiExport::should_post_thread_life()) {
aoqi@0 5418 JvmtiExport::post_thread_start(thread);
aoqi@0 5419 }
aoqi@0 5420
aoqi@0 5421 EventThreadStart event;
aoqi@0 5422 if (event.should_commit()) {
aoqi@0 5423 event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj()));
aoqi@0 5424 event.commit();
aoqi@0 5425 }
aoqi@0 5426
aoqi@0 5427 *(JNIEnv**)penv = thread->jni_environment();
aoqi@0 5428
aoqi@0 5429 // Now leaving the VM, so change thread_state. This is normally automatically taken care
aoqi@0 5430 // of in the JVM_ENTRY. But in this situation we have to do it manually. Notice, that by
aoqi@0 5431 // using ThreadStateTransition::transition, we do a callback to the safepoint code if
aoqi@0 5432 // needed.
aoqi@0 5433
aoqi@0 5434 ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);
aoqi@0 5435
aoqi@0 5436 // Perform any platform dependent FPU setup
aoqi@0 5437 os::setup_fpu();
aoqi@0 5438
aoqi@0 5439 return JNI_OK;
aoqi@0 5440 }
aoqi@0 5441
aoqi@0 5442
aoqi@0 5443 jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) {
aoqi@0 5444 #ifndef USDT2
aoqi@0 5445 DTRACE_PROBE3(hotspot_jni, AttachCurrentThread__entry, vm, penv, _args);
aoqi@0 5446 #else /* USDT2 */
aoqi@0 5447 HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(
aoqi@0 5448 vm, penv, _args);
aoqi@0 5449 #endif /* USDT2 */
aoqi@0 5450 if (!vm_created) {
aoqi@0 5451 #ifndef USDT2
aoqi@0 5452 DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, JNI_ERR);
aoqi@0 5453 #else /* USDT2 */
aoqi@0 5454 HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(
aoqi@0 5455 (uint32_t) JNI_ERR);
aoqi@0 5456 #endif /* USDT2 */
aoqi@0 5457 return JNI_ERR;
aoqi@0 5458 }
aoqi@0 5459
aoqi@0 5460 JNIWrapper("AttachCurrentThread");
aoqi@0 5461 jint ret = attach_current_thread(vm, penv, _args, false);
aoqi@0 5462 #ifndef USDT2
aoqi@0 5463 DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, ret);
aoqi@0 5464 #else /* USDT2 */
aoqi@0 5465 HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(
aoqi@0 5466 ret);
aoqi@0 5467 #endif /* USDT2 */
aoqi@0 5468 return ret;
aoqi@0 5469 }
aoqi@0 5470
aoqi@0 5471
aoqi@0 5472 jint JNICALL jni_DetachCurrentThread(JavaVM *vm) {
aoqi@0 5473 #ifndef USDT2
aoqi@0 5474 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__entry, vm);
aoqi@0 5475 #else /* USDT2 */
aoqi@0 5476 HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY(
aoqi@0 5477 vm);
aoqi@0 5478 #endif /* USDT2 */
aoqi@0 5479 VM_Exit::block_if_vm_exited();
aoqi@0 5480
aoqi@0 5481 JNIWrapper("DetachCurrentThread");
aoqi@0 5482
aoqi@0 5483 // If the thread has been deattacted the operations is a no-op
aoqi@0 5484 if (ThreadLocalStorage::thread() == NULL) {
aoqi@0 5485 #ifndef USDT2
aoqi@0 5486 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK);
aoqi@0 5487 #else /* USDT2 */
aoqi@0 5488 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(
aoqi@0 5489 JNI_OK);
aoqi@0 5490 #endif /* USDT2 */
aoqi@0 5491 return JNI_OK;
aoqi@0 5492 }
aoqi@0 5493
aoqi@0 5494 JavaThread* thread = JavaThread::current();
aoqi@0 5495 if (thread->has_last_Java_frame()) {
aoqi@0 5496 #ifndef USDT2
aoqi@0 5497 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_ERR);
aoqi@0 5498 #else /* USDT2 */
aoqi@0 5499 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(
aoqi@0 5500 (uint32_t) JNI_ERR);
aoqi@0 5501 #endif /* USDT2 */
aoqi@0 5502 // Can't detach a thread that's running java, that can't work.
aoqi@0 5503 return JNI_ERR;
aoqi@0 5504 }
aoqi@0 5505
aoqi@0 5506 // Safepoint support. Have to do call-back to safepoint code, if in the
aoqi@0 5507 // middel of a safepoint operation
aoqi@0 5508 ThreadStateTransition::transition_from_native(thread, _thread_in_vm);
aoqi@0 5509
aoqi@0 5510 // XXX: Note that JavaThread::exit() call below removes the guards on the
aoqi@0 5511 // stack pages set up via enable_stack_{red,yellow}_zone() calls
aoqi@0 5512 // above in jni_AttachCurrentThread. Unfortunately, while the setting
aoqi@0 5513 // of the guards is visible in jni_AttachCurrentThread above,
aoqi@0 5514 // the removal of the guards is buried below in JavaThread::exit()
aoqi@0 5515 // here. The abstraction should be more symmetrically either exposed
aoqi@0 5516 // or hidden (e.g. it could probably be hidden in the same
aoqi@0 5517 // (platform-dependent) methods where we do alternate stack
aoqi@0 5518 // maintenance work?)
aoqi@0 5519 thread->exit(false, JavaThread::jni_detach);
aoqi@0 5520 delete thread;
aoqi@0 5521
aoqi@0 5522 #ifndef USDT2
aoqi@0 5523 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK);
aoqi@0 5524 #else /* USDT2 */
aoqi@0 5525 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(
aoqi@0 5526 JNI_OK);
aoqi@0 5527 #endif /* USDT2 */
aoqi@0 5528 return JNI_OK;
aoqi@0 5529 }
aoqi@0 5530
aoqi@0 5531 #ifndef USDT2
aoqi@0 5532 DT_RETURN_MARK_DECL(GetEnv, jint);
aoqi@0 5533 #else /* USDT2 */
aoqi@0 5534 DT_RETURN_MARK_DECL(GetEnv, jint
aoqi@0 5535 , HOTSPOT_JNI_GETENV_RETURN(_ret_ref));
aoqi@0 5536 #endif /* USDT2 */
aoqi@0 5537
aoqi@0 5538 jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
aoqi@0 5539 #ifndef USDT2
aoqi@0 5540 DTRACE_PROBE3(hotspot_jni, GetEnv__entry, vm, penv, version);
aoqi@0 5541 #else /* USDT2 */
aoqi@0 5542 HOTSPOT_JNI_GETENV_ENTRY(
aoqi@0 5543 vm, penv, version);
aoqi@0 5544 #endif /* USDT2 */
aoqi@0 5545 jint ret = JNI_ERR;
aoqi@0 5546 DT_RETURN_MARK(GetEnv, jint, (const jint&)ret);
aoqi@0 5547
aoqi@0 5548 if (!vm_created) {
aoqi@0 5549 *penv = NULL;
aoqi@0 5550 ret = JNI_EDETACHED;
aoqi@0 5551 return ret;
aoqi@0 5552 }
aoqi@0 5553
aoqi@0 5554 if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) {
aoqi@0 5555 return ret;
aoqi@0 5556 }
aoqi@0 5557
aoqi@0 5558 #ifndef JVMPI_VERSION_1
aoqi@0 5559 // need these in order to be polite about older agents
aoqi@0 5560 #define JVMPI_VERSION_1 ((jint)0x10000001)
aoqi@0 5561 #define JVMPI_VERSION_1_1 ((jint)0x10000002)
aoqi@0 5562 #define JVMPI_VERSION_1_2 ((jint)0x10000003)
aoqi@0 5563 #endif // !JVMPI_VERSION_1
aoqi@0 5564
aoqi@0 5565 Thread* thread = ThreadLocalStorage::thread();
aoqi@0 5566 if (thread != NULL && thread->is_Java_thread()) {
aoqi@0 5567 if (Threads::is_supported_jni_version_including_1_1(version)) {
aoqi@0 5568 *(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment();
aoqi@0 5569 ret = JNI_OK;
aoqi@0 5570 return ret;
aoqi@0 5571
aoqi@0 5572 } else if (version == JVMPI_VERSION_1 ||
aoqi@0 5573 version == JVMPI_VERSION_1_1 ||
aoqi@0 5574 version == JVMPI_VERSION_1_2) {
aoqi@0 5575 tty->print_cr("ERROR: JVMPI, an experimental interface, is no longer supported.");
aoqi@0 5576 tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI).");
aoqi@0 5577 ret = JNI_EVERSION;
aoqi@0 5578 return ret;
aoqi@0 5579 } else if (JvmtiExport::is_jvmdi_version(version)) {
aoqi@0 5580 tty->print_cr("FATAL ERROR: JVMDI is no longer supported.");
aoqi@0 5581 tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI).");
aoqi@0 5582 ret = JNI_EVERSION;
aoqi@0 5583 return ret;
aoqi@0 5584 } else {
aoqi@0 5585 *penv = NULL;
aoqi@0 5586 ret = JNI_EVERSION;
aoqi@0 5587 return ret;
aoqi@0 5588 }
aoqi@0 5589 } else {
aoqi@0 5590 *penv = NULL;
aoqi@0 5591 ret = JNI_EDETACHED;
aoqi@0 5592 return ret;
aoqi@0 5593 }
aoqi@0 5594 }
aoqi@0 5595
aoqi@0 5596
aoqi@0 5597 jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) {
aoqi@0 5598 #ifndef USDT2
aoqi@0 5599 DTRACE_PROBE3(hotspot_jni, AttachCurrentThreadAsDaemon__entry, vm, penv, _args);
aoqi@0 5600 #else /* USDT2 */
aoqi@0 5601 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(
aoqi@0 5602 vm, penv, _args);
aoqi@0 5603 #endif /* USDT2 */
aoqi@0 5604 if (!vm_created) {
aoqi@0 5605 #ifndef USDT2
aoqi@0 5606 DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, JNI_ERR);
aoqi@0 5607 #else /* USDT2 */
aoqi@0 5608 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(
aoqi@0 5609 (uint32_t) JNI_ERR);
aoqi@0 5610 #endif /* USDT2 */
aoqi@0 5611 return JNI_ERR;
aoqi@0 5612 }
aoqi@0 5613
aoqi@0 5614 JNIWrapper("AttachCurrentThreadAsDaemon");
aoqi@0 5615 jint ret = attach_current_thread(vm, penv, _args, true);
aoqi@0 5616 #ifndef USDT2
aoqi@0 5617 DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, ret);
aoqi@0 5618 #else /* USDT2 */
aoqi@0 5619 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(
aoqi@0 5620 ret);
aoqi@0 5621 #endif /* USDT2 */
aoqi@0 5622 return ret;
aoqi@0 5623 }
aoqi@0 5624
aoqi@0 5625
aoqi@0 5626 } // End extern "C"
aoqi@0 5627
aoqi@0 5628 const struct JNIInvokeInterface_ jni_InvokeInterface = {
aoqi@0 5629 NULL,
aoqi@0 5630 NULL,
aoqi@0 5631 NULL,
aoqi@0 5632
aoqi@0 5633 jni_DestroyJavaVM,
aoqi@0 5634 jni_AttachCurrentThread,
aoqi@0 5635 jni_DetachCurrentThread,
aoqi@0 5636 jni_GetEnv,
aoqi@0 5637 jni_AttachCurrentThreadAsDaemon
aoqi@0 5638 };

mercurial