Path: blob/jdk8u272-b10-aarch32-20201026/hotspot/src/share/vm/prims/jni.cpp
48729 views
/*1* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2012 Red Hat, Inc.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "ci/ciReplay.hpp"27#include "classfile/altHashing.hpp"28#include "classfile/classLoader.hpp"29#include "classfile/javaClasses.hpp"30#include "classfile/symbolTable.hpp"31#include "classfile/systemDictionary.hpp"32#include "classfile/vmSymbols.hpp"33#include "interpreter/linkResolver.hpp"34#include "jfr/jfrEvents.hpp"35#include "jfr/support/jfrThreadId.hpp"36#include "utilities/macros.hpp"37#include "utilities/ostream.hpp"38#if INCLUDE_ALL_GCS39#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"40#endif // INCLUDE_ALL_GCS41#include "memory/allocation.hpp"42#include "memory/allocation.inline.hpp"43#include "memory/gcLocker.inline.hpp"44#include "memory/oopFactory.hpp"45#include "memory/universe.inline.hpp"46#include "oops/instanceKlass.hpp"47#include "oops/instanceOop.hpp"48#include "oops/markOop.hpp"49#include "oops/method.hpp"50#include "oops/objArrayKlass.hpp"51#include "oops/objArrayOop.hpp"52#include "oops/oop.inline.hpp"53#include "oops/symbol.hpp"54#include "oops/typeArrayKlass.hpp"55#include "oops/typeArrayOop.hpp"56#include "prims/jni.h"57#include "prims/jniCheck.hpp"58#include "prims/jniExport.hpp"59#include "prims/jniFastGetField.hpp"60#include "prims/jvm.h"61#include "prims/jvm_misc.hpp"62#include "prims/jvmtiExport.hpp"63#include "prims/jvmtiThreadState.hpp"64#include "runtime/compilationPolicy.hpp"65#include "runtime/fieldDescriptor.hpp"66#include "runtime/fprofiler.hpp"67#include "runtime/handles.inline.hpp"68#include "runtime/interfaceSupport.hpp"69#include "runtime/java.hpp"70#include "runtime/javaCalls.hpp"71#include "runtime/jfieldIDWorkaround.hpp"72#include "runtime/orderAccess.inline.hpp"73#include "runtime/reflection.hpp"74#include "runtime/sharedRuntime.hpp"75#include "runtime/signature.hpp"76#include "runtime/thread.inline.hpp"77#include "runtime/vm_operations.hpp"78#include "services/memTracker.hpp"79#include "services/runtimeService.hpp"80#include "utilities/defaultStream.hpp"81#include "utilities/dtrace.hpp"82#include "utilities/events.hpp"83#include "utilities/histogram.hpp"84#ifdef TARGET_OS_FAMILY_linux85# include "os_linux.inline.hpp"86#endif87#ifdef TARGET_OS_FAMILY_solaris88# include "os_solaris.inline.hpp"89#endif90#ifdef TARGET_OS_FAMILY_windows91# include "os_windows.inline.hpp"92#endif93#ifdef TARGET_OS_FAMILY_bsd94# include "os_bsd.inline.hpp"95#endif9697static jint CurrentVersion = JNI_VERSION_1_8;9899100// The DT_RETURN_MARK macros create a scoped object to fire the dtrace101// '-return' probe regardless of the return path is taken out of the function.102// Methods that have multiple return paths use this to avoid having to103// instrument each return path. Methods that use CHECK or THROW must use this104// since those macros can cause an immedate uninstrumented return.105//106// In order to get the return value, a reference to the variable containing107// the return value must be passed to the contructor of the object, and108// the return value must be set before return (since the mark object has109// a reference to it).110//111// Example:112// DT_RETURN_MARK_DECL(SomeFunc, int);113// JNI_ENTRY(int, SomeFunc, ...)114// int return_value = 0;115// DT_RETURN_MARK(SomeFunc, int, (const int&)return_value);116// foo(CHECK_0)117// return_value = 5;118// return return_value;119// JNI_END120#ifndef USDT2121#define DT_RETURN_MARK_DECL(name, type) \122HS_DTRACE_PROBE_DECL1(hotspot_jni, name##__return, type); \123DTRACE_ONLY( \124class DTraceReturnProbeMark_##name { \125public: \126const type& _ret_ref; \127DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \128~DTraceReturnProbeMark_##name() { \129HS_DTRACE_PROBE1(hotspot_jni, name##__return, _ret_ref); \130} \131} \132)133// Void functions are simpler since there's no return value134#define DT_VOID_RETURN_MARK_DECL(name) \135HS_DTRACE_PROBE_DECL0(hotspot_jni, name##__return); \136DTRACE_ONLY( \137class DTraceReturnProbeMark_##name { \138public: \139~DTraceReturnProbeMark_##name() { \140HS_DTRACE_PROBE0(hotspot_jni, name##__return); \141} \142} \143)144145#else /* USDT2 */146147#define DT_RETURN_MARK_DECL(name, type, probe) \148DTRACE_ONLY( \149class DTraceReturnProbeMark_##name { \150public: \151const type& _ret_ref; \152DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \153~DTraceReturnProbeMark_##name() { \154probe; \155} \156} \157)158// Void functions are simpler since there's no return value159#define DT_VOID_RETURN_MARK_DECL(name, probe) \160DTRACE_ONLY( \161class DTraceReturnProbeMark_##name { \162public: \163~DTraceReturnProbeMark_##name() { \164probe; \165} \166} \167)168#endif /* USDT2 */169170// Place these macros in the function to mark the return. Non-void171// functions need the type and address of the return value.172#define DT_RETURN_MARK(name, type, ref) \173DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark(ref) )174#define DT_VOID_RETURN_MARK(name) \175DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark )176177178// Use these to select distinct code for floating-point vs. non-floating point179// situations. Used from within common macros where we need slightly180// different behavior for Float/Double181#define FP_SELECT_Boolean(intcode, fpcode) intcode182#define FP_SELECT_Byte(intcode, fpcode) intcode183#define FP_SELECT_Char(intcode, fpcode) intcode184#define FP_SELECT_Short(intcode, fpcode) intcode185#define FP_SELECT_Object(intcode, fpcode) intcode186#define FP_SELECT_Int(intcode, fpcode) intcode187#define FP_SELECT_Long(intcode, fpcode) intcode188#define FP_SELECT_Float(intcode, fpcode) fpcode189#define FP_SELECT_Double(intcode, fpcode) fpcode190#define FP_SELECT(TypeName, intcode, fpcode) \191FP_SELECT_##TypeName(intcode, fpcode)192193#define COMMA ,194195// Choose DT_RETURN_MARK macros based on the type: float/double -> void196// (dtrace doesn't do FP yet)197#ifndef USDT2198#define DT_RETURN_MARK_DECL_FOR(TypeName, name, type) \199FP_SELECT(TypeName, \200DT_RETURN_MARK_DECL(name, type), DT_VOID_RETURN_MARK_DECL(name) )201#else /* USDT2 */202#define DT_RETURN_MARK_DECL_FOR(TypeName, name, type, probe) \203FP_SELECT(TypeName, \204DT_RETURN_MARK_DECL(name, type, probe), DT_VOID_RETURN_MARK_DECL(name, probe) )205#endif /* USDT2 */206#define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \207FP_SELECT(TypeName, \208DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) )209210211// out-of-line helpers for class jfieldIDWorkaround:212213bool jfieldIDWorkaround::is_valid_jfieldID(Klass* k, jfieldID id) {214if (jfieldIDWorkaround::is_instance_jfieldID(k, id)) {215uintptr_t as_uint = (uintptr_t) id;216intptr_t offset = raw_instance_offset(id);217if (is_checked_jfieldID(id)) {218if (!klass_hash_ok(k, id)) {219return false;220}221}222return InstanceKlass::cast(k)->contains_field_offset(offset);223} else {224JNIid* result = (JNIid*) id;225#ifdef ASSERT226return result != NULL && result->is_static_field_id();227#else228return result != NULL;229#endif230}231}232233234intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, intptr_t offset) {235if (offset <= small_offset_mask) {236Klass* field_klass = k;237Klass* super_klass = field_klass->super();238// With compressed oops the most super class with nonstatic fields would239// be the owner of fields embedded in the header.240while (InstanceKlass::cast(super_klass)->has_nonstatic_fields() &&241InstanceKlass::cast(super_klass)->contains_field_offset(offset)) {242field_klass = super_klass; // super contains the field also243super_klass = field_klass->super();244}245debug_only(No_Safepoint_Verifier nosafepoint;)246uintptr_t klass_hash = field_klass->identity_hash();247return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;248} else {249#if 0250#ifndef PRODUCT251{252ResourceMark rm;253warning("VerifyJNIFields: long offset %d in %s", offset, k->external_name());254}255#endif256#endif257return 0;258}259}260261bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {262uintptr_t as_uint = (uintptr_t) id;263intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;264do {265debug_only(No_Safepoint_Verifier nosafepoint;)266// Could use a non-blocking query for identity_hash here...267if ((k->identity_hash() & klass_mask) == klass_hash)268return true;269k = k->super();270} while (k != NULL);271return false;272}273274void jfieldIDWorkaround::verify_instance_jfieldID(Klass* k, jfieldID id) {275guarantee(jfieldIDWorkaround::is_instance_jfieldID(k, id), "must be an instance field" );276uintptr_t as_uint = (uintptr_t) id;277intptr_t offset = raw_instance_offset(id);278if (VerifyJNIFields) {279if (is_checked_jfieldID(id)) {280guarantee(klass_hash_ok(k, id),281"Bug in native code: jfieldID class must match object");282} else {283#if 0284#ifndef PRODUCT285if (Verbose) {286ResourceMark rm;287warning("VerifyJNIFields: unverified offset %d for %s", offset, k->external_name());288}289#endif290#endif291}292}293guarantee(InstanceKlass::cast(k)->contains_field_offset(offset),294"Bug in native code: jfieldID offset must address interior of object");295}296297// Wrapper to trace JNI functions298299#ifdef ASSERT300Histogram* JNIHistogram;301static volatile jint JNIHistogram_lock = 0;302303class JNITraceWrapper : public StackObj {304public:305JNITraceWrapper(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) {306if (TraceJNICalls) {307va_list ap;308va_start(ap, format);309tty->print("JNI ");310tty->vprint_cr(format, ap);311va_end(ap);312}313}314};315316class JNIHistogramElement : public HistogramElement {317public:318JNIHistogramElement(const char* name);319};320321JNIHistogramElement::JNIHistogramElement(const char* elementName) {322_name = elementName;323uintx count = 0;324325while (Atomic::cmpxchg(1, &JNIHistogram_lock, 0) != 0) {326while (OrderAccess::load_acquire(&JNIHistogram_lock) != 0) {327count +=1;328if ( (WarnOnStalledSpinLock > 0)329&& (count % WarnOnStalledSpinLock == 0)) {330warning("JNIHistogram_lock seems to be stalled");331}332}333}334335336if(JNIHistogram == NULL)337JNIHistogram = new Histogram("JNI Call Counts",100);338339JNIHistogram->add_element(this);340Atomic::dec(&JNIHistogram_lock);341}342343#define JNICountWrapper(arg) \344static JNIHistogramElement* e = new JNIHistogramElement(arg); \345/* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \346if (e != NULL) e->increment_count()347#define JNIWrapper(arg) JNICountWrapper(arg); JNITraceWrapper(arg)348#else349#define JNIWrapper(arg)350#endif351352353// Implementation of JNI entries354355#ifndef USDT2356DT_RETURN_MARK_DECL(DefineClass, jclass);357#else /* USDT2 */358DT_RETURN_MARK_DECL(DefineClass, jclass359, HOTSPOT_JNI_DEFINECLASS_RETURN(_ret_ref));360#endif /* USDT2 */361362JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef,363const jbyte *buf, jsize bufLen))364JNIWrapper("DefineClass");365366#ifndef USDT2367DTRACE_PROBE5(hotspot_jni, DefineClass__entry,368env, name, loaderRef, buf, bufLen);369#else /* USDT2 */370HOTSPOT_JNI_DEFINECLASS_ENTRY(371env, (char*) name, loaderRef, (char*) buf, bufLen);372#endif /* USDT2 */373jclass cls = NULL;374DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls);375376TempNewSymbol class_name = NULL;377// Since exceptions can be thrown, class initialization can take place378// if name is NULL no check for class name in .class stream has to be made.379if (name != NULL) {380const int str_len = (int)strlen(name);381if (str_len > Symbol::max_length()) {382// It's impossible to create this class; the name cannot fit383// into the constant pool.384THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);385}386class_name = SymbolTable::new_symbol(name, CHECK_NULL);387}388ResourceMark rm(THREAD);389ClassFileStream st((u1*) buf, bufLen, NULL);390Handle class_loader (THREAD, JNIHandles::resolve(loaderRef));391392if (UsePerfData && !class_loader.is_null()) {393// check whether the current caller thread holds the lock or not.394// If not, increment the corresponding counter395if (ObjectSynchronizer::396query_lock_ownership((JavaThread*)THREAD, class_loader) !=397ObjectSynchronizer::owner_self) {398ClassLoader::sync_JNIDefineClassLockFreeCounter()->inc();399}400}401Klass* k = SystemDictionary::resolve_from_stream(class_name, class_loader,402Handle(), &st, true,403CHECK_NULL);404405if (TraceClassResolution && k != NULL) {406trace_class_resolution(k);407}408409cls = (jclass)JNIHandles::make_local(410env, k->java_mirror());411return cls;412JNI_END413414415416static bool first_time_FindClass = true;417418#ifndef USDT2419DT_RETURN_MARK_DECL(FindClass, jclass);420#else /* USDT2 */421DT_RETURN_MARK_DECL(FindClass, jclass422, HOTSPOT_JNI_FINDCLASS_RETURN(_ret_ref));423#endif /* USDT2 */424425JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name))426JNIWrapper("FindClass");427#ifndef USDT2428DTRACE_PROBE2(hotspot_jni, FindClass__entry, env, name);429#else /* USDT2 */430HOTSPOT_JNI_FINDCLASS_ENTRY(431env, (char *)name);432#endif /* USDT2 */433434jclass result = NULL;435DT_RETURN_MARK(FindClass, jclass, (const jclass&)result);436437// Remember if we are the first invocation of jni_FindClass438bool first_time = first_time_FindClass;439first_time_FindClass = false;440441// Sanity check the name: it cannot be null or larger than the maximum size442// name we can fit in the constant pool.443if (name == NULL || (int)strlen(name) > Symbol::max_length()) {444THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);445}446447//%note jni_3448Handle loader;449Handle protection_domain;450// Find calling class451instanceKlassHandle k (THREAD, thread->security_get_caller_class(0));452if (k.not_null()) {453loader = Handle(THREAD, k->class_loader());454// Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed455// in the correct class context.456if (loader.is_null() &&457k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) {458JavaValue result(T_OBJECT);459JavaCalls::call_static(&result, k,460vmSymbols::getFromClass_name(),461vmSymbols::void_class_signature(),462thread);463if (HAS_PENDING_EXCEPTION) {464Handle ex(thread, thread->pending_exception());465CLEAR_PENDING_EXCEPTION;466THROW_HANDLE_0(ex);467}468oop mirror = (oop) result.get_jobject();469loader = Handle(THREAD,470InstanceKlass::cast(java_lang_Class::as_Klass(mirror))->class_loader());471protection_domain = Handle(THREAD,472InstanceKlass::cast(java_lang_Class::as_Klass(mirror))->protection_domain());473}474} else {475// We call ClassLoader.getSystemClassLoader to obtain the system class loader.476loader = Handle(THREAD, SystemDictionary::java_system_loader());477}478479TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);480result = find_class_from_class_loader(env, sym, true, loader,481protection_domain, true, thread);482483if (TraceClassResolution && result != NULL) {484trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));485}486487// If we were the first invocation of jni_FindClass, we enable compilation again488// rather than just allowing invocation counter to overflow and decay.489// Controlled by flag DelayCompilationDuringStartup.490if (first_time && !CompileTheWorld)491CompilationPolicy::completed_vm_startup();492493return result;494JNI_END495496#ifndef USDT2497DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID);498#else /* USDT2 */499DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID500, HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN((uintptr_t)_ret_ref));501#endif /* USDT2 */502503JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method))504JNIWrapper("FromReflectedMethod");505#ifndef USDT2506DTRACE_PROBE2(hotspot_jni, FromReflectedMethod__entry, env, method);507#else /* USDT2 */508HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY(509env, method);510#endif /* USDT2 */511jmethodID ret = NULL;512DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret);513514// method is a handle to a java.lang.reflect.Method object515oop reflected = JNIHandles::resolve_non_null(method);516oop mirror = NULL;517int slot = 0;518519if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) {520mirror = java_lang_reflect_Constructor::clazz(reflected);521slot = java_lang_reflect_Constructor::slot(reflected);522} else {523assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type");524mirror = java_lang_reflect_Method::clazz(reflected);525slot = java_lang_reflect_Method::slot(reflected);526}527Klass* k = java_lang_Class::as_Klass(mirror);528529KlassHandle k1(THREAD, k);530// Make sure class is initialized before handing id's out to methods531k1()->initialize(CHECK_NULL);532Method* m = InstanceKlass::cast(k1())->method_with_idnum(slot);533ret = m==NULL? NULL : m->jmethod_id(); // return NULL if reflected method deleted534return ret;535JNI_END536537#ifndef USDT2538DT_RETURN_MARK_DECL(FromReflectedField, jfieldID);539#else /* USDT2 */540DT_RETURN_MARK_DECL(FromReflectedField, jfieldID541, HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN((uintptr_t)_ret_ref));542#endif /* USDT2 */543544JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field))545JNIWrapper("FromReflectedField");546#ifndef USDT2547DTRACE_PROBE2(hotspot_jni, FromReflectedField__entry, env, field);548#else /* USDT2 */549HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY(550env, field);551#endif /* USDT2 */552jfieldID ret = NULL;553DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret);554555// field is a handle to a java.lang.reflect.Field object556oop reflected = JNIHandles::resolve_non_null(field);557oop mirror = java_lang_reflect_Field::clazz(reflected);558Klass* k = java_lang_Class::as_Klass(mirror);559int slot = java_lang_reflect_Field::slot(reflected);560int modifiers = java_lang_reflect_Field::modifiers(reflected);561562KlassHandle k1(THREAD, k);563// Make sure class is initialized before handing id's out to fields564k1()->initialize(CHECK_NULL);565566// First check if this is a static field567if (modifiers & JVM_ACC_STATIC) {568intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot );569JNIid* id = InstanceKlass::cast(k1())->jni_id_for(offset);570assert(id != NULL, "corrupt Field object");571debug_only(id->set_is_static_field_id();)572// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*573ret = jfieldIDWorkaround::to_static_jfieldID(id);574return ret;575}576577// The slot is the index of the field description in the field-array578// The jfieldID is the offset of the field within the object579// It may also have hash bits for k, if VerifyJNIFields is turned on.580intptr_t offset = InstanceKlass::cast(k1())->field_offset( slot );581assert(InstanceKlass::cast(k1())->contains_field_offset(offset), "stay within object");582ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset);583return ret;584JNI_END585586#ifndef USDT2587DT_RETURN_MARK_DECL(ToReflectedMethod, jobject);588#else /* USDT2 */589DT_RETURN_MARK_DECL(ToReflectedMethod, jobject590, HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));591#endif /* USDT2 */592593JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))594JNIWrapper("ToReflectedMethod");595#ifndef USDT2596DTRACE_PROBE4(hotspot_jni, ToReflectedMethod__entry, env, cls, method_id, isStatic);597#else /* USDT2 */598HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(599env, cls, (uintptr_t) method_id, isStatic);600#endif /* USDT2 */601jobject ret = NULL;602DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);603604methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));605assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");606oop reflection_method;607if (m->is_initializer()) {608reflection_method = Reflection::new_constructor(m, CHECK_NULL);609} else {610reflection_method = Reflection::new_method(m, UseNewReflection, false, CHECK_NULL);611}612ret = JNIHandles::make_local(env, reflection_method);613return ret;614JNI_END615616#ifndef USDT2617DT_RETURN_MARK_DECL(GetSuperclass, jclass);618#else /* USDT2 */619DT_RETURN_MARK_DECL(GetSuperclass, jclass620, HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));621#endif /* USDT2 */622623JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))624JNIWrapper("GetSuperclass");625#ifndef USDT2626DTRACE_PROBE2(hotspot_jni, GetSuperclass__entry, env, sub);627#else /* USDT2 */628HOTSPOT_JNI_GETSUPERCLASS_ENTRY(629env, sub);630#endif /* USDT2 */631jclass obj = NULL;632DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);633634oop mirror = JNIHandles::resolve_non_null(sub);635// primitive classes return NULL636if (java_lang_Class::is_primitive(mirror)) return NULL;637638// Rules of Class.getSuperClass as implemented by KLass::java_super:639// arrays return Object640// interfaces return NULL641// proper classes return Klass::super()642Klass* k = java_lang_Class::as_Klass(mirror);643if (k->is_interface()) return NULL;644645// return mirror for superclass646Klass* super = k->java_super();647// super2 is the value computed by the compiler's getSuperClass intrinsic:648debug_only(Klass* super2 = ( k->oop_is_array()649? SystemDictionary::Object_klass()650: k->super() ) );651assert(super == super2,652"java_super computation depends on interface, array, other super");653obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(super->java_mirror());654return obj;655JNI_END656657JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))658JNIWrapper("IsSubclassOf");659#ifndef USDT2660DTRACE_PROBE3(hotspot_jni, IsAssignableFrom__entry, env, sub, super);661#else /* USDT2 */662HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(663env, sub, super);664#endif /* USDT2 */665oop sub_mirror = JNIHandles::resolve_non_null(sub);666oop super_mirror = JNIHandles::resolve_non_null(super);667if (java_lang_Class::is_primitive(sub_mirror) ||668java_lang_Class::is_primitive(super_mirror)) {669jboolean ret = (sub_mirror == super_mirror);670#ifndef USDT2671DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret);672#else /* USDT2 */673HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(674ret);675#endif /* USDT2 */676return ret;677}678Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);679Klass* super_klass = java_lang_Class::as_Klass(super_mirror);680assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");681jboolean ret = sub_klass->is_subtype_of(super_klass) ?682JNI_TRUE : JNI_FALSE;683#ifndef USDT2684DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret);685#else /* USDT2 */686HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(687ret);688#endif /* USDT2 */689return ret;690JNI_END691692#ifndef USDT2693DT_RETURN_MARK_DECL(Throw, jint);694#else /* USDT2 */695DT_RETURN_MARK_DECL(Throw, jint696, HOTSPOT_JNI_THROW_RETURN(_ret_ref));697#endif /* USDT2 */698699JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))700JNIWrapper("Throw");701#ifndef USDT2702DTRACE_PROBE2(hotspot_jni, Throw__entry, env, obj);703#else /* USDT2 */704HOTSPOT_JNI_THROW_ENTRY(705env, obj);706#endif /* USDT2 */707jint ret = JNI_OK;708DT_RETURN_MARK(Throw, jint, (const jint&)ret);709710THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);711ShouldNotReachHere();712return 0; // Mute compiler.713JNI_END714715#ifndef USDT2716DT_RETURN_MARK_DECL(ThrowNew, jint);717#else /* USDT2 */718DT_RETURN_MARK_DECL(ThrowNew, jint719, HOTSPOT_JNI_THROWNEW_RETURN(_ret_ref));720#endif /* USDT2 */721722JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message))723JNIWrapper("ThrowNew");724#ifndef USDT2725DTRACE_PROBE3(hotspot_jni, ThrowNew__entry, env, clazz, message);726#else /* USDT2 */727HOTSPOT_JNI_THROWNEW_ENTRY(728env, clazz, (char *) message);729#endif /* USDT2 */730jint ret = JNI_OK;731DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret);732733InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));734Symbol* name = k->name();735Handle class_loader (THREAD, k->class_loader());736Handle protection_domain (THREAD, k->protection_domain());737THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);738ShouldNotReachHere();739return 0; // Mute compiler.740JNI_END741742743// JNI functions only transform a pending async exception to a synchronous744// exception in ExceptionOccurred and ExceptionCheck calls, since745// delivering an async exception in other places won't change the native746// code's control flow and would be harmful when native code further calls747// JNI functions with a pending exception. Async exception is also checked748// during the call, so ExceptionOccurred/ExceptionCheck won't return749// false but deliver the async exception at the very end during750// state transition.751752static void jni_check_async_exceptions(JavaThread *thread) {753assert(thread == Thread::current(), "must be itself");754thread->check_and_handle_async_exceptions();755}756757JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env))758JNIWrapper("ExceptionOccurred");759#ifndef USDT2760DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__entry, env);761#else /* USDT2 */762HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY(763env);764#endif /* USDT2 */765jni_check_async_exceptions(thread);766oop exception = thread->pending_exception();767jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception);768#ifndef USDT2769DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__return, ret);770#else /* USDT2 */771HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(772ret);773#endif /* USDT2 */774return ret;775JNI_END776777778JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env))779JNIWrapper("ExceptionDescribe");780#ifndef USDT2781DTRACE_PROBE1(hotspot_jni, ExceptionDescribe__entry, env);782#else /* USDT2 */783HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY(784env);785#endif /* USDT2 */786if (thread->has_pending_exception()) {787Handle ex(thread, thread->pending_exception());788thread->clear_pending_exception();789if (ex->is_a(SystemDictionary::ThreadDeath_klass())) {790// Don't print anything if we are being killed.791} else {792jio_fprintf(defaultStream::error_stream(), "Exception ");793if (thread != NULL && thread->threadObj() != NULL) {794ResourceMark rm(THREAD);795jio_fprintf(defaultStream::error_stream(),796"in thread \"%s\" ", thread->get_thread_name());797}798if (ex->is_a(SystemDictionary::Throwable_klass())) {799JavaValue result(T_VOID);800JavaCalls::call_virtual(&result,801ex,802KlassHandle(THREAD,803SystemDictionary::Throwable_klass()),804vmSymbols::printStackTrace_name(),805vmSymbols::void_method_signature(),806THREAD);807// If an exception is thrown in the call it gets thrown away. Not much808// we can do with it. The native code that calls this, does not check809// for the exception - hence, it might still be in the thread when DestroyVM gets810// called, potentially causing a few asserts to trigger - since no pending exception811// is expected.812CLEAR_PENDING_EXCEPTION;813} else {814ResourceMark rm(THREAD);815jio_fprintf(defaultStream::error_stream(),816". Uncaught exception of type %s.",817ex->klass()->external_name());818}819}820}821#ifndef USDT2822DTRACE_PROBE(hotspot_jni, ExceptionDescribe__return);823#else /* USDT2 */824HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN(825);826#endif /* USDT2 */827JNI_END828829830JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env))831JNIWrapper("ExceptionClear");832#ifndef USDT2833DTRACE_PROBE1(hotspot_jni, ExceptionClear__entry, env);834#else /* USDT2 */835HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY(836env);837#endif /* USDT2 */838839// The jni code might be using this API to clear java thrown exception.840// So just mark jvmti thread exception state as exception caught.841JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state();842if (state != NULL && state->is_exception_detected()) {843state->set_exception_caught();844}845thread->clear_pending_exception();846#ifndef USDT2847DTRACE_PROBE(hotspot_jni, ExceptionClear__return);848#else /* USDT2 */849HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN(850);851#endif /* USDT2 */852JNI_END853854855JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg))856JNIWrapper("FatalError");857#ifndef USDT2858DTRACE_PROBE2(hotspot_jni, FatalError__entry, env, msg);859#else /* USDT2 */860HOTSPOT_JNI_FATALERROR_ENTRY(861env, (char *) msg);862#endif /* USDT2 */863tty->print_cr("FATAL ERROR in native method: %s", msg);864thread->print_stack();865os::abort(); // Dump core and abort866JNI_END867868869JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity))870JNIWrapper("PushLocalFrame");871#ifndef USDT2872DTRACE_PROBE2(hotspot_jni, PushLocalFrame__entry, env, capacity);873#else /* USDT2 */874HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY(875env, capacity);876#endif /* USDT2 */877//%note jni_11878if (capacity < 0 ||879((MaxJNILocalCapacity > 0) && (capacity > MaxJNILocalCapacity))) {880#ifndef USDT2881DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR);882#else /* USDT2 */883HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(884(uint32_t)JNI_ERR);885#endif /* USDT2 */886return JNI_ERR;887}888JNIHandleBlock* old_handles = thread->active_handles();889JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);890assert(new_handles != NULL, "should not be NULL");891new_handles->set_pop_frame_link(old_handles);892thread->set_active_handles(new_handles);893jint ret = JNI_OK;894#ifndef USDT2895DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, ret);896#else /* USDT2 */897HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(898ret);899#endif /* USDT2 */900return ret;901JNI_END902903904JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result))905JNIWrapper("PopLocalFrame");906#ifndef USDT2907DTRACE_PROBE2(hotspot_jni, PopLocalFrame__entry, env, result);908#else /* USDT2 */909HOTSPOT_JNI_POPLOCALFRAME_ENTRY(910env, result);911#endif /* USDT2 */912//%note jni_11913Handle result_handle(thread, JNIHandles::resolve(result));914JNIHandleBlock* old_handles = thread->active_handles();915JNIHandleBlock* new_handles = old_handles->pop_frame_link();916if (new_handles != NULL) {917// As a sanity check we only release the handle blocks if the pop_frame_link is not NULL.918// This way code will still work if PopLocalFrame is called without a corresponding919// PushLocalFrame call. Note that we set the pop_frame_link to NULL explicitly, otherwise920// the release_block call will release the blocks.921thread->set_active_handles(new_handles);922old_handles->set_pop_frame_link(NULL); // clear link we won't release new_handles below923JNIHandleBlock::release_block(old_handles, thread); // may block924result = JNIHandles::make_local(thread, result_handle());925}926#ifndef USDT2927DTRACE_PROBE1(hotspot_jni, PopLocalFrame__return, result);928#else /* USDT2 */929HOTSPOT_JNI_POPLOCALFRAME_RETURN(930result);931#endif /* USDT2 */932return result;933JNI_END934935936JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref))937JNIWrapper("NewGlobalRef");938#ifndef USDT2939DTRACE_PROBE2(hotspot_jni, NewGlobalRef__entry, env, ref);940#else /* USDT2 */941HOTSPOT_JNI_NEWGLOBALREF_ENTRY(942env, ref);943#endif /* USDT2 */944Handle ref_handle(thread, JNIHandles::resolve(ref));945jobject ret = JNIHandles::make_global(ref_handle);946#ifndef USDT2947DTRACE_PROBE1(hotspot_jni, NewGlobalRef__return, ret);948#else /* USDT2 */949HOTSPOT_JNI_NEWGLOBALREF_RETURN(950ret);951#endif /* USDT2 */952return ret;953JNI_END954955// Must be JNI_ENTRY (with HandleMark)956JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref))957JNIWrapper("DeleteGlobalRef");958#ifndef USDT2959DTRACE_PROBE2(hotspot_jni, DeleteGlobalRef__entry, env, ref);960#else /* USDT2 */961HOTSPOT_JNI_DELETEGLOBALREF_ENTRY(962env, ref);963#endif /* USDT2 */964JNIHandles::destroy_global(ref);965#ifndef USDT2966DTRACE_PROBE(hotspot_jni, DeleteGlobalRef__return);967#else /* USDT2 */968HOTSPOT_JNI_DELETEGLOBALREF_RETURN(969);970#endif /* USDT2 */971JNI_END972973JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj))974JNIWrapper("DeleteLocalRef");975#ifndef USDT2976DTRACE_PROBE2(hotspot_jni, DeleteLocalRef__entry, env, obj);977#else /* USDT2 */978HOTSPOT_JNI_DELETELOCALREF_ENTRY(979env, obj);980#endif /* USDT2 */981JNIHandles::destroy_local(obj);982#ifndef USDT2983DTRACE_PROBE(hotspot_jni, DeleteLocalRef__return);984#else /* USDT2 */985HOTSPOT_JNI_DELETELOCALREF_RETURN(986);987#endif /* USDT2 */988JNI_END989990JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2))991JNIWrapper("IsSameObject");992#ifndef USDT2993DTRACE_PROBE3(hotspot_jni, IsSameObject__entry, env, r1, r2);994#else /* USDT2 */995HOTSPOT_JNI_ISSAMEOBJECT_ENTRY(996env, r1, r2);997#endif /* USDT2 */998oop a = JNIHandles::resolve(r1);999oop b = JNIHandles::resolve(r2);1000jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE;1001#ifndef USDT21002DTRACE_PROBE1(hotspot_jni, IsSameObject__return, ret);1003#else /* USDT2 */1004HOTSPOT_JNI_ISSAMEOBJECT_RETURN(1005ret);1006#endif /* USDT2 */1007return ret;1008JNI_END100910101011JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref))1012JNIWrapper("NewLocalRef");1013#ifndef USDT21014DTRACE_PROBE2(hotspot_jni, NewLocalRef__entry, env, ref);1015#else /* USDT2 */1016HOTSPOT_JNI_NEWLOCALREF_ENTRY(1017env, ref);1018#endif /* USDT2 */1019jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref));1020#ifndef USDT21021DTRACE_PROBE1(hotspot_jni, NewLocalRef__return, ret);1022#else /* USDT2 */1023HOTSPOT_JNI_NEWLOCALREF_RETURN(1024ret);1025#endif /* USDT2 */1026return ret;1027JNI_END10281029JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity))1030JNIWrapper("EnsureLocalCapacity");1031#ifndef USDT21032DTRACE_PROBE2(hotspot_jni, EnsureLocalCapacity__entry, env, capacity);1033#else /* USDT2 */1034HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY(1035env, capacity);1036#endif /* USDT2 */1037jint ret;1038if (capacity >= 0 &&1039((MaxJNILocalCapacity <= 0) || (capacity <= MaxJNILocalCapacity))) {1040ret = JNI_OK;1041} else {1042ret = JNI_ERR;1043}1044#ifndef USDT21045DTRACE_PROBE1(hotspot_jni, EnsureLocalCapacity__return, ret);1046#else /* USDT2 */1047HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN(1048ret);1049#endif /* USDT2 */1050return ret;1051JNI_END10521053// Return the Handle Type1054JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj))1055JNIWrapper("GetObjectRefType");1056#ifndef USDT21057DTRACE_PROBE2(hotspot_jni, GetObjectRefType__entry, env, obj);1058#else /* USDT2 */1059HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY(1060env, obj);1061#endif /* USDT2 */1062jobjectRefType ret;1063if (JNIHandles::is_local_handle(thread, obj) ||1064JNIHandles::is_frame_handle(thread, obj))1065ret = JNILocalRefType;1066else if (JNIHandles::is_global_handle(obj))1067ret = JNIGlobalRefType;1068else if (JNIHandles::is_weak_global_handle(obj))1069ret = JNIWeakGlobalRefType;1070else1071ret = JNIInvalidRefType;1072#ifndef USDT21073DTRACE_PROBE1(hotspot_jni, GetObjectRefType__return, ret);1074#else /* USDT2 */1075HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN(1076(void *) ret);1077#endif /* USDT2 */1078return ret;1079JNI_END108010811082class JNI_ArgumentPusher : public SignatureIterator {1083protected:1084JavaCallArguments* _arguments;10851086virtual void get_bool () = 0;1087virtual void get_char () = 0;1088virtual void get_short () = 0;1089virtual void get_byte () = 0;1090virtual void get_int () = 0;1091virtual void get_long () = 0;1092virtual void get_float () = 0;1093virtual void get_double () = 0;1094virtual void get_object () = 0;10951096JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) {1097this->_return_type = T_ILLEGAL;1098_arguments = NULL;1099}11001101public:1102virtual void iterate( uint64_t fingerprint ) = 0;11031104void set_java_argument_object(JavaCallArguments *arguments) { _arguments = arguments; }11051106inline void do_bool() { if (!is_return_type()) get_bool(); }1107inline void do_char() { if (!is_return_type()) get_char(); }1108inline void do_short() { if (!is_return_type()) get_short(); }1109inline void do_byte() { if (!is_return_type()) get_byte(); }1110inline void do_int() { if (!is_return_type()) get_int(); }1111inline void do_long() { if (!is_return_type()) get_long(); }1112inline void do_float() { if (!is_return_type()) get_float(); }1113inline void do_double() { if (!is_return_type()) get_double(); }1114inline void do_object(int begin, int end) { if (!is_return_type()) get_object(); }1115inline void do_array(int begin, int end) { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array1116inline void do_void() { }11171118JavaCallArguments* arguments() { return _arguments; }1119void push_receiver(Handle h) { _arguments->push_oop(h); }1120};112111221123class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {1124protected:1125va_list _ap;11261127inline void get_bool() {1128// Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and1129// 0 to JNI_FALSE. Boolean return values from native are normalized the same in1130// TemplateInterpreterGenerator::generate_result_handler_for and1131// SharedRuntime::generate_native_wrapper.1132jboolean b = va_arg(_ap, jint);1133_arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE));1134}1135inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg1136inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg1137inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg1138inline void get_int() { _arguments->push_int(va_arg(_ap, jint)); }11391140// each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests11411142inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); }1143inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg1144inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); }1145inline void get_object() { _arguments->push_jobject(va_arg(_ap, jobject)); }11461147inline void set_ap(va_list rap) {1148#ifdef va_copy1149va_copy(_ap, rap);1150#elif defined (__va_copy)1151__va_copy(_ap, rap);1152#else1153_ap = rap;1154#endif1155}11561157public:1158JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap)1159: JNI_ArgumentPusher(signature) {1160set_ap(rap);1161}1162JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)1163: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {1164set_ap(rap);1165}11661167// Optimized path if we have the bitvector form of signature1168void iterate( uint64_t fingerprint ) {1169if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate();// Must be too many arguments1170else {1171_return_type = (BasicType)((fingerprint >> static_feature_size) &1172result_feature_mask);11731174assert(fingerprint, "Fingerprint should not be 0");1175fingerprint = fingerprint >> (static_feature_size + result_feature_size);1176while ( 1 ) {1177switch ( fingerprint & parameter_feature_mask ) {1178case bool_parm:1179get_bool();1180break;1181case char_parm:1182get_char();1183break;1184case short_parm:1185get_short();1186break;1187case byte_parm:1188get_byte();1189break;1190case int_parm:1191get_int();1192break;1193case obj_parm:1194get_object();1195break;1196case long_parm:1197get_long();1198break;1199case float_parm:1200get_float();1201break;1202case double_parm:1203get_double();1204break;1205case done_parm:1206return;1207break;1208default:1209ShouldNotReachHere();1210break;1211}1212fingerprint >>= parameter_feature_size;1213}1214}1215}1216};121712181219class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {1220protected:1221const jvalue *_ap;12221223inline void get_bool() {1224// Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and1225// 0 to JNI_FALSE. Boolean return values from native are normalized the same in1226// TemplateInterpreterGenerator::generate_result_handler_for and1227// SharedRuntime::generate_native_wrapper.1228jboolean b = (_ap++)->z;1229_arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE));1230}1231inline void get_char() { _arguments->push_int((jint)(_ap++)->c); }1232inline void get_short() { _arguments->push_int((jint)(_ap++)->s); }1233inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); }1234inline void get_int() { _arguments->push_int((jint)(_ap++)->i); }12351236inline void get_long() { _arguments->push_long((_ap++)->j); }1237inline void get_float() { _arguments->push_float((_ap++)->f); }1238inline void get_double() { _arguments->push_double((_ap++)->d);}1239inline void get_object() { _arguments->push_jobject((_ap++)->l); }12401241inline void set_ap(const jvalue *rap) { _ap = rap; }12421243public:1244JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap)1245: JNI_ArgumentPusher(signature) {1246set_ap(rap);1247}1248JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)1249: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {1250set_ap(rap);1251}12521253// Optimized path if we have the bitvector form of signature1254void iterate( uint64_t fingerprint ) {1255if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate(); // Must be too many arguments1256else {1257_return_type = (BasicType)((fingerprint >> static_feature_size) &1258result_feature_mask);1259assert(fingerprint, "Fingerprint should not be 0");1260fingerprint = fingerprint >> (static_feature_size + result_feature_size);1261while ( 1 ) {1262switch ( fingerprint & parameter_feature_mask ) {1263case bool_parm:1264get_bool();1265break;1266case char_parm:1267get_char();1268break;1269case short_parm:1270get_short();1271break;1272case byte_parm:1273get_byte();1274break;1275case int_parm:1276get_int();1277break;1278case obj_parm:1279get_object();1280break;1281case long_parm:1282get_long();1283break;1284case float_parm:1285get_float();1286break;1287case double_parm:1288get_double();1289break;1290case done_parm:1291return;1292break;1293default:1294ShouldNotReachHere();1295break;1296}1297fingerprint >>= parameter_feature_size;1298}1299}1300}1301};130213031304enum JNICallType {1305JNI_STATIC,1306JNI_VIRTUAL,1307JNI_NONVIRTUAL1308};1309131013111312static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {1313methodHandle method(THREAD, Method::resolve_jmethod_id(method_id));13141315// Create object to hold arguments for the JavaCall, and associate it with1316// the jni parser1317ResourceMark rm(THREAD);1318int number_of_parameters = method->size_of_parameters();1319JavaCallArguments java_args(number_of_parameters);1320args->set_java_argument_object(&java_args);13211322assert(method->is_static(), "method should be static");13231324// Fill out JavaCallArguments object1325args->iterate( Fingerprinter(method).fingerprint() );1326// Initialize result type1327result->set_type(args->get_ret_type());13281329// Invoke the method. Result is returned as oop.1330JavaCalls::call(result, method, &java_args, CHECK);13311332// Convert result1333if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {1334result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));1335}1336}133713381339static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {1340oop recv = JNIHandles::resolve(receiver);1341if (recv == NULL) {1342THROW(vmSymbols::java_lang_NullPointerException());1343}1344Handle h_recv(THREAD, recv);13451346int number_of_parameters;1347Method* selected_method;1348{1349Method* m = Method::resolve_jmethod_id(method_id);1350number_of_parameters = m->size_of_parameters();1351Klass* holder = m->method_holder();1352if (call_type != JNI_VIRTUAL) {1353selected_method = m;1354} else if (!m->has_itable_index()) {1355// non-interface call -- for that little speed boost, don't handlize1356debug_only(No_Safepoint_Verifier nosafepoint;)1357// jni_GetMethodID makes sure class is linked and initialized1358// so m should have a valid vtable index.1359assert(m->valid_vtable_index(), "no valid vtable index");1360int vtbl_index = m->vtable_index();1361if (vtbl_index != Method::nonvirtual_vtable_index) {1362Klass* k = h_recv->klass();1363// k might be an arrayKlassOop but all vtables start at1364// the same place. The cast is to avoid virtual call and assertion.1365InstanceKlass *ik = (InstanceKlass*)k;1366selected_method = ik->method_at_vtable(vtbl_index);1367} else {1368// final method1369selected_method = m;1370}1371} else {1372// interface call1373KlassHandle h_holder(THREAD, holder);13741375int itbl_index = m->itable_index();1376Klass* k = h_recv->klass();1377selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);1378}1379}13801381methodHandle method(THREAD, selected_method);13821383// Create object to hold arguments for the JavaCall, and associate it with1384// the jni parser1385ResourceMark rm(THREAD);1386JavaCallArguments java_args(number_of_parameters);1387args->set_java_argument_object(&java_args);13881389// handle arguments1390assert(!method->is_static(), "method should not be static");1391args->push_receiver(h_recv); // Push jobject handle13921393// Fill out JavaCallArguments object1394args->iterate( Fingerprinter(method).fingerprint() );1395// Initialize result type1396result->set_type(args->get_ret_type());13971398// Invoke the method. Result is returned as oop.1399JavaCalls::call(result, method, &java_args, CHECK);14001401// Convert result1402if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {1403result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));1404}1405}140614071408static instanceOop alloc_object(jclass clazz, TRAPS) {1409KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));1410k()->check_valid_for_instantiation(false, CHECK_NULL);1411InstanceKlass::cast(k())->initialize(CHECK_NULL);1412instanceOop ih = InstanceKlass::cast(k())->allocate_instance(THREAD);1413return ih;1414}14151416#ifndef USDT21417DT_RETURN_MARK_DECL(AllocObject, jobject);1418#else /* USDT2 */1419DT_RETURN_MARK_DECL(AllocObject, jobject1420, HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));1421#endif /* USDT2 */14221423JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))1424JNIWrapper("AllocObject");14251426#ifndef USDT21427DTRACE_PROBE2(hotspot_jni, AllocObject__entry, env, clazz);1428#else /* USDT2 */1429HOTSPOT_JNI_ALLOCOBJECT_ENTRY(1430env, clazz);1431#endif /* USDT2 */1432jobject ret = NULL;1433DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);14341435instanceOop i = alloc_object(clazz, CHECK_NULL);1436ret = JNIHandles::make_local(env, i);1437return ret;1438JNI_END14391440#ifndef USDT21441DT_RETURN_MARK_DECL(NewObjectA, jobject);1442#else /* USDT2 */1443DT_RETURN_MARK_DECL(NewObjectA, jobject1444, HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));1445#endif /* USDT2 */14461447JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))1448JNIWrapper("NewObjectA");1449#ifndef USDT21450DTRACE_PROBE3(hotspot_jni, NewObjectA__entry, env, clazz, methodID);1451#else /* USDT2 */1452HOTSPOT_JNI_NEWOBJECTA_ENTRY(1453env, clazz, (uintptr_t) methodID);1454#endif /* USDT2 */1455jobject obj = NULL;1456DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj);14571458instanceOop i = alloc_object(clazz, CHECK_NULL);1459obj = JNIHandles::make_local(env, i);1460JavaValue jvalue(T_VOID);1461JNI_ArgumentPusherArray ap(methodID, args);1462jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);1463return obj;1464JNI_END14651466#ifndef USDT21467DT_RETURN_MARK_DECL(NewObjectV, jobject);1468#else /* USDT2 */1469DT_RETURN_MARK_DECL(NewObjectV, jobject1470, HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));1471#endif /* USDT2 */14721473JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))1474JNIWrapper("NewObjectV");1475#ifndef USDT21476DTRACE_PROBE3(hotspot_jni, NewObjectV__entry, env, clazz, methodID);1477#else /* USDT2 */1478HOTSPOT_JNI_NEWOBJECTV_ENTRY(1479env, clazz, (uintptr_t) methodID);1480#endif /* USDT2 */1481jobject obj = NULL;1482DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);14831484instanceOop i = alloc_object(clazz, CHECK_NULL);1485obj = JNIHandles::make_local(env, i);1486JavaValue jvalue(T_VOID);1487JNI_ArgumentPusherVaArg ap(methodID, args);1488jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);1489return obj;1490JNI_END14911492#ifndef USDT21493DT_RETURN_MARK_DECL(NewObject, jobject);1494#else /* USDT2 */1495DT_RETURN_MARK_DECL(NewObject, jobject1496, HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));1497#endif /* USDT2 */14981499JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))1500JNIWrapper("NewObject");1501#ifndef USDT21502DTRACE_PROBE3(hotspot_jni, NewObject__entry, env, clazz, methodID);1503#else /* USDT2 */1504HOTSPOT_JNI_NEWOBJECT_ENTRY(1505env, clazz, (uintptr_t) methodID);1506#endif /* USDT2 */1507jobject obj = NULL;1508DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);15091510instanceOop i = alloc_object(clazz, CHECK_NULL);1511obj = JNIHandles::make_local(env, i);1512va_list args;1513va_start(args, methodID);1514JavaValue jvalue(T_VOID);1515JNI_ArgumentPusherVaArg ap(methodID, args);1516jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);1517va_end(args);1518return obj;1519JNI_END152015211522JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))1523JNIWrapper("GetObjectClass");1524#ifndef USDT21525DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj);1526#else /* USDT2 */1527HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(1528env, obj);1529#endif /* USDT2 */1530Klass* k = JNIHandles::resolve_non_null(obj)->klass();1531jclass ret =1532(jclass) JNIHandles::make_local(env, k->java_mirror());1533#ifndef USDT21534DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret);1535#else /* USDT2 */1536HOTSPOT_JNI_GETOBJECTCLASS_RETURN(1537ret);1538#endif /* USDT2 */1539return ret;1540JNI_END15411542JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))1543JNIWrapper("IsInstanceOf");1544#ifndef USDT21545DTRACE_PROBE3(hotspot_jni, IsInstanceOf__entry, env, obj, clazz);1546#else /* USDT2 */1547HOTSPOT_JNI_ISINSTANCEOF_ENTRY(1548env, obj, clazz);1549#endif /* USDT2 */1550jboolean ret = JNI_TRUE;1551if (obj != NULL) {1552ret = JNI_FALSE;1553Klass* k = java_lang_Class::as_Klass(1554JNIHandles::resolve_non_null(clazz));1555if (k != NULL) {1556ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE;1557}1558}1559#ifndef USDT21560DTRACE_PROBE1(hotspot_jni, IsInstanceOf__return, ret);1561#else /* USDT2 */1562HOTSPOT_JNI_ISINSTANCEOF_RETURN(1563ret);1564#endif /* USDT2 */1565return ret;1566JNI_END156715681569static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str,1570const char *sig, bool is_static, TRAPS) {1571// %%%% This code should probably just call into a method in the LinkResolver1572//1573// The class should have been loaded (we have an instance of the class1574// passed in) so the method and signature should already be in the symbol1575// table. If they're not there, the method doesn't exist.1576const char *name_to_probe = (name_str == NULL)1577? vmSymbols::object_initializer_name()->as_C_string()1578: name_str;1579TempNewSymbol name = SymbolTable::probe(name_to_probe, (int)strlen(name_to_probe));1580TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig));15811582if (name == NULL || signature == NULL) {1583THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);1584}15851586// Throw a NoSuchMethodError exception if we have an instance of a1587// primitive java.lang.Class1588if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) {1589THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);1590}15911592KlassHandle klass(THREAD,1593java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));15941595// Make sure class is linked and initialized before handing id's out to1596// Method*s.1597klass()->initialize(CHECK_NULL);15981599Method* m;1600if (name == vmSymbols::object_initializer_name() ||1601name == vmSymbols::class_initializer_name()) {1602// Never search superclasses for constructors1603if (klass->oop_is_instance()) {1604m = InstanceKlass::cast(klass())->find_method(name, signature);1605} else {1606m = NULL;1607}1608} else {1609m = klass->lookup_method(name, signature);1610if (m == NULL && klass->oop_is_instance()) {1611m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature);1612}1613}1614if (m == NULL || (m->is_static() != is_static)) {1615THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);1616}1617return m->jmethod_id();1618}161916201621JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz,1622const char *name, const char *sig))1623JNIWrapper("GetMethodID");1624#ifndef USDT21625DTRACE_PROBE4(hotspot_jni, GetMethodID__entry, env, clazz, name, sig);1626#else /* USDT2 */1627HOTSPOT_JNI_GETMETHODID_ENTRY(1628env, clazz, (char *) name, (char *) sig);1629#endif /* USDT2 */1630jmethodID ret = get_method_id(env, clazz, name, sig, false, thread);1631#ifndef USDT21632DTRACE_PROBE1(hotspot_jni, GetMethodID__return, ret);1633#else /* USDT2 */1634HOTSPOT_JNI_GETMETHODID_RETURN(1635(uintptr_t) ret);1636#endif /* USDT2 */1637return ret;1638JNI_END163916401641JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz,1642const char *name, const char *sig))1643JNIWrapper("GetStaticMethodID");1644#ifndef USDT21645DTRACE_PROBE4(hotspot_jni, GetStaticMethodID__entry, env, clazz, name, sig);1646#else /* USDT2 */1647HOTSPOT_JNI_GETSTATICMETHODID_ENTRY(1648env, (char *) clazz, (char *) name, (char *)sig);1649#endif /* USDT2 */1650jmethodID ret = get_method_id(env, clazz, name, sig, true, thread);1651#ifndef USDT21652DTRACE_PROBE1(hotspot_jni, GetStaticMethodID__return, ret);1653#else /* USDT2 */1654HOTSPOT_JNI_GETSTATICMETHODID_RETURN(1655(uintptr_t) ret);1656#endif /* USDT2 */1657return ret;1658JNI_END1659166016611662//1663// Calling Methods1664//16651666#ifndef USDT21667#define DEFINE_CALLMETHOD(ResultType, Result, Tag) \1668\1669DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType);\1670DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType);\1671DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType);\1672\1673JNI_ENTRY(ResultType, \1674jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \1675JNIWrapper("Call" XSTR(Result) "Method"); \1676\1677DTRACE_PROBE3(hotspot_jni, Call##Result##Method__entry, env, obj, methodID); \1678ResultType ret = 0;\1679DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \1680(const ResultType&)ret);\1681\1682va_list args; \1683va_start(args, methodID); \1684JavaValue jvalue(Tag); \1685JNI_ArgumentPusherVaArg ap(methodID, args); \1686jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \1687va_end(args); \1688ret = jvalue.get_##ResultType(); \1689return ret;\1690JNI_END \1691\1692\1693JNI_ENTRY(ResultType, \1694jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \1695JNIWrapper("Call" XSTR(Result) "MethodV"); \1696\1697DTRACE_PROBE3(hotspot_jni, Call##Result##MethodV__entry, env, obj, methodID); \1698ResultType ret = 0;\1699DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \1700(const ResultType&)ret);\1701\1702JavaValue jvalue(Tag); \1703JNI_ArgumentPusherVaArg ap(methodID, args); \1704jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \1705ret = jvalue.get_##ResultType(); \1706return ret;\1707JNI_END \1708\1709\1710JNI_ENTRY(ResultType, \1711jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \1712JNIWrapper("Call" XSTR(Result) "MethodA"); \1713DTRACE_PROBE3(hotspot_jni, Call##Result##MethodA__entry, env, obj, methodID); \1714ResultType ret = 0;\1715DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \1716(const ResultType&)ret);\1717\1718JavaValue jvalue(Tag); \1719JNI_ArgumentPusherArray ap(methodID, args); \1720jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \1721ret = jvalue.get_##ResultType(); \1722return ret;\1723JNI_END17241725// the runtime type of subword integral basic types is integer1726DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN)1727DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE)1728DEFINE_CALLMETHOD(jchar, Char, T_CHAR)1729DEFINE_CALLMETHOD(jshort, Short, T_SHORT)17301731DEFINE_CALLMETHOD(jobject, Object, T_OBJECT)1732DEFINE_CALLMETHOD(jint, Int, T_INT)1733DEFINE_CALLMETHOD(jlong, Long, T_LONG)1734DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT)1735DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE)17361737DT_VOID_RETURN_MARK_DECL(CallVoidMethod);1738DT_VOID_RETURN_MARK_DECL(CallVoidMethodV);1739DT_VOID_RETURN_MARK_DECL(CallVoidMethodA);17401741#else /* USDT2 */17421743#define DEFINE_CALLMETHOD(ResultType, Result, Tag \1744, EntryProbe, ReturnProbe) \1745\1746DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType \1747, ReturnProbe); \1748\1749JNI_ENTRY(ResultType, \1750jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \1751JNIWrapper("Call" XSTR(Result) "Method"); \1752\1753EntryProbe; \1754ResultType ret = 0;\1755DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \1756(const ResultType&)ret);\1757\1758va_list args; \1759va_start(args, methodID); \1760JavaValue jvalue(Tag); \1761JNI_ArgumentPusherVaArg ap(methodID, args); \1762jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \1763va_end(args); \1764ret = jvalue.get_##ResultType(); \1765return ret;\1766JNI_END17671768// the runtime type of subword integral basic types is integer1769DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN1770, HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1771HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref))1772DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE1773, HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1774HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref))1775DEFINE_CALLMETHOD(jchar, Char, T_CHAR1776, HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1777HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref))1778DEFINE_CALLMETHOD(jshort, Short, T_SHORT1779, HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1780HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref))17811782DEFINE_CALLMETHOD(jobject, Object, T_OBJECT1783, HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1784HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref))1785DEFINE_CALLMETHOD(jint, Int, T_INT,1786HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1787HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref))1788DEFINE_CALLMETHOD(jlong, Long, T_LONG1789, HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1790HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref))1791// Float and double probes don't return value because dtrace doesn't currently support it1792DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT1793, HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1794HOTSPOT_JNI_CALLFLOATMETHOD_RETURN())1795DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE1796, HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),1797HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN())17981799#define DEFINE_CALLMETHODV(ResultType, Result, Tag \1800, EntryProbe, ReturnProbe) \1801\1802DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType \1803, ReturnProbe); \1804\1805JNI_ENTRY(ResultType, \1806jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \1807JNIWrapper("Call" XSTR(Result) "MethodV"); \1808\1809EntryProbe;\1810ResultType ret = 0;\1811DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \1812(const ResultType&)ret);\1813\1814JavaValue jvalue(Tag); \1815JNI_ArgumentPusherVaArg ap(methodID, args); \1816jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \1817ret = jvalue.get_##ResultType(); \1818return ret;\1819JNI_END18201821// the runtime type of subword integral basic types is integer1822DEFINE_CALLMETHODV(jboolean, Boolean, T_BOOLEAN1823, HOTSPOT_JNI_CALLBOOLEANMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1824HOTSPOT_JNI_CALLBOOLEANMETHODV_RETURN(_ret_ref))1825DEFINE_CALLMETHODV(jbyte, Byte, T_BYTE1826, HOTSPOT_JNI_CALLBYTEMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1827HOTSPOT_JNI_CALLBYTEMETHODV_RETURN(_ret_ref))1828DEFINE_CALLMETHODV(jchar, Char, T_CHAR1829, HOTSPOT_JNI_CALLCHARMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1830HOTSPOT_JNI_CALLCHARMETHODV_RETURN(_ret_ref))1831DEFINE_CALLMETHODV(jshort, Short, T_SHORT1832, HOTSPOT_JNI_CALLSHORTMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1833HOTSPOT_JNI_CALLSHORTMETHODV_RETURN(_ret_ref))18341835DEFINE_CALLMETHODV(jobject, Object, T_OBJECT1836, HOTSPOT_JNI_CALLOBJECTMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1837HOTSPOT_JNI_CALLOBJECTMETHODV_RETURN(_ret_ref))1838DEFINE_CALLMETHODV(jint, Int, T_INT,1839HOTSPOT_JNI_CALLINTMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1840HOTSPOT_JNI_CALLINTMETHODV_RETURN(_ret_ref))1841DEFINE_CALLMETHODV(jlong, Long, T_LONG1842, HOTSPOT_JNI_CALLLONGMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1843HOTSPOT_JNI_CALLLONGMETHODV_RETURN(_ret_ref))1844// Float and double probes don't return value because dtrace doesn't currently support it1845DEFINE_CALLMETHODV(jfloat, Float, T_FLOAT1846, HOTSPOT_JNI_CALLFLOATMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1847HOTSPOT_JNI_CALLFLOATMETHODV_RETURN())1848DEFINE_CALLMETHODV(jdouble, Double, T_DOUBLE1849, HOTSPOT_JNI_CALLDOUBLEMETHODV_ENTRY(env, obj, (uintptr_t)methodID),1850HOTSPOT_JNI_CALLDOUBLEMETHODV_RETURN())18511852#define DEFINE_CALLMETHODA(ResultType, Result, Tag \1853, EntryProbe, ReturnProbe) \1854\1855DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType \1856, ReturnProbe); \1857\1858JNI_ENTRY(ResultType, \1859jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \1860JNIWrapper("Call" XSTR(Result) "MethodA"); \1861EntryProbe; \1862ResultType ret = 0;\1863DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \1864(const ResultType&)ret);\1865\1866JavaValue jvalue(Tag); \1867JNI_ArgumentPusherArray ap(methodID, args); \1868jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \1869ret = jvalue.get_##ResultType(); \1870return ret;\1871JNI_END18721873// the runtime type of subword integral basic types is integer1874DEFINE_CALLMETHODA(jboolean, Boolean, T_BOOLEAN1875, HOTSPOT_JNI_CALLBOOLEANMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1876HOTSPOT_JNI_CALLBOOLEANMETHODA_RETURN(_ret_ref))1877DEFINE_CALLMETHODA(jbyte, Byte, T_BYTE1878, HOTSPOT_JNI_CALLBYTEMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1879HOTSPOT_JNI_CALLBYTEMETHODA_RETURN(_ret_ref))1880DEFINE_CALLMETHODA(jchar, Char, T_CHAR1881, HOTSPOT_JNI_CALLCHARMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1882HOTSPOT_JNI_CALLCHARMETHODA_RETURN(_ret_ref))1883DEFINE_CALLMETHODA(jshort, Short, T_SHORT1884, HOTSPOT_JNI_CALLSHORTMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1885HOTSPOT_JNI_CALLSHORTMETHODA_RETURN(_ret_ref))18861887DEFINE_CALLMETHODA(jobject, Object, T_OBJECT1888, HOTSPOT_JNI_CALLOBJECTMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1889HOTSPOT_JNI_CALLOBJECTMETHODA_RETURN(_ret_ref))1890DEFINE_CALLMETHODA(jint, Int, T_INT,1891HOTSPOT_JNI_CALLINTMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1892HOTSPOT_JNI_CALLINTMETHODA_RETURN(_ret_ref))1893DEFINE_CALLMETHODA(jlong, Long, T_LONG1894, HOTSPOT_JNI_CALLLONGMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1895HOTSPOT_JNI_CALLLONGMETHODA_RETURN(_ret_ref))1896// Float and double probes don't return value because dtrace doesn't currently support it1897DEFINE_CALLMETHODA(jfloat, Float, T_FLOAT1898, HOTSPOT_JNI_CALLFLOATMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1899HOTSPOT_JNI_CALLFLOATMETHODA_RETURN())1900DEFINE_CALLMETHODA(jdouble, Double, T_DOUBLE1901, HOTSPOT_JNI_CALLDOUBLEMETHODA_ENTRY(env, obj, (uintptr_t)methodID),1902HOTSPOT_JNI_CALLDOUBLEMETHODA_RETURN())19031904DT_VOID_RETURN_MARK_DECL(CallVoidMethod, HOTSPOT_JNI_CALLVOIDMETHOD_RETURN());1905DT_VOID_RETURN_MARK_DECL(CallVoidMethodV, HOTSPOT_JNI_CALLVOIDMETHODV_RETURN());1906DT_VOID_RETURN_MARK_DECL(CallVoidMethodA, HOTSPOT_JNI_CALLVOIDMETHODA_RETURN());19071908#endif /* USDT2 */19091910JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...))1911JNIWrapper("CallVoidMethod");1912#ifndef USDT21913DTRACE_PROBE3(hotspot_jni, CallVoidMethod__entry, env, obj, methodID);1914#else /* USDT2 */1915HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY(1916env, obj, (uintptr_t) methodID);1917#endif /* USDT2 */1918DT_VOID_RETURN_MARK(CallVoidMethod);19191920va_list args;1921va_start(args, methodID);1922JavaValue jvalue(T_VOID);1923JNI_ArgumentPusherVaArg ap(methodID, args);1924jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);1925va_end(args);1926JNI_END192719281929JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args))1930JNIWrapper("CallVoidMethodV");1931#ifndef USDT21932DTRACE_PROBE3(hotspot_jni, CallVoidMethodV__entry, env, obj, methodID);1933#else /* USDT2 */1934HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY(1935env, obj, (uintptr_t) methodID);1936#endif /* USDT2 */1937DT_VOID_RETURN_MARK(CallVoidMethodV);19381939JavaValue jvalue(T_VOID);1940JNI_ArgumentPusherVaArg ap(methodID, args);1941jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);1942JNI_END194319441945JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args))1946JNIWrapper("CallVoidMethodA");1947#ifndef USDT21948DTRACE_PROBE3(hotspot_jni, CallVoidMethodA__entry, env, obj, methodID);1949#else /* USDT2 */1950HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY(1951env, obj, (uintptr_t) methodID);1952#endif /* USDT2 */1953DT_VOID_RETURN_MARK(CallVoidMethodA);19541955JavaValue jvalue(T_VOID);1956JNI_ArgumentPusherArray ap(methodID, args);1957jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);1958JNI_END195919601961#ifndef USDT21962#define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag) \1963\1964DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType);\1965DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType);\1966DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType);\1967\1968JNI_ENTRY(ResultType, \1969jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \1970JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \1971\1972DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##Method__entry, env, obj, cls, methodID);\1973ResultType ret;\1974DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \1975(const ResultType&)ret);\1976\1977va_list args; \1978va_start(args, methodID); \1979JavaValue jvalue(Tag); \1980JNI_ArgumentPusherVaArg ap(methodID, args); \1981jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \1982va_end(args); \1983ret = jvalue.get_##ResultType(); \1984return ret;\1985JNI_END \1986\1987JNI_ENTRY(ResultType, \1988jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \1989JNIWrapper("CallNonvitual" XSTR(Result) "#MethodV"); \1990DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodV__entry, env, obj, cls, methodID);\1991ResultType ret;\1992DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \1993(const ResultType&)ret);\1994\1995JavaValue jvalue(Tag); \1996JNI_ArgumentPusherVaArg ap(methodID, args); \1997jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \1998ret = jvalue.get_##ResultType(); \1999return ret;\2000JNI_END \2001\2002JNI_ENTRY(ResultType, \2003jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \2004JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \2005DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodA__entry, env, obj, cls, methodID);\2006ResultType ret;\2007DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \2008(const ResultType&)ret);\2009\2010JavaValue jvalue(Tag); \2011JNI_ArgumentPusherArray ap(methodID, args); \2012jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \2013ret = jvalue.get_##ResultType(); \2014return ret;\2015JNI_END20162017// the runtime type of subword integral basic types is integer2018DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN)2019DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE)2020DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR)2021DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT)20222023DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT)2024DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT)2025DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG)2026DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT)2027DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE)202820292030DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod);2031DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV);2032DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA);20332034#else /* USDT2 */20352036#define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag \2037, EntryProbe, ReturnProbe) \2038\2039DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType \2040, ReturnProbe);\2041\2042JNI_ENTRY(ResultType, \2043jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \2044JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \2045\2046EntryProbe;\2047ResultType ret;\2048DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \2049(const ResultType&)ret);\2050\2051va_list args; \2052va_start(args, methodID); \2053JavaValue jvalue(Tag); \2054JNI_ArgumentPusherVaArg ap(methodID, args); \2055jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \2056va_end(args); \2057ret = jvalue.get_##ResultType(); \2058return ret;\2059JNI_END20602061// the runtime type of subword integral basic types is integer2062DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN2063, HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2064HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN(_ret_ref))2065DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE2066, HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2067HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN(_ret_ref))2068DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR2069, HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2070HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN(_ret_ref))2071DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT2072, HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2073HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN(_ret_ref))20742075DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT2076, HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2077HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN(_ret_ref))2078DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT2079, HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2080HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN(_ret_ref))2081DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG2082, HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2083// Float and double probes don't return value because dtrace doesn't currently support it2084HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN(_ret_ref))2085DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT2086, HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2087HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN())2088DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE2089, HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),2090HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN())20912092#define DEFINE_CALLNONVIRTUALMETHODV(ResultType, Result, Tag \2093, EntryProbe, ReturnProbe) \2094\2095DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType \2096, ReturnProbe);\2097\2098JNI_ENTRY(ResultType, \2099jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \2100JNIWrapper("CallNonvitual" XSTR(Result) "MethodV"); \2101\2102EntryProbe;\2103ResultType ret;\2104DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \2105(const ResultType&)ret);\2106\2107JavaValue jvalue(Tag); \2108JNI_ArgumentPusherVaArg ap(methodID, args); \2109jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \2110ret = jvalue.get_##ResultType(); \2111return ret;\2112JNI_END21132114// the runtime type of subword integral basic types is integer2115DEFINE_CALLNONVIRTUALMETHODV(jboolean, Boolean, T_BOOLEAN2116, HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2117HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN(_ret_ref))2118DEFINE_CALLNONVIRTUALMETHODV(jbyte, Byte, T_BYTE2119, HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2120HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN(_ret_ref))2121DEFINE_CALLNONVIRTUALMETHODV(jchar, Char, T_CHAR2122, HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2123HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN(_ret_ref))2124DEFINE_CALLNONVIRTUALMETHODV(jshort, Short, T_SHORT2125, HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2126HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN(_ret_ref))21272128DEFINE_CALLNONVIRTUALMETHODV(jobject, Object, T_OBJECT2129, HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2130HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN(_ret_ref))2131DEFINE_CALLNONVIRTUALMETHODV(jint, Int, T_INT2132, HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2133HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN(_ret_ref))2134DEFINE_CALLNONVIRTUALMETHODV(jlong, Long, T_LONG2135, HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2136// Float and double probes don't return value because dtrace doesn't currently support it2137HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN(_ret_ref))2138DEFINE_CALLNONVIRTUALMETHODV(jfloat, Float, T_FLOAT2139, HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2140HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN())2141DEFINE_CALLNONVIRTUALMETHODV(jdouble, Double, T_DOUBLE2142, HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),2143HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN())21442145#define DEFINE_CALLNONVIRTUALMETHODA(ResultType, Result, Tag \2146, EntryProbe, ReturnProbe) \2147\2148DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType \2149, ReturnProbe);\2150\2151JNI_ENTRY(ResultType, \2152jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \2153JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \2154\2155EntryProbe;\2156ResultType ret;\2157DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \2158(const ResultType&)ret);\2159\2160JavaValue jvalue(Tag); \2161JNI_ArgumentPusherArray ap(methodID, args); \2162jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \2163ret = jvalue.get_##ResultType(); \2164return ret;\2165JNI_END21662167// the runtime type of subword integral basic types is integer2168DEFINE_CALLNONVIRTUALMETHODA(jboolean, Boolean, T_BOOLEAN2169, HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2170HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN(_ret_ref))2171DEFINE_CALLNONVIRTUALMETHODA(jbyte, Byte, T_BYTE2172, HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2173HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN(_ret_ref))2174DEFINE_CALLNONVIRTUALMETHODA(jchar, Char, T_CHAR2175, HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2176HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN(_ret_ref))2177DEFINE_CALLNONVIRTUALMETHODA(jshort, Short, T_SHORT2178, HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2179HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN(_ret_ref))21802181DEFINE_CALLNONVIRTUALMETHODA(jobject, Object, T_OBJECT2182, HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2183HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN(_ret_ref))2184DEFINE_CALLNONVIRTUALMETHODA(jint, Int, T_INT2185, HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2186HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN(_ret_ref))2187DEFINE_CALLNONVIRTUALMETHODA(jlong, Long, T_LONG2188, HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2189// Float and double probes don't return value because dtrace doesn't currently support it2190HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN(_ret_ref))2191DEFINE_CALLNONVIRTUALMETHODA(jfloat, Float, T_FLOAT2192, HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2193HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN())2194DEFINE_CALLNONVIRTUALMETHODA(jdouble, Double, T_DOUBLE2195, HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),2196HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN())21972198DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod2199, HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN());2200DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV2201, HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN());2202DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA2203, HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN());2204#endif /* USDT2 */22052206JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...))2207JNIWrapper("CallNonvirtualVoidMethod");22082209#ifndef USDT22210DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethod__entry,2211env, obj, cls, methodID);2212#else /* USDT2 */2213HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY(2214env, obj, cls, (uintptr_t) methodID);2215#endif /* USDT2 */2216DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod);22172218va_list args;2219va_start(args, methodID);2220JavaValue jvalue(T_VOID);2221JNI_ArgumentPusherVaArg ap(methodID, args);2222jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);2223va_end(args);2224JNI_END222522262227JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args))2228JNIWrapper("CallNonvirtualVoidMethodV");22292230#ifndef USDT22231DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodV__entry,2232env, obj, cls, methodID);2233#else /* USDT2 */2234HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY(2235env, obj, cls, (uintptr_t) methodID);2236#endif /* USDT2 */2237DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV);22382239JavaValue jvalue(T_VOID);2240JNI_ArgumentPusherVaArg ap(methodID, args);2241jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);2242JNI_END224322442245JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args))2246JNIWrapper("CallNonvirtualVoidMethodA");2247#ifndef USDT22248DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodA__entry,2249env, obj, cls, methodID);2250#else /* USDT2 */2251HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY(2252env, obj, cls, (uintptr_t) methodID);2253#endif /* USDT2 */2254DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA);2255JavaValue jvalue(T_VOID);2256JNI_ArgumentPusherArray ap(methodID, args);2257jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);2258JNI_END225922602261#ifndef USDT22262#define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag) \2263\2264DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType);\2265DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType);\2266DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType);\2267\2268JNI_ENTRY(ResultType, \2269jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \2270JNIWrapper("CallStatic" XSTR(Result) "Method"); \2271\2272DTRACE_PROBE3(hotspot_jni, CallStatic##Result##Method__entry, env, cls, methodID);\2273ResultType ret = 0;\2274DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \2275(const ResultType&)ret);\2276\2277va_list args; \2278va_start(args, methodID); \2279JavaValue jvalue(Tag); \2280JNI_ArgumentPusherVaArg ap(methodID, args); \2281jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \2282va_end(args); \2283ret = jvalue.get_##ResultType(); \2284return ret;\2285JNI_END \2286\2287JNI_ENTRY(ResultType, \2288jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \2289JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \2290DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodV__entry, env, cls, methodID);\2291ResultType ret = 0;\2292DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \2293(const ResultType&)ret);\2294\2295JavaValue jvalue(Tag); \2296JNI_ArgumentPusherVaArg ap(methodID, args); \2297jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \2298ret = jvalue.get_##ResultType(); \2299return ret;\2300JNI_END \2301\2302JNI_ENTRY(ResultType, \2303jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \2304JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \2305DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodA__entry, env, cls, methodID);\2306ResultType ret = 0;\2307DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \2308(const ResultType&)ret);\2309\2310JavaValue jvalue(Tag); \2311JNI_ArgumentPusherArray ap(methodID, args); \2312jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \2313ret = jvalue.get_##ResultType(); \2314return ret;\2315JNI_END23162317// the runtime type of subword integral basic types is integer2318DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN)2319DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE)2320DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR)2321DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT)23222323DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT)2324DEFINE_CALLSTATICMETHOD(jint, Int, T_INT)2325DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG)2326DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT)2327DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE)232823292330DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod);2331DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV);2332DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA);23332334#else /* USDT2 */23352336#define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag \2337, EntryProbe, ResultProbe) \2338\2339DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType \2340, ResultProbe); \2341\2342JNI_ENTRY(ResultType, \2343jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \2344JNIWrapper("CallStatic" XSTR(Result) "Method"); \2345\2346EntryProbe; \2347ResultType ret = 0;\2348DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \2349(const ResultType&)ret);\2350\2351va_list args; \2352va_start(args, methodID); \2353JavaValue jvalue(Tag); \2354JNI_ArgumentPusherVaArg ap(methodID, args); \2355jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \2356va_end(args); \2357ret = jvalue.get_##ResultType(); \2358return ret;\2359JNI_END23602361// the runtime type of subword integral basic types is integer2362DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN2363, HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2364HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN(_ret_ref));2365DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE2366, HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2367HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN(_ret_ref));2368DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR2369, HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2370HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN(_ret_ref));2371DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT2372, HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2373HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN(_ret_ref));23742375DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT2376, HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2377HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN(_ret_ref));2378DEFINE_CALLSTATICMETHOD(jint, Int, T_INT2379, HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2380HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN(_ret_ref));2381DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG2382, HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2383HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN(_ret_ref));2384// Float and double probes don't return value because dtrace doesn't currently support it2385DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT2386, HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2387HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN());2388DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE2389, HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY(env, cls, (uintptr_t)methodID),2390HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN());23912392#define DEFINE_CALLSTATICMETHODV(ResultType, Result, Tag \2393, EntryProbe, ResultProbe) \2394\2395DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType \2396, ResultProbe); \2397\2398JNI_ENTRY(ResultType, \2399jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \2400JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \2401\2402EntryProbe; \2403ResultType ret = 0;\2404DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \2405(const ResultType&)ret);\2406\2407JavaValue jvalue(Tag); \2408JNI_ArgumentPusherVaArg ap(methodID, args); \2409/* Make sure class is initialized before trying to invoke its method */ \2410KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls))); \2411k()->initialize(CHECK_0); \2412jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \2413va_end(args); \2414ret = jvalue.get_##ResultType(); \2415return ret;\2416JNI_END24172418// the runtime type of subword integral basic types is integer2419DEFINE_CALLSTATICMETHODV(jboolean, Boolean, T_BOOLEAN2420, HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2421HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN(_ret_ref));2422DEFINE_CALLSTATICMETHODV(jbyte, Byte, T_BYTE2423, HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2424HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN(_ret_ref));2425DEFINE_CALLSTATICMETHODV(jchar, Char, T_CHAR2426, HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2427HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN(_ret_ref));2428DEFINE_CALLSTATICMETHODV(jshort, Short, T_SHORT2429, HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2430HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN(_ret_ref));24312432DEFINE_CALLSTATICMETHODV(jobject, Object, T_OBJECT2433, HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2434HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN(_ret_ref));2435DEFINE_CALLSTATICMETHODV(jint, Int, T_INT2436, HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2437HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN(_ret_ref));2438DEFINE_CALLSTATICMETHODV(jlong, Long, T_LONG2439, HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2440HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN(_ret_ref));2441// Float and double probes don't return value because dtrace doesn't currently support it2442DEFINE_CALLSTATICMETHODV(jfloat, Float, T_FLOAT2443, HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2444HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN());2445DEFINE_CALLSTATICMETHODV(jdouble, Double, T_DOUBLE2446, HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY(env, cls, (uintptr_t)methodID),2447HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN());24482449#define DEFINE_CALLSTATICMETHODA(ResultType, Result, Tag \2450, EntryProbe, ResultProbe) \2451\2452DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType \2453, ResultProbe); \2454\2455JNI_ENTRY(ResultType, \2456jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \2457JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \2458\2459EntryProbe; \2460ResultType ret = 0;\2461DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \2462(const ResultType&)ret);\2463\2464JavaValue jvalue(Tag); \2465JNI_ArgumentPusherArray ap(methodID, args); \2466jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \2467ret = jvalue.get_##ResultType(); \2468return ret;\2469JNI_END24702471// the runtime type of subword integral basic types is integer2472DEFINE_CALLSTATICMETHODA(jboolean, Boolean, T_BOOLEAN2473, HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2474HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN(_ret_ref));2475DEFINE_CALLSTATICMETHODA(jbyte, Byte, T_BYTE2476, HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2477HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN(_ret_ref));2478DEFINE_CALLSTATICMETHODA(jchar, Char, T_CHAR2479, HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2480HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN(_ret_ref));2481DEFINE_CALLSTATICMETHODA(jshort, Short, T_SHORT2482, HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2483HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN(_ret_ref));24842485DEFINE_CALLSTATICMETHODA(jobject, Object, T_OBJECT2486, HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2487HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN(_ret_ref));2488DEFINE_CALLSTATICMETHODA(jint, Int, T_INT2489, HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2490HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN(_ret_ref));2491DEFINE_CALLSTATICMETHODA(jlong, Long, T_LONG2492, HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2493HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN(_ret_ref));2494// Float and double probes don't return value because dtrace doesn't currently support it2495DEFINE_CALLSTATICMETHODA(jfloat, Float, T_FLOAT2496, HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2497HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN());2498DEFINE_CALLSTATICMETHODA(jdouble, Double, T_DOUBLE2499, HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY(env, cls, (uintptr_t)methodID),2500HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN());25012502DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod2503, HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN());2504DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV2505, HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN());2506DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA2507, HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN());2508#endif /* USDT2 */25092510JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...))2511JNIWrapper("CallStaticVoidMethod");2512#ifndef USDT22513DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethod__entry, env, cls, methodID);2514#else /* USDT2 */2515HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY(2516env, cls, (uintptr_t) methodID);2517#endif /* USDT2 */2518DT_VOID_RETURN_MARK(CallStaticVoidMethod);25192520va_list args;2521va_start(args, methodID);2522JavaValue jvalue(T_VOID);2523JNI_ArgumentPusherVaArg ap(methodID, args);2524jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);2525va_end(args);2526JNI_END252725282529JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args))2530JNIWrapper("CallStaticVoidMethodV");2531#ifndef USDT22532DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodV__entry, env, cls, methodID);2533#else /* USDT2 */2534HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY(2535env, cls, (uintptr_t) methodID);2536#endif /* USDT2 */2537DT_VOID_RETURN_MARK(CallStaticVoidMethodV);25382539JavaValue jvalue(T_VOID);2540JNI_ArgumentPusherVaArg ap(methodID, args);2541jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);2542JNI_END254325442545JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args))2546JNIWrapper("CallStaticVoidMethodA");2547#ifndef USDT22548DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodA__entry, env, cls, methodID);2549#else /* USDT2 */2550HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY(2551env, cls, (uintptr_t) methodID);2552#endif /* USDT2 */2553DT_VOID_RETURN_MARK(CallStaticVoidMethodA);25542555JavaValue jvalue(T_VOID);2556JNI_ArgumentPusherArray ap(methodID, args);2557jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);2558JNI_END255925602561//2562// Accessing Fields2563//256425652566#ifndef USDT22567DT_RETURN_MARK_DECL(GetFieldID, jfieldID);2568#else /* USDT2 */2569DT_RETURN_MARK_DECL(GetFieldID, jfieldID2570, HOTSPOT_JNI_GETFIELDID_RETURN((uintptr_t)_ret_ref));2571#endif /* USDT2 */25722573JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz,2574const char *name, const char *sig))2575JNIWrapper("GetFieldID");2576#ifndef USDT22577DTRACE_PROBE4(hotspot_jni, GetFieldID__entry, env, clazz, name, sig);2578#else /* USDT2 */2579HOTSPOT_JNI_GETFIELDID_ENTRY(2580env, clazz, (char *) name, (char *) sig);2581#endif /* USDT2 */2582jfieldID ret = 0;2583DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret);25842585// The class should have been loaded (we have an instance of the class2586// passed in) so the field and signature should already be in the symbol2587// table. If they're not there, the field doesn't exist.2588TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));2589TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));2590if (fieldname == NULL || signame == NULL) {2591THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);2592}2593KlassHandle k(THREAD,2594java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));2595// Make sure class is initialized before handing id's out to fields2596k()->initialize(CHECK_NULL);25972598fieldDescriptor fd;2599if (!k()->oop_is_instance() ||2600!InstanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) {2601THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);2602}26032604// A jfieldID for a non-static field is simply the offset of the field within the instanceOop2605// It may also have hash bits for k, if VerifyJNIFields is turned on.2606ret = jfieldIDWorkaround::to_instance_jfieldID(k(), fd.offset());2607return ret;2608JNI_END260926102611JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))2612JNIWrapper("GetObjectField");2613#ifndef USDT22614DTRACE_PROBE3(hotspot_jni, GetObjectField__entry, env, obj, fieldID);2615#else /* USDT2 */2616HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(2617env, obj, (uintptr_t) fieldID);2618#endif /* USDT2 */2619oop o = JNIHandles::resolve_non_null(obj);2620Klass* k = o->klass();2621int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);2622// Keep JVMTI addition small and only check enabled flag here.2623// jni_GetField_probe() assumes that is okay to create handles.2624if (JvmtiExport::should_post_field_access()) {2625o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);2626}2627jobject ret = JNIHandles::make_local(env, o->obj_field(offset));2628#if INCLUDE_ALL_GCS2629// If G1 is enabled and we are accessing the value of the referent2630// field in a reference object then we need to register a non-null2631// referent with the SATB barrier.2632if (UseG1GC) {2633bool needs_barrier = false;26342635if (ret != NULL &&2636offset == java_lang_ref_Reference::referent_offset &&2637InstanceKlass::cast(k)->reference_type() != REF_NONE) {2638assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity");2639needs_barrier = true;2640}26412642if (needs_barrier) {2643oop referent = JNIHandles::resolve(ret);2644G1SATBCardTableModRefBS::enqueue(referent);2645}2646}2647#endif // INCLUDE_ALL_GCS2648#ifndef USDT22649DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret);2650#else /* USDT2 */2651HOTSPOT_JNI_GETOBJECTFIELD_RETURN(2652ret);2653#endif /* USDT2 */2654return ret;2655JNI_END265626572658#ifndef USDT22659#define DEFINE_GETFIELD(Return,Fieldname,Result) \2660\2661DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return);\2662\2663JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \2664JNIWrapper("Get" XSTR(Result) "Field"); \2665\2666DTRACE_PROBE3(hotspot_jni, Get##Result##Field__entry, env, obj, fieldID);\2667Return ret = 0;\2668DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\2669\2670oop o = JNIHandles::resolve_non_null(obj); \2671Klass* k = o->klass(); \2672int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \2673/* Keep JVMTI addition small and only check enabled flag here. */ \2674/* jni_GetField_probe_nh() assumes that is not okay to create handles */ \2675/* and creates a ResetNoHandleMark. */ \2676if (JvmtiExport::should_post_field_access()) { \2677o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \2678} \2679ret = o->Fieldname##_field(offset); \2680return ret; \2681JNI_END26822683DEFINE_GETFIELD(jboolean, bool, Boolean)2684DEFINE_GETFIELD(jbyte, byte, Byte)2685DEFINE_GETFIELD(jchar, char, Char)2686DEFINE_GETFIELD(jshort, short, Short)2687DEFINE_GETFIELD(jint, int, Int)2688DEFINE_GETFIELD(jlong, long, Long)2689DEFINE_GETFIELD(jfloat, float, Float)2690DEFINE_GETFIELD(jdouble, double, Double)26912692#else /* USDT2 */26932694#define DEFINE_GETFIELD(Return,Fieldname,Result \2695, EntryProbe, ReturnProbe) \2696\2697DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \2698, ReturnProbe); \2699\2700JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \2701JNIWrapper("Get" XSTR(Result) "Field"); \2702\2703EntryProbe; \2704Return ret = 0;\2705DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\2706\2707oop o = JNIHandles::resolve_non_null(obj); \2708Klass* k = o->klass(); \2709int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \2710/* Keep JVMTI addition small and only check enabled flag here. */ \2711/* jni_GetField_probe_nh() assumes that is not okay to create handles */ \2712/* and creates a ResetNoHandleMark. */ \2713if (JvmtiExport::should_post_field_access()) { \2714o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \2715} \2716ret = o->Fieldname##_field(offset); \2717return ret; \2718JNI_END27192720DEFINE_GETFIELD(jboolean, bool, Boolean2721, HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2722HOTSPOT_JNI_GETBOOLEANFIELD_RETURN(_ret_ref))2723DEFINE_GETFIELD(jbyte, byte, Byte2724, HOTSPOT_JNI_GETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2725HOTSPOT_JNI_GETBYTEFIELD_RETURN(_ret_ref))2726DEFINE_GETFIELD(jchar, char, Char2727, HOTSPOT_JNI_GETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2728HOTSPOT_JNI_GETCHARFIELD_RETURN(_ret_ref))2729DEFINE_GETFIELD(jshort, short, Short2730, HOTSPOT_JNI_GETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2731HOTSPOT_JNI_GETSHORTFIELD_RETURN(_ret_ref))2732DEFINE_GETFIELD(jint, int, Int2733, HOTSPOT_JNI_GETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2734HOTSPOT_JNI_GETINTFIELD_RETURN(_ret_ref))2735DEFINE_GETFIELD(jlong, long, Long2736, HOTSPOT_JNI_GETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2737HOTSPOT_JNI_GETLONGFIELD_RETURN(_ret_ref))2738// Float and double probes don't return value because dtrace doesn't currently support it2739DEFINE_GETFIELD(jfloat, float, Float2740, HOTSPOT_JNI_GETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2741HOTSPOT_JNI_GETFLOATFIELD_RETURN())2742DEFINE_GETFIELD(jdouble, double, Double2743, HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2744HOTSPOT_JNI_GETDOUBLEFIELD_RETURN())2745#endif /* USDT2 */27462747address jni_GetBooleanField_addr() {2748return (address)jni_GetBooleanField;2749}2750address jni_GetByteField_addr() {2751return (address)jni_GetByteField;2752}2753address jni_GetCharField_addr() {2754return (address)jni_GetCharField;2755}2756address jni_GetShortField_addr() {2757return (address)jni_GetShortField;2758}2759address jni_GetIntField_addr() {2760return (address)jni_GetIntField;2761}2762address jni_GetLongField_addr() {2763return (address)jni_GetLongField;2764}2765address jni_GetFloatField_addr() {2766return (address)jni_GetFloatField;2767}2768address jni_GetDoubleField_addr() {2769return (address)jni_GetDoubleField;2770}27712772JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))2773JNIWrapper("SetObjectField");2774#ifndef USDT22775DTRACE_PROBE4(hotspot_jni, SetObjectField__entry, env, obj, fieldID, value);2776#else /* USDT2 */2777HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(2778env, obj, (uintptr_t) fieldID, value);2779#endif /* USDT2 */2780oop o = JNIHandles::resolve_non_null(obj);2781Klass* k = o->klass();2782int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);2783// Keep JVMTI addition small and only check enabled flag here.2784// jni_SetField_probe_nh() assumes that is not okay to create handles2785// and creates a ResetNoHandleMark.2786if (JvmtiExport::should_post_field_modification()) {2787jvalue field_value;2788field_value.l = value;2789o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value);2790}2791o->obj_field_put(offset, JNIHandles::resolve(value));2792#ifndef USDT22793DTRACE_PROBE(hotspot_jni, SetObjectField__return);2794#else /* USDT2 */2795HOTSPOT_JNI_SETOBJECTFIELD_RETURN(2796);2797#endif /* USDT2 */2798JNI_END27992800#ifndef USDT22801#define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType) \2802\2803JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \2804JNIWrapper("Set" XSTR(Result) "Field"); \2805\2806FP_SELECT_##Result( \2807DTRACE_PROBE4(hotspot_jni, Set##Result##Field__entry, env, obj, fieldID, value), \2808DTRACE_PROBE3(hotspot_jni, Set##Result##Field__entry, env, obj, fieldID)); \2809\2810oop o = JNIHandles::resolve_non_null(obj); \2811Klass* k = o->klass(); \2812int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \2813/* Keep JVMTI addition small and only check enabled flag here. */ \2814/* jni_SetField_probe_nh() assumes that is not okay to create handles */ \2815/* and creates a ResetNoHandleMark. */ \2816if (JvmtiExport::should_post_field_modification()) { \2817jvalue field_value; \2818field_value.unionType = value; \2819o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \2820} \2821o->Fieldname##_field_put(offset, value); \2822DTRACE_PROBE(hotspot_jni, Set##Result##Field__return);\2823JNI_END28242825DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z)2826DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b)2827DEFINE_SETFIELD(jchar, char, Char, 'C', c)2828DEFINE_SETFIELD(jshort, short, Short, 'S', s)2829DEFINE_SETFIELD(jint, int, Int, 'I', i)2830DEFINE_SETFIELD(jlong, long, Long, 'J', j)2831DEFINE_SETFIELD(jfloat, float, Float, 'F', f)2832DEFINE_SETFIELD(jdouble, double, Double, 'D', d)28332834#else /* USDT2 */28352836#define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \2837, EntryProbe, ReturnProbe) \2838\2839JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \2840JNIWrapper("Set" XSTR(Result) "Field"); \2841\2842EntryProbe; \2843\2844oop o = JNIHandles::resolve_non_null(obj); \2845Klass* k = o->klass(); \2846int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \2847/* Keep JVMTI addition small and only check enabled flag here. */ \2848/* jni_SetField_probe_nh() assumes that is not okay to create handles */ \2849/* and creates a ResetNoHandleMark. */ \2850if (JvmtiExport::should_post_field_modification()) { \2851jvalue field_value; \2852field_value.unionType = value; \2853o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \2854} \2855if (SigType == 'Z') { value = ((jboolean)value) & 1; } \2856o->Fieldname##_field_put(offset, value); \2857ReturnProbe; \2858JNI_END28592860DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z2861, HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),2862HOTSPOT_JNI_SETBOOLEANFIELD_RETURN())2863DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b2864, HOTSPOT_JNI_SETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),2865HOTSPOT_JNI_SETBYTEFIELD_RETURN())2866DEFINE_SETFIELD(jchar, char, Char, 'C', c2867, HOTSPOT_JNI_SETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),2868HOTSPOT_JNI_SETCHARFIELD_RETURN())2869DEFINE_SETFIELD(jshort, short, Short, 'S', s2870, HOTSPOT_JNI_SETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),2871HOTSPOT_JNI_SETSHORTFIELD_RETURN())2872DEFINE_SETFIELD(jint, int, Int, 'I', i2873, HOTSPOT_JNI_SETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),2874HOTSPOT_JNI_SETINTFIELD_RETURN())2875DEFINE_SETFIELD(jlong, long, Long, 'J', j2876, HOTSPOT_JNI_SETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),2877HOTSPOT_JNI_SETLONGFIELD_RETURN())2878// Float and double probes don't return value because dtrace doesn't currently support it2879DEFINE_SETFIELD(jfloat, float, Float, 'F', f2880, HOTSPOT_JNI_SETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2881HOTSPOT_JNI_SETFLOATFIELD_RETURN())2882DEFINE_SETFIELD(jdouble, double, Double, 'D', d2883, HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),2884HOTSPOT_JNI_SETDOUBLEFIELD_RETURN())2885#endif /* USDT2 */28862887#ifndef USDT22888DT_RETURN_MARK_DECL(ToReflectedField, jobject);2889#else /* USDT2 */2890DT_RETURN_MARK_DECL(ToReflectedField, jobject2891, HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(_ret_ref));2892#endif /* USDT2 */28932894JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic))2895JNIWrapper("ToReflectedField");2896#ifndef USDT22897DTRACE_PROBE4(hotspot_jni, ToReflectedField__entry,2898env, cls, fieldID, isStatic);2899#else /* USDT2 */2900HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY(2901env, cls, (uintptr_t) fieldID, isStatic);2902#endif /* USDT2 */2903jobject ret = NULL;2904DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret);29052906fieldDescriptor fd;2907bool found = false;2908Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));29092910assert(jfieldIDWorkaround::is_static_jfieldID(fieldID) == (isStatic != 0), "invalid fieldID");29112912if (isStatic) {2913// Static field. The fieldID a JNIid specifying the field holder and the offset within the Klass*.2914JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);2915assert(id->is_static_field_id(), "invalid static field id");2916found = id->find_local_field(&fd);2917} else {2918// Non-static field. The fieldID is really the offset of the field within the instanceOop.2919int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);2920found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, &fd);2921}2922assert(found, "bad fieldID passed into jni_ToReflectedField");2923oop reflected = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);2924ret = JNIHandles::make_local(env, reflected);2925return ret;2926JNI_END292729282929//2930// Accessing Static Fields2931//2932#ifndef USDT22933DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID);2934#else /* USDT2 */2935DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID2936, HOTSPOT_JNI_GETSTATICFIELDID_RETURN((uintptr_t)_ret_ref));2937#endif /* USDT2 */29382939JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz,2940const char *name, const char *sig))2941JNIWrapper("GetStaticFieldID");2942#ifndef USDT22943DTRACE_PROBE4(hotspot_jni, GetStaticFieldID__entry, env, clazz, name, sig);2944#else /* USDT2 */2945HOTSPOT_JNI_GETSTATICFIELDID_ENTRY(2946env, clazz, (char *) name, (char *) sig);2947#endif /* USDT2 */2948jfieldID ret = NULL;2949DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret);29502951// The class should have been loaded (we have an instance of the class2952// passed in) so the field and signature should already be in the symbol2953// table. If they're not there, the field doesn't exist.2954TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));2955TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));2956if (fieldname == NULL || signame == NULL) {2957THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);2958}2959KlassHandle k(THREAD,2960java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));2961// Make sure class is initialized before handing id's out to static fields2962k()->initialize(CHECK_NULL);29632964fieldDescriptor fd;2965if (!k()->oop_is_instance() ||2966!InstanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) {2967THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);2968}29692970// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*2971JNIid* id = fd.field_holder()->jni_id_for(fd.offset());2972debug_only(id->set_is_static_field_id();)29732974debug_only(id->verify(fd.field_holder()));29752976ret = jfieldIDWorkaround::to_static_jfieldID(id);2977return ret;2978JNI_END297929802981JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID))2982JNIWrapper("GetStaticObjectField");2983#ifndef USDT22984DTRACE_PROBE3(hotspot_jni, GetStaticObjectField__entry, env, clazz, fieldID);2985#else /* USDT2 */2986HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY(2987env, clazz, (uintptr_t) fieldID);2988#endif /* USDT2 */2989#if INCLUDE_JNI_CHECK2990DEBUG_ONLY(Klass* param_k = jniCheck::validate_class(thread, clazz);)2991#endif // INCLUDE_JNI_CHECK2992JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);2993assert(id->is_static_field_id(), "invalid static field id");2994// Keep JVMTI addition small and only check enabled flag here.2995// jni_GetField_probe() assumes that is okay to create handles.2996if (JvmtiExport::should_post_field_access()) {2997JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true);2998}2999jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset()));3000#ifndef USDT23001DTRACE_PROBE1(hotspot_jni, GetStaticObjectField__return, ret);3002#else /* USDT2 */3003HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(3004ret);3005#endif /* USDT2 */3006return ret;3007JNI_END30083009#ifndef USDT23010#define DEFINE_GETSTATICFIELD(Return,Fieldname,Result) \3011\3012DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return);\3013\3014JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \3015JNIWrapper("GetStatic" XSTR(Result) "Field"); \3016DTRACE_PROBE3(hotspot_jni, GetStatic##Result##Field__entry, env, clazz, fieldID);\3017Return ret = 0;\3018DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \3019(const Return&)ret);\3020JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \3021assert(id->is_static_field_id(), "invalid static field id"); \3022/* Keep JVMTI addition small and only check enabled flag here. */ \3023/* jni_GetField_probe() assumes that is okay to create handles. */ \3024if (JvmtiExport::should_post_field_access()) { \3025JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \3026} \3027ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \3028return ret;\3029JNI_END30303031DEFINE_GETSTATICFIELD(jboolean, bool, Boolean)3032DEFINE_GETSTATICFIELD(jbyte, byte, Byte)3033DEFINE_GETSTATICFIELD(jchar, char, Char)3034DEFINE_GETSTATICFIELD(jshort, short, Short)3035DEFINE_GETSTATICFIELD(jint, int, Int)3036DEFINE_GETSTATICFIELD(jlong, long, Long)3037DEFINE_GETSTATICFIELD(jfloat, float, Float)3038DEFINE_GETSTATICFIELD(jdouble, double, Double)30393040#else /* USDT2 */30413042#define DEFINE_GETSTATICFIELD(Return,Fieldname,Result \3043, EntryProbe, ReturnProbe) \3044\3045DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return \3046, ReturnProbe); \3047\3048JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \3049JNIWrapper("GetStatic" XSTR(Result) "Field"); \3050EntryProbe; \3051Return ret = 0;\3052DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \3053(const Return&)ret);\3054JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \3055assert(id->is_static_field_id(), "invalid static field id"); \3056/* Keep JVMTI addition small and only check enabled flag here. */ \3057/* jni_GetField_probe() assumes that is okay to create handles. */ \3058if (JvmtiExport::should_post_field_access()) { \3059JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \3060} \3061ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \3062return ret;\3063JNI_END30643065DEFINE_GETSTATICFIELD(jboolean, bool, Boolean3066, HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(_ret_ref))3067DEFINE_GETSTATICFIELD(jbyte, byte, Byte3068, HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(_ret_ref) )3069DEFINE_GETSTATICFIELD(jchar, char, Char3070, HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(_ret_ref) )3071DEFINE_GETSTATICFIELD(jshort, short, Short3072, HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(_ret_ref) )3073DEFINE_GETSTATICFIELD(jint, int, Int3074, HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(_ret_ref) )3075DEFINE_GETSTATICFIELD(jlong, long, Long3076, HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(_ret_ref) )3077// Float and double probes don't return value because dtrace doesn't currently support it3078DEFINE_GETSTATICFIELD(jfloat, float, Float3079, HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() )3080DEFINE_GETSTATICFIELD(jdouble, double, Double3081, HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() )3082#endif /* USDT2 */30833084JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value))3085JNIWrapper("SetStaticObjectField");3086#ifndef USDT23087DTRACE_PROBE4(hotspot_jni, SetStaticObjectField__entry, env, clazz, fieldID, value);3088#else /* USDT2 */3089HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY(3090env, clazz, (uintptr_t) fieldID, value);3091#endif /* USDT2 */3092JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);3093assert(id->is_static_field_id(), "invalid static field id");3094// Keep JVMTI addition small and only check enabled flag here.3095// jni_SetField_probe() assumes that is okay to create handles.3096if (JvmtiExport::should_post_field_modification()) {3097jvalue field_value;3098field_value.l = value;3099JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value);3100}3101id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value));3102#ifndef USDT23103DTRACE_PROBE(hotspot_jni, SetStaticObjectField__return);3104#else /* USDT2 */3105HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN(3106);3107#endif /* USDT2 */3108JNI_END310931103111#ifndef USDT23112#define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType) \3113\3114JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \3115JNIWrapper("SetStatic" XSTR(Result) "Field"); \3116FP_SELECT_##Result( \3117DTRACE_PROBE4(hotspot_jni, SetStatic##Result##Field__entry, env, clazz, fieldID, value), \3118DTRACE_PROBE3(hotspot_jni, SetStatic##Result##Field__entry, env, clazz, fieldID)); \3119\3120JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \3121assert(id->is_static_field_id(), "invalid static field id"); \3122/* Keep JVMTI addition small and only check enabled flag here. */ \3123/* jni_SetField_probe() assumes that is okay to create handles. */ \3124if (JvmtiExport::should_post_field_modification()) { \3125jvalue field_value; \3126field_value.unionType = value; \3127JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \3128} \3129id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \3130DTRACE_PROBE(hotspot_jni, SetStatic##Result##Field__return);\3131JNI_END31323133DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z)3134DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b)3135DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c)3136DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s)3137DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i)3138DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j)3139DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f)3140DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d)31413142#else /* USDT2 */31433144#define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType \3145, EntryProbe, ReturnProbe) \3146\3147JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \3148JNIWrapper("SetStatic" XSTR(Result) "Field"); \3149EntryProbe; \3150\3151JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \3152assert(id->is_static_field_id(), "invalid static field id"); \3153/* Keep JVMTI addition small and only check enabled flag here. */ \3154/* jni_SetField_probe() assumes that is okay to create handles. */ \3155if (JvmtiExport::should_post_field_modification()) { \3156jvalue field_value; \3157field_value.unionType = value; \3158JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \3159} \3160if (SigType == 'Z') { value = ((jboolean)value) & 1; } \3161id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \3162ReturnProbe;\3163JNI_END31643165DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z3166, HOTSPOT_JNI_SETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t)fieldID, value),3167HOTSPOT_JNI_SETBOOLEANFIELD_RETURN())3168DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b3169, HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),3170HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN())3171DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c3172, HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),3173HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN())3174DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s3175, HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),3176HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN())3177DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i3178, HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),3179HOTSPOT_JNI_SETSTATICINTFIELD_RETURN())3180DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j3181, HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),3182HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN())3183// Float and double probes don't return value because dtrace doesn't currently support it3184DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f3185, HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),3186HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN())3187DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d3188, HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),3189HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN())3190#endif /* USDT2 */31913192//3193// String Operations3194//31953196// Unicode Interface31973198#ifndef USDT23199DT_RETURN_MARK_DECL(NewString, jstring);3200#else /* USDT2 */3201DT_RETURN_MARK_DECL(NewString, jstring3202, HOTSPOT_JNI_NEWSTRING_RETURN(_ret_ref));3203#endif /* USDT2 */32043205JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len))3206JNIWrapper("NewString");3207#ifndef USDT23208DTRACE_PROBE3(hotspot_jni, NewString__entry, env, unicodeChars, len);3209#else /* USDT2 */3210HOTSPOT_JNI_NEWSTRING_ENTRY(3211env, (uint16_t *) unicodeChars, len);3212#endif /* USDT2 */3213jstring ret = NULL;3214DT_RETURN_MARK(NewString, jstring, (const jstring&)ret);3215oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL);3216ret = (jstring) JNIHandles::make_local(env, string);3217return ret;3218JNI_END321932203221JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string))3222JNIWrapper("GetStringLength");3223#ifndef USDT23224DTRACE_PROBE2(hotspot_jni, GetStringLength__entry, env, string);3225#else /* USDT2 */3226HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(3227env, string);3228#endif /* USDT2 */3229jsize ret = 0;3230oop s = JNIHandles::resolve_non_null(string);3231if (java_lang_String::value(s) != NULL) {3232ret = java_lang_String::length(s);3233}3234#ifndef USDT23235DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret);3236#else /* USDT2 */3237HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(3238ret);3239#endif /* USDT2 */3240return ret;3241JNI_END324232433244JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(3245JNIEnv *env, jstring string, jboolean *isCopy))3246JNIWrapper("GetStringChars");3247#ifndef USDT23248DTRACE_PROBE3(hotspot_jni, GetStringChars__entry, env, string, isCopy);3249#else /* USDT2 */3250HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(3251env, string, (uintptr_t *) isCopy);3252#endif /* USDT2 */3253jchar* buf = NULL;3254oop s = JNIHandles::resolve_non_null(string);3255typeArrayOop s_value = java_lang_String::value(s);3256if (s_value != NULL) {3257int s_len = java_lang_String::length(s);3258int s_offset = java_lang_String::offset(s);3259buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination3260/* JNI Specification states return NULL on OOM */3261if (buf != NULL) {3262if (s_len > 0) {3263memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);3264}3265buf[s_len] = 0;3266//%note jni_53267if (isCopy != NULL) {3268*isCopy = JNI_TRUE;3269}3270}3271}3272#ifndef USDT23273DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf);3274#else /* USDT2 */3275HOTSPOT_JNI_GETSTRINGCHARS_RETURN(3276buf);3277#endif /* USDT2 */3278return buf;3279JNI_END328032813282JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars))3283JNIWrapper("ReleaseStringChars");3284#ifndef USDT23285DTRACE_PROBE3(hotspot_jni, ReleaseStringChars__entry, env, str, chars);3286#else /* USDT2 */3287HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY(3288env, str, (uint16_t *) chars);3289#endif /* USDT2 */3290//%note jni_63291if (chars != NULL) {3292// Since String objects are supposed to be immutable, don't copy any3293// new data back. A bad user will have to go after the char array.3294FreeHeap((void*) chars);3295}3296#ifndef USDT23297DTRACE_PROBE(hotspot_jni, ReleaseStringChars__return);3298#else /* USDT2 */3299HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN(3300);3301#endif /* USDT2 */3302JNI_END330333043305// UTF Interface33063307#ifndef USDT23308DT_RETURN_MARK_DECL(NewStringUTF, jstring);3309#else /* USDT2 */3310DT_RETURN_MARK_DECL(NewStringUTF, jstring3311, HOTSPOT_JNI_NEWSTRINGUTF_RETURN(_ret_ref));3312#endif /* USDT2 */33133314JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes))3315JNIWrapper("NewStringUTF");3316#ifndef USDT23317DTRACE_PROBE2(hotspot_jni, NewStringUTF__entry, env, bytes);3318#else /* USDT2 */3319HOTSPOT_JNI_NEWSTRINGUTF_ENTRY(3320env, (char *) bytes);3321#endif /* USDT2 */3322jstring ret;3323DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret);33243325oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL);3326ret = (jstring) JNIHandles::make_local(env, result);3327return ret;3328JNI_END332933303331JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string))3332JNIWrapper("GetStringUTFLength");3333#ifndef USDT23334DTRACE_PROBE2(hotspot_jni, GetStringUTFLength__entry, env, string);3335#else /* USDT2 */3336HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(3337env, string);3338#endif /* USDT2 */3339jsize ret = 0;3340oop java_string = JNIHandles::resolve_non_null(string);3341if (java_lang_String::value(java_string) != NULL) {3342ret = java_lang_String::utf8_length(java_string);3343}3344#ifndef USDT23345DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret);3346#else /* USDT2 */3347HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(3348ret);3349#endif /* USDT2 */3350return ret;3351JNI_END335233533354JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy))3355JNIWrapper("GetStringUTFChars");3356#ifndef USDT23357DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy);3358#else /* USDT2 */3359HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(3360env, string, (uintptr_t *) isCopy);3361#endif /* USDT2 */3362char* result = NULL;3363oop java_string = JNIHandles::resolve_non_null(string);3364if (java_lang_String::value(java_string) != NULL) {3365size_t length = java_lang_String::utf8_length(java_string);3366/* JNI Specification states return NULL on OOM */3367result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);3368if (result != NULL) {3369java_lang_String::as_utf8_string(java_string, result, (int) length + 1);3370if (isCopy != NULL) {3371*isCopy = JNI_TRUE;3372}3373}3374}3375#ifndef USDT23376DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);3377#else /* USDT2 */3378HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN(3379result);3380#endif /* USDT2 */3381return result;3382JNI_END338333843385JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars))3386JNIWrapper("ReleaseStringUTFChars");3387#ifndef USDT23388DTRACE_PROBE3(hotspot_jni, ReleaseStringUTFChars__entry, env, str, chars);3389#else /* USDT2 */3390HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY(3391env, str, (char *) chars);3392#endif /* USDT2 */3393if (chars != NULL) {3394FreeHeap((char*) chars);3395}3396#ifndef USDT23397DTRACE_PROBE(hotspot_jni, ReleaseStringUTFChars__return);3398#else /* USDT2 */3399HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN(3400);3401#endif /* USDT2 */3402JNI_END340334043405JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array))3406JNIWrapper("GetArrayLength");3407#ifndef USDT23408DTRACE_PROBE2(hotspot_jni, GetArrayLength__entry, env, array);3409#else /* USDT2 */3410HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(3411env, array);3412#endif /* USDT2 */3413arrayOop a = arrayOop(JNIHandles::resolve_non_null(array));3414assert(a->is_array(), "must be array");3415jsize ret = a->length();3416#ifndef USDT23417DTRACE_PROBE1(hotspot_jni, GetArrayLength__return, ret);3418#else /* USDT2 */3419HOTSPOT_JNI_GETARRAYLENGTH_RETURN(3420ret);3421#endif /* USDT2 */3422return ret;3423JNI_END342434253426//3427// Object Array Operations3428//34293430#ifndef USDT23431DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray);3432#else /* USDT2 */3433DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray3434, HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(_ret_ref));3435#endif /* USDT2 */34363437JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement))3438JNIWrapper("NewObjectArray");3439#ifndef USDT23440DTRACE_PROBE4(hotspot_jni, NewObjectArray__entry, env, length, elementClass, initialElement);3441#else /* USDT2 */3442HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(3443env, length, elementClass, initialElement);3444#endif /* USDT2 */3445jobjectArray ret = NULL;3446DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret);3447KlassHandle ek(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass)));3448Klass* ako = ek()->array_klass(CHECK_NULL);3449KlassHandle ak = KlassHandle(THREAD, ako);3450ObjArrayKlass::cast(ak())->initialize(CHECK_NULL);3451objArrayOop result = ObjArrayKlass::cast(ak())->allocate(length, CHECK_NULL);3452oop initial_value = JNIHandles::resolve(initialElement);3453if (initial_value != NULL) { // array already initialized with NULL3454for (int index = 0; index < length; index++) {3455result->obj_at_put(index, initial_value);3456}3457}3458ret = (jobjectArray) JNIHandles::make_local(env, result);3459return ret;3460JNI_END34613462#ifndef USDT23463DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject);3464#else /* USDT2 */3465DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject3466, HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));3467#endif /* USDT2 */34683469JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))3470JNIWrapper("GetObjectArrayElement");3471#ifndef USDT23472DTRACE_PROBE3(hotspot_jni, GetObjectArrayElement__entry, env, array, index);3473#else /* USDT2 */3474HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(3475env, array, index);3476#endif /* USDT2 */3477jobject ret = NULL;3478DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);3479objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));3480if (a->is_within_bounds(index)) {3481ret = JNIHandles::make_local(env, a->obj_at(index));3482return ret;3483} else {3484char buf[jintAsStringSize];3485sprintf(buf, "%d", index);3486THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), buf);3487}3488JNI_END34893490#ifndef USDT23491DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement);3492#else /* USDT2 */3493DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement3494, HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());3495#endif /* USDT2 */34963497JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))3498JNIWrapper("SetObjectArrayElement");3499#ifndef USDT23500DTRACE_PROBE4(hotspot_jni, SetObjectArrayElement__entry, env, array, index, value);3501#else /* USDT2 */3502HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(3503env, array, index, value);3504#endif /* USDT2 */3505DT_VOID_RETURN_MARK(SetObjectArrayElement);35063507objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));3508oop v = JNIHandles::resolve(value);3509if (a->is_within_bounds(index)) {3510if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {3511a->obj_at_put(index, v);3512} else {3513THROW(vmSymbols::java_lang_ArrayStoreException());3514}3515} else {3516char buf[jintAsStringSize];3517sprintf(buf, "%d", index);3518THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), buf);3519}3520JNI_END352135223523#ifndef USDT23524#define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \3525\3526DT_RETURN_MARK_DECL(New##Result##Array, Return); \3527\3528JNI_ENTRY(Return, \3529jni_New##Result##Array(JNIEnv *env, jsize len)) \3530JNIWrapper("New" XSTR(Result) "Array"); \3531DTRACE_PROBE2(hotspot_jni, New##Result##Array__entry, env, len);\3532Return ret = NULL;\3533DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\3534\3535oop obj= oopFactory::Allocator(len, CHECK_0); \3536ret = (Return) JNIHandles::make_local(env, obj); \3537return ret;\3538JNI_END35393540DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean)3541DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte)3542DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short)3543DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char)3544DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int)3545DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long)3546DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float)3547DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double)35483549#else /* USDT2 */35503551#define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \3552,EntryProbe,ReturnProbe) \3553\3554DT_RETURN_MARK_DECL(New##Result##Array, Return \3555, ReturnProbe); \3556\3557JNI_ENTRY(Return, \3558jni_New##Result##Array(JNIEnv *env, jsize len)) \3559JNIWrapper("New" XSTR(Result) "Array"); \3560EntryProbe; \3561Return ret = NULL;\3562DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\3563\3564oop obj= oopFactory::Allocator(len, CHECK_0); \3565ret = (Return) JNIHandles::make_local(env, obj); \3566return ret;\3567JNI_END35683569DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean,3570HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY(env, len),3571HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN(_ret_ref))3572DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte,3573HOTSPOT_JNI_NEWBYTEARRAY_ENTRY(env, len),3574HOTSPOT_JNI_NEWBYTEARRAY_RETURN(_ret_ref))3575DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short,3576HOTSPOT_JNI_NEWSHORTARRAY_ENTRY(env, len),3577HOTSPOT_JNI_NEWSHORTARRAY_RETURN(_ret_ref))3578DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char,3579HOTSPOT_JNI_NEWCHARARRAY_ENTRY(env, len),3580HOTSPOT_JNI_NEWCHARARRAY_RETURN(_ret_ref))3581DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int,3582HOTSPOT_JNI_NEWINTARRAY_ENTRY(env, len),3583HOTSPOT_JNI_NEWINTARRAY_RETURN(_ret_ref))3584DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long,3585HOTSPOT_JNI_NEWLONGARRAY_ENTRY(env, len),3586HOTSPOT_JNI_NEWLONGARRAY_RETURN(_ret_ref))3587DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float,3588HOTSPOT_JNI_NEWFLOATARRAY_ENTRY(env, len),3589HOTSPOT_JNI_NEWFLOATARRAY_RETURN(_ret_ref))3590DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double,3591HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(env, len),3592HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(_ret_ref))3593#endif /* USDT2 */35943595// Return an address which will fault if the caller writes to it.35963597static char* get_bad_address() {3598static char* bad_address = NULL;3599if (bad_address == NULL) {3600size_t size = os::vm_allocation_granularity();3601bad_address = os::reserve_memory(size);3602if (bad_address != NULL) {3603os::protect_memory(bad_address, size, os::MEM_PROT_READ,3604/*is_committed*/false);3605MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal);3606}3607}3608return bad_address;3609}361036113612#ifndef USDT23613#define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag) \3614\3615JNI_QUICK_ENTRY(ElementType*, \3616jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \3617JNIWrapper("Get" XSTR(Result) "ArrayElements"); \3618DTRACE_PROBE3(hotspot_jni, Get##Result##ArrayElements__entry, env, array, isCopy);\3619/* allocate an chunk of memory in c land */ \3620typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \3621ElementType* result; \3622int len = a->length(); \3623if (len == 0) { \3624/* Empty array: legal but useless, can't return NULL. \3625* Return a pointer to something useless. \3626* Avoid asserts in typeArrayOop. */ \3627result = (ElementType*)get_bad_address(); \3628} else { \3629/* JNI Specification states return NULL on OOM */ \3630result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \3631if (result != NULL) { \3632/* copy the array to the c chunk */ \3633memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \3634if (isCopy) { \3635*isCopy = JNI_TRUE; \3636} \3637} \3638} \3639DTRACE_PROBE1(hotspot_jni, Get##Result##ArrayElements__return, result);\3640return result; \3641JNI_END36423643DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool)3644DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte)3645DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short)3646DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char)3647DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int)3648DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long)3649DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float)3650DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double)36513652#else /* USDT2 */36533654#define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag \3655, EntryProbe, ReturnProbe) \3656\3657JNI_QUICK_ENTRY(ElementType*, \3658jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \3659JNIWrapper("Get" XSTR(Result) "ArrayElements"); \3660EntryProbe; \3661/* allocate an chunk of memory in c land */ \3662typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \3663ElementType* result; \3664int len = a->length(); \3665if (len == 0) { \3666/* Empty array: legal but useless, can't return NULL. \3667* Return a pointer to something useless. \3668* Avoid asserts in typeArrayOop. */ \3669result = (ElementType*)get_bad_address(); \3670} else { \3671/* JNI Specification states return NULL on OOM */ \3672result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \3673if (result != NULL) { \3674/* copy the array to the c chunk */ \3675memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \3676if (isCopy) { \3677*isCopy = JNI_TRUE; \3678} \3679} \3680} \3681ReturnProbe; \3682return result; \3683JNI_END36843685DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool3686, HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),3687HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN((uintptr_t*)result))3688DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte3689, HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),3690HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN((char*)result))3691DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short3692, HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy),3693HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN((uint16_t*)result))3694DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char3695, HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy),3696HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN(result))3697DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int3698, HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),3699HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN((uint32_t*)result))3700DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long3701, HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),3702HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN(((uintptr_t*)result)))3703// Float and double probes don't return value because dtrace doesn't currently support it3704DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float3705, HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),3706HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN(result))3707DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double3708, HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),3709HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(result))3710#endif /* USDT2 */37113712#ifndef USDT23713#define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag) \3714\3715JNI_QUICK_ENTRY(void, \3716jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \3717ElementType *buf, jint mode)) \3718JNIWrapper("Release" XSTR(Result) "ArrayElements"); \3719DTRACE_PROBE4(hotspot_jni, Release##Result##ArrayElements__entry, env, array, buf, mode);\3720typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \3721int len = a->length(); \3722if (len != 0) { /* Empty array: nothing to free or copy. */ \3723if ((mode == 0) || (mode == JNI_COMMIT)) { \3724memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \3725} \3726if ((mode == 0) || (mode == JNI_ABORT)) { \3727FreeHeap(buf); \3728} \3729} \3730DTRACE_PROBE(hotspot_jni, Release##Result##ArrayElements__return);\3731JNI_END37323733DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool)3734DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte)3735DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short)3736DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char)3737DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int)3738DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long)3739DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float)3740DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double)37413742#else /* USDT2 */37433744#define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag \3745, EntryProbe, ReturnProbe);\3746\3747JNI_QUICK_ENTRY(void, \3748jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \3749ElementType *buf, jint mode)) \3750JNIWrapper("Release" XSTR(Result) "ArrayElements"); \3751EntryProbe; \3752typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \3753int len = a->length(); \3754if (len != 0) { /* Empty array: nothing to free or copy. */ \3755if ((mode == 0) || (mode == JNI_COMMIT)) { \3756memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \3757} \3758if ((mode == 0) || (mode == JNI_ABORT)) { \3759FreeHeap(buf); \3760} \3761} \3762ReturnProbe; \3763JNI_END37643765DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool3766, HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode),3767HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN())3768DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte3769, HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY(env, array, (char *) buf, mode),3770HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN())3771DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short3772, HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode),3773HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN())3774DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char3775, HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode),3776HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN())3777DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int3778, HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY(env, array, (uint32_t *) buf, mode),3779HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN())3780DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long3781, HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode),3782HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN())3783DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float3784, HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY(env, array, (float *) buf, mode),3785HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN())3786DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double3787, HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(env, array, (double *) buf, mode),3788HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN())3789#endif /* USDT2 */37903791#ifndef USDT23792#define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \3793DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion);\3794\3795JNI_ENTRY(void, \3796jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \3797jsize len, ElementType *buf)) \3798JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \3799DTRACE_PROBE5(hotspot_jni, Get##Result##ArrayRegion__entry, env, array, start, len, buf);\3800DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \3801typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \3802if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \3803THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \3804} else { \3805if (len > 0) { \3806int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \3807memcpy((u_char*) buf, \3808(u_char*) src->Tag##_at_addr(start), \3809len << sc); \3810} \3811} \3812JNI_END38133814DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool)3815DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte)3816DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short)3817DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char)3818DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int)3819DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long)3820DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float)3821DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double)38223823#else /* USDT2 */38243825#define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \3826, EntryProbe, ReturnProbe); \3827DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion \3828, ReturnProbe); \3829\3830JNI_ENTRY(void, \3831jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \3832jsize len, ElementType *buf)) \3833JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \3834EntryProbe; \3835DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \3836typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \3837if (start < 0 || len < 0 || (start > src->length() - len)) { \3838THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \3839} else { \3840if (len > 0) { \3841int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \3842memcpy((u_char*) buf, \3843(u_char*) src->Tag##_at_addr(start), \3844len << sc); \3845} \3846} \3847JNI_END38483849DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool3850, HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),3851HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN());3852DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte3853, HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf),3854HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN());3855DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short3856, HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),3857HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN());3858DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char3859, HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t*) buf),3860HOTSPOT_JNI_GETCHARARRAYREGION_RETURN());3861DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int3862, HOTSPOT_JNI_GETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t*) buf),3863HOTSPOT_JNI_GETINTARRAYREGION_RETURN());3864DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long3865, HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),3866HOTSPOT_JNI_GETLONGARRAYREGION_RETURN());3867DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float3868, HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf),3869HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN());3870DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double3871, HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf),3872HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN());3873#endif /* USDT2 */38743875#ifndef USDT23876#define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \3877DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion);\3878\3879JNI_ENTRY(void, \3880jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \3881jsize len, const ElementType *buf)) \3882JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \3883DTRACE_PROBE5(hotspot_jni, Set##Result##ArrayRegion__entry, env, array, start, len, buf);\3884DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \3885typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \3886if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \3887THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \3888} else { \3889if (len > 0) { \3890int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \3891memcpy((u_char*) dst->Tag##_at_addr(start), \3892(u_char*) buf, \3893len << sc); \3894} \3895} \3896JNI_END38973898DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool)3899DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte)3900DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short)3901DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char)3902DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int)3903DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long)3904DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float)3905DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double)39063907#else /* USDT2 */39083909#define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \3910, EntryProbe, ReturnProbe); \3911DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion \3912,ReturnProbe); \3913\3914JNI_ENTRY(void, \3915jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \3916jsize len, const ElementType *buf)) \3917JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \3918EntryProbe; \3919DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \3920typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \3921if (start < 0 || len < 0 || (start > dst->length() - len)) { \3922THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \3923} else { \3924if (len > 0) { \3925int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \3926memcpy((u_char*) dst->Tag##_at_addr(start), \3927(u_char*) buf, \3928len << sc); \3929} \3930} \3931JNI_END39323933DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool3934, HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *)buf),3935HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN())3936DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte3937, HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf),3938HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN())3939DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short3940, HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),3941HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN())3942DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char3943, HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),3944HOTSPOT_JNI_SETCHARARRAYREGION_RETURN())3945DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int3946, HOTSPOT_JNI_SETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t *) buf),3947HOTSPOT_JNI_SETINTARRAYREGION_RETURN())3948DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long3949, HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),3950HOTSPOT_JNI_SETLONGARRAYREGION_RETURN())3951DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float3952, HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf),3953HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN())3954DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double3955, HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf),3956HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN())3957#endif /* USDT2 */395839593960//3961// Interception of natives3962//39633964// The RegisterNatives call being attempted tried to register with a method that3965// is not native. Ask JVM TI what prefixes have been specified. Then check3966// to see if the native method is now wrapped with the prefixes. See the3967// SetNativeMethodPrefix(es) functions in the JVM TI Spec for details.3968static Method* find_prefixed_native(KlassHandle k,3969Symbol* name, Symbol* signature, TRAPS) {3970#if INCLUDE_JVMTI3971ResourceMark rm(THREAD);3972Method* method;3973int name_len = name->utf8_length();3974char* name_str = name->as_utf8();3975int prefix_count;3976char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);3977for (int i = 0; i < prefix_count; i++) {3978char* prefix = prefixes[i];3979int prefix_len = (int)strlen(prefix);39803981// try adding this prefix to the method name and see if it matches another method name3982int trial_len = name_len + prefix_len;3983char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1);3984strcpy(trial_name_str, prefix);3985strcat(trial_name_str, name_str);3986TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len);3987if (trial_name == NULL) {3988continue; // no such symbol, so this prefix wasn't used, try the next prefix3989}3990method = k()->lookup_method(trial_name, signature);3991if (method == NULL) {3992continue; // signature doesn't match, try the next prefix3993}3994if (method->is_native()) {3995method->set_is_prefixed_native();3996return method; // wahoo, we found a prefixed version of the method, return it3997}3998// found as non-native, so prefix is good, add it, probably just need more prefixes3999name_len = trial_len;4000name_str = trial_name_str;4001}4002#endif // INCLUDE_JVMTI4003return NULL; // not found4004}40054006static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) {4007Method* method = k()->lookup_method(name, signature);4008if (method == NULL) {4009ResourceMark rm;4010stringStream st;4011st.print("Method %s name or signature does not match",4012Method::name_and_sig_as_C_string(k(), name, signature));4013THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);4014}4015if (!method->is_native()) {4016// trying to register to a non-native method, see if a JVM TI agent has added prefix(es)4017method = find_prefixed_native(k, name, signature, THREAD);4018if (method == NULL) {4019ResourceMark rm;4020stringStream st;4021st.print("Method %s is not declared as native",4022Method::name_and_sig_as_C_string(k(), name, signature));4023THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);4024}4025}40264027if (entry != NULL) {4028method->set_native_function(entry,4029Method::native_bind_event_is_interesting);4030} else {4031method->clear_native_function();4032}4033if (PrintJNIResolving) {4034ResourceMark rm(THREAD);4035tty->print_cr("[Registering JNI native method %s.%s]",4036method->method_holder()->external_name(),4037method->name()->as_C_string());4038}4039return true;4040}40414042#ifndef USDT24043DT_RETURN_MARK_DECL(RegisterNatives, jint);4044#else /* USDT2 */4045DT_RETURN_MARK_DECL(RegisterNatives, jint4046, HOTSPOT_JNI_REGISTERNATIVES_RETURN(_ret_ref));4047#endif /* USDT2 */40484049JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,4050const JNINativeMethod *methods,4051jint nMethods))4052JNIWrapper("RegisterNatives");4053#ifndef USDT24054DTRACE_PROBE4(hotspot_jni, RegisterNatives__entry, env, clazz, methods, nMethods);4055#else /* USDT2 */4056HOTSPOT_JNI_REGISTERNATIVES_ENTRY(4057env, clazz, (void *) methods, nMethods);4058#endif /* USDT2 */4059jint ret = 0;4060DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret);40614062KlassHandle h_k(thread, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));40634064for (int index = 0; index < nMethods; index++) {4065const char* meth_name = methods[index].name;4066const char* meth_sig = methods[index].signature;4067int meth_name_len = (int)strlen(meth_name);40684069// The class should have been loaded (we have an instance of the class4070// passed in) so the method and signature should already be in the symbol4071// table. If they're not there, the method doesn't exist.4072TempNewSymbol name = SymbolTable::probe(meth_name, meth_name_len);4073TempNewSymbol signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));40744075if (name == NULL || signature == NULL) {4076ResourceMark rm;4077stringStream st;4078st.print("Method %s.%s%s not found", h_k()->external_name(), meth_name, meth_sig);4079// Must return negative value on failure4080THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1);4081}40824083bool res = register_native(h_k, name, signature,4084(address) methods[index].fnPtr, THREAD);4085if (!res) {4086ret = -1;4087break;4088}4089}4090return ret;4091JNI_END409240934094JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz))4095JNIWrapper("UnregisterNatives");4096#ifndef USDT24097DTRACE_PROBE2(hotspot_jni, UnregisterNatives__entry, env, clazz);4098#else /* USDT2 */4099HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(4100env, clazz);4101#endif /* USDT2 */4102Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));4103//%note jni_24104if (k->oop_is_instance()) {4105for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) {4106Method* m = InstanceKlass::cast(k)->methods()->at(index);4107if (m->is_native()) {4108m->clear_native_function();4109m->set_signature_handler(NULL);4110}4111}4112}4113#ifndef USDT24114DTRACE_PROBE1(hotspot_jni, UnregisterNatives__return, 0);4115#else /* USDT2 */4116HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(41170);4118#endif /* USDT2 */4119return 0;4120JNI_END41214122//4123// Monitor functions4124//41254126#ifndef USDT24127DT_RETURN_MARK_DECL(MonitorEnter, jint);4128#else /* USDT2 */4129DT_RETURN_MARK_DECL(MonitorEnter, jint4130, HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));4131#endif /* USDT2 */41324133JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))4134#ifndef USDT24135DTRACE_PROBE2(hotspot_jni, MonitorEnter__entry, env, jobj);4136#else /* USDT2 */4137HOTSPOT_JNI_MONITORENTER_ENTRY(4138env, jobj);4139#endif /* USDT2 */4140jint ret = JNI_ERR;4141DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);41424143// If the object is null, we can't do anything with it4144if (jobj == NULL) {4145THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);4146}41474148Handle obj(thread, JNIHandles::resolve_non_null(jobj));4149ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));4150ret = JNI_OK;4151return ret;4152JNI_END41534154#ifndef USDT24155DT_RETURN_MARK_DECL(MonitorExit, jint);4156#else /* USDT2 */4157DT_RETURN_MARK_DECL(MonitorExit, jint4158, HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));4159#endif /* USDT2 */41604161JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))4162#ifndef USDT24163DTRACE_PROBE2(hotspot_jni, MonitorExit__entry, env, jobj);4164#else /* USDT2 */4165HOTSPOT_JNI_MONITOREXIT_ENTRY(4166env, jobj);4167#endif /* USDT2 */4168jint ret = JNI_ERR;4169DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);41704171// Don't do anything with a null object4172if (jobj == NULL) {4173THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);4174}41754176Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));4177ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));41784179ret = JNI_OK;4180return ret;4181JNI_END41824183//4184// Extensions4185//41864187#ifndef USDT24188DT_VOID_RETURN_MARK_DECL(GetStringRegion);4189#else /* USDT2 */4190DT_VOID_RETURN_MARK_DECL(GetStringRegion4191, HOTSPOT_JNI_GETSTRINGREGION_RETURN());4192#endif /* USDT2 */41934194JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf))4195JNIWrapper("GetStringRegion");4196#ifndef USDT24197DTRACE_PROBE5(hotspot_jni, GetStringRegion__entry, env, string, start, len, buf);4198#else /* USDT2 */4199HOTSPOT_JNI_GETSTRINGREGION_ENTRY(4200env, string, start, len, buf);4201#endif /* USDT2 */4202DT_VOID_RETURN_MARK(GetStringRegion);4203oop s = JNIHandles::resolve_non_null(string);4204int s_len = java_lang_String::length(s);4205if (start < 0 || len < 0 || start > s_len - len) {4206THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());4207} else {4208if (len > 0) {4209int s_offset = java_lang_String::offset(s);4210typeArrayOop s_value = java_lang_String::value(s);4211memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len);4212}4213}4214JNI_END42154216#ifndef USDT24217DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion);4218#else /* USDT2 */4219DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion4220, HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN());4221#endif /* USDT2 */42224223JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf))4224JNIWrapper("GetStringUTFRegion");4225#ifndef USDT24226DTRACE_PROBE5(hotspot_jni, GetStringUTFRegion__entry, env, string, start, len, buf);4227#else /* USDT2 */4228HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(4229env, string, start, len, buf);4230#endif /* USDT2 */4231DT_VOID_RETURN_MARK(GetStringUTFRegion);4232oop s = JNIHandles::resolve_non_null(string);4233int s_len = java_lang_String::length(s);4234if (start < 0 || len < 0 || start > s_len - len) {4235THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());4236} else {4237//%note jni_74238if (len > 0) {4239ResourceMark rm(THREAD);4240char *utf_region = java_lang_String::as_utf8_string(s, start, len);4241int utf_len = (int)strlen(utf_region);4242memcpy(buf, utf_region, utf_len);4243buf[utf_len] = 0;4244} else {4245// JDK null-terminates the buffer even in len is zero4246if (buf != NULL) {4247buf[0] = 0;4248}4249}4250}4251JNI_END425242534254JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy))4255JNIWrapper("GetPrimitiveArrayCritical");4256#ifndef USDT24257DTRACE_PROBE3(hotspot_jni, GetPrimitiveArrayCritical__entry, env, array, isCopy);4258#else /* USDT2 */4259HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(4260env, array, (uintptr_t *) isCopy);4261#endif /* USDT2 */4262GC_locker::lock_critical(thread);4263if (isCopy != NULL) {4264*isCopy = JNI_FALSE;4265}4266oop a = JNIHandles::resolve_non_null(array);4267assert(a->is_array(), "just checking");4268BasicType type;4269if (a->is_objArray()) {4270type = T_OBJECT;4271} else {4272type = TypeArrayKlass::cast(a->klass())->element_type();4273}4274void* ret = arrayOop(a)->base(type);4275#ifndef USDT24276DTRACE_PROBE1(hotspot_jni, GetPrimitiveArrayCritical__return, ret);4277#else /* USDT2 */4278HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN(4279ret);4280#endif /* USDT2 */4281return ret;4282JNI_END428342844285JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode))4286JNIWrapper("ReleasePrimitiveArrayCritical");4287#ifndef USDT24288DTRACE_PROBE4(hotspot_jni, ReleasePrimitiveArrayCritical__entry, env, array, carray, mode);4289#else /* USDT2 */4290HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(4291env, array, carray, mode);4292#endif /* USDT2 */4293// The array, carray and mode arguments are ignored4294GC_locker::unlock_critical(thread);4295#ifndef USDT24296DTRACE_PROBE(hotspot_jni, ReleasePrimitiveArrayCritical__return);4297#else /* USDT2 */4298HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN(4299);4300#endif /* USDT2 */4301JNI_END430243034304JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy))4305JNIWrapper("GetStringCritical");4306#ifndef USDT24307DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy);4308#else /* USDT2 */4309HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(4310env, string, (uintptr_t *) isCopy);4311#endif /* USDT2 */4312GC_locker::lock_critical(thread);4313if (isCopy != NULL) {4314*isCopy = JNI_FALSE;4315}4316oop s = JNIHandles::resolve_non_null(string);4317int s_len = java_lang_String::length(s);4318typeArrayOop s_value = java_lang_String::value(s);4319int s_offset = java_lang_String::offset(s);4320const jchar* ret;4321if (s_len > 0) {4322ret = s_value->char_at_addr(s_offset);4323} else {4324ret = (jchar*) s_value->base(T_CHAR);4325}4326#ifndef USDT24327DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret);4328#else /* USDT2 */4329HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN(4330(uint16_t *) ret);4331#endif /* USDT2 */4332return ret;4333JNI_END433443354336JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars))4337JNIWrapper("ReleaseStringCritical");4338#ifndef USDT24339DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars);4340#else /* USDT2 */4341HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(4342env, str, (uint16_t *) chars);4343#endif /* USDT2 */4344// The str and chars arguments are ignored4345GC_locker::unlock_critical(thread);4346#ifndef USDT24347DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return);4348#else /* USDT2 */4349HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN(4350);4351#endif /* USDT2 */4352JNI_END435343544355JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))4356JNIWrapper("jni_NewWeakGlobalRef");4357#ifndef USDT24358DTRACE_PROBE2(hotspot_jni, NewWeakGlobalRef__entry, env, ref);4359#else /* USDT2 */4360HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(4361env, ref);4362#endif /* USDT2 */4363Handle ref_handle(thread, JNIHandles::resolve(ref));4364jweak ret = JNIHandles::make_weak_global(ref_handle);4365#ifndef USDT24366DTRACE_PROBE1(hotspot_jni, NewWeakGlobalRef__return, ret);4367#else /* USDT2 */4368HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(4369ret);4370#endif /* USDT2 */4371return ret;4372JNI_END43734374// Must be JNI_ENTRY (with HandleMark)4375JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))4376JNIWrapper("jni_DeleteWeakGlobalRef");4377#ifndef USDT24378DTRACE_PROBE2(hotspot_jni, DeleteWeakGlobalRef__entry, env, ref);4379#else /* USDT2 */4380HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(4381env, ref);4382#endif /* USDT2 */4383JNIHandles::destroy_weak_global(ref);4384#ifndef USDT24385DTRACE_PROBE(hotspot_jni, DeleteWeakGlobalRef__return);4386#else /* USDT2 */4387HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN(4388);4389#endif /* USDT2 */4390JNI_END439143924393JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env))4394JNIWrapper("jni_ExceptionCheck");4395#ifndef USDT24396DTRACE_PROBE1(hotspot_jni, ExceptionCheck__entry, env);4397#else /* USDT2 */4398HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(4399env);4400#endif /* USDT2 */4401jni_check_async_exceptions(thread);4402jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;4403#ifndef USDT24404DTRACE_PROBE1(hotspot_jni, ExceptionCheck__return, ret);4405#else /* USDT2 */4406HOTSPOT_JNI_EXCEPTIONCHECK_RETURN(4407ret);4408#endif /* USDT2 */4409return ret;4410JNI_END441144124413// Initialization state for three routines below relating to4414// java.nio.DirectBuffers4415static jint directBufferSupportInitializeStarted = 0;4416static volatile jint directBufferSupportInitializeEnded = 0;4417static volatile jint directBufferSupportInitializeFailed = 0;4418static jclass bufferClass = NULL;4419static jclass directBufferClass = NULL;4420static jclass directByteBufferClass = NULL;4421static jmethodID directByteBufferConstructor = NULL;4422static jfieldID directBufferAddressField = NULL;4423static jfieldID bufferCapacityField = NULL;44244425static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) {4426Handle loader; // null (bootstrap) loader4427Handle protection_domain; // null protection domain44284429TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);4430jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);44314432if (TraceClassResolution && result != NULL) {4433trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));4434}4435return result;4436}44374438// These lookups are done with the NULL (bootstrap) ClassLoader to4439// circumvent any security checks that would be done by jni_FindClass.4440JNI_ENTRY(bool, lookupDirectBufferClasses(JNIEnv* env))4441{4442if ((bufferClass = lookupOne(env, "java/nio/Buffer", thread)) == NULL) { return false; }4443if ((directBufferClass = lookupOne(env, "sun/nio/ch/DirectBuffer", thread)) == NULL) { return false; }4444if ((directByteBufferClass = lookupOne(env, "java/nio/DirectByteBuffer", thread)) == NULL) { return false; }4445return true;4446}4447JNI_END444844494450static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) {4451if (directBufferSupportInitializeFailed) {4452return false;4453}44544455if (Atomic::cmpxchg(1, &directBufferSupportInitializeStarted, 0) == 0) {4456if (!lookupDirectBufferClasses(env)) {4457directBufferSupportInitializeFailed = 1;4458return false;4459}44604461// Make global references for these4462bufferClass = (jclass) env->NewGlobalRef(bufferClass);4463directBufferClass = (jclass) env->NewGlobalRef(directBufferClass);4464directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass);44654466// Get needed field and method IDs4467directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>", "(JI)V");4468if (env->ExceptionCheck()) {4469env->ExceptionClear();4470directBufferSupportInitializeFailed = 1;4471return false;4472}4473directBufferAddressField = env->GetFieldID(bufferClass, "address", "J");4474if (env->ExceptionCheck()) {4475env->ExceptionClear();4476directBufferSupportInitializeFailed = 1;4477return false;4478}4479bufferCapacityField = env->GetFieldID(bufferClass, "capacity", "I");4480if (env->ExceptionCheck()) {4481env->ExceptionClear();4482directBufferSupportInitializeFailed = 1;4483return false;4484}44854486if ((directByteBufferConstructor == NULL) ||4487(directBufferAddressField == NULL) ||4488(bufferCapacityField == NULL)) {4489directBufferSupportInitializeFailed = 1;4490return false;4491}44924493directBufferSupportInitializeEnded = 1;4494} else {4495while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) {4496// Set state as yield_all can call os:sleep. On Solaris, yield_all calls4497// os::sleep which requires the VM state transition. On other platforms, it4498// is not necessary. The following call to change the VM state is purposely4499// put inside the loop to avoid potential deadlock when multiple threads4500// try to call this method. See 6791815 for more details.4501ThreadInVMfromNative tivn(thread);4502os::yield_all();4503}4504}45054506return !directBufferSupportInitializeFailed;4507}45084509extern "C" jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, jlong capacity)4510{4511// thread_from_jni_environment() will block if VM is gone.4512JavaThread* thread = JavaThread::thread_from_jni_environment(env);45134514JNIWrapper("jni_NewDirectByteBuffer");4515#ifndef USDT24516DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity);4517#else /* USDT2 */4518HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY(4519env, address, capacity);4520#endif /* USDT2 */45214522if (!directBufferSupportInitializeEnded) {4523if (!initializeDirectBufferSupport(env, thread)) {4524#ifndef USDT24525DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL);4526#else /* USDT2 */4527HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(4528NULL);4529#endif /* USDT2 */4530return NULL;4531}4532}45334534// Being paranoid about accidental sign extension on address4535jlong addr = (jlong) ((uintptr_t) address);4536// NOTE that package-private DirectByteBuffer constructor currently4537// takes int capacity4538jint cap = (jint) capacity;4539jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap);4540#ifndef USDT24541DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, ret);4542#else /* USDT2 */4543HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(4544ret);4545#endif /* USDT2 */4546return ret;4547}45484549#ifndef USDT24550DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*);4551#else /* USDT2 */4552DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*4553, HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref));4554#endif /* USDT2 */45554556extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)4557{4558// thread_from_jni_environment() will block if VM is gone.4559JavaThread* thread = JavaThread::thread_from_jni_environment(env);45604561JNIWrapper("jni_GetDirectBufferAddress");4562#ifndef USDT24563DTRACE_PROBE2(hotspot_jni, GetDirectBufferAddress__entry, env, buf);4564#else /* USDT2 */4565HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY(4566env, buf);4567#endif /* USDT2 */4568void* ret = NULL;4569DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret);45704571if (!directBufferSupportInitializeEnded) {4572if (!initializeDirectBufferSupport(env, thread)) {4573return 0;4574}4575}45764577if ((buf != NULL) && (!env->IsInstanceOf(buf, directBufferClass))) {4578return 0;4579}45804581ret = (void*)(intptr_t)env->GetLongField(buf, directBufferAddressField);4582return ret;4583}45844585#ifndef USDT24586DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong);4587#else /* USDT2 */4588DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong4589, HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(_ret_ref));4590#endif /* USDT2 */45914592extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf)4593{4594// thread_from_jni_environment() will block if VM is gone.4595JavaThread* thread = JavaThread::thread_from_jni_environment(env);45964597JNIWrapper("jni_GetDirectBufferCapacity");4598#ifndef USDT24599DTRACE_PROBE2(hotspot_jni, GetDirectBufferCapacity__entry, env, buf);4600#else /* USDT2 */4601HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY(4602env, buf);4603#endif /* USDT2 */4604jlong ret = -1;4605DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret);46064607if (!directBufferSupportInitializeEnded) {4608if (!initializeDirectBufferSupport(env, thread)) {4609ret = 0;4610return ret;4611}4612}46134614if (buf == NULL) {4615return -1;4616}46174618if (!env->IsInstanceOf(buf, directBufferClass)) {4619return -1;4620}46214622// NOTE that capacity is currently an int in the implementation4623ret = env->GetIntField(buf, bufferCapacityField);4624return ret;4625}462646274628JNI_LEAF(jint, jni_GetVersion(JNIEnv *env))4629JNIWrapper("GetVersion");4630#ifndef USDT24631DTRACE_PROBE1(hotspot_jni, GetVersion__entry, env);4632#else /* USDT2 */4633HOTSPOT_JNI_GETVERSION_ENTRY(4634env);4635#endif /* USDT2 */4636#ifndef USDT24637DTRACE_PROBE1(hotspot_jni, GetVersion__return, CurrentVersion);4638#else /* USDT2 */4639HOTSPOT_JNI_GETVERSION_RETURN(4640CurrentVersion);4641#endif /* USDT2 */4642return CurrentVersion;4643JNI_END46444645extern struct JavaVM_ main_vm;46464647JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm))4648JNIWrapper("jni_GetJavaVM");4649#ifndef USDT24650DTRACE_PROBE2(hotspot_jni, GetJavaVM__entry, env, vm);4651#else /* USDT2 */4652HOTSPOT_JNI_GETJAVAVM_ENTRY(4653env, (void **) vm);4654#endif /* USDT2 */4655*vm = (JavaVM *)(&main_vm);4656#ifndef USDT24657DTRACE_PROBE1(hotspot_jni, GetJavaVM__return, JNI_OK);4658#else /* USDT2 */4659HOTSPOT_JNI_GETJAVAVM_RETURN(4660JNI_OK);4661#endif /* USDT2 */4662return JNI_OK;4663JNI_END46644665// Structure containing all jni functions4666struct JNINativeInterface_ jni_NativeInterface = {4667NULL,4668NULL,4669NULL,46704671NULL,46724673jni_GetVersion,46744675jni_DefineClass,4676jni_FindClass,46774678jni_FromReflectedMethod,4679jni_FromReflectedField,46804681jni_ToReflectedMethod,46824683jni_GetSuperclass,4684jni_IsAssignableFrom,46854686jni_ToReflectedField,46874688jni_Throw,4689jni_ThrowNew,4690jni_ExceptionOccurred,4691jni_ExceptionDescribe,4692jni_ExceptionClear,4693jni_FatalError,46944695jni_PushLocalFrame,4696jni_PopLocalFrame,46974698jni_NewGlobalRef,4699jni_DeleteGlobalRef,4700jni_DeleteLocalRef,4701jni_IsSameObject,47024703jni_NewLocalRef,4704jni_EnsureLocalCapacity,47054706jni_AllocObject,4707jni_NewObject,4708jni_NewObjectV,4709jni_NewObjectA,47104711jni_GetObjectClass,4712jni_IsInstanceOf,47134714jni_GetMethodID,47154716jni_CallObjectMethod,4717jni_CallObjectMethodV,4718jni_CallObjectMethodA,4719jni_CallBooleanMethod,4720jni_CallBooleanMethodV,4721jni_CallBooleanMethodA,4722jni_CallByteMethod,4723jni_CallByteMethodV,4724jni_CallByteMethodA,4725jni_CallCharMethod,4726jni_CallCharMethodV,4727jni_CallCharMethodA,4728jni_CallShortMethod,4729jni_CallShortMethodV,4730jni_CallShortMethodA,4731jni_CallIntMethod,4732jni_CallIntMethodV,4733jni_CallIntMethodA,4734jni_CallLongMethod,4735jni_CallLongMethodV,4736jni_CallLongMethodA,4737jni_CallFloatMethod,4738jni_CallFloatMethodV,4739jni_CallFloatMethodA,4740jni_CallDoubleMethod,4741jni_CallDoubleMethodV,4742jni_CallDoubleMethodA,4743jni_CallVoidMethod,4744jni_CallVoidMethodV,4745jni_CallVoidMethodA,47464747jni_CallNonvirtualObjectMethod,4748jni_CallNonvirtualObjectMethodV,4749jni_CallNonvirtualObjectMethodA,4750jni_CallNonvirtualBooleanMethod,4751jni_CallNonvirtualBooleanMethodV,4752jni_CallNonvirtualBooleanMethodA,4753jni_CallNonvirtualByteMethod,4754jni_CallNonvirtualByteMethodV,4755jni_CallNonvirtualByteMethodA,4756jni_CallNonvirtualCharMethod,4757jni_CallNonvirtualCharMethodV,4758jni_CallNonvirtualCharMethodA,4759jni_CallNonvirtualShortMethod,4760jni_CallNonvirtualShortMethodV,4761jni_CallNonvirtualShortMethodA,4762jni_CallNonvirtualIntMethod,4763jni_CallNonvirtualIntMethodV,4764jni_CallNonvirtualIntMethodA,4765jni_CallNonvirtualLongMethod,4766jni_CallNonvirtualLongMethodV,4767jni_CallNonvirtualLongMethodA,4768jni_CallNonvirtualFloatMethod,4769jni_CallNonvirtualFloatMethodV,4770jni_CallNonvirtualFloatMethodA,4771jni_CallNonvirtualDoubleMethod,4772jni_CallNonvirtualDoubleMethodV,4773jni_CallNonvirtualDoubleMethodA,4774jni_CallNonvirtualVoidMethod,4775jni_CallNonvirtualVoidMethodV,4776jni_CallNonvirtualVoidMethodA,47774778jni_GetFieldID,47794780jni_GetObjectField,4781jni_GetBooleanField,4782jni_GetByteField,4783jni_GetCharField,4784jni_GetShortField,4785jni_GetIntField,4786jni_GetLongField,4787jni_GetFloatField,4788jni_GetDoubleField,47894790jni_SetObjectField,4791jni_SetBooleanField,4792jni_SetByteField,4793jni_SetCharField,4794jni_SetShortField,4795jni_SetIntField,4796jni_SetLongField,4797jni_SetFloatField,4798jni_SetDoubleField,47994800jni_GetStaticMethodID,48014802jni_CallStaticObjectMethod,4803jni_CallStaticObjectMethodV,4804jni_CallStaticObjectMethodA,4805jni_CallStaticBooleanMethod,4806jni_CallStaticBooleanMethodV,4807jni_CallStaticBooleanMethodA,4808jni_CallStaticByteMethod,4809jni_CallStaticByteMethodV,4810jni_CallStaticByteMethodA,4811jni_CallStaticCharMethod,4812jni_CallStaticCharMethodV,4813jni_CallStaticCharMethodA,4814jni_CallStaticShortMethod,4815jni_CallStaticShortMethodV,4816jni_CallStaticShortMethodA,4817jni_CallStaticIntMethod,4818jni_CallStaticIntMethodV,4819jni_CallStaticIntMethodA,4820jni_CallStaticLongMethod,4821jni_CallStaticLongMethodV,4822jni_CallStaticLongMethodA,4823jni_CallStaticFloatMethod,4824jni_CallStaticFloatMethodV,4825jni_CallStaticFloatMethodA,4826jni_CallStaticDoubleMethod,4827jni_CallStaticDoubleMethodV,4828jni_CallStaticDoubleMethodA,4829jni_CallStaticVoidMethod,4830jni_CallStaticVoidMethodV,4831jni_CallStaticVoidMethodA,48324833jni_GetStaticFieldID,48344835jni_GetStaticObjectField,4836jni_GetStaticBooleanField,4837jni_GetStaticByteField,4838jni_GetStaticCharField,4839jni_GetStaticShortField,4840jni_GetStaticIntField,4841jni_GetStaticLongField,4842jni_GetStaticFloatField,4843jni_GetStaticDoubleField,48444845jni_SetStaticObjectField,4846jni_SetStaticBooleanField,4847jni_SetStaticByteField,4848jni_SetStaticCharField,4849jni_SetStaticShortField,4850jni_SetStaticIntField,4851jni_SetStaticLongField,4852jni_SetStaticFloatField,4853jni_SetStaticDoubleField,48544855jni_NewString,4856jni_GetStringLength,4857jni_GetStringChars,4858jni_ReleaseStringChars,48594860jni_NewStringUTF,4861jni_GetStringUTFLength,4862jni_GetStringUTFChars,4863jni_ReleaseStringUTFChars,48644865jni_GetArrayLength,48664867jni_NewObjectArray,4868jni_GetObjectArrayElement,4869jni_SetObjectArrayElement,48704871jni_NewBooleanArray,4872jni_NewByteArray,4873jni_NewCharArray,4874jni_NewShortArray,4875jni_NewIntArray,4876jni_NewLongArray,4877jni_NewFloatArray,4878jni_NewDoubleArray,48794880jni_GetBooleanArrayElements,4881jni_GetByteArrayElements,4882jni_GetCharArrayElements,4883jni_GetShortArrayElements,4884jni_GetIntArrayElements,4885jni_GetLongArrayElements,4886jni_GetFloatArrayElements,4887jni_GetDoubleArrayElements,48884889jni_ReleaseBooleanArrayElements,4890jni_ReleaseByteArrayElements,4891jni_ReleaseCharArrayElements,4892jni_ReleaseShortArrayElements,4893jni_ReleaseIntArrayElements,4894jni_ReleaseLongArrayElements,4895jni_ReleaseFloatArrayElements,4896jni_ReleaseDoubleArrayElements,48974898jni_GetBooleanArrayRegion,4899jni_GetByteArrayRegion,4900jni_GetCharArrayRegion,4901jni_GetShortArrayRegion,4902jni_GetIntArrayRegion,4903jni_GetLongArrayRegion,4904jni_GetFloatArrayRegion,4905jni_GetDoubleArrayRegion,49064907jni_SetBooleanArrayRegion,4908jni_SetByteArrayRegion,4909jni_SetCharArrayRegion,4910jni_SetShortArrayRegion,4911jni_SetIntArrayRegion,4912jni_SetLongArrayRegion,4913jni_SetFloatArrayRegion,4914jni_SetDoubleArrayRegion,49154916jni_RegisterNatives,4917jni_UnregisterNatives,49184919jni_MonitorEnter,4920jni_MonitorExit,49214922jni_GetJavaVM,49234924jni_GetStringRegion,4925jni_GetStringUTFRegion,49264927jni_GetPrimitiveArrayCritical,4928jni_ReleasePrimitiveArrayCritical,49294930jni_GetStringCritical,4931jni_ReleaseStringCritical,49324933jni_NewWeakGlobalRef,4934jni_DeleteWeakGlobalRef,49354936jni_ExceptionCheck,49374938jni_NewDirectByteBuffer,4939jni_GetDirectBufferAddress,4940jni_GetDirectBufferCapacity,49414942// New 1_6 features49434944jni_GetObjectRefType4945};494649474948// For jvmti use to modify jni function table.4949// Java threads in native contiues to run until it is transitioned4950// to VM at safepoint. Before the transition or before it is blocked4951// for safepoint it may access jni function table. VM could crash if4952// any java thread access the jni function table in the middle of memcpy.4953// To avoid this each function pointers are copied automically.4954void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {4955assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");4956intptr_t *a = (intptr_t *) jni_functions();4957intptr_t *b = (intptr_t *) new_jni_NativeInterface;4958for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {4959Atomic::store_ptr(*b++, a++);4960}4961}49624963void quicken_jni_functions() {4964// Replace Get<Primitive>Field with fast versions4965if (UseFastJNIAccessors && !JvmtiExport::can_post_field_access()4966&& !VerifyJNIFields && !TraceJNICalls && !CountJNICalls && !CheckJNICalls4967#if defined(_WINDOWS) && defined(IA32) && defined(COMPILER2)4968// windows x86 currently needs SEH wrapper and the gain of the fast4969// versions currently isn't certain for server vm on uniprocessor.4970&& os::is_MP()4971#endif4972) {4973address func;4974func = JNI_FastGetField::generate_fast_get_boolean_field();4975if (func != (address)-1) {4976jni_NativeInterface.GetBooleanField = (GetBooleanField_t)func;4977}4978func = JNI_FastGetField::generate_fast_get_byte_field();4979if (func != (address)-1) {4980jni_NativeInterface.GetByteField = (GetByteField_t)func;4981}4982func = JNI_FastGetField::generate_fast_get_char_field();4983if (func != (address)-1) {4984jni_NativeInterface.GetCharField = (GetCharField_t)func;4985}4986func = JNI_FastGetField::generate_fast_get_short_field();4987if (func != (address)-1) {4988jni_NativeInterface.GetShortField = (GetShortField_t)func;4989}4990func = JNI_FastGetField::generate_fast_get_int_field();4991if (func != (address)-1) {4992jni_NativeInterface.GetIntField = (GetIntField_t)func;4993}4994func = JNI_FastGetField::generate_fast_get_long_field();4995if (func != (address)-1) {4996jni_NativeInterface.GetLongField = (GetLongField_t)func;4997}4998func = JNI_FastGetField::generate_fast_get_float_field();4999if (func != (address)-1) {5000jni_NativeInterface.GetFloatField = (GetFloatField_t)func;5001}5002func = JNI_FastGetField::generate_fast_get_double_field();5003if (func != (address)-1) {5004jni_NativeInterface.GetDoubleField = (GetDoubleField_t)func;5005}5006}5007}50085009// Returns the function structure5010struct JNINativeInterface_* jni_functions() {5011#if INCLUDE_JNI_CHECK5012if (CheckJNICalls) return jni_functions_check();5013#endif // INCLUDE_JNI_CHECK5014return &jni_NativeInterface;5015}50165017// Returns the function structure5018struct JNINativeInterface_* jni_functions_nocheck() {5019return &jni_NativeInterface;5020}50215022static void post_thread_start_event(const JavaThread* jt) {5023assert(jt != NULL, "invariant");5024EventThreadStart event;5025if (event.should_commit()) {5026event.set_thread(JFR_THREAD_ID(jt));5027event.commit();5028}5029}50305031// Invocation API503250335034// Forward declaration5035extern const struct JNIInvokeInterface_ jni_InvokeInterface;50365037// Global invocation API vars5038volatile jint vm_created = 0;5039// Indicate whether it is safe to recreate VM5040volatile jint safe_to_recreate_vm = 1;5041struct JavaVM_ main_vm = {&jni_InvokeInterface};504250435044#define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */5045enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };50465047#ifndef USDT25048HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*);5049DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint);5050#else /* USDT2 */5051DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint5052, HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(_ret_ref));5053#endif /* USDT2 */50545055_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {5056#ifndef USDT25057HS_DTRACE_PROBE1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, args_);5058#else /* USDT2 */5059HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY(5060args_);5061#endif /* USDT2 */5062JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_;5063jint ret = JNI_ERR;5064DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret);50655066if (Threads::is_supported_jni_version(args->version)) {5067ret = JNI_OK;5068}5069// 1.1 style no longer supported in hotspot.5070// According the JNI spec, we should update args->version on return.5071// We also use the structure to communicate with launcher about default5072// stack size.5073if (args->version == JNI_VERSION_1_1) {5074args->version = JNI_VERSION_1_2;5075// javaStackSize is int in arguments structure5076assert(jlong(ThreadStackSize) * K < INT_MAX, "integer overflow");5077args->javaStackSize = (jint)(ThreadStackSize * K);5078}5079return ret;5080}50815082#ifndef PRODUCT50835084#include "gc_implementation/shared/gcTimer.hpp"5085#include "gc_interface/collectedHeap.hpp"5086#if INCLUDE_ALL_GCS5087#include "gc_implementation/g1/heapRegionRemSet.hpp"5088#endif5089#include "memory/guardedMemory.hpp"5090#include "utilities/quickSort.hpp"5091#include "utilities/ostream.hpp"5092#if INCLUDE_VM_STRUCTS5093#include "runtime/vmStructs.hpp"5094#endif50955096#define run_unit_test(unit_test_function_call) \5097tty->print_cr("Running test: " #unit_test_function_call); \5098unit_test_function_call50995100// Forward declaration5101void TestOS_test();5102void TestReservedSpace_test();5103void TestReserveMemorySpecial_test();5104void TestVirtualSpace_test();5105void TestMetaspaceAux_test();5106void SpaceManager_test_adjust_initial_chunk_size();5107void TestMetachunk_test();5108void TestVirtualSpaceNode_test();5109void TestNewSize_test();5110void TestKlass_test();5111void Test_linked_list();5112void TestResourcehash_test();5113void TestChunkedList_test();5114#if INCLUDE_ALL_GCS5115void TestOldFreeSpaceCalculation_test();5116void TestG1BiasedArray_test();5117void TestBufferingOopClosure_test();5118void TestCodeCacheRemSet_test();5119void FreeRegionList_test();5120void ChunkManager_test_list_index();5121#endif51225123void execute_internal_vm_tests() {5124if (ExecuteInternalVMTests) {5125tty->print_cr("Running internal VM tests");5126run_unit_test(TestOS_test());5127run_unit_test(TestReservedSpace_test());5128run_unit_test(TestReserveMemorySpecial_test());5129run_unit_test(TestVirtualSpace_test());5130run_unit_test(TestMetaspaceAux_test());5131run_unit_test(TestMetachunk_test());5132run_unit_test(TestVirtualSpaceNode_test());5133run_unit_test(GlobalDefinitions::test_globals());5134run_unit_test(GlobalDefinitions::test_proper_unit());5135run_unit_test(GCTimerAllTest::all());5136run_unit_test(arrayOopDesc::test_max_array_length());5137run_unit_test(CollectedHeap::test_is_in());5138run_unit_test(QuickSort::test_quick_sort());5139run_unit_test(GuardedMemory::test_guarded_memory());5140run_unit_test(AltHashing::test_alt_hash());5141run_unit_test(test_loggc_filename());5142run_unit_test(test_snprintf());5143run_unit_test(TestNewSize_test());5144run_unit_test(TestKlass_test());5145run_unit_test(TestResourcehash_test());5146run_unit_test(Test_linked_list());5147run_unit_test(TestChunkedList_test());5148run_unit_test(ObjectMonitor::sanity_checks());5149#if INCLUDE_VM_STRUCTS5150run_unit_test(VMStructs::test());5151#endif5152#if INCLUDE_ALL_GCS5153run_unit_test(TestOldFreeSpaceCalculation_test());5154run_unit_test(TestG1BiasedArray_test());5155run_unit_test(HeapRegionRemSet::test_prt());5156run_unit_test(SpaceManager_test_adjust_initial_chunk_size());5157run_unit_test(ChunkManager_test_list_index());5158run_unit_test(TestBufferingOopClosure_test());5159run_unit_test(TestCodeCacheRemSet_test());5160if (UseG1GC) {5161run_unit_test(FreeRegionList_test());5162}5163#endif5164tty->print_cr("All internal VM tests passed");5165}5166}51675168#undef run_unit_test51695170#endif51715172#ifndef USDT25173HS_DTRACE_PROBE_DECL3(hotspot_jni, CreateJavaVM__entry, vm, penv, args);5174DT_RETURN_MARK_DECL(CreateJavaVM, jint);5175#else /* USDT2 */5176DT_RETURN_MARK_DECL(CreateJavaVM, jint5177, HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref));5178#endif /* USDT2 */51795180_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {5181#ifndef USDT25182HS_DTRACE_PROBE3(hotspot_jni, CreateJavaVM__entry, vm, penv, args);5183#else /* USDT2 */5184HOTSPOT_JNI_CREATEJAVAVM_ENTRY(5185(void **) vm, penv, args);5186#endif /* USDT2 */51875188jint result = JNI_ERR;5189DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result);51905191// We're about to use Atomic::xchg for synchronization. Some Zero5192// platforms use the GCC builtin __sync_lock_test_and_set for this,5193// but __sync_lock_test_and_set is not guaranteed to do what we want5194// on all architectures. So we check it works before relying on it.5195#if defined(ZERO) && defined(ASSERT)5196{5197jint a = 0xcafebabe;5198jint b = Atomic::xchg(0xdeadbeef, &a);5199void *c = &a;5200void *d = Atomic::xchg_ptr(&b, &c);5201assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works");5202assert(c == &b && d == &a, "Atomic::xchg_ptr() works");5203}5204#endif // ZERO && ASSERT52055206// At the moment it's only possible to have one Java VM,5207// since some of the runtime state is in global variables.52085209// We cannot use our mutex locks here, since they only work on5210// Threads. We do an atomic compare and exchange to ensure only5211// one thread can call this method at a time52125213// We use Atomic::xchg rather than Atomic::add/dec since on some platforms5214// the add/dec implementations are dependent on whether we are running5215// on a multiprocessor, and at this stage of initialization the os::is_MP5216// function used to determine this will always return false. Atomic::xchg5217// does not have this problem.5218if (Atomic::xchg(1, &vm_created) == 1) {5219return JNI_EEXIST; // already created, or create attempt in progress5220}5221if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) {5222return JNI_ERR; // someone tried and failed and retry not allowed.5223}52245225assert(vm_created == 1, "vm_created is true during the creation");52265227/**5228* Certain errors during initialization are recoverable and do not5229* prevent this method from being called again at a later time5230* (perhaps with different arguments). However, at a certain5231* point during initialization if an error occurs we cannot allow5232* this function to be called again (or it will crash). In those5233* situations, the 'canTryAgain' flag is set to false, which atomically5234* sets safe_to_recreate_vm to 1, such that any new call to5235* JNI_CreateJavaVM will immediately fail using the above logic.5236*/5237bool can_try_again = true;52385239result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again);5240if (result == JNI_OK) {5241JavaThread *thread = JavaThread::current();5242/* thread is thread_in_vm here */5243*vm = (JavaVM *)(&main_vm);5244*(JNIEnv**)penv = thread->jni_environment();52455246// Tracks the time application was running before GC5247RuntimeService::record_application_start();52485249// Notify JVMTI5250if (JvmtiExport::should_post_thread_life()) {5251JvmtiExport::post_thread_start(thread);5252}52535254post_thread_start_event(thread);52555256#ifndef PRODUCT5257#ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED5258#define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()5259#endif52605261// Check if we should compile all classes on bootclasspath5262if (CompileTheWorld) ClassLoader::compile_the_world();5263if (ReplayCompiles) ciReplay::replay(thread);52645265// Some platforms (like Win*) need a wrapper around these test5266// functions in order to properly handle error conditions.5267CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(test_error_handler);5268CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(execute_internal_vm_tests);5269#endif52705271// Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.5272ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);5273} else {5274if (can_try_again) {5275// reset safe_to_recreate_vm to 1 so that retrial would be possible5276safe_to_recreate_vm = 1;5277}52785279// Creation failed. We must reset vm_created5280*vm = 0;5281*(JNIEnv**)penv = 0;5282// reset vm_created last to avoid race condition. Use OrderAccess to5283// control both compiler and architectural-based reordering.5284OrderAccess::release_store(&vm_created, 0);5285}52865287return result;5288}52895290#ifndef USDT25291HS_DTRACE_PROBE_DECL3(hotspot_jni, GetCreatedJavaVMs__entry, \5292JavaVM**, jsize, jsize*);5293HS_DTRACE_PROBE_DECL1(hotspot_jni, GetCreatedJavaVMs__return, jint);5294#endif /* !USDT2 */52955296_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) {5297// See bug 4367188, the wrapper can sometimes cause VM crashes5298// JNIWrapper("GetCreatedJavaVMs");5299#ifndef USDT25300HS_DTRACE_PROBE3(hotspot_jni, GetCreatedJavaVMs__entry, \5301vm_buf, bufLen, numVMs);5302#else /* USDT2 */5303HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY(5304(void **) vm_buf, bufLen, (uintptr_t *) numVMs);5305#endif /* USDT2 */5306if (vm_created) {5307if (numVMs != NULL) *numVMs = 1;5308if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm);5309} else {5310if (numVMs != NULL) *numVMs = 0;5311}5312#ifndef USDT25313HS_DTRACE_PROBE1(hotspot_jni, GetCreatedJavaVMs__return, JNI_OK);5314#else /* USDT2 */5315HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN(5316JNI_OK);5317#endif /* USDT2 */5318return JNI_OK;5319}53205321extern "C" {53225323#ifndef USDT25324DT_RETURN_MARK_DECL(DestroyJavaVM, jint);5325#else /* USDT2 */5326DT_RETURN_MARK_DECL(DestroyJavaVM, jint5327, HOTSPOT_JNI_DESTROYJAVAVM_RETURN(_ret_ref));5328#endif /* USDT2 */53295330jint JNICALL jni_DestroyJavaVM(JavaVM *vm) {5331#ifndef USDT25332DTRACE_PROBE1(hotspot_jni, DestroyJavaVM__entry, vm);5333#else /* USDT2 */5334HOTSPOT_JNI_DESTROYJAVAVM_ENTRY(5335vm);5336#endif /* USDT2 */5337jint res = JNI_ERR;5338DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res);53395340if (!vm_created) {5341res = JNI_ERR;5342return res;5343}53445345JNIWrapper("DestroyJavaVM");5346JNIEnv *env;5347JavaVMAttachArgs destroyargs;5348destroyargs.version = CurrentVersion;5349destroyargs.name = (char *)"DestroyJavaVM";5350destroyargs.group = NULL;5351res = vm->AttachCurrentThread((void **)&env, (void *)&destroyargs);5352if (res != JNI_OK) {5353return res;5354}53555356// Since this is not a JVM_ENTRY we have to set the thread state manually before entering.5357JavaThread* thread = JavaThread::current();5358ThreadStateTransition::transition_from_native(thread, _thread_in_vm);5359if (Threads::destroy_vm()) {5360// Should not change thread state, VM is gone5361vm_created = false;5362res = JNI_OK;5363return res;5364} else {5365ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);5366res = JNI_ERR;5367return res;5368}5369}537053715372static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool daemon) {5373JavaVMAttachArgs *args = (JavaVMAttachArgs *) _args;53745375// Check below commented out from JDK1.2fcs as well5376/*5377if (args && (args->version != JNI_VERSION_1_1 || args->version != JNI_VERSION_1_2)) {5378return JNI_EVERSION;5379}5380*/53815382Thread* t = ThreadLocalStorage::get_thread_slow();5383if (t != NULL) {5384// If the thread has been attached this operation is a no-op5385*(JNIEnv**)penv = ((JavaThread*) t)->jni_environment();5386return JNI_OK;5387}53885389// Create a thread and mark it as attaching so it will be skipped by the5390// ThreadsListEnumerator - see CR 64043065391JavaThread* thread = new JavaThread(true);53925393// Set correct safepoint info. The thread is going to call into Java when5394// initializing the Java level thread object. Hence, the correct state must5395// be set in order for the Safepoint code to deal with it correctly.5396thread->set_thread_state(_thread_in_vm);5397// Must do this before initialize_thread_local_storage5398thread->record_stack_base_and_size();53995400thread->initialize_thread_local_storage();54015402if (!os::create_attached_thread(thread)) {5403delete thread;5404return JNI_ERR;5405}5406// Enable stack overflow checks5407thread->create_stack_guard_pages();54085409thread->initialize_tlab();54105411thread->cache_global_variables();54125413// Crucial that we do not have a safepoint check for this thread, since it has5414// not been added to the Thread list yet.5415{ Threads_lock->lock_without_safepoint_check();5416// This must be inside this lock in order to get FullGCALot to work properly, i.e., to5417// avoid this thread trying to do a GC before it is added to the thread-list5418thread->set_active_handles(JNIHandleBlock::allocate_block());5419Threads::add(thread, daemon);5420Threads_lock->unlock();5421}5422// Create thread group and name info from attach arguments5423oop group = NULL;5424char* thread_name = NULL;5425if (args != NULL && Threads::is_supported_jni_version(args->version)) {5426group = JNIHandles::resolve(args->group);5427thread_name = args->name; // may be NULL5428}5429if (group == NULL) group = Universe::main_thread_group();54305431// Create Java level thread object and attach it to this thread5432bool attach_failed = false;5433{5434EXCEPTION_MARK;5435HandleMark hm(THREAD);5436Handle thread_group(THREAD, group);5437thread->allocate_threadObj(thread_group, thread_name, daemon, THREAD);5438if (HAS_PENDING_EXCEPTION) {5439CLEAR_PENDING_EXCEPTION;5440// cleanup outside the handle mark.5441attach_failed = true;5442}5443}54445445if (attach_failed) {5446// Added missing cleanup5447thread->cleanup_failed_attach_current_thread();5448return JNI_ERR;5449}54505451// mark the thread as no longer attaching5452// this uses a fence to push the change through so we don't have5453// to regrab the threads_lock5454thread->set_done_attaching_via_jni();54555456// Set java thread status.5457java_lang_Thread::set_thread_status(thread->threadObj(),5458java_lang_Thread::RUNNABLE);54595460// Notify the debugger5461if (JvmtiExport::should_post_thread_life()) {5462JvmtiExport::post_thread_start(thread);5463}54645465post_thread_start_event(thread);54665467*(JNIEnv**)penv = thread->jni_environment();54685469// Now leaving the VM, so change thread_state. This is normally automatically taken care5470// of in the JVM_ENTRY. But in this situation we have to do it manually. Notice, that by5471// using ThreadStateTransition::transition, we do a callback to the safepoint code if5472// needed.54735474ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native);54755476// Perform any platform dependent FPU setup5477os::setup_fpu();54785479return JNI_OK;5480}548154825483jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) {5484#ifndef USDT25485DTRACE_PROBE3(hotspot_jni, AttachCurrentThread__entry, vm, penv, _args);5486#else /* USDT2 */5487HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(5488vm, penv, _args);5489#endif /* USDT2 */5490if (!vm_created) {5491#ifndef USDT25492DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, JNI_ERR);5493#else /* USDT2 */5494HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(5495(uint32_t) JNI_ERR);5496#endif /* USDT2 */5497return JNI_ERR;5498}54995500JNIWrapper("AttachCurrentThread");5501jint ret = attach_current_thread(vm, penv, _args, false);5502#ifndef USDT25503DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, ret);5504#else /* USDT2 */5505HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(5506ret);5507#endif /* USDT2 */5508return ret;5509}551055115512jint JNICALL jni_DetachCurrentThread(JavaVM *vm) {5513#ifndef USDT25514DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__entry, vm);5515#else /* USDT2 */5516HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY(5517vm);5518#endif /* USDT2 */5519VM_Exit::block_if_vm_exited();55205521JNIWrapper("DetachCurrentThread");55225523// If the thread has been deattacted the operations is a no-op5524if (ThreadLocalStorage::thread() == NULL) {5525#ifndef USDT25526DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK);5527#else /* USDT2 */5528HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(5529JNI_OK);5530#endif /* USDT2 */5531return JNI_OK;5532}55335534JavaThread* thread = JavaThread::current();5535if (thread->has_last_Java_frame()) {5536#ifndef USDT25537DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_ERR);5538#else /* USDT2 */5539HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(5540(uint32_t) JNI_ERR);5541#endif /* USDT2 */5542// Can't detach a thread that's running java, that can't work.5543return JNI_ERR;5544}55455546// Safepoint support. Have to do call-back to safepoint code, if in the5547// middel of a safepoint operation5548ThreadStateTransition::transition_from_native(thread, _thread_in_vm);55495550// XXX: Note that JavaThread::exit() call below removes the guards on the5551// stack pages set up via enable_stack_{red,yellow}_zone() calls5552// above in jni_AttachCurrentThread. Unfortunately, while the setting5553// of the guards is visible in jni_AttachCurrentThread above,5554// the removal of the guards is buried below in JavaThread::exit()5555// here. The abstraction should be more symmetrically either exposed5556// or hidden (e.g. it could probably be hidden in the same5557// (platform-dependent) methods where we do alternate stack5558// maintenance work?)5559thread->exit(false, JavaThread::jni_detach);5560delete thread;55615562#ifndef USDT25563DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK);5564#else /* USDT2 */5565HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(5566JNI_OK);5567#endif /* USDT2 */5568return JNI_OK;5569}55705571#ifndef USDT25572DT_RETURN_MARK_DECL(GetEnv, jint);5573#else /* USDT2 */5574DT_RETURN_MARK_DECL(GetEnv, jint5575, HOTSPOT_JNI_GETENV_RETURN(_ret_ref));5576#endif /* USDT2 */55775578jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {5579#ifndef USDT25580DTRACE_PROBE3(hotspot_jni, GetEnv__entry, vm, penv, version);5581#else /* USDT2 */5582HOTSPOT_JNI_GETENV_ENTRY(5583vm, penv, version);5584#endif /* USDT2 */5585jint ret = JNI_ERR;5586DT_RETURN_MARK(GetEnv, jint, (const jint&)ret);55875588if (!vm_created) {5589*penv = NULL;5590ret = JNI_EDETACHED;5591return ret;5592}55935594if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) {5595return ret;5596}55975598#ifndef JVMPI_VERSION_15599// need these in order to be polite about older agents5600#define JVMPI_VERSION_1 ((jint)0x10000001)5601#define JVMPI_VERSION_1_1 ((jint)0x10000002)5602#define JVMPI_VERSION_1_2 ((jint)0x10000003)5603#endif // !JVMPI_VERSION_156045605Thread* thread = ThreadLocalStorage::thread();5606if (thread != NULL && thread->is_Java_thread()) {5607if (Threads::is_supported_jni_version_including_1_1(version)) {5608*(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment();5609ret = JNI_OK;5610return ret;56115612} else if (version == JVMPI_VERSION_1 ||5613version == JVMPI_VERSION_1_1 ||5614version == JVMPI_VERSION_1_2) {5615tty->print_cr("ERROR: JVMPI, an experimental interface, is no longer supported.");5616tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI).");5617ret = JNI_EVERSION;5618return ret;5619} else if (JvmtiExport::is_jvmdi_version(version)) {5620tty->print_cr("FATAL ERROR: JVMDI is no longer supported.");5621tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI).");5622ret = JNI_EVERSION;5623return ret;5624} else {5625*penv = NULL;5626ret = JNI_EVERSION;5627return ret;5628}5629} else {5630*penv = NULL;5631ret = JNI_EDETACHED;5632return ret;5633}5634}563556365637jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) {5638#ifndef USDT25639DTRACE_PROBE3(hotspot_jni, AttachCurrentThreadAsDaemon__entry, vm, penv, _args);5640#else /* USDT2 */5641HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(5642vm, penv, _args);5643#endif /* USDT2 */5644if (!vm_created) {5645#ifndef USDT25646DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, JNI_ERR);5647#else /* USDT2 */5648HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(5649(uint32_t) JNI_ERR);5650#endif /* USDT2 */5651return JNI_ERR;5652}56535654JNIWrapper("AttachCurrentThreadAsDaemon");5655jint ret = attach_current_thread(vm, penv, _args, true);5656#ifndef USDT25657DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, ret);5658#else /* USDT2 */5659HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(5660ret);5661#endif /* USDT2 */5662return ret;5663}566456655666} // End extern "C"56675668const struct JNIInvokeInterface_ jni_InvokeInterface = {5669NULL,5670NULL,5671NULL,56725673jni_DestroyJavaVM,5674jni_AttachCurrentThread,5675jni_DetachCurrentThread,5676jni_GetEnv,5677jni_AttachCurrentThreadAsDaemon5678};567956805681