< prev index next >
src/java.base/share/native/libjava/jni_util.c
Print this page
rev 17266 : 8181147: JNI_GetStringPlatformChars should have a fast path for UTF-8
Reviewed-by: martin, erikj, chegar
*** 440,454 ****
done:
(*env)->DeleteLocalRef(env, cls);
return obj;
}
! /* Optimized for char set ISO_8559_1 */
static jstring
! newString8859_1(JNIEnv *env, const char *str)
{
- int len = (int)strlen(str);
jchar buf[512];
jchar *str1;
jstring result;
int i;
--- 440,453 ----
done:
(*env)->DeleteLocalRef(env, cls);
return obj;
}
! /* Optimized for charset ISO_8559_1 */
static jstring
! newSizedString8859_1(JNIEnv *env, const char *str, const int len)
{
jchar buf[512];
jchar *str1;
jstring result;
int i;
*** 467,476 ****
--- 466,485 ----
if (str1 != buf)
free(str1);
return result;
}
+ static jstring
+ newString8859_1(JNIEnv *env, const char *str)
+ {
+ int len = (int)strlen(str);
+ return newSizedString8859_1(env, str, len);
+ }
+
+ static const jbyte LATIN1 = 0;
+ static const jbyte UTF16 = 1;
+
static const char*
getString8859_1Chars(JNIEnv *env, jstring jstr)
{
int i;
char *result;
*** 499,509 ****
(*env)->ReleaseStringCritical(env, jstr, str);
return result;
}
! /* Optimized for char set ISO646-US (us-ascii) */
static jstring
newString646_US(JNIEnv *env, const char *str)
{
int len = (int)strlen(str);
jchar buf[512];
--- 508,518 ----
(*env)->ReleaseStringCritical(env, jstr, str);
return result;
}
! /* Optimized for charset ISO646-US (us-ascii) */
static jstring
newString646_US(JNIEnv *env, const char *str)
{
int len = (int)strlen(str);
jchar buf[512];
*** 571,581 ****
0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
};
! /* Optimized for char set Cp1252 */
static jstring
newStringCp1252(JNIEnv *env, const char *str)
{
int len = (int) strlen(str);
jchar buf[512];
--- 580,590 ----
0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
};
! /* Optimized for charset Cp1252 */
static jstring
newStringCp1252(JNIEnv *env, const char *str)
{
int len = (int) strlen(str);
jchar buf[512];
*** 669,680 ****
/* Cached method IDs */
static jmethodID String_init_ID; /* String(byte[], enc) */
static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
! int getFastEncoding() {
! return fastEncoding;
}
/* Initialize the fast encoding. If the "sun.jnu.encoding" property
* has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
*/
--- 678,770 ----
/* Cached method IDs */
static jmethodID String_init_ID; /* String(byte[], enc) */
static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
! /* Cached field IDs */
! static jfieldID String_coder_ID; /* String.coder */
! static jfieldID String_value_ID; /* String.value */
!
! static jboolean isJNUEncodingSupported = JNI_FALSE;
! static jboolean jnuEncodingSupported(JNIEnv *env) {
! jboolean exe;
! if (isJNUEncodingSupported == JNI_TRUE) {
! return JNI_TRUE;
! }
! isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
! env, &exe,
! "java/nio/charset/Charset",
! "isSupported",
! "(Ljava/lang/String;)Z",
! jnuEncoding).z;
! return isJNUEncodingSupported;
! }
!
! /* Create a new string by converting str to a heap-allocated byte array and
! * calling the appropriate String constructor.
! */
! static jstring
! newSizedStringJava(JNIEnv *env, const char *str, const int len)
! {
! jstring result = NULL;
! jbyteArray bytes = 0;
!
! if ((*env)->EnsureLocalCapacity(env, 2) < 0)
! return NULL;
!
! bytes = (*env)->NewByteArray(env, len);
! if (bytes != NULL) {
! jclass strClazz = JNU_ClassString(env);
! CHECK_NULL_RETURN(strClazz, 0);
! (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
! if (jnuEncodingSupported(env)) {
! result = (*env)->NewObject(env, strClazz,
! String_init_ID, bytes, jnuEncoding);
! } else {
! /*If the encoding specified in sun.jnu.encoding is not endorsed
! by "Charset.isSupported" we have to fall back to use String(byte[])
! explicitly here without specifying the encoding name, in which the
! StringCoding class will pickup the iso-8859-1 as the fallback
! converter for us.
! */
! jmethodID mid = (*env)->GetMethodID(env, strClazz,
! "<init>", "([B)V");
! if (mid != NULL) {
! result = (*env)->NewObject(env, strClazz, mid, bytes);
! }
! }
! (*env)->DeleteLocalRef(env, bytes);
! return result;
! }
! return NULL;
! }
!
! static jstring
! newStringJava(JNIEnv *env, const char *str)
! {
! int len = (int)strlen(str);
! return newSizedStringJava(env, str, len);
! }
!
! /* Optimized for charset UTF-8 */
! static jstring
! newStringUTF8(JNIEnv *env, const char *str)
! {
! int len;
! const unsigned char *p;
! unsigned char asciiCheck;
! for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) {
! asciiCheck |= *p;
! }
! len = (int)((const char*)p - str);
!
! if (asciiCheck < 0x80) {
! // ascii fast-path
! return newSizedString8859_1(env, str, len);
! }
!
! return newSizedStringJava(env, str, len);
}
/* Initialize the fast encoding. If the "sun.jnu.encoding" property
* has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
*/
*** 716,736 ****
* "en_UK" locale -> "ISO8859-1" (on 2.6)
*/
if ((strcmp(encname, "8859_1") == 0) ||
(strcmp(encname, "ISO8859-1") == 0) ||
(strcmp(encname, "ISO8859_1") == 0) ||
! (strcmp(encname, "ISO-8859-1") == 0))
fastEncoding = FAST_8859_1;
! else if (strcmp(encname, "ISO646-US") == 0)
fastEncoding = FAST_646_US;
! else if (strcmp(encname, "Cp1252") == 0 ||
/* This is a temporary fix until we move */
/* to wide character versions of all Windows */
/* calls. */
! strcmp(encname, "utf-16le") == 0)
fastEncoding = FAST_CP1252;
! else {
fastEncoding = NO_FAST_ENCODING;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
}
(*env)->ReleaseStringUTFChars(env, enc, encname);
}
--- 806,829 ----
* "en_UK" locale -> "ISO8859-1" (on 2.6)
*/
if ((strcmp(encname, "8859_1") == 0) ||
(strcmp(encname, "ISO8859-1") == 0) ||
(strcmp(encname, "ISO8859_1") == 0) ||
! (strcmp(encname, "ISO-8859-1") == 0)) {
fastEncoding = FAST_8859_1;
! } else if (strcmp(encname, "UTF-8") == 0) {
! fastEncoding = FAST_UTF_8;
! jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
! } else if (strcmp(encname, "ISO646-US") == 0) {
fastEncoding = FAST_646_US;
! } else if (strcmp(encname, "Cp1252") == 0 ||
/* This is a temporary fix until we move */
/* to wide character versions of all Windows */
/* calls. */
! strcmp(encname, "utf-16le") == 0) {
fastEncoding = FAST_CP1252;
! } else {
fastEncoding = NO_FAST_ENCODING;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
}
(*env)->ReleaseStringUTFChars(env, enc, encname);
}
*** 748,788 ****
String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
"getBytes", "(Ljava/lang/String;)[B");
CHECK_NULL(String_getBytes_ID);
String_init_ID = (*env)->GetMethodID(env, strClazz,
"<init>", "([BLjava/lang/String;)V");
}
- static jboolean isJNUEncodingSupported = JNI_FALSE;
- static jboolean jnuEncodingSupported(JNIEnv *env) {
- jboolean exe;
- if (isJNUEncodingSupported == JNI_TRUE) {
- return JNI_TRUE;
- }
- isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
- env, &exe,
- "java/nio/charset/Charset",
- "isSupported",
- "(Ljava/lang/String;)Z",
- jnuEncoding).z;
- return isJNUEncodingSupported;
- }
-
-
JNIEXPORT jstring
NewStringPlatform(JNIEnv *env, const char *str)
{
return JNU_NewStringPlatform(env, str);
}
JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str)
{
- jstring result = NULL;
- jbyteArray hab = 0;
- int len;
-
if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
}
--- 841,863 ----
String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
"getBytes", "(Ljava/lang/String;)[B");
CHECK_NULL(String_getBytes_ID);
String_init_ID = (*env)->GetMethodID(env, strClazz,
"<init>", "([BLjava/lang/String;)V");
+ String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
+ String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B");
}
JNIEXPORT jstring
NewStringPlatform(JNIEnv *env, const char *str)
{
return JNU_NewStringPlatform(env, str);
}
JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str)
{
if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
}
*** 790,858 ****
return newString8859_1(env, str);
if (fastEncoding == FAST_646_US)
return newString646_US(env, str);
if (fastEncoding == FAST_CP1252)
return newStringCp1252(env, str);
!
! if ((*env)->EnsureLocalCapacity(env, 2) < 0)
! return NULL;
!
! len = (int)strlen(str);
! hab = (*env)->NewByteArray(env, len);
! if (hab != 0) {
! jclass strClazz = JNU_ClassString(env);
! CHECK_NULL_RETURN(strClazz, 0);
! (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
! if (jnuEncodingSupported(env)) {
! result = (*env)->NewObject(env, strClazz,
! String_init_ID, hab, jnuEncoding);
! } else {
! /*If the encoding specified in sun.jnu.encoding is not endorsed
! by "Charset.isSupported" we have to fall back to use String(byte[])
! explicitly here without specifying the encoding name, in which the
! StringCoding class will pickup the iso-8859-1 as the fallback
! converter for us.
! */
! jmethodID mid = (*env)->GetMethodID(env, strClazz,
! "<init>", "([B)V");
! if (mid != NULL) {
! result = (*env)->NewObject(env, strClazz, mid, hab);
! }
! }
! (*env)->DeleteLocalRef(env, hab);
! return result;
! }
! return NULL;
}
JNIEXPORT const char *
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
return JNU_GetStringPlatformChars(env, jstr, isCopy);
}
! JNIEXPORT const char * JNICALL
! JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
! {
char *result = NULL;
jbyteArray hab = 0;
- if (isCopy)
- *isCopy = JNI_TRUE;
-
- if (fastEncoding == NO_ENCODING_YET) {
- initializeEncoding(env);
- JNU_CHECK_EXCEPTION_RETURN(env, 0);
- }
-
- if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
- return getString8859_1Chars(env, jstr);
- if (fastEncoding == FAST_646_US)
- return getString646_USChars(env, jstr);
- if (fastEncoding == FAST_CP1252)
- return getStringCp1252Chars(env, jstr);
-
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
return 0;
if (jnuEncodingSupported(env)) {
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
--- 865,889 ----
return newString8859_1(env, str);
if (fastEncoding == FAST_646_US)
return newString646_US(env, str);
if (fastEncoding == FAST_CP1252)
return newStringCp1252(env, str);
! if (fastEncoding == FAST_UTF_8)
! return newStringUTF8(env, str);
! return newStringJava(env, str);
}
JNIEXPORT const char *
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
return JNU_GetStringPlatformChars(env, jstr, isCopy);
}
! static const char* getStringBytes(JNIEnv *env, jstring jstr) {
char *result = NULL;
jbyteArray hab = 0;
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
return 0;
if (jnuEncodingSupported(env)) {
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
*** 881,890 ****
--- 912,995 ----
(*env)->DeleteLocalRef(env, hab);
return result;
}
+ static const char*
+ getStringUTF8(JNIEnv *env, jstring jstr)
+ {
+ int i;
+ char *result;
+ jarray value;
+ jint len;
+ const jbyte *str;
+ jint rlen;
+ int ri;
+ jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
+ if (coder != LATIN1) {
+ return getStringBytes(env, jstr);
+ }
+ value = (jarray)(*env)->GetObjectField(env, jstr, String_value_ID);
+ len = (*env)->GetArrayLength(env, value);
+ str = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, value, NULL);
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ rlen = len;
+ // we need two bytes for each latin-1 char above 127 (negative jbytes)
+ for (i = 0; i < len; i++) {
+ if (str[i] < 0) {
+ rlen++;
+ }
+ }
+
+ result = MALLOC_MIN4(rlen);
+ if (result == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, jstr, (void *)str, 0);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ for (ri = 0, i = 0; i < len; i++) {
+ jbyte c = str[i];
+ if (c < 0) {
+ result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6));
+ result[ri++] = (char)(0x80 | (c & 0x3f));
+ } else {
+ result[ri++] = c;
+ }
+ }
+ result[rlen] = '\0';
+ (*env)->ReleasePrimitiveArrayCritical(env, jstr, (void *)str, 0);
+ return result;
+ }
+
+ JNIEXPORT const char * JNICALL
+ JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
+ {
+
+ if (isCopy)
+ *isCopy = JNI_TRUE;
+
+ if (fastEncoding == NO_ENCODING_YET) {
+ initializeEncoding(env);
+ JNU_CHECK_EXCEPTION_RETURN(env, 0);
+ }
+
+ if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
+ return getString8859_1Chars(env, jstr);
+ if (fastEncoding == FAST_646_US)
+ return getString646_USChars(env, jstr);
+ if (fastEncoding == FAST_CP1252)
+ return getStringCp1252Chars(env, jstr);
+ if (fastEncoding == FAST_UTF_8)
+ return getStringUTF8(env, jstr);
+ else
+ return getStringBytes(env, jstr);
+ }
JNIEXPORT void JNICALL
JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
{
free((void *)str);
}
< prev index next >