8217442: Optimize native accesses to String.value

Reviewed-by: shade, dholmes
This commit is contained in:
Claes Redestad 2019-01-22 11:22:44 +01:00
parent 5f5d4425c2
commit 911c7ff446
5 changed files with 75 additions and 57 deletions

View File

@ -421,7 +421,7 @@ Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jch
oop obj = java_string();
// Typical usage is to convert all '/' to '.' in string.
typeArrayOop value = java_lang_String::value(obj);
int length = java_lang_String::length(obj);
int length = java_lang_String::length(obj, value);
bool is_latin1 = java_lang_String::is_latin1(obj);
// First check if any from_char exist
@ -485,7 +485,7 @@ Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jch
jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) {
typeArrayOop value = java_lang_String::value(java_string);
length = java_lang_String::length(java_string);
length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
jchar* result = NEW_RESOURCE_ARRAY_RETURN_NULL(jchar, length);
@ -506,11 +506,11 @@ jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS)
}
unsigned int java_lang_String::hash_code(oop java_string) {
int length = java_lang_String::length(java_string);
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string, value);
// Zero length string will hash to zero with String.hashCode() function.
if (length == 0) return 0;
typeArrayOop value = java_lang_String::value(java_string);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (is_latin1) {
@ -522,7 +522,7 @@ unsigned int java_lang_String::hash_code(oop java_string) {
char* java_lang_String::as_quoted_ascii(oop java_string) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
int length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (length == 0) return NULL;
@ -547,7 +547,7 @@ char* java_lang_String::as_quoted_ascii(oop java_string) {
Symbol* java_lang_String::as_symbol(oop java_string, TRAPS) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
int length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
jchar* base = (length == 0) ? NULL : value->char_at_addr(0);
@ -564,7 +564,7 @@ Symbol* java_lang_String::as_symbol(oop java_string, TRAPS) {
Symbol* java_lang_String::as_symbol_or_null(oop java_string) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
int length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
jchar* base = (length == 0) ? NULL : value->char_at_addr(0);
@ -577,23 +577,28 @@ Symbol* java_lang_String::as_symbol_or_null(oop java_string) {
}
}
int java_lang_String::utf8_length(oop java_string) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
bool is_latin1 = java_lang_String::is_latin1(java_string);
int java_lang_String::utf8_length(oop java_string, typeArrayOop value) {
assert(oopDesc::equals_raw(value, java_lang_String::value(java_string)),
"value must be same as java_lang_String::value(java_string)");
int length = java_lang_String::length(java_string, value);
if (length == 0) {
return 0;
}
if (!is_latin1) {
if (!java_lang_String::is_latin1(java_string)) {
return UNICODE::utf8_length(value->char_at_addr(0), length);
} else {
return UNICODE::utf8_length(value->byte_at_addr(0), length);
}
}
int java_lang_String::utf8_length(oop java_string) {
typeArrayOop value = java_lang_String::value(java_string);
return utf8_length(java_string, value);
}
char* java_lang_String::as_utf8_string(oop java_string) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
int length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
jchar* position = (length == 0) ? NULL : value->char_at_addr(0);
@ -604,24 +609,29 @@ char* java_lang_String::as_utf8_string(oop java_string) {
}
}
char* java_lang_String::as_utf8_string(oop java_string, typeArrayOop value, char* buf, int buflen) {
assert(oopDesc::equals_raw(value, java_lang_String::value(java_string)),
"value must be same as java_lang_String::value(java_string)");
int length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
jchar* position = (length == 0) ? NULL : value->char_at_addr(0);
return UNICODE::as_utf8(position, length, buf, buflen);
} else {
jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0);
return UNICODE::as_utf8(position, length, buf, buflen);
}
}
char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
jchar* position = (length == 0) ? NULL : value->char_at_addr(0);
return UNICODE::as_utf8(position, length, buf, buflen);
} else {
jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0);
return UNICODE::as_utf8(position, length, buf, buflen);
}
typeArrayOop value = java_lang_String::value(java_string);
return as_utf8_string(java_string, value, buf, buflen);
}
char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
assert(start + len <= length, "just checking");
bool is_latin1 = java_lang_String::is_latin1(java_string);
assert(start + len <= java_lang_String::length(java_string), "just checking");
if (!is_latin1) {
jchar* position = value->char_at_addr(start);
return UNICODE::as_utf8(position, len);
@ -631,11 +641,11 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
}
}
char* java_lang_String::as_utf8_string(oop java_string, int start, int len, char* buf, int buflen) {
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
assert(start + len <= length, "just checking");
bool is_latin1 = java_lang_String::is_latin1(java_string);
char* java_lang_String::as_utf8_string(oop java_string, typeArrayOop value, int start, int len, char* buf, int buflen) {
assert(oopDesc::equals_raw(value, java_lang_String::value(java_string)),
"value must be same as java_lang_String::value(java_string)");
assert(start + len <= java_lang_String::length(java_string), "just checking");
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
jchar* position = value->char_at_addr(start);
return UNICODE::as_utf8(position, len, buf, buflen);
@ -649,7 +659,7 @@ bool java_lang_String::equals(oop java_string, const jchar* chars, int len) {
assert(java_string->klass() == SystemDictionary::String_klass(),
"must be java_string");
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
int length = java_lang_String::length(java_string);
int length = java_lang_String::length(java_string, value);
if (length != len) {
return false;
}
@ -676,10 +686,10 @@ bool java_lang_String::equals(oop str1, oop str2) {
assert(str2->klass() == SystemDictionary::String_klass(),
"must be java String");
typeArrayOop value1 = java_lang_String::value_no_keepalive(str1);
int length1 = java_lang_String::length(str1);
int length1 = java_lang_String::length(str1, value1);
bool is_latin1 = java_lang_String::is_latin1(str1);
typeArrayOop value2 = java_lang_String::value_no_keepalive(str2);
int length2 = java_lang_String::length(str2);
int length2 = java_lang_String::length(str2, value2);
bool is_latin2 = java_lang_String::is_latin1(str2);
if ((length1 != length2) || (is_latin1 != is_latin2)) {
@ -707,7 +717,7 @@ void java_lang_String::print(oop java_string, outputStream* st) {
return;
}
int length = java_lang_String::length(java_string);
int length = java_lang_String::length(java_string, value);
bool is_latin1 = java_lang_String::is_latin1(java_string);
st->print("\"");

View File

@ -147,13 +147,16 @@ class java_lang_String : AllStatic {
static inline unsigned int hash(oop java_string);
static inline bool is_latin1(oop java_string);
static inline int length(oop java_string);
static inline int length(oop java_string, typeArrayOop string_value);
static int utf8_length(oop java_string);
static int utf8_length(oop java_string, typeArrayOop string_value);
// String converters
static char* as_utf8_string(oop java_string);
static char* as_utf8_string(oop java_string, char* buf, int buflen);
static char* as_utf8_string(oop java_string, int start, int len);
static char* as_utf8_string(oop java_string, int start, int len, char* buf, int buflen);
static char* as_utf8_string(oop java_string, typeArrayOop value, char* buf, int buflen);
static char* as_utf8_string(oop java_string, typeArrayOop value, int start, int len, char* buf, int buflen);
static char* as_platform_dependent_str(Handle java_string, TRAPS);
static jchar* as_unicode_string(oop java_string, int& length, TRAPS);
// produce an ascii string with all other values quoted using \u####

View File

@ -71,10 +71,11 @@ bool java_lang_String::is_latin1(oop java_string) {
assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
return coder == CODER_LATIN1;
}
int java_lang_String::length(oop java_string) {
int java_lang_String::length(oop java_string, typeArrayOop value) {
assert(initialized, "Must be initialized");
assert(is_instance(java_string), "must be java_string");
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
assert(oopDesc::equals_raw(value, java_lang_String::value(java_string)),
"value must be same as java_lang_String::value(java_string)");
if (value == NULL) {
return 0;
}
@ -85,6 +86,12 @@ int java_lang_String::length(oop java_string) {
}
return arr_length;
}
int java_lang_String::length(oop java_string) {
assert(initialized, "Must be initialized");
assert(is_instance(java_string), "must be java_string");
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
return length(java_string, value);
}
bool java_lang_String::is_instance_inlined(oop obj) {
return obj != NULL && obj->klass() == SystemDictionary::String_klass();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -474,15 +474,16 @@ const char* JfrJavaSupport::c_str(jstring string, Thread* t) {
}
const char* temp = NULL;
const oop java_string = resolve_non_null(string);
if (java_lang_String::value(java_string) != NULL) {
const size_t length = java_lang_String::utf8_length(java_string);
const typeArrayOop value = java_lang_String::value(java_string);
if (value != NULL) {
const size_t length = java_lang_String::utf8_length(java_string, value);
temp = NEW_RESOURCE_ARRAY_IN_THREAD(t, const char, (length + 1));
if (temp == NULL) {
JfrJavaSupport::throw_out_of_memory_error("Unable to allocate thread local native memory", t);
return NULL;
}
assert(temp != NULL, "invariant");
java_lang_String::as_utf8_string(java_string, const_cast<char*>(temp), (int) length + 1);
java_lang_String::as_utf8_string(java_string, value, const_cast<char*>(temp), (int) length + 1);
}
return temp;
}

View File

@ -2428,9 +2428,7 @@ JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string))
HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(env, string);
jsize ret = 0;
oop s = JNIHandles::resolve_non_null(string);
if (java_lang_String::value(s) != NULL) {
ret = java_lang_String::length(s);
}
ret = java_lang_String::length(s);
HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(ret);
return ret;
JNI_END
@ -2444,7 +2442,7 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
oop s = JNIHandles::resolve_non_null(string);
typeArrayOop s_value = java_lang_String::value(s);
if (s_value != NULL) {
int s_len = java_lang_String::length(s);
int s_len = java_lang_String::length(s, s_value);
bool is_latin1 = java_lang_String::is_latin1(s);
buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
/* JNI Specification states return NULL on OOM */
@ -2504,11 +2502,8 @@ JNI_END
JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string))
JNIWrapper("GetStringUTFLength");
HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(env, string);
jsize ret = 0;
oop java_string = JNIHandles::resolve_non_null(string);
if (java_lang_String::value(java_string) != NULL) {
ret = java_lang_String::utf8_length(java_string);
}
jsize ret = java_lang_String::utf8_length(java_string);
HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(ret);
return ret;
JNI_END
@ -2519,12 +2514,13 @@ JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboole
HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(env, string, (uintptr_t *) isCopy);
char* result = NULL;
oop java_string = JNIHandles::resolve_non_null(string);
if (java_lang_String::value(java_string) != NULL) {
size_t length = java_lang_String::utf8_length(java_string);
typeArrayOop s_value = java_lang_String::value(java_string);
if (s_value != NULL) {
size_t length = java_lang_String::utf8_length(java_string, s_value);
/* JNI Specification states return NULL on OOM */
result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
if (result != NULL) {
java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
java_lang_String::as_utf8_string(java_string, s_value, result, (int) length + 1);
if (isCopy != NULL) {
*isCopy = JNI_TRUE;
}
@ -3097,12 +3093,12 @@ JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, js
HOTSPOT_JNI_GETSTRINGREGION_ENTRY(env, string, start, len, buf);
DT_VOID_RETURN_MARK(GetStringRegion);
oop s = JNIHandles::resolve_non_null(string);
int s_len = java_lang_String::length(s);
typeArrayOop s_value = java_lang_String::value(s);
int s_len = java_lang_String::length(s, s_value);
if (start < 0 || len < 0 || start > s_len - len) {
THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
} else {
if (len > 0) {
typeArrayOop s_value = java_lang_String::value(s);
bool is_latin1 = java_lang_String::is_latin1(s);
if (!is_latin1) {
ArrayAccess<>::arraycopy_to_native(s_value, typeArrayOopDesc::element_offset<jchar>(start),
@ -3124,14 +3120,15 @@ JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start,
HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(env, string, start, len, buf);
DT_VOID_RETURN_MARK(GetStringUTFRegion);
oop s = JNIHandles::resolve_non_null(string);
int s_len = java_lang_String::length(s);
typeArrayOop s_value = java_lang_String::value(s);
int s_len = java_lang_String::length(s, s_value);
if (start < 0 || len < 0 || start > s_len - len) {
THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
} else {
//%note jni_7
if (len > 0) {
// Assume the buffer is large enough as the JNI spec. does not require user error checking
java_lang_String::as_utf8_string(s, start, len, buf, INT_MAX);
java_lang_String::as_utf8_string(s, s_value, start, len, buf, INT_MAX);
// as_utf8_string null-terminates the result string
} else {
// JDK null-terminates the buffer even in len is zero
@ -3203,7 +3200,7 @@ JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jbool
ret = (jchar*) s_value->base(T_CHAR);
} else {
// Inflate latin1 encoded string to UTF16
int s_len = java_lang_String::length(s);
int s_len = java_lang_String::length(s, s_value);
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) {