< prev index next >

src/share/vm/prims/jni.cpp

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as --- 1,7 ---- /* ! * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as
*** 40,49 **** --- 40,50 ---- #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #endif // INCLUDE_ALL_GCS #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.inline.hpp" + #include "gc_implementation/shenandoah/shenandoahStringDedup.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceOop.hpp" #include "oops/markOop.hpp"
*** 4316,4346 **** HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN( ); #endif /* USDT2 */ JNI_END JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringCritical"); #ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy); #else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY( env, string, (uintptr_t *) isCopy); #endif /* USDT2 */ ! if (isCopy != NULL) { ! *isCopy = JNI_FALSE; ! } ! oop s = lock_gc_or_pin_object(thread, string); ! int s_len = java_lang_String::length(s); ! typeArrayOop s_value = java_lang_String::value(s); ! int s_offset = java_lang_String::offset(s); ! const jchar* ret; ! if (s_len > 0) { ! ret = s_value->char_at_addr(s_offset); } else { ret = (jchar*) s_value->base(T_CHAR); } #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret); #else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN( --- 4317,4378 ---- HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN( ); #endif /* USDT2 */ JNI_END + // If a copy of string value should be returned instead + static bool should_copy_string_value() { + // To prevent deduplication from replacing the value array while setting up or in + // the critical section. That would lead to the release operation + // unpinning the wrong object. + return Universe::heap()->supports_object_pinning() && ShenandoahStringDedup::is_enabled(); + } + + static typeArrayOop lock_gc_or_pin_string_value(JavaThread* thread, oop str) { + if (Universe::heap()->supports_object_pinning()) { + typeArrayOop s_value = java_lang_String::value(str); + return (typeArrayOop) Universe::heap()->pin_object(thread, s_value); + } else { + Handle h(thread, str); // Handlize across potential safepoint. + GC_locker::lock_critical(thread); + return java_lang_String::value(h()); + } + } + + static void unlock_gc_or_unpin_string_value(JavaThread* thread, oop str) { + if (Universe::heap()->supports_object_pinning()) { + typeArrayOop s_value = java_lang_String::value(str); + Universe::heap()->unpin_object(thread, s_value); + } else { + GC_locker::unlock_critical(thread); + } + } JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringCritical"); #ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy); #else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY( env, string, (uintptr_t *) isCopy); #endif /* USDT2 */ ! oop s = JNIHandles::resolve_non_null(string); ! jchar* ret; ! if (should_copy_string_value()) { ! typeArrayOop s_value = java_lang_String::value(s); ! int s_len = java_lang_String::length(s); ! ret = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination ! /* JNI Specification states return NULL on OOM */ ! if (ret != NULL) { ! memcpy(ret, s_value->char_at_addr(0), s_len * sizeof(jchar)); ! ret[s_len] = 0; ! } ! if (isCopy != NULL) *isCopy = JNI_TRUE; } else { + typeArrayOop s_value = lock_gc_or_pin_string_value(thread, s); ret = (jchar*) s_value->base(T_CHAR); + if (isCopy != NULL) *isCopy = JNI_FALSE; } #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret); #else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN(
*** 4356,4367 **** DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars); #else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY( env, str, (uint16_t *) chars); #endif /* USDT2 */ ! // The str and chars arguments are ignored ! unlock_gc_or_unpin_object(thread, str); #ifndef USDT2 DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return); #else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN( ); --- 4388,4406 ---- DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars); #else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY( env, str, (uint16_t *) chars); #endif /* USDT2 */ ! if (should_copy_string_value()) { ! // For copied string value, free jchar array allocated by earlier call to GetStringCritical. ! // This assumes that ReleaseStringCritical bookends GetStringCritical. ! FREE_C_HEAP_ARRAY(jchar, chars, mtInternal); ! } else { ! oop s = JNIHandles::resolve_non_null(str); ! // For not copied string value, drop the associated gc-locker/pin. ! unlock_gc_or_unpin_string_value(thread, s); ! } #ifndef USDT2 DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return); #else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN( );
< prev index next >