src/share/vm/prims/jni.cpp

Thu, 27 Feb 2020 06:41:35 +0000

author
andrew
date
Thu, 27 Feb 2020 06:41:35 +0000
changeset 9845
68172de2a0d7
parent 9679
2afa5ff125ac
child 9852
70aa912cebe5
child 9896
1b8c45b8216a
permissions
-rw-r--r--

8055283: Expand ResourceHashtable with C_HEAP allocation, removal and some unit tests
Reviewed-by: phh

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

mercurial